* dispextern.h (PREPARE_FACE_FOR_DISPLAY): Remove as a duplicate of ...
[bpt/emacs.git] / src / xdisp.c
index 9a3c27f..71398b8 100644 (file)
@@ -1,6 +1,7 @@
 /* Display generation from window structure and buffer text.
 
 /* Display generation from window structure and buffer text.
 
-Copyright (C) 1985-1988, 1993-1995, 1997-2013 Free Software Foundation, Inc.
+Copyright (C) 1985-1988, 1993-1995, 1997-2014 Free Software Foundation,
+Inc.
 
 This file is part of GNU Emacs.
 
 
 This file is part of GNU Emacs.
 
@@ -570,7 +571,7 @@ static struct glyph scratch_glyphs[MAX_SCRATCH_GLYPHS];
 
 /* Ascent and height of the last line processed by move_it_to.  */
 
 
 /* Ascent and height of the last line processed by move_it_to.  */
 
-static int last_max_ascent, last_height;
+static int last_height;
 
 /* Non-zero if there's a help-echo in the echo area.  */
 
 
 /* Non-zero if there's a help-echo in the echo area.  */
 
@@ -1018,23 +1019,25 @@ window_text_bottom_y (struct window *w)
 int
 window_box_width (struct window *w, enum glyph_row_area area)
 {
 int
 window_box_width (struct window *w, enum glyph_row_area area)
 {
-  int pixels = w->pixel_width;
+  int width = w->pixel_width;
 
   if (!w->pseudo_window_p)
     {
 
   if (!w->pseudo_window_p)
     {
-      pixels -= WINDOW_SCROLL_BAR_AREA_WIDTH (w);
-      pixels -= WINDOW_RIGHT_DIVIDER_WIDTH (w);
+      width -= WINDOW_SCROLL_BAR_AREA_WIDTH (w);
+      width -= WINDOW_RIGHT_DIVIDER_WIDTH (w);
 
       if (area == TEXT_AREA)
 
       if (area == TEXT_AREA)
-       pixels -= (WINDOW_MARGINS_WIDTH (w)
+       width -= (WINDOW_MARGINS_WIDTH (w)
                   + WINDOW_FRINGES_WIDTH (w));
       else if (area == LEFT_MARGIN_AREA)
                   + WINDOW_FRINGES_WIDTH (w));
       else if (area == LEFT_MARGIN_AREA)
-       pixels = WINDOW_LEFT_MARGIN_WIDTH (w);
+       width = WINDOW_LEFT_MARGIN_WIDTH (w);
       else if (area == RIGHT_MARGIN_AREA)
       else if (area == RIGHT_MARGIN_AREA)
-       pixels = WINDOW_RIGHT_MARGIN_WIDTH (w);
+       width = WINDOW_RIGHT_MARGIN_WIDTH (w);
     }
 
     }
 
-  return pixels;
+  /* With wide margins, fringes, etc. we might end up with a negative
+     width, correct that here.  */
+  return max (0, width);
 }
 
 
 }
 
 
@@ -1114,7 +1117,8 @@ window_box_left_offset (struct window *w, enum glyph_row_area area)
           && WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w))
     x += WINDOW_LEFT_FRINGE_WIDTH (w);
 
           && WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w))
     x += WINDOW_LEFT_FRINGE_WIDTH (w);
 
-  return x;
+  /* Don't return more than the window's pixel width.  */
+  return min (x, w->pixel_width);
 }
 
 
 }
 
 
@@ -1125,7 +1129,9 @@ window_box_left_offset (struct window *w, enum glyph_row_area area)
 int
 window_box_right_offset (struct window *w, enum glyph_row_area area)
 {
 int
 window_box_right_offset (struct window *w, enum glyph_row_area area)
 {
-  return window_box_left_offset (w, area) + window_box_width (w, area);
+  /* Don't return more than the window's pixel width.  */
+  return min (window_box_left_offset (w, area) + window_box_width (w, area),
+             w->pixel_width);
 }
 
 /* Return the frame-relative coordinate of the left edge of display
 }
 
 /* Return the frame-relative coordinate of the left edge of display
@@ -1256,12 +1262,23 @@ Value is the height in pixels of the line at point.  */)
   struct it it;
   struct text_pos pt;
   struct window *w = XWINDOW (selected_window);
   struct it it;
   struct text_pos pt;
   struct window *w = XWINDOW (selected_window);
+  struct buffer *old_buffer = NULL;
+  Lisp_Object result;
 
 
+  if (XBUFFER (w->contents) != current_buffer)
+    {
+      old_buffer = current_buffer;
+      set_buffer_internal_1 (XBUFFER (w->contents));
+    }
   SET_TEXT_POS (pt, PT, PT_BYTE);
   start_display (&it, w, pt);
   it.vpos = it.current_y = 0;
   last_height = 0;
   SET_TEXT_POS (pt, PT, PT_BYTE);
   start_display (&it, w, pt);
   it.vpos = it.current_y = 0;
   last_height = 0;
-  return make_number (line_bottom_y (&it));
+  result = make_number (line_bottom_y (&it));
+  if (old_buffer)
+    set_buffer_internal_1 (old_buffer);
+
+  return result;
 }
 
 /* Return the default pixel height of text lines in window W.  The
 }
 
 /* Return the default pixel height of text lines in window W.  The
@@ -2413,7 +2430,13 @@ remember_mouse_glyph (struct frame *f, int gx, int gy, NativeRectangle *rect)
            }
 
          if (part != ON_MODE_LINE && part != ON_HEADER_LINE)
            }
 
          if (part != ON_MODE_LINE && part != ON_HEADER_LINE)
-           gx += window_box_left_offset (w, area);
+           {
+             gx += window_box_left_offset (w, area);
+             /* Don't expand over the modeline to make sure the vertical
+                drag cursor is shown early enough.  */
+             height = min (height,
+                           max (0, WINDOW_BOX_HEIGHT_NO_MODE_LINE (w) - gy));
+           }
        }
       else
        {
        }
       else
        {
@@ -2421,6 +2444,10 @@ remember_mouse_glyph (struct frame *f, int gx, int gy, NativeRectangle *rect)
          gx = (x / width) * width;
          y -= gy;
          gy += (y / height) * height;
          gx = (x / width) * width;
          y -= gy;
          gy += (y / height) * height;
+         if (part != ON_MODE_LINE && part != ON_HEADER_LINE)
+           /* See comment above.  */
+           height = min (height,
+                         max (0, WINDOW_BOX_HEIGHT_NO_MODE_LINE (w) - gy));
        }
       break;
 
        }
       break;
 
@@ -2435,7 +2462,22 @@ remember_mouse_glyph (struct frame *f, int gx, int gy, NativeRectangle *rect)
       gx = (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
            ? window_box_right_offset (w, RIGHT_MARGIN_AREA)
            : window_box_right_offset (w, TEXT_AREA));
       gx = (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
            ? window_box_right_offset (w, RIGHT_MARGIN_AREA)
            : window_box_right_offset (w, TEXT_AREA));
-      width = WINDOW_RIGHT_FRINGE_WIDTH (w);
+      if (WINDOW_RIGHT_DIVIDER_WIDTH (w) == 0
+         && !WINDOW_HAS_VERTICAL_SCROLL_BAR (w)
+         && !WINDOW_RIGHTMOST_P (w))
+       if (gx < WINDOW_PIXEL_WIDTH (w) - width)
+         /* Make sure the vertical border can get her own glyph to the
+            right of the one we build here.  */
+         width = WINDOW_RIGHT_FRINGE_WIDTH (w) - width;
+       else
+         width = WINDOW_PIXEL_WIDTH (w) - gx;
+      else
+       width = WINDOW_RIGHT_FRINGE_WIDTH (w);
+
+      goto row_glyph;
+
+    case ON_VERTICAL_BORDER:
+      gx = WINDOW_PIXEL_WIDTH (w) - width;
       goto row_glyph;
 
     case ON_SCROLL_BAR:
       goto row_glyph;
 
     case ON_SCROLL_BAR:
@@ -2466,6 +2508,21 @@ remember_mouse_glyph (struct frame *f, int gx, int gy, NativeRectangle *rect)
        }
       break;
 
        }
       break;
 
+    case ON_RIGHT_DIVIDER:
+      gx = WINDOW_PIXEL_WIDTH (w) - WINDOW_RIGHT_DIVIDER_WIDTH (w);
+      width = WINDOW_RIGHT_DIVIDER_WIDTH (w);
+      gy = 0;
+      /* The bottom divider prevails. */
+      height = WINDOW_PIXEL_HEIGHT (w) - WINDOW_BOTTOM_DIVIDER_WIDTH (w);
+      goto add_edge;;
+
+    case ON_BOTTOM_DIVIDER:
+      gx = 0;
+      width = WINDOW_PIXEL_WIDTH (w);
+      gy = WINDOW_PIXEL_HEIGHT (w) - WINDOW_BOTTOM_DIVIDER_WIDTH (w);
+      height = WINDOW_BOTTOM_DIVIDER_WIDTH (w);
+      goto add_edge;
+
     default:
       ;
     virtual_glyph:
     default:
       ;
     virtual_glyph:
