]> code.delx.au - gnu-emacs/blobdiff - src/xdisp.c
Update copyright year to 2015
[gnu-emacs] / src / xdisp.c
index a1e78f1129a7f5e0f2b6e0bb31f5cc7ebd74376e..aa5bfcbcbe423bdaf1336aa5ddca3216657b4055 100644 (file)
@@ -1,6 +1,6 @@
 /* Display generation from window structure and buffer text.
 
-Copyright (C) 1985-1988, 1993-1995, 1997-2014 Free Software Foundation,
+Copyright (C) 1985-1988, 1993-1995, 1997-2015 Free Software Foundation,
 Inc.
 
 This file is part of GNU Emacs.
@@ -347,7 +347,7 @@ Lisp_Object Qtext;
 /* Holds the list (error).  */
 static Lisp_Object list_of_error;
 
-static Lisp_Object Qfontification_functions;
+Lisp_Object Qfontification_functions;
 
 static Lisp_Object Qwrap_prefix;
 static Lisp_Object Qline_prefix;
@@ -905,7 +905,7 @@ 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 redisplay_internal (void);
-static int echo_area_display (int);
+static bool echo_area_display (bool);
 static void redisplay_windows (Lisp_Object);
 static void redisplay_window (Lisp_Object, bool);
 static Lisp_Object redisplay_window_error (Lisp_Object);
@@ -1144,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.  */
@@ -1406,6 +1406,7 @@ pos_visible_p (struct window *w, ptrdiff_t charpos, int *x, int *y,
   struct text_pos top;
   int visible_p = 0;
   struct buffer *old_buffer = NULL;
+  bool r2l = false;
 
   if (FRAME_INITIAL_P (XFRAME (WINDOW_FRAME (w))))
     return visible_p;
@@ -1455,15 +1456,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)
@@ -1476,7 +1481,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);
@@ -1486,11 +1490,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!  */
@@ -1688,6 +1692,8 @@ pos_visible_p (struct window *w, ptrdiff_t charpos, int *x, int *y,
          *rowh = max (0, (min (bottom_y, it.last_visible_y)
                           - max (top_y, window_top_y)));
          *vpos = it.vpos;
+         if (it.bidi_it.paragraph_dir == R2L)
+           r2l = true;
        }
     }
   else
@@ -1717,6 +1723,8 @@ pos_visible_p (struct window *w, ptrdiff_t charpos, int *x, int *y,
                           - max (it2.current_y,
                                  WINDOW_HEADER_LINE_HEIGHT (w))));
          *vpos = it2.vpos;
+         if (it2.bidi_it.paragraph_dir == R2L)
+           r2l = true;
        }
       else
        bidi_unshelve_cache (it2data, 1);
