* xdisp.c (draw_glyphs): Set clipping to highlight boundaries.
[bpt/emacs.git] / src / xdisp.c
index b0fcedb..ab492d0 100644 (file)
@@ -1,6 +1,7 @@
 /* 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.
 
@@ -570,7 +571,7 @@ static struct glyph scratch_glyphs[MAX_SCRATCH_GLYPHS];
 
 /* 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.  */
 
@@ -1018,23 +1019,25 @@ window_text_bottom_y (struct window *w)
 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)
     {
-      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)
-       pixels -= (WINDOW_MARGINS_WIDTH (w)
+       width -= (WINDOW_MARGINS_WIDTH (w)
                   + 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)
-       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);
 
-  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)
 {
-  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
@@ -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 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;
-  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
@@ -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)
-           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
        {
@@ -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;
+         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;
 
@@ -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));
-      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:
@@ -2466,6 +2508,21 @@ remember_mouse_glyph (struct frame *f, int gx, int gy, NativeRectangle *rect)
        }
       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:
@@ -2486,6 +2543,7 @@ remember_mouse_glyph (struct frame *f, int gx, int gy, NativeRectangle *rect)
       goto store_rect;
     }
 
+ add_edge:
   gx += WINDOW_LEFT_EDGE_X (w);
   gy += WINDOW_TOP_EDGE_Y (w);
 
@@ -2803,8 +2861,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 =
-      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);
 
@@ -2921,7 +2980,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 (face->box != FACE_NO_BOX)
+      if (face && face->box != FACE_NO_BOX)
        it->start_of_box_run_p = true;
     }
 
@@ -3906,6 +3965,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.  */
+         /* 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)
@@ -5939,7 +6007,16 @@ pop_it (struct it *it)
       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)
@@ -6408,6 +6485,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.from_disp_str = 0;
       it->bidi_it.string.unibyte = 0;
       it->bidi_it.w = it->w;
     }
@@ -7025,21 +7103,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)
-                      && (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;
-                 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 +8406,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;
-  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.  */
@@ -8322,16 +8423,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
-     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)
     {
-      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)
-       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()                                 \
@@ -8475,8 +8581,8 @@ move_it_in_display_line_to (struct it *it,
          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;
        }
 
@@ -8556,7 +8662,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
-                         && 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;
@@ -8698,9 +8809,11 @@ move_it_in_display_line_to (struct it *it,
            {
              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);
+                     move_it_in_display_line_to (it, closest_pos, -1,
+                                                 MOVE_TO_POS);
                      result = MOVE_POS_MATCH_OR_ZV;
                    }
                  else
@@ -8730,8 +8843,8 @@ move_it_in_display_line_to (struct it *it,
       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.  */
@@ -8757,8 +8870,13 @@ move_it_in_display_line_to (struct it *it,
                      && 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);
+                     move_it_in_display_line_to (it, closest_pos, -1,
+                                                 MOVE_TO_POS);
+                   }
                  result = MOVE_POS_MATCH_OR_ZV;
                  break;
                }
@@ -8772,8 +8890,11 @@ move_it_in_display_line_to (struct it *it,
                   && !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);
+                 move_it_in_display_line_to (it, closest_pos, -1, MOVE_TO_POS);
+               }
              result = MOVE_POS_MATCH_OR_ZV;
              break;
            }
@@ -9096,7 +9217,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;
-      last_max_ascent = it->max_ascent;
       it->max_ascent = it->max_descent = 0;
     }
 
@@ -9123,7 +9243,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;
-      last_max_ascent = it->max_ascent;
     }
 
   if (backup_data)
@@ -9403,6 +9522,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);
+      bool hit_pos_limit = false;
       ptrdiff_t pos_limit;
 
       /* Start at the beginning of the screen line containing IT's
@@ -9419,8 +9539,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);
+
       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.  */
@@ -9464,6 +9587,25 @@ move_it_by_lines (struct it *it, ptrdiff_t dvpos)
          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);
     }
@@ -9492,23 +9634,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.
 
-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
-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
-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.
 
-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 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)
 {
@@ -9576,7 +9722,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);
 
-  /**   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
@@ -9590,14 +9735,7 @@ include the height of any of these lines in the return value.  */)
                      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))