@@ -2486,6 +2543,7 @@ remember_mouse_glyph (struct frame *f, int gx, int gy, NativeRectangle *rect)
       goto store_rect;
     }
 
       goto store_rect;
     }
 
+ add_edge:
   gx += WINDOW_LEFT_EDGE_X (w);
   gy += WINDOW_TOP_EDGE_Y (w);
 
   gx += WINDOW_LEFT_EDGE_X (w);
   gy += WINDOW_TOP_EDGE_Y (w);
 
@@ -2533,8 +2591,8 @@ safe_eval_handler (Lisp_Object arg, ptrdiff_t nargs, Lisp_Object *args)
    following.  Return the result, or nil if something went
    wrong.  Prevent redisplay during the evaluation.  */
 
    following.  Return the result, or nil if something went
    wrong.  Prevent redisplay during the evaluation.  */
 
-Lisp_Object
-safe_call (ptrdiff_t nargs, Lisp_Object func, ...)
+static Lisp_Object
+safe__call (bool inhibit_quit, ptrdiff_t nargs, Lisp_Object func, va_list ap)
 {
   Lisp_Object val;
 
 {
   Lisp_Object val;
 
@@ -2542,21 +2600,20 @@ safe_call (ptrdiff_t nargs, Lisp_Object func, ...)
     val = Qnil;
   else
     {
     val = Qnil;
   else
     {
-      va_list ap;
       ptrdiff_t i;
       ptrdiff_t count = SPECPDL_INDEX ();
       struct gcpro gcpro1;
       Lisp_Object *args = alloca (nargs * word_size);
 
       args[0] = func;
       ptrdiff_t i;
       ptrdiff_t count = SPECPDL_INDEX ();
       struct gcpro gcpro1;
       Lisp_Object *args = alloca (nargs * word_size);
 
       args[0] = func;
-      va_start (ap, func);
       for (i = 1; i < nargs; i++)
        args[i] = va_arg (ap, Lisp_Object);
       for (i = 1; i < nargs; i++)
        args[i] = va_arg (ap, Lisp_Object);
-      va_end (ap);
 
       GCPRO1 (args[0]);
       gcpro1.nvars = nargs;
       specbind (Qinhibit_redisplay, Qt);
 
       GCPRO1 (args[0]);
       gcpro1.nvars = nargs;
       specbind (Qinhibit_redisplay, Qt);
+      if (inhibit_quit)
+       specbind (Qinhibit_quit, Qt);
       /* Use Qt to ensure debugger does not run,
         so there is no possibility of wanting to redisplay.  */
       val = internal_condition_case_n (Ffuncall, nargs, args, Qt,
       /* Use Qt to ensure debugger does not run,
         so there is no possibility of wanting to redisplay.  */
       val = internal_condition_case_n (Ffuncall, nargs, args, Qt,
@@ -2568,6 +2625,17 @@ safe_call (ptrdiff_t nargs, Lisp_Object func, ...)
   return val;
 }
 
   return val;
 }
 
+Lisp_Object
+safe_call (ptrdiff_t nargs, Lisp_Object func, ...)
+{
+  Lisp_Object retval;
+  va_list ap;
+
+  va_start (ap, func);
+  retval = safe__call (false, nargs, func, ap);
+  va_end (ap);
+  return retval;
+}
 
 /* Call function FN with one argument ARG.
    Return the result, or nil if something went wrong.  */
 
 /* Call function FN with one argument ARG.
    Return the result, or nil if something went wrong.  */
@@ -2578,12 +2646,30 @@ safe_call1 (Lisp_Object fn, Lisp_Object arg)
   return safe_call (2, fn, arg);
 }
 
   return safe_call (2, fn, arg);
 }
 
+static Lisp_Object
+safe__call1 (bool inhibit_quit, Lisp_Object fn, ...)
+{
+  Lisp_Object retval;
+  va_list ap;
+
+  va_start (ap, fn);
+  retval = safe__call (inhibit_quit, 2, fn, ap);
+  va_end (ap);
+  return retval;
+}
+
 static Lisp_Object Qeval;
 
 Lisp_Object
 safe_eval (Lisp_Object sexpr)
 {
 static Lisp_Object Qeval;
 
 Lisp_Object
 safe_eval (Lisp_Object sexpr)
 {
-  return safe_call1 (Qeval, sexpr);
+  return safe__call1 (false, Qeval, sexpr);
+}
+
+static Lisp_Object
+safe__eval (bool inhibit_quit, Lisp_Object sexpr)
+{
+  return safe__call1 (inhibit_quit, Qeval, sexpr);
 }
 
 /* Call function FN with two arguments ARG1 and ARG2.
 }
 
 /* Call function FN with two arguments ARG1 and ARG2.
@@ -2803,8 +2889,9 @@ init_iterator (struct it *it, struct window *w,
     it->redisplay_end_trigger_charpos
       = marker_position (w->redisplay_end_trigger);
   else if (INTEGERP (w->redisplay_end_trigger))
     it->redisplay_end_trigger_charpos
       = marker_position (w->redisplay_end_trigger);
   else if (INTEGERP (w->redisplay_end_trigger))
-    it->redisplay_end_trigger_charpos =
-      clip_to_bounds (PTRDIFF_MIN, XINT (w->redisplay_end_trigger), PTRDIFF_MAX);
+    it->redisplay_end_trigger_charpos
+      = clip_to_bounds (PTRDIFF_MIN, XINT (w->redisplay_end_trigger),
+                       PTRDIFF_MAX);
 
   it->tab_width = SANE_TAB_WIDTH (current_buffer);
 
 
   it->tab_width = SANE_TAB_WIDTH (current_buffer);
 
@@ -2921,7 +3008,7 @@ init_iterator (struct it *it, struct window *w,
       /* If we have a boxed mode line, make the first character appear
         with a left box line.  */
       face = FACE_FROM_ID (it->f, remapped_base_face_id);
       /* If we have a boxed mode line, make the first character appear
         with a left box line.  */
       face = FACE_FROM_ID (it->f, remapped_base_face_id);
-      if (face->box != FACE_NO_BOX)
+      if (face && face->box != FACE_NO_BOX)
        it->start_of_box_run_p = true;
     }
 
        it->start_of_box_run_p = true;
     }
 
@@ -3906,6 +3993,15 @@ handle_face_prop (struct it *it)
             For strings from wrap-prefix and line-prefix properties,
             use the default face, possibly remapped via
             Vface_remapping_alist.  */
             For strings from wrap-prefix and line-prefix properties,
             use the default face, possibly remapped via
             Vface_remapping_alist.  */
+         /* Note that the fact that we use the face at _buffer_
+            position means that a 'display' property on an overlay
+            string will not inherit the face of that overlay string,
+            but will instead revert to the face of buffer text
+            covered by the overlay.  This is visible, e.g., when the
+            overlay specifies a box face, but neither the buffer nor
+            the display string do.  This sounds like a design bug,
+            but Emacs always did that since v21.1, so changing that
+            might be a big deal.  */
          base_face_id = it->string_from_prefix_prop_p
            ? (!NILP (Vface_remapping_alist)
               ? lookup_basic_face (it->f, DEFAULT_FACE_ID)
          base_face_id = it->string_from_prefix_prop_p
            ? (!NILP (Vface_remapping_alist)
               ? lookup_basic_face (it->f, DEFAULT_FACE_ID)
@@ -5939,7 +6035,16 @@ pop_it (struct it *it)
       it->object = it->w->contents;
       break;
     case GET_FROM_STRING:
       it->object = it->w->contents;
       break;
     case GET_FROM_STRING:
-      it->object = it->string;
+      {
+       struct face *face = FACE_FROM_ID (it->f, it->face_id);
+
+       /* Restore the face_box_p flag, since it could have been
+          overwritten by the face of the object that we just finished
+          displaying.  */
+       if (face)
+         it->face_box_p = face->box != FACE_NO_BOX;
+       it->object = it->string;
+      }
       break;
     case GET_FROM_DISPLAY_VECTOR:
       if (it->s)
       break;
     case GET_FROM_DISPLAY_VECTOR:
       if (it->s)
@@ -6408,6 +6513,7 @@ reseat_1 (struct it *it, struct text_pos pos, int set_stop_p)
       it->bidi_it.string.s = NULL;
       it->bidi_it.string.lstring = Qnil;
       it->bidi_it.string.bufpos = 0;
       it->bidi_it.string.s = NULL;
       it->bidi_it.string.lstring = Qnil;
       it->bidi_it.string.bufpos = 0;
+      it->bidi_it.string.from_disp_str = 0;
       it->bidi_it.string.unibyte = 0;
       it->bidi_it.w = it->w;
     }
       it->bidi_it.string.unibyte = 0;
       it->bidi_it.w = it->w;
     }
@@ -7025,21 +7131,44 @@ get_next_display_element (struct it *it)
                 If this is the last string character displayed, check
                 the next buffer location.  */
              else if ((IT_STRING_CHARPOS (*it) >= SCHARS (it->string) - 1)
                 If this is the last string character displayed, check
                 the next buffer location.  */
              else if ((IT_STRING_CHARPOS (*it) >= SCHARS (it->string) - 1)
-                      && (it->current.overlay_string_index
-                          == it->n_overlay_strings - 1))
+                      /* n_overlay_strings is unreliable unless
+                         overlay_string_index is non-negative.  */
+                      && ((it->current.overlay_string_index >= 0
+                           && (it->current.overlay_string_index
+                               == it->n_overlay_strings - 1))
+                          /* A string from display property.  */
+                          || it->from_disp_prop_p))
                {
                  ptrdiff_t ignore;
                  int next_face_id;
                  struct text_pos pos = it->current.pos;
                {
                  ptrdiff_t ignore;
                  int next_face_id;
                  struct text_pos pos = it->current.pos;
-                 INC_TEXT_POS (pos, it->multibyte_p);
 
 
-                 next_face_id = face_at_buffer_position
-                   (it->w, CHARPOS (pos), &ignore,
-                    (IT_CHARPOS (*it) + TEXT_PROP_DISTANCE_LIMIT), 0,
-                    -1);
-                 it->end_of_box_run_p
-                   = (FACE_FROM_ID (it->f, next_face_id)->box
-                      == FACE_NO_BOX);
+                 /* For a string from a display property, the next
+                    buffer position is stored in the 'position'
+                    member of the iteration stack slot below the
+                    current one, see handle_single_display_spec.  By
+                    contrast, it->current.pos was is not yet updated
+                    to point to that buffer position; that will
+                    happen in pop_it, after we finish displaying the
+                    current string.  Note that we already checked
+                    above that it->sp is positive, so subtracting one
+                    from it is safe.  */
+                 if (it->from_disp_prop_p)
+                   pos = (it->stack + it->sp - 1)->position;
+                 else
+                   INC_TEXT_POS (pos, it->multibyte_p);
+
+                 if (CHARPOS (pos) >= ZV)
+                   it->end_of_box_run_p = true;
+                 else
+                   {
+                     next_face_id = face_at_buffer_position
+                       (it->w, CHARPOS (pos), &ignore,
+                        CHARPOS (pos) + TEXT_PROP_DISTANCE_LIMIT, 0, -1);
+                     it->end_of_box_run_p
+                       = (FACE_FROM_ID (it->f, next_face_id)->box
+                          == FACE_NO_BOX);
+                   }
                }
            }
        }
                }
            }
        }