@@ -1726,10 +1734,20 @@ pos_visible_p (struct window *w, ptrdiff_t charpos, int *x, int *y,
   if (old_buffer)
     set_buffer_internal_1 (old_buffer);
 
-  if (visible_p && w->hscroll > 0)
-    *x -=
-      window_hscroll_limited (w, WINDOW_XFRAME (w))
-      * WINDOW_FRAME_COLUMN_WIDTH (w);
+  if (visible_p)
+    {
+      if (w->hscroll > 0)
+       *x -=
+         window_hscroll_limited (w, WINDOW_XFRAME (w))
+         * WINDOW_FRAME_COLUMN_WIDTH (w);
+      /* For lines in an R2L paragraph, we need to mirror the X pixel
+         coordinate wrt the text area.  For the reasons, see the
+         commentary in buffer_posn_from_coords and the explanation of
+         the geometry used by the move_it_* functions at the end of
+         the large commentary near the beginning of this file.  */
+      if (r2l)
+       *x = window_box_width (w, TEXT_AREA) - *x - 1;
+    }
 
 #if 0
   /* Debugging code.  */
@@ -2174,7 +2192,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);
@@ -2296,10 +2317,7 @@ get_phys_cursor_geometry (struct window *w, struct glyph_row *row,
      glyph, and `x-stretch-block-cursor' is nil, don't draw a
      rectangle as wide as the glyph, but use a canonical character
      width instead.  */
-  wd = glyph->pixel_width - 1;
-#if defined (HAVE_NTGUI) || defined (HAVE_NS)
-  wd++; /* Why? */
-#endif
+  wd = glyph->pixel_width;
 
   x = w->phys_cursor.x;
   if (x < 0)
@@ -2535,7 +2553,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;
@@ -2623,15 +2641,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);
@@ -2639,7 +2656,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);
     }
 
@@ -2990,12 +3007,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;
@@ -3060,6 +3073,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),
@@ -3413,6 +3439,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;
@@ -3614,6 +3682,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);
@@ -3630,6 +3699,7 @@ next_overlay_change (ptrdiff_t pos)
       endpos = min (endpos, oendpos);
     }
 
+  SAFE_FREE ();
   return endpos;
 }
 
@@ -5051,6 +5121,11 @@ handle_single_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object,
                  iterate_out_of_display_property (it);
                  *position = it->position;
                }
+             /* If we were to display this fringe bitmap,
+                next_element_from_image would have reset this flag.
+                Do the same, to avoid affecting overlays that
+                follow.  */
+             it->ignore_overlay_strings_at_pos_p = 0;
              return 1;
            }
        }
@@ -5070,12 +5145,15 @@ handle_single_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object,
              iterate_out_of_display_property (it);
              *position = it->position;
            }
+         if (it)
+           /* Reset this flag like next_element_from_image would.  */
+           it->ignore_overlay_strings_at_pos_p = 0;
          return 1;
        }
 
       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))))
            {
@@ -5690,10 +5768,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)
@@ -7268,27 +7347,15 @@ set_iterator_to_next (struct it *it, int reseat_p)
       else if (it->cmp_it.id >= 0)
        {
          /* We are currently getting glyphs from a composition.  */
-         int i;
-
          if (! it->bidi_p)
            {
              IT_CHARPOS (*it) += it->cmp_it.nchars;
              IT_BYTEPOS (*it) += it->cmp_it.nbytes;
-             if (it->cmp_it.to < it->cmp_it.nglyphs)
-               {
-                 it->cmp_it.from = it->cmp_it.to;
-               }
-             else
-               {
-                 it->cmp_it.id = -1;
-                 composition_compute_stop_pos (&it->cmp_it, IT_CHARPOS (*it),
-                                               IT_BYTEPOS (*it),
-                                               it->end_charpos, Qnil);
-               }
            }
-         else if (! it->cmp_it.reversed_p)
+         else
            {
-             /* Composition created while scanning forward.  */
+             int i;
+
              /* Update IT's char/byte positions to point to the first
                 character of the next grapheme cluster, or to the
                 character visually after the current composition.  */
@@ -7296,52 +7363,34 @@ set_iterator_to_next (struct it *it, int reseat_p)
                bidi_move_to_visually_next (&it->bidi_it);
              IT_BYTEPOS (*it) = it->bidi_it.bytepos;
              IT_CHARPOS (*it) = it->bidi_it.charpos;
+           }
 
-             if (it->cmp_it.to < it->cmp_it.nglyphs)
-               {
-                 /* Proceed to the next grapheme cluster.  */
-                 it->cmp_it.from = it->cmp_it.to;
-               }
-             else
-               {
-                 /* No more grapheme clusters in this composition.
-                    Find the next stop position.  */
-                 ptrdiff_t stop = it->end_charpos;
-                 if (it->bidi_it.scan_dir < 0)
-                   /* Now we are scanning backward and don't know
-                      where to stop.  */
-                   stop = -1;
-                 composition_compute_stop_pos (&it->cmp_it, IT_CHARPOS (*it),
-                                               IT_BYTEPOS (*it), stop, Qnil);
-               }
+         if ((! it->bidi_p || ! it->cmp_it.reversed_p)
+             && it->cmp_it.to < it->cmp_it.nglyphs)
+           {
+             /* Composition created while scanning forward.  Proceed
+                to the next grapheme cluster.  */
+             it->cmp_it.from = it->cmp_it.to;
+           }
+         else if ((it->bidi_p && it->cmp_it.reversed_p)
+                  && it->cmp_it.from > 0)
+           {
+             /* Composition created while scanning backward.  Proceed
+                to the previous grapheme cluster.  */
+             it->cmp_it.to = it->cmp_it.from;
            }
          else
            {
-             /* Composition created while scanning backward.  */
-             /* Update IT's char/byte positions to point to the last
-                character of the previous grapheme cluster, or the
-                character visually after the current composition.  */
-             for (i = 0; i < it->cmp_it.nchars; i++)
-               bidi_move_to_visually_next (&it->bidi_it);
-             IT_BYTEPOS (*it) = it->bidi_it.bytepos;
-             IT_CHARPOS (*it) = it->bidi_it.charpos;
-             if (it->cmp_it.from > 0)
-               {
-                 /* Proceed to the previous grapheme cluster.  */
-                 it->cmp_it.to = it->cmp_it.from;
-               }
-             else
-               {
-                 /* No more grapheme clusters in this composition.
-                    Find the next stop position.  */
-                 ptrdiff_t stop = it->end_charpos;
-                 if (it->bidi_it.scan_dir < 0)
-                   /* Now we are scanning backward and don't know
-                      where to stop.  */
-                   stop = -1;
-                 composition_compute_stop_pos (&it->cmp_it, IT_CHARPOS (*it),
-                                               IT_BYTEPOS (*it), stop, Qnil);
-               }
+             /* No more grapheme clusters in this composition.
+                Find the next stop position.  */
+             ptrdiff_t stop = it->end_charpos;
+
+             if (it->bidi_it.scan_dir < 0)
+               /* Now we are scanning backward and don't know
+                  where to stop.  */
+               stop = -1;
+             composition_compute_stop_pos (&it->cmp_it, IT_CHARPOS (*it),
+                                           IT_BYTEPOS (*it), stop, Qnil);
            }
        }
       else
@@ -7470,61 +7519,63 @@ set_iterator_to_next (struct it *it, int reseat_p)
        }
       if (it->cmp_it.id >= 0)
        {
-         int i;
-
+         /* We are delivering display elements from a composition.
+            Update the string position past the grapheme cluster
+            we've just processed.  */
          if (! it->bidi_p)
            {
              IT_STRING_CHARPOS (*it) += it->cmp_it.nchars;
              IT_STRING_BYTEPOS (*it) += it->cmp_it.nbytes;
-             if (it->cmp_it.to < it->cmp_it.nglyphs)
-               it->cmp_it.from = it->cmp_it.to;
-             else
-               {
-                 it->cmp_it.id = -1;
-                 composition_compute_stop_pos (&it->cmp_it,
-                                               IT_STRING_CHARPOS (*it),
-                                               IT_STRING_BYTEPOS (*it),
-                                               it->end_charpos, it->string);
-               }
            }
-         else if (! it->cmp_it.reversed_p)
+         else
            {
+             int i;
+
              for (i = 0; i < it->cmp_it.nchars; i++)
                bidi_move_to_visually_next (&it->bidi_it);
              IT_STRING_BYTEPOS (*it) = it->bidi_it.bytepos;
              IT_STRING_CHARPOS (*it) = it->bidi_it.charpos;
+           }
 
-             if (it->cmp_it.to < it->cmp_it.nglyphs)
-               it->cmp_it.from = it->cmp_it.to;
-             else
-               {
-                 ptrdiff_t stop = it->end_charpos;
-                 if (it->bidi_it.scan_dir < 0)
-                   stop = -1;
-                 composition_compute_stop_pos (&it->cmp_it,
-                                               IT_STRING_CHARPOS (*it),
-                                               IT_STRING_BYTEPOS (*it), stop,
-                                               it->string);
-               }
+         /* Did we exhaust all the grapheme clusters of this
+            composition?  */
+         if ((! it->bidi_p || ! it->cmp_it.reversed_p)
+             && (it->cmp_it.to < it->cmp_it.nglyphs))
+           {
+             /* Not all the grapheme clusters were processed yet;
+                advance to the next cluster.  */
+             it->cmp_it.from = it->cmp_it.to;
+           }
+         else if ((it->bidi_p && it->cmp_it.reversed_p)
+                  && it->cmp_it.from > 0)
+           {
+             /* Likewise: advance to the next cluster, but going in
+                the reverse direction.  */
+             it->cmp_it.to = it->cmp_it.from;
            }
          else
            {
-             for (i = 0; i < it->cmp_it.nchars; i++)
-               bidi_move_to_visually_next (&it->bidi_it);
-             IT_STRING_BYTEPOS (*it) = it->bidi_it.bytepos;
-             IT_STRING_CHARPOS (*it) = it->bidi_it.charpos;
-             if (it->cmp_it.from > 0)
-               it->cmp_it.to = it->cmp_it.from;
-             else
+             /* This composition was fully processed; find the next
+                candidate place for checking for composed
+                characters.  */
+             /* Always limit string searches to the string length;
+                any padding spaces are not part of the string, and
+                there cannot be any compositions in that padding.  */
+             ptrdiff_t stop = SCHARS (it->string);
+
+             if (it->bidi_p && it->bidi_it.scan_dir < 0)
+               stop = -1;
+             else if (it->end_charpos < stop)
                {
-                 ptrdiff_t stop = it->end_charpos;
-                 if (it->bidi_it.scan_dir < 0)
-                   stop = -1;
-                 composition_compute_stop_pos (&it->cmp_it,
-                                               IT_STRING_CHARPOS (*it),
-                                               IT_STRING_BYTEPOS (*it), stop,
-                                               it->string);
+                 /* Cf. PRECISION in reseat_to_string: we might be
+                    limited in how many of the string characters we
+                    need to deliver.  */
+                 stop = it->end_charpos;
                }
+             composition_compute_stop_pos (&it->cmp_it,
+                                           IT_STRING_CHARPOS (*it),
+                                           IT_STRING_BYTEPOS (*it), stop,
+                                           it->string);
            }
        }
       else
@@ -7547,12 +7598,17 @@ set_iterator_to_next (struct it *it, int reseat_p)
              bidi_move_to_visually_next (&it->bidi_it);
              IT_STRING_BYTEPOS (*it) = it->bidi_it.bytepos;
              IT_STRING_CHARPOS (*it) = it->bidi_it.charpos;
+             /* If the scan direction changes, we may need to update
+                the place where to check for composed characters.  */
              if (prev_scan_dir != it->bidi_it.scan_dir)
                {
-                 ptrdiff_t stop = it->end_charpos;
+                 ptrdiff_t stop = SCHARS (it->string);
 
                  if (it->bidi_it.scan_dir < 0)
                    stop = -1;
+                 else if (it->end_charpos < stop)
+                   stop = it->end_charpos;
+
                  composition_compute_stop_pos (&it->cmp_it,
                                                IT_STRING_CHARPOS (*it),
                                                IT_STRING_BYTEPOS (*it), stop,
@@ -8273,6 +8329,10 @@ next_element_from_buffer (struct it *it)
       unsigned char *p;
       ptrdiff_t stop;
 
+      /* We moved to the next buffer position, so any info about
+        previously seen overlays is no longer valid.  */
+      it->ignore_overlay_strings_at_pos_p = 0;
+
       /* Maybe run the redisplay end trigger hook.  Performance note:
         This doesn't seem to cost measurable time.  */
       if (it->redisplay_end_trigger_charpos
@@ -8726,12 +8786,7 @@ move_it_in_display_line_to (struct it *it,
                         doesn't fit on the line, e.g. a wide image.  */
                      it->hpos == 0
                      || (new_x == it->last_visible_x
-                         && FRAME_WINDOW_P (it->f)
-                         /* When word-wrap is ON and we have a valid
-                            wrap point, we don't allow the last glyph
-                            to "just barely fit" on the line.  */
-                         && (it->line_wrap != WORD_WRAP
-                             || wrap_it.sp < 0)))
+                         && FRAME_WINDOW_P (it->f)))
                    {
                      ++it->hpos;
                      it->current_x = new_x;
@@ -8798,7 +8853,8 @@ move_it_in_display_line_to (struct it *it,
                                }
                              if (ITERATOR_AT_END_OF_LINE_P (it)
                                  && (it->line_wrap != WORD_WRAP
-                                     || wrap_it.sp < 0))
+                                     || wrap_it.sp < 0
+                                     || IT_OVERFLOW_NEWLINE_INTO_FRINGE (it)))
                                {
                                  result = MOVE_NEWLINE_OR_CR;
                                  break;
@@ -9694,6 +9750,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);
@@ -10147,9 +10204,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 ();
     }
@@ -10210,9 +10267,9 @@ message3_nolog (Lisp_Object m)
       else
        clear_message (true, true);
 
-      do_pending_window_change (0);
-      echo_area_display (1);
-      do_pending_window_change (0);
+      do_pending_window_change (false);
+      echo_area_display (true);
+      do_pending_window_change (false);
       if (FRAME_TERMINAL (f)->frame_up_to_date_hook)
        (*FRAME_TERMINAL (f)->frame_up_to_date_hook) (f);
     }
@@ -10351,11 +10408,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);
@@ -11181,13 +11240,13 @@ clear_garbaged_frames (void)
    is non-zero update selected_frame.  Value is non-zero if the
    mini-windows height has been changed.  */
 
-static int
-echo_area_display (int update_frame_p)
+static bool
+echo_area_display (bool update_frame_p)
 {
   Lisp_Object mini_window;
   struct window *w;
   struct frame *f;
-  int window_height_changed_p = 0;
+  bool window_height_changed_p = false;
   struct frame *sf = SELECTED_FRAME ();
 
   mini_window = FRAME_MINIBUF_WINDOW (sf);
@@ -11250,11 +11309,11 @@ echo_area_display (int update_frame_p)
              /* Window configuration is the same as before.
                 Can do with a display update of the echo area,
                 unless we displayed some mode lines.  */
-             update_single_window (w, 1);
+             update_single_window (w);
              flush_frame (f);
            }
          else
-           update_frame (f, 1, 1);
+           update_frame (f, true, true);
 
          /* If cursor is in the echo area, make sure that the next
             redisplay displays the minibuffer, so that the cursor will
@@ -11725,12 +11784,6 @@ prepare_menu_bars (void)
          menu_bar_hooks_run = update_menu_bar (f, 0, menu_bar_hooks_run);
 #ifdef HAVE_WINDOW_SYSTEM
          update_tool_bar (f, 0);
-#endif
-#ifdef HAVE_NS
-          if (windows_or_buffers_changed
-             && FRAME_NS_P (f))
-            ns_set_doc_edited
-             (f, Fbuffer_modified_p (XWINDOW (f->selected_window)->contents));
 #endif
          UNGCPRO;
        }
@@ -11987,11 +12040,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.  */
@@ -12010,9 +12063,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,
@@ -12123,8 +12179,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
@@ -12135,6 +12193,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
     }
 
@@ -13368,7 +13427,7 @@ redisplay_internal (void)
   struct window *w = XWINDOW (selected_window);
   struct window *sw;
   struct frame *fr;
-  int pending;
+  bool pending;
   bool must_finish = 0, match_p;
   struct text_pos tlbufpos, tlendpos;
   int number_of_visible_frames;
@@ -13428,7 +13487,7 @@ redisplay_internal (void)
   /* Remember the currently selected window.  */
   sw = w;
 
-  pending = 0;
+  pending = false;
   last_escape_glyph_frame = NULL;
   last_escape_glyph_face_id = (1 << FACE_ID_BITS);
   last_glyphless_glyph_frame = NULL;
@@ -13480,7 +13539,7 @@ redisplay_internal (void)
     }
 
   /* Notice any pending interrupt request to change frame size.  */
-  do_pending_window_change (1);
+  do_pending_window_change (true);
 
   /* do_pending_window_change could change the selected_window due to
      frame resizing which makes the selected window too small.  */
@@ -13506,6 +13565,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
@@ -13521,7 +13586,7 @@ redisplay_internal (void)
             echo-area doesn't show through.  */
          && !MINI_WINDOW_P (XWINDOW (selected_window))))
     {
-      int window_height_changed_p = echo_area_display (0);
+      int window_height_changed_p = echo_area_display (false);
 
       if (message_cleared_p)
        update_miniwindow_p = true;
@@ -13729,7 +13794,7 @@ redisplay_internal (void)
        {
          if (!must_finish)
            {
-             do_pending_window_change (1);
+             do_pending_window_change (true);
              /* If selected_window changed, redisplay again.  */
              if (WINDOWP (selected_window)
                  && (w = XWINDOW (selected_window)) != sw)
@@ -13846,14 +13911,14 @@ redisplay_internal (void)
                  if (f->fonts_changed)
                    {
                      adjust_frame_glyphs (f);
-                     f->fonts_changed = 0;
+                     f->fonts_changed = false;
                      goto retry_frame;
                    }
 
                  /* See if we have to hscroll.  */
                  if (!f->already_hscrolled_p)
                    {
-                     f->already_hscrolled_p = 1;
+                     f->already_hscrolled_p = true;
                      if (hscroll_windows (f->root_window))
                        goto retry_frame;
                    }
@@ -13865,9 +13930,9 @@ redisplay_internal (void)
                    unrequest_sigio ();
                  STOP_POLLING;
 
-                 pending |= update_frame (f, 0, 0);
-                 f->cursor_type_changed = 0;
-                 f->updated_p = 1;
+                 pending |= update_frame (f, false, false);
+                 f->cursor_type_changed = false;
+                 f->updated_p = true;
                }
            }
        }
@@ -13928,8 +13993,8 @@ redisplay_internal (void)
            goto retry;
 
          XWINDOW (selected_window)->must_be_updated_p = true;
-         pending = update_frame (sf, 0, 0);
-         sf->cursor_type_changed = 0;
+         pending = update_frame (sf, false, false);
+         sf->cursor_type_changed = false;
        }
 
       /* We may have called echo_area_display at the top of this
@@ -13943,8 +14008,8 @@ redisplay_internal (void)
       if (mini_frame != sf && FRAME_WINDOW_P (mini_frame))
        {
          XWINDOW (mini_window)->must_be_updated_p = true;
-         pending |= update_frame (mini_frame, 0, 0);
-         mini_frame->cursor_type_changed = 0;
+         pending |= update_frame (mini_frame, false, false);
+         mini_frame->cursor_type_changed = false;
          if (!pending && hscroll_windows (mini_window))
            goto retry;
        }
@@ -14021,7 +14086,7 @@ redisplay_internal (void)
     }
 
   /* Change frame size now if a change is pending.  */
-  do_pending_window_change (1);
+  do_pending_window_change (true);
 
   /* If we just did a pending size change, or have additional
      visible frames, or selected_window changed, redisplay again.  */
@@ -14037,7 +14102,7 @@ redisplay_internal (void)
 
   if (clear_face_cache_count > CLEAR_FACE_CACHE_COUNT)
     {
-      clear_face_cache (0);
+      clear_face_cache (false);
       clear_face_cache_count = 0;
     }
 
@@ -14050,6 +14115,9 @@ redisplay_internal (void)
 #endif /* HAVE_WINDOW_SYSTEM */
 
  end_of_redisplay:
+#ifdef HAVE_NS
+  ns_set_doc_edited ();
+#endif
   if (interrupt_input && interrupts_deferred)
     request_sigio ();
 
@@ -14078,9 +14146,9 @@ redisplay_preserve_echo_area (int from_where)
     {
       /* We have a previously displayed message, but no current
         message.  Redisplay the previous message.  */
-      display_last_displayed_message_p = 1;
+      display_last_displayed_message_p = true;
       redisplay_internal ();
-      display_last_displayed_message_p = 0;
+      display_last_displayed_message_p = false;
     }
   else
     redisplay_internal ();
@@ -14929,6 +14997,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.  */
 
@@ -15124,8 +15196,8 @@ try_scrolling (Lisp_Object window, int just_this_one_p,
                 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;
+             if (aggressive_scroll + 2 * this_scroll_margin > height)
+               aggressive_scroll = height - 2 * this_scroll_margin;
              amount_to_scroll = dy + aggressive_scroll;
            }
        }
@@ -15218,8 +15290,8 @@ try_scrolling (Lisp_Object window, int just_this_one_p,
          start_display (&it, w, startp);
 
          if (arg_scroll_conservatively)
-           amount_to_scroll = max (dy, frame_line_height *
-                                   max (scroll_step, temp_scroll_step));
+           amount_to_scroll = max (dy, frame_line_height
+                                   max (scroll_step, temp_scroll_step));
          else if (scroll_step || temp_scroll_step)
            amount_to_scroll = scroll_max;
          else
@@ -15236,8 +15308,8 @@ try_scrolling (Lisp_Object window, int just_this_one_p,
                     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;
+                 if (aggressive_scroll + 2 * this_scroll_margin > height)
+                   aggressive_scroll = height - 2 * this_scroll_margin;
                  amount_to_scroll = dy + aggressive_scroll;
                }
            }
@@ -16102,26 +16174,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;
@@ -16166,7 +16260,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
@@ -16248,16 +16342,29 @@ redisplay_window (Lisp_Object window, bool just_this_one_p)
 
          set_cursor_from_row (w, row, w->desired_matrix, 0, 0, 0, 0);
 
-         /* If we are highlighting the region, then we just changed
-            the region, so redisplay to show it.  */
-         /* FIXME: We need to (re)run pre-redisplay-function!  */
-         /* if (markpos_of_region () >= 0)
+         /* Re-run pre-redisplay-function so it can update the region
+            according to the new position of point.  */
+         /* Other than the cursor, w's redisplay is done so we can set its
+            redisplay to false.  Also the buffer's redisplay can be set to
+            false, since propagate_buffer_redisplay should have already
+            propagated its info to `w' anyway.  */
+         w->redisplay = false;
+         XBUFFER (w->contents)->text->redisplay = false;
+         safe__call1 (true, Vpre_redisplay_function, Fcons (window, Qnil));
+
+         if (w->redisplay || XBUFFER (w->contents)->text->redisplay)
            {
+             /* pre-redisplay-function made changes (e.g. move the region)
+                that require another round of redisplay.  */
              clear_glyph_matrix (w->desired_matrix);
              if (!try_window (window, startp, 0))
                goto need_larger_matrices;
            }
-         */
+       }
+      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
@@ -16323,7 +16430,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
@@ -16348,14 +16456,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;
        }
 