@@ -9853,7 +9991,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.  */
-       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);
@@ -10657,9 +10795,9 @@ resize_mini_window (struct window *w, int exact_p)
       /* 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);
-         move_it_vertically_backward (&it, height);
+         move_it_vertically_backward (&it, height - unit);
          start = it.current.pos;
        }
       else
@@ -12057,8 +12195,8 @@ display_tool_bar_line (struct it *it, int height)
 #define MAX_FRAME_TOOL_BAR_HEIGHT(f) \
   ((FRAME_LINE_HEIGHT (f) * FRAME_LINES (f)))
 
-/* Value is the number of screen lines needed to make all tool-bar
-   items of frame F visible.  The number of actual rows needed is
+/* Value is the number of pixels needed to make all tool-bar items of
+   frame F visible.  The actual number of glyph rows needed is
    returned in *N_ROWS if non-NULL.  */
 
 static int
@@ -12075,8 +12213,7 @@ tool_bar_height (struct frame *f, int *n_rows, bool pixelwise)
      F->desired_tool_bar_string in the tool-bar window of frame F.  */
   init_iterator (&it, w, -1, -1, temp_row, TOOL_BAR_FACE_ID);
   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 = WINDOW_PIXEL_WIDTH (w);
   reseat_to_string (&it, NULL, f->desired_tool_bar_string, 0, 0, 0, -1);
   it.paragraph_embedding = L2R;
 
@@ -12109,7 +12246,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
-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;
@@ -12254,6 +12391,10 @@ redisplay_tool_bar (struct frame *f)
          && it.current_y < max_tool_bar_height)
        change_height_p = 1;
 
+      /* We subtract 1 because display_tool_bar_line advances the
+        glyph_row pointer before returning to its caller.  We want to
+        examine the last glyph row produced by
+        display_tool_bar_line.  */
       row = it.glyph_row - 1;
 
       /* If there are blank lines at the end, except for a partially
@@ -12286,18 +12427,35 @@ redisplay_tool_bar (struct frame *f)
 
          if (change_height_p)
            {
+             /* Current size of the tool-bar window in canonical line
+                units.  */
+             int old_lines = WINDOW_TOTAL_LINES (w);
+             /* Required size of the tool-bar window in canonical
+                line units. */
              int new_lines = ((new_height + FRAME_LINE_HEIGHT (f) - 1)
                               / FRAME_LINE_HEIGHT (f));
-
-             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;
+               }
            }
        }
     }
@@ -12607,15 +12765,25 @@ hscroll_window_tree (Lisp_Object window)
        {
          int h_margin;
          int text_area_width;
-         struct glyph_row *current_cursor_row
-           = MATRIX_ROW (w->current_matrix, w->cursor.vpos);
-         struct glyph_row *desired_cursor_row
-           = MATRIX_ROW (w->desired_matrix, w->cursor.vpos);
-         struct glyph_row *cursor_row
-           = (desired_cursor_row->enabled_p
-              ? desired_cursor_row
-              : current_cursor_row);
-         int row_r2l_p = cursor_row->reversed_p;
+         struct glyph_row *cursor_row;
+         struct glyph_row *bottom_row;
+         int row_r2l_p;
+
+         bottom_row = MATRIX_BOTTOM_TEXT_ROW (w->desired_matrix, w);
+         if (w->cursor.vpos < bottom_row - w->desired_matrix->rows)
+           cursor_row = MATRIX_ROW (w->desired_matrix, w->cursor.vpos);
+         else
+           cursor_row = bottom_row - 1;
+
+         if (!cursor_row->enabled_p)
+           {
+             bottom_row = MATRIX_BOTTOM_TEXT_ROW (w->current_matrix, w);
+             if (w->cursor.vpos < bottom_row - w->current_matrix->rows)
+               cursor_row = MATRIX_ROW (w->current_matrix, w->cursor.vpos);
+             else
+               cursor_row = bottom_row - 1;
+           }
+         row_r2l_p = cursor_row->reversed_p;
 
          text_area_width = window_box_width (w, TEXT_AREA);
 
@@ -15442,29 +15610,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.  */
-                 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))
+                 if (rv)
                    {
-                     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))
-                   {
-                     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;
@@ -15590,7 +15761,8 @@ redisplay_window (Lisp_Object window, bool just_this_one_p)
       && 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.  */
@@ -15736,16 +15908,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?  */
-  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))))
         {
-          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);
         }
     }