@@ -8305,7 +8434,7 @@ move_it_in_display_line_to (struct it *it,
   void *ppos_data = NULL;
   int may_wrap = 0;
   enum it_method prev_method = it->method;
   void *ppos_data = NULL;
   int may_wrap = 0;
   enum it_method prev_method = it->method;
-  ptrdiff_t prev_pos = IT_CHARPOS (*it);
+  ptrdiff_t closest_pos IF_LINT (= 0), prev_pos = IT_CHARPOS (*it);
   int saw_smaller_pos = prev_pos < to_charpos;
 
   /* Don't produce glyphs in produce_glyphs.  */
   int saw_smaller_pos = prev_pos < to_charpos;
 
   /* Don't produce glyphs in produce_glyphs.  */
@@ -8322,16 +8451,21 @@ move_it_in_display_line_to (struct it *it,
   atx_it.sp = -1;
 
   /* Use ppos_it under bidi reordering to save a copy of IT for the
   atx_it.sp = -1;
 
   /* Use ppos_it under bidi reordering to save a copy of IT for the
-     position > CHARPOS that is the closest to CHARPOS.  We restore
-     that position in IT when we have scanned the entire display line
-     without finding a match for CHARPOS and all the character
-     positions are greater than CHARPOS.  */
+     initial position.  We restore that position in IT when we have
+     scanned the entire display line without finding a match for
+     TO_CHARPOS and all the character positions are greater than
+     TO_CHARPOS.  We then restart the scan from the initial position,
+     and stop at CLOSEST_POS, which is a position > TO_CHARPOS that is
+     the closest to TO_CHARPOS.  */
   if (it->bidi_p)
     {
   if (it->bidi_p)
     {
-      SAVE_IT (ppos_it, *it, ppos_data);
-      SET_TEXT_POS (ppos_it.current.pos, ZV, ZV_BYTE);
       if ((op & MOVE_TO_POS) && IT_CHARPOS (*it) >= to_charpos)
       if ((op & MOVE_TO_POS) && IT_CHARPOS (*it) >= to_charpos)
-       SAVE_IT (ppos_it, *it, ppos_data);
+       {
+         SAVE_IT (ppos_it, *it, ppos_data);
+         closest_pos = IT_CHARPOS (*it);
+       }
+      else
+       closest_pos = ZV;
     }
 
 #define BUFFER_POS_REACHED_P()                                 \
     }
 
 #define BUFFER_POS_REACHED_P()                                 \
@@ -8422,7 +8556,7 @@ move_it_in_display_line_to (struct it *it,
        }
       else
        {
        }
       else
        {
-         if (it->line_wrap == WORD_WRAP)
+         if (it->line_wrap == WORD_WRAP && it->area == TEXT_AREA)
            {
              if (IT_DISPLAYING_WHITESPACE (it))
                may_wrap = 1;
            {
              if (IT_DISPLAYING_WHITESPACE (it))
                may_wrap = 1;
@@ -8475,8 +8609,8 @@ move_it_in_display_line_to (struct it *it,
          if (it->bidi_p
              && (op & MOVE_TO_POS)
              && IT_CHARPOS (*it) > to_charpos
          if (it->bidi_p
              && (op & MOVE_TO_POS)
              && IT_CHARPOS (*it) > to_charpos
-             && IT_CHARPOS (*it) < IT_CHARPOS (ppos_it))
-           SAVE_IT (ppos_it, *it, ppos_data);
+             && IT_CHARPOS (*it) < closest_pos)
+           closest_pos = IT_CHARPOS (*it);
          continue;
        }
 
          continue;
        }
 
@@ -8556,7 +8690,12 @@ 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
                         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)))
+                         && 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)))
                    {
                      ++it->hpos;
                      it->current_x = new_x;
                    {
                      ++it->hpos;
                      it->current_x = new_x;
@@ -8698,9 +8837,14 @@ move_it_in_display_line_to (struct it *it,
            {
              if (!saw_smaller_pos && IT_CHARPOS (*it) > to_charpos)
                {
            {
              if (!saw_smaller_pos && IT_CHARPOS (*it) > to_charpos)
                {
-                 if (IT_CHARPOS (ppos_it) < ZV)
+                 if (closest_pos < ZV)
                    {
                      RESTORE_IT (it, &ppos_it, ppos_data);
                    {
                      RESTORE_IT (it, &ppos_it, ppos_data);
+                     /* Don't recurse if closest_pos is equal to
+                        to_charpos, since we have just tried that.  */
+                     if (closest_pos != to_charpos)
+                       move_it_in_display_line_to (it, closest_pos, -1,
+                                                   MOVE_TO_POS);
                      result = MOVE_POS_MATCH_OR_ZV;
                    }
                  else
                      result = MOVE_POS_MATCH_OR_ZV;
                    }
                  else
@@ -8730,8 +8874,8 @@ move_it_in_display_line_to (struct it *it,
       if (it->bidi_p
          && (op & MOVE_TO_POS)
          && IT_CHARPOS (*it) >= to_charpos
       if (it->bidi_p
          && (op & MOVE_TO_POS)
          && IT_CHARPOS (*it) >= to_charpos
-         && IT_CHARPOS (*it) < IT_CHARPOS (ppos_it))
-       SAVE_IT (ppos_it, *it, ppos_data);
+         && IT_CHARPOS (*it) < closest_pos)
+       closest_pos = IT_CHARPOS (*it);
 
       /* Stop if lines are truncated and IT's current x-position is
         past the right edge of the window now.  */
 
       /* Stop if lines are truncated and IT's current x-position is
         past the right edge of the window now.  */
@@ -8757,8 +8901,14 @@ move_it_in_display_line_to (struct it *it,
                      && IT_CHARPOS (*it) > to_charpos))
                {
                  if (it->bidi_p
                      && IT_CHARPOS (*it) > to_charpos))
                {
                  if (it->bidi_p
-                     && !at_eob_p && IT_CHARPOS (ppos_it) < ZV)
-                   RESTORE_IT (it, &ppos_it, ppos_data);
+                     && !BUFFER_POS_REACHED_P ()
+                     && !at_eob_p && closest_pos < ZV)
+                   {
+                     RESTORE_IT (it, &ppos_it, ppos_data);
+                     if (closest_pos != to_charpos)
+                       move_it_in_display_line_to (it, closest_pos, -1,
+                                                   MOVE_TO_POS);
+                   }
                  result = MOVE_POS_MATCH_OR_ZV;
                  break;
                }
                  result = MOVE_POS_MATCH_OR_ZV;
                  break;
                }
@@ -8772,8 +8922,13 @@ move_it_in_display_line_to (struct it *it,
                   && !saw_smaller_pos
                   && IT_CHARPOS (*it) > to_charpos)
            {
                   && !saw_smaller_pos
                   && IT_CHARPOS (*it) > to_charpos)
            {
-             if (IT_CHARPOS (ppos_it) < ZV)
-               RESTORE_IT (it, &ppos_it, ppos_data);
+             if (closest_pos < ZV)
+               {
+                 RESTORE_IT (it, &ppos_it, ppos_data);
+                 if (closest_pos != to_charpos)
+                   move_it_in_display_line_to (it, closest_pos, -1,
+                                               MOVE_TO_POS);
+               }
              result = MOVE_POS_MATCH_OR_ZV;
              break;
            }
              result = MOVE_POS_MATCH_OR_ZV;
              break;
            }
@@ -9096,7 +9251,6 @@ move_it_to (struct it *it, ptrdiff_t to_charpos, int to_x, int to_y, int to_vpos
       it->current_y += it->max_ascent + it->max_descent;
       ++it->vpos;
       last_height = it->max_ascent + it->max_descent;
       it->current_y += it->max_ascent + it->max_descent;
       ++it->vpos;
       last_height = it->max_ascent + it->max_descent;
-      last_max_ascent = it->max_ascent;
       it->max_ascent = it->max_descent = 0;
     }
 
       it->max_ascent = it->max_descent = 0;
     }
 
@@ -9123,7 +9277,6 @@ move_it_to (struct it *it, ptrdiff_t to_charpos, int to_x, int to_y, int to_vpos
       it->current_y += it->max_ascent + it->max_descent;
       ++it->vpos;
       last_height = it->max_ascent + it->max_descent;
       it->current_y += it->max_ascent + it->max_descent;
       ++it->vpos;
       last_height = it->max_ascent + it->max_descent;
-      last_max_ascent = it->max_ascent;
     }
 
   if (backup_data)
     }
 
   if (backup_data)
@@ -9403,6 +9556,7 @@ move_it_by_lines (struct it *it, ptrdiff_t dvpos)
       ptrdiff_t start_charpos, i;
       int nchars_per_row
        = (it->last_visible_x - it->first_visible_x) / FRAME_COLUMN_WIDTH (it->f);
       ptrdiff_t start_charpos, i;
       int nchars_per_row
        = (it->last_visible_x - it->first_visible_x) / FRAME_COLUMN_WIDTH (it->f);
+      bool hit_pos_limit = false;
       ptrdiff_t pos_limit;
 
       /* Start at the beginning of the screen line containing IT's
       ptrdiff_t pos_limit;
 
       /* Start at the beginning of the screen line containing IT's
@@ -9419,8 +9573,11 @@ move_it_by_lines (struct it *it, ptrdiff_t dvpos)
        pos_limit = BEGV;
       else
        pos_limit = max (start_charpos + dvpos * nchars_per_row, BEGV);
        pos_limit = BEGV;
       else
        pos_limit = max (start_charpos + dvpos * nchars_per_row, BEGV);
+
       for (i = -dvpos; i > 0 && IT_CHARPOS (*it) > pos_limit; --i)
        back_to_previous_visible_line_start (it);
       for (i = -dvpos; i > 0 && IT_CHARPOS (*it) > pos_limit; --i)
        back_to_previous_visible_line_start (it);
+      if (i > 0 && IT_CHARPOS (*it) <= pos_limit)
+       hit_pos_limit = true;
       reseat (it, it->current.pos, 1);
 
       /* Move further back if we end up in a string or an image.  */
       reseat (it, it->current.pos, 1);
 
       /* Move further back if we end up in a string or an image.  */
@@ -9464,6 +9621,25 @@ move_it_by_lines (struct it *it, ptrdiff_t dvpos)
          else
            bidi_unshelve_cache (it2data, 1);
        }
          else
            bidi_unshelve_cache (it2data, 1);
        }