@@ -16466,8 +16580,8 @@ redisplay_window (Lisp_Object window, bool just_this_one_p)
     {
       int window_total_lines
        = WINDOW_TOTAL_LINES (w) * FRAME_LINE_HEIGHT (f) / frame_line_height;
-      int margin =
-       scroll_margin > 0
+      int margin
+       scroll_margin > 0
        ? min (scroll_margin, window_total_lines / 4)
        : 0;
       ptrdiff_t margin_pos = CHARPOS (startp);
@@ -18651,10 +18765,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)
@@ -18689,7 +18803,10 @@ DEFUN ("dump-glyph-matrix", Fdump_glyph_matrix,
        doc: /* Dump the current matrix of the selected window to stderr.
 Shows contents of glyph row structures.  With non-nil
 parameter GLYPHS, dump glyphs as well.  If GLYPHS is 1 show
-glyphs in short form, otherwise show glyphs in long form.  */)
+glyphs in short form, otherwise show glyphs in long form.
+
+Interactively, no argument means show glyphs in short form;
+with numeric argument, its value is passed as the GLYPHS flag.  */)
   (Lisp_Object glyphs)
 {
   struct window *w = XWINDOW (selected_window);
@@ -18707,11 +18824,16 @@ glyphs in short form, otherwise show glyphs in long form.  */)
 
 
 DEFUN ("dump-frame-glyph-matrix", Fdump_frame_glyph_matrix,
-       Sdump_frame_glyph_matrix, 0, 0, "", doc: /* */)
+       Sdump_frame_glyph_matrix, 0, 0, "", doc: /* Dump the current glyph matrix of the selected frame to stderr.
+Only text-mode frames have frame glyph matrices.  */)
   (void)
 {
   struct frame *f = XFRAME (selected_frame);
-  dump_glyph_matrix (f->current_matrix, 1);
+
+  if (f->current_matrix)
+    dump_glyph_matrix (f->current_matrix, 1);
+  else
+    fprintf (stderr, "*** This frame doesn't have a frame glyph matrix ***\n");
   return Qnil;
 }
 