@@ -16258,12 +16434,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
-     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)
     {
-      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);
     }
 
@@ -17297,9 +17511,16 @@ row_containing_pos (struct window *w, ptrdiff_t charpos,
 
    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
+   0   if otherwise unsuccessful
 
    The following steps are performed:
 
@@ -17374,6 +17595,12 @@ try_window_id (struct window *w)
   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
@@ -18461,6 +18688,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.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);
@@ -20073,7 +20301,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
-         && (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)))
        {
@@ -20106,19 +20339,26 @@ display_line (struct it *it)
                  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);
                    }
-               }
-             else
-               {
-                 row->used[TEXT_AREA] = i;
-                 produce_special_glyphs (it, IT_TRUNCATION);
+                 it->hpos = hpos_before;
                }
            }
          else if (IT_OVERFLOW_NEWLINE_INTO_FRINGE (it))
@@ -20137,13 +20377,13 @@ display_line (struct it *it)
                  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';
-         it->hpos = hpos_before;
          break;
        }
     }
@@ -20157,9 +20397,12 @@ display_line (struct it *it)
       && 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;
     }
@@ -20362,6 +20605,7 @@ See also `bidi-paragraph-direction'.  */)
       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
@@ -20695,6 +20939,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;
+             /* 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
@@ -20733,7 +21001,12 @@ Value is the new character position of point.  */)
            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;
 
@@ -20852,8 +21125,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;
-  /* 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))
     {
@@ -20864,8 +21136,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;
-      /* 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 */
@@ -22403,7 +22674,7 @@ decode_mode_spec (struct window *w, register int c, int field_width,
        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++ = ' ';
@@ -23151,7 +23422,7 @@ calc_pixel_width_or_height (double *res, struct it *it, Lisp_Object prop,
            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;
     }
@@ -23203,7 +23474,7 @@ calc_pixel_width_or_height (double *res, struct it *it, Lisp_Object prop,
              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;
        }
@@ -24318,13 +24589,16 @@ draw_glyphs (struct window *w, int x, struct glyph_row *row,
          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);
-         clip_head = head;
+         if (clip_head == NULL)
+           clip_head = head;
        }
 
       /* Prepend glyph strings for glyphs in front of the first glyph
@@ -24345,7 +24619,8 @@ draw_glyphs (struct window *w, int x, struct glyph_row *row,
          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)
@@ -24369,13 +24644,16 @@ draw_glyphs (struct window *w, int x, struct glyph_row *row,
          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);
-         clip_tail = tail;
+         if (clip_tail == NULL)
+           clip_tail = tail;
        }
 
       /* Append glyph strings for glyphs following the last glyph
@@ -24393,7 +24671,8 @@ draw_glyphs (struct window *w, int x, struct glyph_row *row,
          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);
@@ -27055,7 +27334,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
-      /* 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.  */
@@ -28272,8 +28551,8 @@ note_mode_line_or_margin_highlight (Lisp_Object window, int x, int y,
          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))
                {
@@ -28289,6 +28568,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))
        {
+         bool draggable = (! WINDOW_BOTTOMMOST_P (w)
+                           || minibuf_level
+                           || NILP (Vresize_mini_windows));
+
          dpyinfo = FRAME_DISPLAY_INFO (f);
          if (STRINGP (string))
            {
@@ -28305,11 +28588,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);
-                 if (!KEYMAPP (map))
+                 if (!KEYMAPP (map) && draggable)
                    cursor = dpyinfo->vertical_scroll_bar_cursor;
                }
            }
-         else
+         else if (draggable)
            /* Default mode-line pointer.  */
            cursor = FRAME_DISPLAY_INFO (f)->vertical_scroll_bar_cursor;
        }
@@ -28528,7 +28811,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);
-      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
@@ -28543,10 +28836,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)
-    {
-      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;
@@ -29237,7 +29535,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 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);
     }
@@ -30082,8 +30381,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.
-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,