+      else if (hit_pos_limit && pos_limit > BEGV
+              && dvpos < 0 && it2.vpos < -dvpos)
+       {
+         /* If we hit the limit, but still didn't make it far enough
+            back, that means there's a display string with a newline
+            covering a large chunk of text, and that caused
+            back_to_previous_visible_line_start try to go too far.
+            Punish those who commit such atrocities by going back
+            until we've reached DVPOS, after lifting the limit, which
+            could make it slow for very long lines.  "If it hurts,
+            don't do that!"  */
+         dvpos += it2.vpos;
+         RESTORE_IT (it, it, it2data);
+         for (i = -dvpos; i > 0; --i)
+           {
+             back_to_previous_visible_line_start (it);
+             it->vpos--;
+           }
+       }
       else
        RESTORE_IT (it, it, it2data);
     }
       else
        RESTORE_IT (it, it, it2data);
     }
@@ -9492,23 +9668,27 @@ character.  TO, if non-nil, specifies the last text position and
 defaults to the maximum accessible position of the buffer.  If TO is t,
 use the maximum accessible position that is not a newline character.
 
 defaults to the maximum accessible position of the buffer.  If TO is t,
 use the maximum accessible position that is not a newline character.
 
-The optional argument X_LIMIT, if non-nil, specifies the maximum text
-width that can be returned.  X_LIMIT nil or omitted, means to use the
+The optional argument X-LIMIT, if non-nil, specifies the maximum text
+width that can be returned.  X-LIMIT nil or omitted, means to use the
 pixel-width of WINDOW's body; use this if you do not intend to change
 the width of WINDOW.  Use the maximum width WINDOW may assume if you
 pixel-width of WINDOW's body; use this if you do not intend to change
 the width of WINDOW.  Use the maximum width WINDOW may assume if you
-intend to change WINDOW's width.
+intend to change WINDOW's width.  In any case, text whose x-coordinate
+is beyond X-LIMIT is ignored.  Since calculating the width of long lines
+can take some time, it's always a good idea to make this argument as
+small as possible; in particular, if the buffer contains long lines that
+shall be truncated anyway.
 
 
-The optional argument Y_LIMIT, if non-nil, specifies the maximum text
+The optional argument Y-LIMIT, if non-nil, specifies the maximum text
 height that can be returned.  Text lines whose y-coordinate is beyond
 height that can be returned.  Text lines whose y-coordinate is beyond
-Y_LIMIT are ignored.  Since calculating the text height of a large
+Y-LIMIT are ignored.  Since calculating the text height of a large
 buffer can take some time, it makes sense to specify this argument if
 the size of the buffer is unknown.
 
 buffer can take some time, it makes sense to specify this argument if
 the size of the buffer is unknown.
 
-Optional argument MODE_AND_HEADER_LINE nil or omitted means do not
+Optional argument MODE-AND-HEADER-LINE nil or omitted means do not
 include the height of the mode- or header-line of WINDOW in the return
 value.  If it is either the symbol `mode-line' or `header-line', include
 only the height of that line, if present, in the return value.  If t,
 include the height of the mode- or header-line of WINDOW in the return
 value.  If it is either the symbol `mode-line' or `header-line', include
 only the height of that line, if present, in the return value.  If t,
-include the height of any of these lines in the return value.  */)
+include the height of both, if present, in the return value.  */)
   (Lisp_Object window, Lisp_Object from, Lisp_Object to, Lisp_Object x_limit, Lisp_Object y_limit,
    Lisp_Object mode_and_header_line)
 {
   (Lisp_Object window, Lisp_Object from, Lisp_Object to, Lisp_Object x_limit, Lisp_Object y_limit,
    Lisp_Object mode_and_header_line)
 {
@@ -9576,7 +9756,6 @@ include the height of any of these lines in the return value.  */)
   SET_TEXT_POS (startp, start, CHAR_TO_BYTE (start));
   start_display (&it, w, startp);
 
   SET_TEXT_POS (startp, start, CHAR_TO_BYTE (start));
   start_display (&it, w, startp);
 
-  /**   move_it_vertically_backward (&it, 0); **/
   if (NILP (x_limit))
     x = move_it_to (&it, end, -1, max_y, -1, MOVE_TO_POS | MOVE_TO_Y);
   else
   if (NILP (x_limit))
     x = move_it_to (&it, end, -1, max_y, -1, MOVE_TO_POS | MOVE_TO_Y);
   else
@@ -9590,14 +9769,7 @@ include the height of any of these lines in the return value.  */)
                      MOVE_TO_POS | MOVE_TO_X | MOVE_TO_Y);
     }
 
                      MOVE_TO_POS | MOVE_TO_X | MOVE_TO_Y);
     }
 
-  if (start == end)
-    y = it.current_y;
-  else
-    {
-      /* Count last line.  */
-      last_height = 0;
-      y = line_bottom_y (&it); /* - y; */
-    }
+  y = it.current_y + it.max_ascent + it.max_descent;
 
   if (!EQ (mode_and_header_line, Qheader_line)
       && !EQ (mode_and_header_line, Qt))
 
   if (!EQ (mode_and_header_line, Qheader_line)
       && !EQ (mode_and_header_line, Qt))
@@ -9853,7 +10025,7 @@ message_dolog (const char *m, ptrdiff_t nbytes, bool nlflag, bool multibyte)
         incrementing windows_or_buffers_changed even if *Messages* is
         shown in some window.  So we must manually set
         windows_or_buffers_changed here to make up for that.  */
         incrementing windows_or_buffers_changed even if *Messages* is
         shown in some window.  So we must manually set
         windows_or_buffers_changed here to make up for that.  */
-       windows_or_buffers_changed = old_windows_or_buffers_changed;
+      windows_or_buffers_changed = old_windows_or_buffers_changed;
       bset_redisplay (current_buffer);
 
       set_buffer_internal (oldbuf);
       bset_redisplay (current_buffer);
 
       set_buffer_internal (oldbuf);