@@ -18807,7 +18929,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;
@@ -19328,7 +19450,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 =
@@ -20293,7 +20426,8 @@ display_line (struct it *it)
                        {
                          /* If line-wrap is on, check if a previous
                             wrap point was found.  */
-                         if (wrap_row_used > 0
+                         if (!IT_OVERFLOW_NEWLINE_INTO_FRINGE (it)
+                             && wrap_row_used > 0
                              /* Even if there is a previous wrap
                                 point, continue the line here as
                                 usual, if (i) the previous character
@@ -20323,6 +20457,18 @@ display_line (struct it *it)
                                  row->continued_p = 0;
                                  row->exact_window_width_line_p = 1;
                                }
+                             /* If line-wrap is on, check if a
+                                previous wrap point was found.  */
+                             else if (wrap_row_used > 0
+                                      /* Even if there is a previous wrap
+                                         point, continue the line here as
+                                         usual, if (i) the previous character
+                                         was a space or tab AND (ii) the
+                                         current character is not.  */
+                                      && (!may_wrap
+                                          || IT_DISPLAYING_WHITESPACE (it)))
+                               goto back_to_wrap;
+
                            }
                        }
                      else if (it->bidi_p)
@@ -20469,9 +20615,17 @@ display_line (struct it *it)
                  /* 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.  */
-                 if (row->reversed_p && new_x > it->last_visible_x)
-                   row->x = it->last_visible_x - new_x;
+                    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
                {
@@ -20545,7 +20699,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)))
        {
@@ -20622,10 +20779,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);
-         if (IT_BYTEPOS (*it) <= BEG_BYTE)
-           row->ends_at_zv_p = true;
+         /* 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 = FETCH_BYTE (IT_BYTEPOS (*it) - 1) != '\n';
+           row->ends_at_zv_p = false;
          break;
        }
     }
@@ -20828,7 +20990,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'
@@ -20870,6 +21033,143 @@ See also `bidi-paragraph-direction'.  */)
     }
 }
 