@@ -10029,19 +10201,17 @@ message_with_string (const char *m, Lisp_Object string, int log)
     {
       if (m)
        {
     {
       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;
 
          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);
          if (!cursor_in_echo_area)
            fprintf (stderr, "\n");
          fflush (stderr);
-         xfree (fmt);
        }
     }
   else if (INTERACTIVE)
        }
     }
   else if (INTERACTIVE)
@@ -10657,9 +10827,9 @@ resize_mini_window (struct window *w, int exact_p)
       /* Compute a suitable window start.  */
       if (height > max_height)
        {
       /* Compute a suitable window start.  */
       if (height > max_height)
        {
-         height = max_height;
+         height = (max_height / unit) * unit;
          init_iterator (&it, w, ZV, ZV_BYTE, NULL, DEFAULT_FACE_ID);
          init_iterator (&it, w, ZV, ZV_BYTE, NULL, DEFAULT_FACE_ID);
-         move_it_vertically_backward (&it, height);
+         move_it_vertically_backward (&it, height - unit);
          start = it.current.pos;
        }
       else
          start = it.current.pos;
        }
       else
@@ -11405,7 +11575,7 @@ prepare_menu_bars (void)
                }
            }
        }
                }
            }
        }
-      safe_call1 (Vpre_redisplay_function, windows);
+      safe__call1 (true, Vpre_redisplay_function, windows);
     }
 
   /* Update all frame titles based on their buffer names, etc.  We do
     }
 
   /* Update all frame titles based on their buffer names, etc.  We do
@@ -12108,7 +12278,7 @@ 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.
 If FRAME is nil or omitted, use the selected frame.  Optional argument
        0, 2, 0,
        doc: /* Return the number of lines occupied by the tool bar of FRAME.
 If FRAME is nil or omitted, use the selected frame.  Optional argument
-PIXELWISE non-nil means return the height of the tool bar inpixels.  */)
+PIXELWISE non-nil means return the height of the tool bar in pixels.  */)
   (Lisp_Object frame, Lisp_Object pixelwise)
 {
   int height = 0;
   (Lisp_Object frame, Lisp_Object pixelwise)
 {
   int height = 0;
@@ -12289,18 +12459,35 @@ redisplay_tool_bar (struct frame *f)
 
          if (change_height_p)
            {
 
          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));
              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))));
-             /* Always do that now.  */
-             clear_glyph_matrix (w->desired_matrix);
-             f->n_tool_bar_rows = nrows;
-             f->fonts_changed = 1;
-             return 1;
+             /* 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;
+               }
            }
        }
     }
            }
        }
     }
@@ -15455,29 +15642,32 @@ try_cursor_movement (Lisp_Object window, struct text_pos startp, int *scroll_ste
                  /* As soon as we've found the exact match for point,
                     or the first suitable row whose ends_at_zv_p flag
                     is set, we are done.  */
                  /* As soon as we've found the exact match for point,
                     or the first suitable row whose ends_at_zv_p flag
                     is set, we are done.  */
-                 at_zv_p =
-                   MATRIX_ROW (w->current_matrix, w->cursor.vpos)->ends_at_zv_p;
-                 if (rv && !at_zv_p
-                     && w->cursor.hpos >= 0
-                     && w->cursor.hpos < MATRIX_ROW_USED (w->current_matrix,
-                                                          w->cursor.vpos))
-                   {
-                     struct glyph_row *candidate =
-                       MATRIX_ROW (w->current_matrix, w->cursor.vpos);
-                     struct glyph *g =
-                       candidate->glyphs[TEXT_AREA] + w->cursor.hpos;
-                     ptrdiff_t endpos = MATRIX_ROW_END_CHARPOS (candidate);
-
-                     exact_match_p =
-                       (BUFFERP (g->object) && g->charpos == PT)
-                       || (INTEGERP (g->object)
-                           && (g->charpos == PT
-                               || (g->charpos == 0 && endpos - 1 == PT)));
-                   }
-                 if (rv && (at_zv_p || exact_match_p))
+                 if (rv)
                    {
                    {
-                     rc = CURSOR_MOVEMENT_SUCCESS;
-                     break;
+                     at_zv_p = MATRIX_ROW (w->current_matrix,
+                                           w->cursor.vpos)->ends_at_zv_p;
+                     if (!at_zv_p
+                         && w->cursor.hpos >= 0
+                         && w->cursor.hpos < MATRIX_ROW_USED (w->current_matrix,
+                                                              w->cursor.vpos))
+                       {
+                         struct glyph_row *candidate =
+                           MATRIX_ROW (w->current_matrix, w->cursor.vpos);
+                         struct glyph *g =
+                           candidate->glyphs[TEXT_AREA] + w->cursor.hpos;
+                         ptrdiff_t endpos = MATRIX_ROW_END_CHARPOS (candidate);
+
+                         exact_match_p =
+                           (BUFFERP (g->object) && g->charpos == PT)
+                           || (INTEGERP (g->object)
+                               && (g->charpos == PT
+                                   || (g->charpos == 0 && endpos - 1 == PT)));
+                       }
+                     if (at_zv_p || exact_match_p)
+                       {
+                         rc = CURSOR_MOVEMENT_SUCCESS;
+                         break;
+                       }
                    }
                  if (MATRIX_ROW_BOTTOM_Y (row) == last_y)
                    break;
                    }
                  if (MATRIX_ROW_BOTTOM_Y (row) == last_y)
                    break;
@@ -15520,9 +15710,6 @@ try_cursor_movement (Lisp_Object window, struct text_pos startp, int *scroll_ste
   return rc;
 }
 
   return rc;
 }
 
-#if !defined USE_TOOLKIT_SCROLL_BARS || defined USE_GTK
-static
-#endif
 void
 set_vertical_scroll_bar (struct window *w)
 {
 void
 set_vertical_scroll_bar (struct window *w)
 {
@@ -15603,7 +15790,8 @@ redisplay_window (Lisp_Object window, bool just_this_one_p)
       && REDISPLAY_SOME_P ()
       && !w->redisplay
       && !f->redisplay
       && REDISPLAY_SOME_P ()
       && !w->redisplay
       && !f->redisplay
-      && !buffer->text->redisplay)
+      && !buffer->text->redisplay
+      && BUF_PT (buffer) == w->last_point)
     return;
 
   /* Make sure that both W's markers are valid.  */
     return;
 
   /* Make sure that both W's markers are valid.  */
@@ -15749,16 +15937,20 @@ redisplay_window (Lisp_Object window, bool just_this_one_p)
      this may be a bit late to catch such changes, but the rest of
      redisplay goes (non-fatally) haywire when the display table is
      changed, so why should we worry about doing any better?  */
      this may be a bit late to catch such changes, but the rest of
      redisplay goes (non-fatally) haywire when the display table is
      changed, so why should we worry about doing any better?  */
-  if (current_buffer->width_run_cache)
+  if (current_buffer->width_run_cache
+      || (current_buffer->base_buffer
+         && current_buffer->base_buffer->width_run_cache))
     {
       struct Lisp_Char_Table *disptab = buffer_display_table ();
 
       if (! disptab_matches_widthtab
          (disptab, XVECTOR (BVAR (current_buffer, width_table))))
         {
     {
       struct Lisp_Char_Table *disptab = buffer_display_table ();
 
       if (! disptab_matches_widthtab
          (disptab, XVECTOR (BVAR (current_buffer, width_table))))
         {
-          invalidate_region_cache (current_buffer,
-                                   current_buffer->width_run_cache,
-                                   BEG, Z);
+         struct buffer *buf = current_buffer;
+
+         if (buf->base_buffer)
+           buf = buf->base_buffer;
+          invalidate_region_cache (buf, buf->width_run_cache, BEG, Z);
           recompute_width_table (current_buffer, disptab);
         }
     }
           recompute_width_table (current_buffer, disptab);
         }
     }
@@ -16271,12 +16463,50 @@ redisplay_window (Lisp_Object window, bool just_this_one_p)
   /* Consider the following case: Window starts at BEGV, there is
      invisible, intangible text at BEGV, so that display starts at
      some point START > BEGV.  It can happen that we are called with
   /* Consider the following case: Window starts at BEGV, there is
      invisible, intangible text at BEGV, so that display starts at
      some point START > BEGV.  It can happen that we are called with
-     PT somewhere between BEGV and START.  Try to handle that case.  */
+     PT somewhere between BEGV and START.  Try to handle that case,
+     and similar ones.  */
   if (w->cursor.vpos < 0)
     {
   if (w->cursor.vpos < 0)
     {
-      struct glyph_row *row = w->current_matrix->rows;
-      if (row->mode_line_p)
-       ++row;
+      /* First, try locating the proper glyph row for PT.  */
+      struct glyph_row *row =
+       row_containing_pos (w, PT, w->current_matrix->rows, NULL, 0);
+
+      /* Sometimes point is at the beginning of invisible text that is
+        before the 1st character displayed in the row.  In that case,
+        row_containing_pos fails to find the row, because no glyphs
+        with appropriate buffer positions are present in the row.
+        Therefore, we next try to find the row which shows the 1st
+        position after the invisible text.  */
+      if (!row)
+       {
+         Lisp_Object val =
+           get_char_property_and_overlay (make_number (PT), Qinvisible,
+                                          Qnil, NULL);
+
+         if (TEXT_PROP_MEANS_INVISIBLE (val))
+           {
+             ptrdiff_t alt_pos;
+             Lisp_Object invis_end =
+               Fnext_single_char_property_change (make_number (PT), Qinvisible,
+                                                  Qnil, Qnil);
+
+             if (NATNUMP (invis_end))
+               alt_pos = XFASTINT (invis_end);
+             else
+               alt_pos = ZV;
+             row = row_containing_pos (w, alt_pos, w->current_matrix->rows,
+                                       NULL, 0);
+           }
+       }
+      /* Finally, fall back on the first row of the window after the
+        header line (if any).  This is slightly better than not
+        displaying the cursor at all.  */
+      if (!row)
+       {
+         row = w->current_matrix->rows;
+         if (row->mode_line_p)
+           ++row;
+       }
       set_cursor_from_row (w, row, w->current_matrix, 0, 0, 0, 0);
     }
 
       set_cursor_from_row (w, row, w->current_matrix, 0, 0, 0, 0);
     }
 
@@ -17310,9 +17540,16 @@ row_containing_pos (struct window *w, ptrdiff_t charpos,
 
    Value is
 
 
    Value is
 
-   1   if display has been updated
-   0   if otherwise unsuccessful
+   >= 1        if successful, i.e. display has been updated
+         specifically:
+         1 means the changes were in front of a newline that precedes
+           the window start, and the whole current matrix was reused
+         2 means the changes were after the last position displayed
+           in the window, and the whole current matrix was reused
+         3 means portions of the current matrix were reused, while
+           some of the screen lines were redrawn
    -1  if redisplay with same window start is known not to succeed
    -1  if redisplay with same window start is known not to succeed
+   0   if otherwise unsuccessful
 
    The following steps are performed:
 
 
    The following steps are performed:
 
@@ -17387,6 +17624,12 @@ try_window_id (struct window *w)
   if (windows_or_buffers_changed || f->cursor_type_changed)
     GIVE_UP (2);
 
   if (windows_or_buffers_changed || f->cursor_type_changed)
     GIVE_UP (2);
 
+  /* This function's optimizations cannot be used if overlays have
+     changed in the buffer displayed by the window, so give up if they
+     have.  */
+  if (w->last_overlay_modified != OVERLAY_MODIFF)
+    GIVE_UP (21);
+
   /* Verify that narrowing has not changed.
      Also verify that we were not told to prevent redisplay optimizations.
      It would be nice to further
   /* Verify that narrowing has not changed.
      Also verify that we were not told to prevent redisplay optimizations.
      It would be nice to further
@@ -18474,6 +18717,7 @@ insert_left_trunc_glyphs (struct it *it)
   truncate_it.current_x = 0;
   truncate_it.face_id = DEFAULT_FACE_ID;
   truncate_it.glyph_row = &scratch_glyph_row;
   truncate_it.current_x = 0;
   truncate_it.face_id = DEFAULT_FACE_ID;
   truncate_it.glyph_row = &scratch_glyph_row;
+  truncate_it.area = TEXT_AREA;
   truncate_it.glyph_row->used[TEXT_AREA] = 0;
   CHARPOS (truncate_it.position) = BYTEPOS (truncate_it.position) = -1;
   truncate_it.object = make_number (0);
   truncate_it.glyph_row->used[TEXT_AREA] = 0;
   CHARPOS (truncate_it.position) = BYTEPOS (truncate_it.position) = -1;
   truncate_it.object = make_number (0);
@@ -20086,7 +20330,12 @@ display_line (struct it *it)
       /* If we truncate lines, we are done when the last displayed
         glyphs reach past the right margin of the window.  */
       if (it->line_wrap == TRUNCATE
       /* If we truncate lines, we are done when the last displayed
         glyphs reach past the right margin of the window.  */
       if (it->line_wrap == TRUNCATE
-         && (FRAME_WINDOW_P (it->f) && WINDOW_RIGHT_FRINGE_WIDTH (it->w)
+         && ((FRAME_WINDOW_P (it->f)
+              /* Images are preprocessed in produce_image_glyph such
+                 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))
              ? (it->current_x >= it->last_visible_x)
              : (it->current_x > it->last_visible_x)))
        {
              ? (it->current_x >= it->last_visible_x)
              : (it->current_x > it->last_visible_x)))
        {
@@ -20119,19 +20368,26 @@ display_line (struct it *it)
                  i = row->used[TEXT_AREA] - (i + 1);
                }
 
                  i = row->used[TEXT_AREA] - (i + 1);
                }
 
-             it->current_x = x_before;
-             if (!FRAME_WINDOW_P (it->f))
+             /* produce_special_glyphs overwrites the last glyph, so
+                we don't want that if we want to keep that last
+                glyph, which means it's an image.  */
+             if (it->current_x > it->last_visible_x)
                {
                {
-                 for (n = row->used[TEXT_AREA]; i < n; ++i)
+                 it->current_x = x_before;
+                 if (!FRAME_WINDOW_P (it->f))
+                   {
+                     for (n = row->used[TEXT_AREA]; i < n; ++i)
+                       {
+                         row->used[TEXT_AREA] = i;
+                         produce_special_glyphs (it, IT_TRUNCATION);
+                       }
+                   }
+                 else
                    {
                      row->used[TEXT_AREA] = i;
                      produce_special_glyphs (it, IT_TRUNCATION);
                    }
                    {
                      row->used[TEXT_AREA] = i;
                      produce_special_glyphs (it, IT_TRUNCATION);
                    }
-               }
-             else
-               {
-                 row->used[TEXT_AREA] = i;
-                 produce_special_glyphs (it, IT_TRUNCATION);
+                 it->hpos = hpos_before;
                }
            }
          else if (IT_OVERFLOW_NEWLINE_INTO_FRINGE (it))
                }
            }
          else if (IT_OVERFLOW_NEWLINE_INTO_FRINGE (it))
@@ -20150,13 +20406,13 @@ display_line (struct it *it)
                  goto at_end_of_line;
                }
              it->current_x = x_before;
                  goto at_end_of_line;
                }
              it->current_x = x_before;
+             it->hpos = hpos_before;
            }
 
          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';
            }
 
          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';
-         it->hpos = hpos_before;
          break;
        }
     }
          break;
        }
     }
@@ -20170,9 +20426,12 @@ display_line (struct it *it)
       && IT_CHARPOS (*it) != CHARPOS (row->start.pos))
     {
       if (!FRAME_WINDOW_P (it->f)
       && IT_CHARPOS (*it) != CHARPOS (row->start.pos))
     {
       if (!FRAME_WINDOW_P (it->f)
-         || (row->reversed_p
-             ? WINDOW_RIGHT_FRINGE_WIDTH (it->w)
-             : WINDOW_LEFT_FRINGE_WIDTH (it->w)) == 0)
+         || (((row->reversed_p
+               ? WINDOW_RIGHT_FRINGE_WIDTH (it->w)
+               : WINDOW_LEFT_FRINGE_WIDTH (it->w)) == 0)
+             /* Don't let insert_left_trunc_glyphs overwrite the
+                first glyph of the row if it is an image.  */
+             && row->glyphs[TEXT_AREA]->type != IMAGE_GLYPH))
        insert_left_trunc_glyphs (it);
       row->truncated_on_left_p = 1;
     }
        insert_left_trunc_glyphs (it);
       row->truncated_on_left_p = 1;
     }