+DEFUN ("bidi-find-overridden-directionality",
+       Fbidi_find_overridden_directionality,
+       Sbidi_find_overridden_directionality, 2, 3, 0,
+       doc: /* Return position between FROM and TO where directionality was overridden.
+
+This function returns the first character position in the specified
+region of OBJECT where there is a character whose `bidi-class' property
+is `L', but which was forced to display as `R' by a directional
+override, and likewise with characters whose `bidi-class' is `R'
+or `AL' that were forced to display as `L'.
+
+If no such character is found, the function returns nil.
+
+OBJECT is a Lisp string or buffer to search for overridden
+directionality, and defaults to the current buffer if nil or omitted.
+OBJECT can also be a window, in which case the function will search
+the buffer displayed in that window.  Passing the window instead of
+a buffer is preferable when the buffer is displayed in some window,
+because this function will then be able to correctly account for
+window-specific overlays, which can affect the results.
+
+Strong directional characters `L', `R', and `AL' can have their
+intrinsic directionality overridden by directional override
+control characters RLO \(u+202e) and LRO \(u+202d).  See the
+function `get-char-code-property' for a way to inquire about
+the `bidi-class' property of a character.  */)
+  (Lisp_Object from, Lisp_Object to, Lisp_Object object)
+{
+  struct buffer *buf = current_buffer;
+  struct buffer *old = buf;
+  struct window *w = NULL;
+  bool frame_window_p = FRAME_WINDOW_P (SELECTED_FRAME ());
+  struct bidi_it itb;
+  ptrdiff_t from_pos, to_pos, from_bpos;
+  void *itb_data;
+
+  if (!NILP (object))
+    {
+      if (BUFFERP (object))
+       buf = XBUFFER (object);
+      else if (WINDOWP (object))
+       {
+         w = decode_live_window (object);
+         buf = XBUFFER (w->contents);
+         frame_window_p = FRAME_WINDOW_P (XFRAME (w->frame));
+       }
+      else
+       CHECK_STRING (object);
+    }
+
+  if (STRINGP (object))
+    {
+      /* Characters in unibyte strings are always treated by bidi.c as
+        strong LTR.  */
+      if (!STRING_MULTIBYTE (object)
+         /* When we are loading loadup.el, the character property
+            tables needed for bidi iteration are not yet
+            available.  */
+         || !NILP (Vpurify_flag))
+       return Qnil;
+
+      validate_subarray (object, from, to, SCHARS (object), &from_pos, &to_pos);
+      if (from_pos >= SCHARS (object))
+       return Qnil;
+
+      /* Set up the bidi iterator.  */
+      itb_data = bidi_shelve_cache ();
+      itb.paragraph_dir = NEUTRAL_DIR;
+      itb.string.lstring = object;
+      itb.string.s = NULL;
+      itb.string.schars = SCHARS (object);
+      itb.string.bufpos = 0;
+      itb.string.from_disp_str = 0;
+      itb.string.unibyte = 0;
+      itb.w = w;
+      bidi_init_it (0, 0, frame_window_p, &itb);
+    }
+  else
+    {
+      /* Nothing this fancy can happen in unibyte buffers, or in a
+        buffer that disabled reordering, or if FROM is at EOB.  */
+      if (NILP (BVAR (buf, bidi_display_reordering))
+         || NILP (BVAR (buf, enable_multibyte_characters))
+         /* When we are loading loadup.el, the character property
+            tables needed for bidi iteration are not yet
+            available.  */
+         || !NILP (Vpurify_flag))
+       return Qnil;
+
+      set_buffer_temp (buf);
+      validate_region (&from, &to);
+      from_pos = XINT (from);
+      to_pos = XINT (to);
+      if (from_pos >= ZV)
+       return Qnil;
+
+      /* Set up the bidi iterator.  */
+      itb_data = bidi_shelve_cache ();
+      from_bpos = CHAR_TO_BYTE (from_pos);
+      if (from_pos == BEGV)
+       {
+         itb.charpos = BEGV;
+         itb.bytepos = BEGV_BYTE;
+       }
+      else if (FETCH_CHAR (from_bpos - 1) == '\n')
+       {
+         itb.charpos = from_pos;
+         itb.bytepos = from_bpos;
+       }
+      else
+       itb.charpos = find_newline_no_quit (from_pos, CHAR_TO_BYTE (from_pos),
+                                           -1, &itb.bytepos);
+      itb.paragraph_dir = NEUTRAL_DIR;
+      itb.string.s = NULL;
+      itb.string.lstring = Qnil;
+      itb.string.bufpos = 0;
+      itb.string.from_disp_str = 0;
+      itb.string.unibyte = 0;
+      itb.w = w;
+      bidi_init_it (itb.charpos, itb.bytepos, frame_window_p, &itb);
+    }
+
+  ptrdiff_t found;
+  do {
+    /* For the purposes of this function, the actual base direction of
+       the paragraph doesn't matter, so just set it to L2R.  */
+    bidi_paragraph_init (L2R, &itb, 0);
+    while ((found = bidi_find_first_overridden (&itb)) < from_pos)
+      ;
+  } while (found == ZV && itb.ch == '\n' && itb.charpos < to_pos);
+
+  bidi_unshelve_cache (itb_data, 0);
+  set_buffer_temp (old);
+
+  return (from_pos <= found && found < to_pos) ? make_number (found) : Qnil;
+}
+
 DEFUN ("move-point-visually", Fmove_point_visually,
        Smove_point_visually, 1, 1, 0,
        doc: /* Move point in the visual order in the specified DIRECTION.
@@ -20939,7 +21239,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;
@@ -22749,10 +23049,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
        {
@@ -22888,7 +23186,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 "";
@@ -24668,7 +24966,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);                                                       \
@@ -24696,7 +24994,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.  */                            \
@@ -24731,7 +25029,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);                                                                  \
@@ -24883,6 +25181,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;
@@ -25082,6 +25381,7 @@ draw_glyphs (struct window *w, int x, struct glyph_row *row,
 
   RELEASE_HDC (hdc, f);
 
+  SAFE_FREE ();
   return x_reached;
 }
 
@@ -25821,14 +26121,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
@@ -27567,6 +27866,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)))
@@ -27813,7 +28116,7 @@ show_mouse_face (Mouse_HLInfo *hlinfo, enum draw_glyphs_face draw)
 
 #ifdef HAVE_WINDOW_SYSTEM
   /* Change the mouse cursor.  */
-  if (FRAME_WINDOW_P (f))
+  if (FRAME_WINDOW_P (f) && NILP (do_mouse_tracking))
     {
 #if ! defined (USE_GTK) && ! defined (HAVE_NS)
       if (draw == DRAW_NORMAL_TEXT
@@ -29341,6 +29644,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.  */
@@ -29622,6 +29927,7 @@ note_mouse_highlight (struct frame *f, int x, int y)
       BEGV = obegv;
       ZV = ozv;
       current_buffer = obuf;
+      SAFE_FREE ();
     }
 
  set_cursor:
@@ -30141,8 +30447,6 @@ expose_frame (struct frame *f, int x, int y, int w, int h)
       r.x = r.y = 0;
       r.width = FRAME_TEXT_WIDTH (f);
       r.height = FRAME_TEXT_HEIGHT (f);
-/**       r.width = FRAME_COLUMN_WIDTH (f) * FRAME_COLS (f); **/
-/**       r.height = FRAME_LINE_HEIGHT (f) * FRAME_LINES (f); **/
     }
   else
     {
@@ -30295,6 +30599,7 @@ syms_of_xdisp (void)
   defsubr (&Scurrent_bidi_paragraph_direction);
   defsubr (&Swindow_text_pixel_size);
   defsubr (&Smove_point_visually);
+  defsubr (&Sbidi_find_overridden_directionality);
 
   DEFSYM (Qmenu_bar_update_hook, "menu-bar-update-hook");
   DEFSYM (Qoverriding_terminal_local_map, "overriding-terminal-local-map");
@@ -30577,9 +30882,12 @@ all the functions in the list are called, with the frame as argument.  */);
   DEFVAR_LISP ("window-scroll-functions", Vwindow_scroll_functions,
     doc: /* List of functions to call before redisplaying a window with scrolling.
 Each function is called with two arguments, the window and its new
-display-start position.  Note that these functions are also called by
-`set-window-buffer'.  Also note that the value of `window-end' is not
-valid when these functions are called.
+display-start position.
+These functions are called whenever the `window-start' marker is modified,
+either to point into another buffer (e.g. via `set-window-buffer') or another
+place in the same buffer.
+Note that the value of `window-end' is not valid when these functions are
+called.
 
 Warning: Do not use this feature to alter the way the window
 is scrolled.  It is not designed for that, and such use probably won't