@@ -20375,6 +20634,7 @@ See also `bidi-paragraph-direction'.  */)
       itb.string.s = NULL;
       itb.string.lstring = Qnil;
       itb.string.bufpos = 0;
       itb.string.s = NULL;
       itb.string.lstring = Qnil;
       itb.string.bufpos = 0;
+      itb.string.from_disp_str = 0;
       itb.string.unibyte = 0;
       /* We have no window to use here for ignoring window-specific
         overlays.  Using NULL for window pointer will cause
       itb.string.unibyte = 0;
       /* We have no window to use here for ignoring window-specific
         overlays.  Using NULL for window pointer will cause
@@ -20708,6 +20968,30 @@ Value is the new character position of point.  */)
              move_it_by_lines (&it, -1);
              target_x = it.last_visible_x - !FRAME_WINDOW_P (it.f);
              target_is_eol_p = true;
              move_it_by_lines (&it, -1);
              target_x = it.last_visible_x - !FRAME_WINDOW_P (it.f);
              target_is_eol_p = true;
+             /* Under word-wrap, we don't know the x coordinate of
+                the last character displayed on the previous line,
+                which immediately precedes the wrap point.  To find
+                out its x coordinate, we try moving to the right
+                margin of the window, which will stop at the wrap
+                point, and then reset target_x to point at the
+                character that precedes the wrap point.  This is not
+                needed on GUI frames, because (see below) there we
+                move from the left margin one grapheme cluster at a
+                time, and stop when we hit the wrap point.  */
+             if (!FRAME_WINDOW_P (it.f) && it.line_wrap == WORD_WRAP)
+               {
+                 void *it_data = NULL;
+                 struct it it2;
+
+                 SAVE_IT (it2, it, it_data);
+                 move_it_in_display_line_to (&it, ZV, target_x,
+                                             MOVE_TO_POS | MOVE_TO_X);
+                 /* If we arrived at target_x, that _is_ the last
+                    character on the previous line.  */
+                 if (it.current_x != target_x)
+                   target_x = it.current_x - 1;
+                 RESTORE_IT (&it, &it2, it_data);
+               }
            }
        }
       else
            }
        }
       else
@@ -20746,7 +21030,12 @@ Value is the new character position of point.  */)
            new_pos = it.current.pos;
 
          while (it.current_x + it.pixel_width <= target_x
            new_pos = it.current.pos;
 
          while (it.current_x + it.pixel_width <= target_x
-                && rc == MOVE_X_REACHED)
+                && (rc == MOVE_X_REACHED
+                    /* Under word-wrap, move_it_in_display_line_to
+                       stops at correct coordinates, but sometimes
+                       returns MOVE_POS_MATCH_OR_ZV.  */
+                    || (it.line_wrap == WORD_WRAP
+                        && rc == MOVE_POS_MATCH_OR_ZV)))
            {
              int new_x = it.current_x + it.pixel_width;
 
            {
              int new_x = it.current_x + it.pixel_width;
 
@@ -20865,8 +21154,7 @@ display_menu_bar (struct window *w)
   eassert (!FRAME_WINDOW_P (f));
   init_iterator (&it, w, -1, -1, f->desired_matrix->rows, MENU_FACE_ID);
   it.first_visible_x = 0;
   eassert (!FRAME_WINDOW_P (f));
   init_iterator (&it, w, -1, -1, f->desired_matrix->rows, MENU_FACE_ID);
   it.first_visible_x = 0;
-  /* PXW: Use FRAME_PIXEL_WIDTH (f) here?  */
-  it.last_visible_x = FRAME_TOTAL_COLS (f) * FRAME_COLUMN_WIDTH (f);
+  it.last_visible_x = FRAME_PIXEL_WIDTH (f);
 #elif defined (HAVE_X_WINDOWS) /* X without toolkit.  */
   if (FRAME_WINDOW_P (f))
     {
 #elif defined (HAVE_X_WINDOWS) /* X without toolkit.  */
   if (FRAME_WINDOW_P (f))
     {
@@ -20877,8 +21165,7 @@ display_menu_bar (struct window *w)
       init_iterator (&it, menu_w, -1, -1, menu_w->desired_matrix->rows,
                     MENU_FACE_ID);
       it.first_visible_x = 0;
       init_iterator (&it, menu_w, -1, -1, menu_w->desired_matrix->rows,
                     MENU_FACE_ID);
       it.first_visible_x = 0;
-      /* PXW: Use FRAME_PIXEL_WIDTH (f) here?  */
-      it.last_visible_x = FRAME_TOTAL_COLS (f) * FRAME_COLUMN_WIDTH (f);
+      it.last_visible_x = FRAME_PIXEL_WIDTH (f);
     }
   else
 #endif /* not USE_X_TOOLKIT and not USE_GTK */
     }
   else
 #endif /* not USE_X_TOOLKIT and not USE_GTK */
@@ -21599,7 +21886,7 @@ display_mode_element (struct it *it, int depth, int field_width, int precision,
            if (CONSP (XCDR (elt)))
              {
                Lisp_Object spec;
            if (CONSP (XCDR (elt)))
              {
                Lisp_Object spec;
-               spec = safe_eval (XCAR (XCDR (elt)));
+               spec = safe__eval (true, XCAR (XCDR (elt)));
                n += display_mode_element (it, depth, field_width - n,
                                           precision - n, spec, props,
                                           risky);
                n += display_mode_element (it, depth, field_width - n,
                                           precision - n, spec, props,
                                           risky);
@@ -22416,7 +22703,7 @@ decode_mode_spec (struct window *w, register int c, int field_width,
        return decode_mode_spec_buf;
     no_value:
         {
        return decode_mode_spec_buf;
     no_value:
         {
-         charp = decode_mode_spec_buf;
+         char *p = decode_mode_spec_buf;
          int pad = width - 2;
          while (pad-- > 0)
            *p++ = ' ';
          int pad = width - 2;
          while (pad-- > 0)
            *p++ = ' ';
@@ -23164,7 +23451,7 @@ calc_pixel_width_or_height (double *res, struct it *it, Lisp_Object prop,
            return OK_PIXELS (WINDOW_SCROLL_BAR_AREA_WIDTH (it->w));
        }
 
            return OK_PIXELS (WINDOW_SCROLL_BAR_AREA_WIDTH (it->w));
        }
 
-      prop = buffer_local_value_1 (prop, it->w->contents);
+      prop = buffer_local_value (prop, it->w->contents);
       if (EQ (prop, Qunbound))
        prop = Qnil;
     }
       if (EQ (prop, Qunbound))
        prop = Qnil;
     }
@@ -23216,7 +23503,7 @@ calc_pixel_width_or_height (double *res, struct it *it, Lisp_Object prop,
              return OK_PIXELS (pixels);
            }
 
              return OK_PIXELS (pixels);
            }
 
-         car = buffer_local_value_1 (car, it->w->contents);
+         car = buffer_local_value (car, it->w->contents);
          if (EQ (car, Qunbound))
            car = Qnil;
        }
          if (EQ (car, Qunbound))
            car = Qnil;
        }
@@ -23393,7 +23680,7 @@ get_char_face_and_encoding (struct frame *f, int c, int face_id,
 #endif
     {
       eassert (face != NULL);
 #endif
     {
       eassert (face != NULL);
-      PREPARE_FACE_FOR_DISPLAY (f, face);
+      prepare_face_for_display (f, face);
     }
 
   return face;
     }
 
   return face;
@@ -23416,7 +23703,7 @@ get_glyph_face_and_encoding (struct frame *f, struct glyph *glyph,
 
   /* Make sure X resources of the face are allocated.  */
   eassert (face != NULL);
 
   /* 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;
 
   if (two_byte_p)
     *two_byte_p = 0;
@@ -23733,7 +24020,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
   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];
 }
   eassert (s->face);
   return glyph - s->row->glyphs[s->area];
 }
@@ -24331,13 +24618,16 @@ draw_glyphs (struct window *w, int x, struct glyph_row *row,
          else
            overlap_hl = DRAW_NORMAL_TEXT;
 
          else
            overlap_hl = DRAW_NORMAL_TEXT;
 
+         if (hl != overlap_hl)
+           clip_head = head;
          j = i;
          BUILD_GLYPH_STRINGS (j, start, h, t,
                               overlap_hl, dummy_x, last_x);
          start = i;
          compute_overhangs_and_x (t, head->x, 1);
          prepend_glyph_string_lists (&head, &tail, h, t);
          j = i;
          BUILD_GLYPH_STRINGS (j, start, h, t,
                               overlap_hl, dummy_x, last_x);
          start = i;
          compute_overhangs_and_x (t, head->x, 1);
          prepend_glyph_string_lists (&head, &tail, h, t);
-         clip_head = head;
+         if (clip_head == NULL)
+           clip_head = head;
        }
 
       /* Prepend glyph strings for glyphs in front of the first glyph
        }
 
       /* Prepend glyph strings for glyphs in front of the first glyph
@@ -24358,7 +24648,8 @@ draw_glyphs (struct window *w, int x, struct glyph_row *row,
          else
            overlap_hl = DRAW_NORMAL_TEXT;
 
          else
            overlap_hl = DRAW_NORMAL_TEXT;
 
-         clip_head = head;
+         if (hl == overlap_hl || clip_head == NULL)
+           clip_head = head;
          BUILD_GLYPH_STRINGS (i, start, h, t,
                               overlap_hl, dummy_x, last_x);
          for (s = h; s; s = s->next)
          BUILD_GLYPH_STRINGS (i, start, h, t,
                               overlap_hl, dummy_x, last_x);
          for (s = h; s; s = s->next)
@@ -24382,13 +24673,16 @@ draw_glyphs (struct window *w, int x, struct glyph_row *row,
          else
            overlap_hl = DRAW_NORMAL_TEXT;
 
          else
            overlap_hl = DRAW_NORMAL_TEXT;
 
+         if (hl != overlap_hl)
+           clip_tail = tail;
          BUILD_GLYPH_STRINGS (end, i, h, t,
                               overlap_hl, x, last_x);
          /* Because BUILD_GLYPH_STRINGS updates the first argument,
             we don't have `end = i;' here.  */
          compute_overhangs_and_x (h, tail->x + tail->width, 0);
          append_glyph_string_lists (&head, &tail, h, t);
          BUILD_GLYPH_STRINGS (end, i, h, t,
                               overlap_hl, x, last_x);
          /* Because BUILD_GLYPH_STRINGS updates the first argument,
             we don't have `end = i;' here.  */
          compute_overhangs_and_x (h, tail->x + tail->width, 0);
          append_glyph_string_lists (&head, &tail, h, t);
-         clip_tail = tail;
+         if (clip_tail == NULL)
+           clip_tail = tail;
        }
 
       /* Append glyph strings for glyphs following the last glyph
        }
 
       /* Append glyph strings for glyphs following the last glyph
@@ -24406,7 +24700,8 @@ draw_glyphs (struct window *w, int x, struct glyph_row *row,
          else
            overlap_hl = DRAW_NORMAL_TEXT;
 
          else
            overlap_hl = DRAW_NORMAL_TEXT;
 
-         clip_tail = tail;
+         if (hl == overlap_hl || clip_tail == NULL)
+           clip_tail = tail;
          i++;                  /* We must include the Ith glyph.  */
          BUILD_GLYPH_STRINGS (end, i, h, t,
                               overlap_hl, x, last_x);
          i++;                  /* We must include the Ith glyph.  */
          BUILD_GLYPH_STRINGS (end, i, h, t,
                               overlap_hl, x, last_x);
@@ -24674,7 +24969,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.  */
   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)
     {
 
   if (it->image_id < 0)
     {
@@ -24952,7 +25247,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);
     {
       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
 
     }
 #endif
 
@@ -25416,7 +25711,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);
 
       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)
        {
 
       if (it->glyphless_method == GLYPHLESS_DISPLAY_ACRONYM)
        {
@@ -26757,9 +27052,6 @@ draw_phys_cursor_glyph (struct window *w, struct glyph_row *row,
 
 /* Erase the image of a cursor of window W from the screen.  */
 
 
 /* Erase the image of a cursor of window W from the screen.  */
 
-#ifndef HAVE_NTGUI
-static
-#endif
 void
 erase_phys_cursor (struct window *w)
 {
 void
 erase_phys_cursor (struct window *w)
 {
@@ -27068,7 +27360,7 @@ show_mouse_face (Mouse_HLInfo *hlinfo, enum draw_glyphs_face draw)
   if (/* If window is in the process of being destroyed, don't bother
         to do anything.  */
       w->current_matrix != NULL
   if (/* If window is in the process of being destroyed, don't bother
         to do anything.  */
       w->current_matrix != NULL
-      /* Don't update mouse highlight if hidden */
+      /* Don't update mouse highlight if hidden */
       && (draw != DRAW_MOUSE_FACE || !hlinfo->mouse_face_hidden)
       /* Recognize when we are called to operate on rows that don't exist
         anymore.  This can happen when a window is split.  */
       && (draw != DRAW_MOUSE_FACE || !hlinfo->mouse_face_hidden)
       /* Recognize when we are called to operate on rows that don't exist
         anymore.  This can happen when a window is split.  */
@@ -28285,8 +28577,8 @@ note_mode_line_or_margin_highlight (Lisp_Object window, int x, int y,
          else if (area == ON_MODE_LINE)
            {
              Lisp_Object default_help
          else if (area == ON_MODE_LINE)
            {
              Lisp_Object default_help
-               = buffer_local_value_1 (Qmode_line_default_help_echo,
-                                       w->contents);
+               = buffer_local_value (Qmode_line_default_help_echo,
+                                     w->contents);
 
              if (STRINGP (default_help))
                {
 
              if (STRINGP (default_help))
                {
@@ -28302,6 +28594,10 @@ note_mode_line_or_margin_highlight (Lisp_Object window, int x, int y,
       /* Change the mouse pointer according to what is under it.  */
       if (FRAME_WINDOW_P (f))
        {
       /* Change the mouse pointer according to what is under it.  */
       if (FRAME_WINDOW_P (f))
        {
+         bool draggable = (! WINDOW_BOTTOMMOST_P (w)
+                           || minibuf_level
+                           || NILP (Vresize_mini_windows));
+
          dpyinfo = FRAME_DISPLAY_INFO (f);
          if (STRINGP (string))
            {
          dpyinfo = FRAME_DISPLAY_INFO (f);
          if (STRINGP (string))
            {
@@ -28318,11 +28614,11 @@ note_mode_line_or_margin_highlight (Lisp_Object window, int x, int y,
                  map = Fget_text_property (pos, Qlocal_map, string);
                  if (!KEYMAPP (map))
                    map = Fget_text_property (pos, Qkeymap, string);
                  map = Fget_text_property (pos, Qlocal_map, string);
                  if (!KEYMAPP (map))
                    map = Fget_text_property (pos, Qkeymap, string);
-                 if (!KEYMAPP (map))
+                 if (!KEYMAPP (map) && draggable)
                    cursor = dpyinfo->vertical_scroll_bar_cursor;
                }
            }
                    cursor = dpyinfo->vertical_scroll_bar_cursor;
                }
            }
-         else
+         else if (draggable)
            /* Default mode-line pointer.  */
            cursor = FRAME_DISPLAY_INFO (f)->vertical_scroll_bar_cursor;
        }
            /* Default mode-line pointer.  */
            cursor = FRAME_DISPLAY_INFO (f)->vertical_scroll_bar_cursor;
        }
@@ -28541,7 +28837,17 @@ note_mouse_highlight (struct frame *f, int x, int y)
       || part == ON_LEFT_MARGIN || part == ON_RIGHT_MARGIN)
     {
       note_mode_line_or_margin_highlight (window, x, y, part);
       || part == ON_LEFT_MARGIN || part == ON_RIGHT_MARGIN)
     {
       note_mode_line_or_margin_highlight (window, x, y, part);
-      return;
+
+#ifdef HAVE_WINDOW_SYSTEM
+      if (part == ON_LEFT_MARGIN || part == ON_RIGHT_MARGIN)
+       {
+         cursor = FRAME_X_OUTPUT (f)->nontext_cursor;
+         /* Show non-text cursor (Bug#16647).  */
+         goto set_cursor;
+       }
+      else
+#endif
+       return;
     }
 
 #ifdef HAVE_WINDOW_SYSTEM
     }
 
 #ifdef HAVE_WINDOW_SYSTEM
@@ -28556,10 +28862,15 @@ note_mouse_highlight (struct frame *f, int x, int y)
       help_echo_string = build_string ("drag-mouse-1: resize");
     }
   else if (part == ON_BOTTOM_DIVIDER)
       help_echo_string = build_string ("drag-mouse-1: resize");
     }
   else if (part == ON_BOTTOM_DIVIDER)
-    {
-      cursor = FRAME_X_OUTPUT (f)->vertical_drag_cursor;
-      help_echo_string = build_string ("drag-mouse-1: resize");
-    }
+    if (! WINDOW_BOTTOMMOST_P (w)
+       || minibuf_level
+       || NILP (Vresize_mini_windows))
+      {
+       cursor = FRAME_X_OUTPUT (f)->vertical_drag_cursor;
+       help_echo_string = build_string ("drag-mouse-1: resize");
+      }
+    else
+      cursor = FRAME_X_OUTPUT (f)->nontext_cursor;
   else if (part == ON_LEFT_FRINGE || part == ON_RIGHT_FRINGE
           || part == ON_SCROLL_BAR)
     cursor = FRAME_X_OUTPUT (f)->nontext_cursor;
   else if (part == ON_LEFT_FRINGE || part == ON_RIGHT_FRINGE
           || part == ON_SCROLL_BAR)
     cursor = FRAME_X_OUTPUT (f)->nontext_cursor;
@@ -29250,7 +29561,8 @@ x_draw_right_divider (struct window *w)
       int x0 = WINDOW_RIGHT_EDGE_X (w) - WINDOW_RIGHT_DIVIDER_WIDTH (w);
       int x1 = WINDOW_RIGHT_EDGE_X (w);
       int y0 = WINDOW_TOP_EDGE_Y (w);
       int x0 = WINDOW_RIGHT_EDGE_X (w) - WINDOW_RIGHT_DIVIDER_WIDTH (w);
       int x1 = WINDOW_RIGHT_EDGE_X (w);
       int y0 = WINDOW_TOP_EDGE_Y (w);
-      int y1 = WINDOW_BOTTOM_EDGE_Y (w);
+      /* The bottom divider prevails.  */
+      int y1 = WINDOW_BOTTOM_EDGE_Y (w) - WINDOW_BOTTOM_DIVIDER_WIDTH (w);
 
       FRAME_RIF (f)->draw_window_divider (w, x0, x1, y0, y1);
     }
 
       FRAME_RIF (f)->draw_window_divider (w, x0, x1, y0, y1);
     }
@@ -30095,8 +30407,8 @@ Bind this around calls to `message' to let it take effect.  */);
   DEFVAR_LISP ("menu-bar-update-hook",  Vmenu_bar_update_hook,
     doc: /* Normal hook run to update the menu bar definitions.
 Redisplay runs this hook before it redisplays the menu bar.
   DEFVAR_LISP ("menu-bar-update-hook",  Vmenu_bar_update_hook,
     doc: /* Normal hook run to update the menu bar definitions.
 Redisplay runs this hook before it redisplays the menu bar.
-This is used to update submenus such as Buffers,
-whose contents depend on various data.  */);
+This is used to update menus such as Buffers, whose contents depend on
+various data.  */);
   Vmenu_bar_update_hook = Qnil;
 
   DEFVAR_LISP ("menu-updating-frame", Vmenu_updating_frame,
   Vmenu_bar_update_hook = Qnil;
 
   DEFVAR_LISP ("menu-updating-frame", Vmenu_updating_frame,