]> code.delx.au - gnu-emacs/blobdiff - src/xdisp.c
(CLEAR_IMAGE_CACHE_COUNT): New const.
[gnu-emacs] / src / xdisp.c
index 071e85ae29d0520d45ecd9fad65184ab09b18c77..9c2d3c2554d4bc1cc73b16dd90ebedaad0635176 100644 (file)
@@ -1,6 +1,6 @@
 /* Display generation from window structure and buffer text.
-   Copyright (C) 1985,86,87,88,93,94,95,97,98,99,2000,01,02,03,04
-   Free Software Foundation, Inc.
+   Copyright (C) 1985, 1986, 1987, 1988, 1993, 1994, 1995, 1997, 1998, 1999,
+     2000, 2001, 2002, 2003, 2004, 2005  Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -215,6 +215,8 @@ extern int pending_menu_activation;
 extern int interrupt_input;
 extern int command_loop_level;
 
+extern Lisp_Object do_mouse_tracking;
+
 extern int minibuffer_auto_raise;
 extern Lisp_Object Vminibuffer_list;
 
@@ -262,6 +264,10 @@ int mouse_autoselect_window;
 
 int auto_raise_tool_bar_buttons_p;
 
+/* Non-zero means to reposition window if cursor line is only partially visible.  */
+
+int make_cursor_line_fully_visible_p;
+
 /* Margin around tool bar buttons in pixels.  */
 
 Lisp_Object Vtool_bar_button_margin;
@@ -302,15 +308,20 @@ Lisp_Object Qleft_margin, Qright_margin, Qspace_width, Qraise;
 Lisp_Object Qslice;
 Lisp_Object Qcenter;
 Lisp_Object Qmargin, Qpointer;
-Lisp_Object Qline_height, Qtotal;
+Lisp_Object Qline_height;
 extern Lisp_Object Qheight;
 extern Lisp_Object QCwidth, QCheight, QCascent;
 extern Lisp_Object Qscroll_bar;
+extern Lisp_Object Qcursor;
 
 /* Non-nil means highlight trailing whitespace.  */
 
 Lisp_Object Vshow_trailing_whitespace;
 
+/* Non-nil means escape non-break space and hyphens.  */
+
+Lisp_Object Vshow_nonbreak_escape;
+
 #ifdef HAVE_WINDOW_SYSTEM
 extern Lisp_Object Voverflow_newline_into_fringe;
 
@@ -335,6 +346,10 @@ Lisp_Object Vvoid_text_area_pointer;
 
 Lisp_Object Qtrailing_whitespace;
 
+/* Name and number of the face used to highlight escape glyphs.  */
+
+Lisp_Object Qescape_glyph;
+
 /* The symbol `image' which is the car of the lists used to represent
    images in Lisp.  */
 
@@ -766,6 +781,13 @@ enum move_it_result
 #define CLEAR_FACE_CACHE_COUNT 500
 static int clear_face_cache_count;
 
+/* Similarly for the image cache.  */
+
+#ifdef HAVE_WINDOW_SYSTEM
+#define CLEAR_IMAGE_CACHE_COUNT        101
+static int clear_image_cache_count;
+#endif
+
 /* Record the previous terminal frame we displayed.  */
 
 static struct frame *previous_terminal_frame;
@@ -800,9 +822,9 @@ static struct glyph_slice null_glyph_slice = { 0, 0, 0, 0 };
 \f
 /* Function prototypes.  */
 
-static void setup_for_ellipsis P_ ((struct it *));
+static void setup_for_ellipsis P_ ((struct it *, int));
 static void mark_window_display_accurate_1 P_ ((struct window *, int));
-static int single_display_prop_string_p P_ ((Lisp_Object, Lisp_Object));
+static int single_display_spec_string_p P_ ((Lisp_Object, Lisp_Object));
 static int display_prop_string_p P_ ((Lisp_Object, Lisp_Object));
 static int cursor_row_p P_ ((struct window *, struct glyph_row *));
 static int redisplay_mode_lines P_ ((Lisp_Object, int));
@@ -812,7 +834,6 @@ static char *decode_mode_spec_coding P_ ((Lisp_Object, char *, int));
 static int invisible_text_between_p P_ ((struct it *, int, int));
 #endif
 
-static int next_element_from_ellipsis P_ ((struct it *));
 static void pint2str P_ ((char *, int, int));
 static void pint2hrstr P_ ((char *, int, int));
 static struct text_pos run_window_scroll_functions P_ ((Lisp_Object,
@@ -824,7 +845,7 @@ static int store_frame_title P_ ((const unsigned char *, int, int));
 static void x_consider_frame_title P_ ((Lisp_Object));
 static void handle_stop P_ ((struct it *));
 static int tool_bar_lines_needed P_ ((struct frame *));
-static int single_display_prop_intangible_p P_ ((Lisp_Object));
+static int single_display_spec_intangible_p P_ ((Lisp_Object));
 static void ensure_echo_area_buffers P_ ((void));
 static Lisp_Object unwind_with_echo_area_buffer P_ ((Lisp_Object));
 static Lisp_Object with_echo_area_buffer_unwind_data P_ ((struct window *));
@@ -849,7 +870,7 @@ static struct glyph_row *get_overlay_arrow_glyph_row P_ ((struct window *,
                                                          Lisp_Object));
 static void extend_face_to_end_of_line P_ ((struct it *));
 static int append_space_for_newline P_ ((struct it *, int));
-static int make_cursor_line_fully_visible P_ ((struct window *, int));
+static int cursor_row_fully_visible_p P_ ((struct window *, int, int));
 static int try_scrolling P_ ((Lisp_Object, int, EMACS_INT, EMACS_INT, int, int));
 static int try_cursor_movement P_ ((Lisp_Object, struct text_pos, int *));
 static int trailing_whitespace_p P_ ((int));
@@ -885,8 +906,9 @@ static void next_overlay_string P_ ((struct it *));
 static void reseat P_ ((struct it *, struct text_pos, int));
 static void reseat_1 P_ ((struct it *, struct text_pos, int));
 static void back_to_previous_visible_line_start P_ ((struct it *));
-static void reseat_at_previous_visible_line_start P_ ((struct it *));
+void reseat_at_previous_visible_line_start P_ ((struct it *));
 static void reseat_at_next_visible_line_start P_ ((struct it *, int));
+static int next_element_from_ellipsis P_ ((struct it *));
 static int next_element_from_display_vector P_ ((struct it *));
 static int next_element_from_string P_ ((struct it *));
 static int next_element_from_c_string P_ ((struct it *));
@@ -918,7 +940,7 @@ static void compute_string_pos P_ ((struct text_pos *, struct text_pos,
                                    Lisp_Object));
 static int face_before_or_after_it_pos P_ ((struct it *, int));
 static int next_overlay_change P_ ((int));
-static int handle_single_display_prop P_ ((struct it *, Lisp_Object,
+static int handle_single_display_spec P_ ((struct it *, Lisp_Object,
                                           Lisp_Object, struct text_pos *,
                                           int));
 static int underlying_face_id P_ ((struct it *));
@@ -1228,28 +1250,31 @@ line_bottom_y (it)
 }
 
 
-/* Return 1 if position CHARPOS is visible in window W.  Set *FULLY to
-   1 if POS is visible and the line containing POS is fully visible.
+/* Return 1 if position CHARPOS is visible in window W.
+   If visible, set *X and *Y to pixel coordinates of top left corner.
+   Set *RTOP and *RBOT to pixel height of an invisible area of glyph at POS.
    EXACT_MODE_LINE_HEIGHTS_P non-zero means compute exact mode-line
    and header-lines heights.  */
 
 int
-pos_visible_p (w, charpos, fully, x, y, exact_mode_line_heights_p)
+pos_visible_p (w, charpos, x, y, rtop, rbot, exact_mode_line_heights_p)
      struct window *w;
-     int charpos, *fully, *x, *y, exact_mode_line_heights_p;
+     int charpos, *x, *y, *rtop, *rbot, exact_mode_line_heights_p;
 {
   struct it it;
   struct text_pos top;
-  int visible_p;
+  int visible_p = 0;
   struct buffer *old_buffer = NULL;
 
+  if (noninteractive)
+    return visible_p;
+
   if (XBUFFER (w->buffer) != current_buffer)
     {
       old_buffer = current_buffer;
       set_buffer_internal_1 (XBUFFER (w->buffer));
     }
 
-  *fully = visible_p = 0;
   SET_TEXT_POS_FROM_MARKER (top, w->start);
 
   /* Compute exact mode line heights, if requested.  */
@@ -1267,35 +1292,38 @@ pos_visible_p (w, charpos, fully, x, y, exact_mode_line_heights_p)
     }
 
   start_display (&it, w, top);
-  move_it_to (&it, charpos, 0, it.last_visible_y, -1,
-             MOVE_TO_POS | MOVE_TO_X | MOVE_TO_Y);
+  move_it_to (&it, charpos, -1, it.last_visible_y, -1,
+             MOVE_TO_POS | MOVE_TO_Y);
 
   /* Note that we may overshoot because of invisible text.  */
   if (IT_CHARPOS (it) >= charpos)
     {
       int top_y = it.current_y;
-      int bottom_y = line_bottom_y (&it);
+      int bottom_y = (last_height = 0, line_bottom_y (&it));
       int window_top_y = WINDOW_HEADER_LINE_HEIGHT (w);
 
       if (top_y < window_top_y)
        visible_p = bottom_y > window_top_y;
       else if (top_y < it.last_visible_y)
-       {
          visible_p = 1;
-         *fully = bottom_y <= it.last_visible_y;
-       }
       if (visible_p && x)
        {
          *x = it.current_x;
-         *y = max (top_y + it.max_ascent - it.ascent, window_top_y);
+         *y = max (top_y + max (0, it.max_ascent - it.ascent), window_top_y);
+         if (rtop)
+           {
+             *rtop = max (0, window_top_y - top_y);
+             *rbot = max (0, bottom_y - it.last_visible_y);
+           }
        }
     }
-  else if (it.current_y + it.max_ascent + it.max_descent > it.last_visible_y)
+  else
     {
       struct it it2;
 
       it2 = it;
-      move_it_by_lines (&it, 1, 0);
+      if (IT_CHARPOS (it) < ZV && FETCH_BYTE (IT_BYTEPOS (it)) != '\n')
+       move_it_by_lines (&it, 1, 0);
       if (charpos < IT_CHARPOS (it))
        {
          visible_p = 1;
@@ -1304,6 +1332,12 @@ pos_visible_p (w, charpos, fully, x, y, exact_mode_line_heights_p)
              move_it_to (&it2, charpos, -1, -1, -1, MOVE_TO_POS);
              *x = it2.current_x;
              *y = it2.current_y + it2.max_ascent - it2.ascent;
+             if (rtop)
+               {
+                 *rtop = max (0, -it2.current_y);
+                 *rbot = max (0, ((it2.current_y + it2.max_ascent + it2.max_descent)
+                                  - it.last_visible_y));
+               }
            }
        }
     }
@@ -1761,6 +1795,24 @@ get_glyph_string_clip_rect (s, nr)
       r.height = s->row->visible_height;
     }
 
+  if (s->clip_head)
+    if (r.x < s->clip_head->x)
+      {
+       if (r.width >= s->clip_head->x - r.x)
+         r.width -= s->clip_head->x - r.x;
+       else
+         r.width = 0;
+       r.x = s->clip_head->x;
+      }
+  if (s->clip_tail)
+    if (r.x + r.width > s->clip_tail->x + s->clip_tail->background_width)
+      {
+       if (s->clip_tail->x + s->clip_tail->background_width >= r.x)
+         r.width = s->clip_tail->x + s->clip_tail->background_width - r.x;
+       else
+         r.width = 0;
+      }
+
   /* If S draws overlapping rows, it's sufficient to use the top and
      bottom of the window for clipping because this glyph string
      intentionally draws over other lines.  */
@@ -1782,7 +1834,8 @@ get_glyph_string_clip_rect (s, nr)
 
       /* If drawing a tool-bar window, draw it over the internal border
         at the top of the window.  */
-      if (s->w == XWINDOW (s->f->tool_bar_window))
+      if (WINDOWP (s->f->tool_bar_window)
+         && s->w == XWINDOW (s->f->tool_bar_window))
        r.y -= FRAME_INTERNAL_BORDER_WIDTH (s->f);
     }
 
@@ -1793,7 +1846,7 @@ get_glyph_string_clip_rect (s, nr)
   if (s->hl == DRAW_CURSOR)
     {
       struct glyph *glyph = s->first_glyph;
-      int height;
+      int height, max_y;
 
       if (s->x > r.x)
        {
@@ -1802,13 +1855,26 @@ get_glyph_string_clip_rect (s, nr)
        }
       r.width = min (r.width, glyph->pixel_width);
 
-      /* Don't draw cursor glyph taller than our actual glyph.  */
-      height = max (FRAME_LINE_HEIGHT (s->f), glyph->ascent + glyph->descent);
-      if (height < r.height)
+      /* If r.y is below window bottom, ensure that we still see a cursor.  */
+      height = min (glyph->ascent + glyph->descent,
+                   min (FRAME_LINE_HEIGHT (s->f), s->row->visible_height));
+      max_y = window_text_bottom_y (s->w) - height;
+      max_y = WINDOW_TO_FRAME_PIXEL_Y (s->w, max_y);
+      if (s->ybase - glyph->ascent > max_y)
+       {
+         r.y = max_y;
+         r.height = height;
+       }
+      else
        {
-         int max_y = r.y + r.height;
-         r.y = min (max_y, s->ybase + glyph->descent - height);
-         r.height = min (max_y - r.y, height);
+         /* Don't draw cursor glyph taller than our actual glyph.  */
+         height = max (FRAME_LINE_HEIGHT (s->f), glyph->ascent + glyph->descent);
+         if (height < r.height)
+           {
+             max_y = r.y + r.height;
+             r.y = min (max_y, max (r.y, s->ybase + glyph->descent - height));
+             r.height = min (max_y - r.y, height);
+           }
        }
     }
 
@@ -1819,6 +1885,64 @@ get_glyph_string_clip_rect (s, nr)
 #endif
 }
 
+
+/* EXPORT:
+   Return the position and height of the phys cursor in window W.
+   Set w->phys_cursor_width to width of phys cursor.
+*/
+
+int
+get_phys_cursor_geometry (w, row, glyph, heightp)
+     struct window *w;
+     struct glyph_row *row;
+     struct glyph *glyph;
+     int *heightp;
+{
+  struct frame *f = XFRAME (WINDOW_FRAME (w));
+  int x, y, wd, h, h0, y0;
+
+  /* Compute the width of the rectangle to draw.  If on a stretch
+     glyph, and `x-stretch-block-cursor' is nil, don't draw a
+     rectangle as wide as the glyph, but use a canonical character
+     width instead.  */
+  wd = glyph->pixel_width - 1;
+#ifdef HAVE_NTGUI
+  wd++; /* Why? */
+#endif
+  if (glyph->type == STRETCH_GLYPH
+      && !x_stretch_cursor_p)
+    wd = min (FRAME_COLUMN_WIDTH (f), wd);
+  w->phys_cursor_width = wd;
+
+  y = w->phys_cursor.y + row->ascent - glyph->ascent;
+
+  /* If y is below window bottom, ensure that we still see a cursor.  */
+  h0 = min (FRAME_LINE_HEIGHT (f), row->visible_height);
+
+  h = max (h0, glyph->ascent + glyph->descent);
+  h0 = min (h0, glyph->ascent + glyph->descent);
+
+  y0 = WINDOW_HEADER_LINE_HEIGHT (w);
+  if (y < y0)
+    {
+      h = max (h - (y0 - y) + 1, h0);
+      y = y0 - 1;
+    }
+  else
+    {
+      y0 = window_text_bottom_y (w) - h0;
+      if (y > y0)
+       {
+         h += y - y0;
+         y = y0;
+       }
+    }
+
+  *heightp = h - 1;
+  return WINDOW_TO_FRAME_PIXEL_Y (w, y);
+}
+
+
 #endif /* HAVE_WINDOW_SYSTEM */
 
 \f
@@ -1928,7 +2052,7 @@ static void
 check_it (it)
      struct it *it;
 {
-  if (it->method == next_element_from_string)
+  if (it->method == GET_FROM_STRING)
     {
       xassert (STRINGP (it->string));
       xassert (IT_STRING_CHARPOS (*it) >= 0);
@@ -1936,7 +2060,7 @@ check_it (it)
   else
     {
       xassert (IT_STRING_CHARPOS (*it) < 0);
-      if (it->method == next_element_from_buffer)
+      if (it->method == GET_FROM_BUFFER)
        {
          /* Check that character and byte positions agree.  */
          xassert (IT_CHARPOS (*it) == BYTE_TO_CHAR (IT_BYTEPOS (*it)));
@@ -2072,6 +2196,7 @@ init_iterator (it, w, charpos, bytepos, row, base_face_id)
                                  * FRAME_LINE_HEIGHT (it->f));
       else if (it->f->extra_line_spacing > 0)
        it->extra_line_spacing = it->f->extra_line_spacing;
+      it->max_extra_line_spacing = 0;
     }
 
   /* If realized faces have been removed, e.g. because of face
@@ -2420,7 +2545,10 @@ init_from_display_pos (it, w, pos)
      after-string.  */
   init_iterator (it, w, charpos, bytepos, NULL, DEFAULT_FACE_ID);
 
-  for (i = 0; i < it->n_overlay_strings; ++i)
+  /* This only scans the current chunk -- it should scan all chunks.
+     However, OVERLAY_STRING_CHUNK_SIZE has been increased from 3 in 21.1
+     to 16 in 22.1 to make this a lesser problem.  */
+  for (i = 0; i < it->n_overlay_strings && i < OVERLAY_STRING_CHUNK_SIZE; ++i)
     {
       const char *s = SDATA (it->overlay_strings[i]);
       const char *e = s + SBYTES (it->overlay_strings[i]);
@@ -2445,7 +2573,7 @@ init_from_display_pos (it, w, pos)
         property for an image, the iterator will be set up for that
         image, and we have to undo that setup first before we can
         correct the overlay string index.  */
-      if (it->method == next_element_from_image)
+      if (it->method == GET_FROM_IMAGE)
        pop_it (it);
 
       /* We already have the first chunk of overlay strings in
@@ -2468,7 +2596,7 @@ init_from_display_pos (it, w, pos)
       it->string = it->overlay_strings[relative_index];
       xassert (STRINGP (it->string));
       it->current.string_pos = pos->string_pos;
-      it->method = next_element_from_string;
+      it->method = GET_FROM_STRING;
     }
 
 #if 0 /* This is bogus because POS not having an overlay string
@@ -2484,7 +2612,7 @@ init_from_display_pos (it, w, pos)
       while (it->sp)
        pop_it (it);
       it->current.overlay_string_index = -1;
-      it->method = next_element_from_buffer;
+      it->method = GET_FROM_BUFFER;
       if (CHARPOS (pos->pos) == ZV)
        it->overlay_strings_at_end_processed_p = 1;
     }
@@ -2598,7 +2726,7 @@ handle_stop (it)
        {
          /* Don't check for overlay strings below when set to deliver
             characters from a display vector.  */
-         if (it->method == next_element_from_display_vector)
+         if (it->method == GET_FROM_DISPLAY_VECTOR)
            handle_overlay_change_p = 0;
 
          /* Handle overlay changes.  */
@@ -3218,7 +3346,7 @@ handle_invisible_prop (it)
              it->stack[it->sp - 1].display_ellipsis_p = display_ellipsis_p;
            }
          else if (display_ellipsis_p)
-           setup_for_ellipsis (it);
+           setup_for_ellipsis (it, 0);
        }
     }
 
@@ -3226,14 +3354,17 @@ handle_invisible_prop (it)
 }
 
 
-/* Make iterator IT return `...' next.  */
+/* Make iterator IT return `...' next.
+   Replaces LEN characters from buffer.  */
 
 static void
-setup_for_ellipsis (it)
+setup_for_ellipsis (it, len)
      struct it *it;
+     int len;
 {
-  if (it->dp
-      && VECTORP (DISP_INVIS_VECTOR (it->dp)))
+  /* Use the display table definition for `...'.  Invalid glyphs
+     will be handled by the method returning elements from dpvec.  */
+  if (it->dp && VECTORP (DISP_INVIS_VECTOR (it->dp)))
     {
       struct Lisp_Vector *v = XVECTOR (DISP_INVIS_VECTOR (it->dp));
       it->dpvec = v->contents;
@@ -3246,13 +3377,15 @@ setup_for_ellipsis (it)
       it->dpend = default_invis_vector + 3;
     }
 
-  /* The ellipsis display does not replace the display of the
-     character at the new position.  Indicate this by setting
-     IT->dpvec_char_len to zero.  */
-  it->dpvec_char_len = 0;
-
+  it->dpvec_char_len = len;
   it->current.dpvec_index = 0;
-  it->method = next_element_from_display_vector;
+  it->dpvec_face_id = -1;
+
+  /* Remember the current face id in case glyphs specify faces.
+     IT's face is restored in set_iterator_to_next.  */
+  it->saved_face_id = it->face_id;
+  it->method = GET_FROM_DISPLAY_VECTOR;
+  it->ellipsis_p = 1;
 }
 
 
@@ -3262,7 +3395,10 @@ setup_for_ellipsis (it)
  ***********************************************************************/
 
 /* Set up iterator IT from `display' property at its current position.
-   Called from handle_stop.  */
+   Called from handle_stop.
+   We return HANDLED_RETURN if some part of the display property
+   overrides the display of the buffer text itself.
+   Otherwise we return HANDLED_NORMALLY.  */
 
 static enum prop_handled
 handle_display_prop (it)
@@ -3270,6 +3406,7 @@ handle_display_prop (it)
 {
   Lisp_Object prop, object;
   struct text_pos *position;
+  /* Nonzero if some property replaces the display of the text itself.  */
   int display_replaced_p = 0;
 
   if (STRINGP (it->string))
@@ -3317,7 +3454,7 @@ handle_display_prop (it)
     {
       for (; CONSP (prop); prop = XCDR (prop))
        {
-         if (handle_single_display_prop (it, XCAR (prop), object,
+         if (handle_single_display_spec (it, XCAR (prop), object,
                                          position, display_replaced_p))
            display_replaced_p = 1;
        }
@@ -3326,13 +3463,13 @@ handle_display_prop (it)
     {
       int i;
       for (i = 0; i < ASIZE (prop); ++i)
-       if (handle_single_display_prop (it, AREF (prop, i), object,
+       if (handle_single_display_spec (it, AREF (prop, i), object,
                                        position, display_replaced_p))
          display_replaced_p = 1;
     }
   else
     {
-      if (handle_single_display_prop (it, prop, object, position, 0))
+      if (handle_single_display_spec (it, prop, object, position, 0))
        display_replaced_p = 1;
     }
 
@@ -3364,42 +3501,44 @@ display_prop_end (it, object, start_pos)
 }
 
 
-/* Set up IT from a single `display' sub-property value PROP.  OBJECT
+/* Set up IT from a single `display' specification PROP.  OBJECT
    is the object in which the `display' property was found.  *POSITION
    is the position at which it was found.  DISPLAY_REPLACED_P non-zero
-   means that we previously saw a display sub-property which already
+   means that we previously saw a display specification which already
    replaced text display with something else, for example an image;
-   ignore such properties after the first one has been processed.
+   we ignore such properties after the first one has been processed.
 
-   If PROP is a `space' or `image' sub-property, set *POSITION to the
-   end position of the `display' property.
+   If PROP is a `space' or `image' specification, and in some other
+   cases too, set *POSITION to the position where the `display'
+   property ends.
 
    Value is non-zero if something was found which replaces the display
    of buffer or string text.  */
 
 static int
-handle_single_display_prop (it, prop, object, position,
+handle_single_display_spec (it, spec, object, position,
                            display_replaced_before_p)
      struct it *it;
-     Lisp_Object prop;
+     Lisp_Object spec;
      Lisp_Object object;
      struct text_pos *position;
      int display_replaced_before_p;
 {
-  Lisp_Object value;
-  int replaces_text_display_p = 0;
   Lisp_Object form;
+  Lisp_Object location, value;
+  struct text_pos start_pos;
+  int valid_p;
 
-  /* If PROP is a list of the form `(when FORM . VALUE)', FORM is
-     evaluated.  If the result is nil, VALUE is ignored.  */
+  /* If SPEC is a list of the form `(when FORM . VALUE)', evaluate FORM.
+     If the result is non-nil, use VALUE instead of SPEC.  */
   form = Qt;
-  if (CONSP (prop) && EQ (XCAR (prop), Qwhen))
+  if (CONSP (spec) && EQ (XCAR (spec), Qwhen))
     {
-      prop = XCDR (prop);
-      if (!CONSP (prop))
+      spec = XCDR (spec);
+      if (!CONSP (spec))
        return 0;
-      form = XCAR (prop);
-      prop = XCDR (prop);
+      form = XCAR (spec);
+      spec = XCDR (spec);
     }
 
   if (!NILP (form) && !EQ (form, Qt))
@@ -3425,15 +3564,15 @@ handle_single_display_prop (it, prop, object, position,
   if (NILP (form))
     return 0;
 
-  if (CONSP (prop)
-      && EQ (XCAR (prop), Qheight)
-      && CONSP (XCDR (prop)))
+  /* Handle `(height HEIGHT)' specifications.  */
+  if (CONSP (spec)
+      && EQ (XCAR (spec), Qheight)
+      && CONSP (XCDR (spec)))
     {
       if (FRAME_TERMCAP_P (it->f) || FRAME_MSDOS_P (it->f))
        return 0;
 
-      /* `(height HEIGHT)'.  */
-      it->font_height = XCAR (XCDR (prop));
+      it->font_height = XCAR (XCDR (spec));
       if (!NILP (it->font_height))
        {
          struct face *face = FACE_FROM_ID (it->f, it->face_id);
@@ -3474,7 +3613,6 @@ handle_single_display_prop (it, prop, object, position,
            {
              /* Evaluate IT->font_height with `height' bound to the
                 current specified height to get the new height.  */
-             Lisp_Object value;
              int count = SPECPDL_INDEX ();
 
              specbind (Qheight, face->lface[LFACE_HEIGHT_INDEX]);
@@ -3488,29 +3626,35 @@ handle_single_display_prop (it, prop, object, position,
          if (new_height > 0)
            it->face_id = face_with_height (it->f, it->face_id, new_height);
        }
+
+      return 0;
     }
-  else if (CONSP (prop)
-          && EQ (XCAR (prop), Qspace_width)
-          && CONSP (XCDR (prop)))
+
+  /* Handle `(space_width WIDTH)'.  */
+  if (CONSP (spec)
+      && EQ (XCAR (spec), Qspace_width)
+      && CONSP (XCDR (spec)))
     {
-      /* `(space_width WIDTH)'.  */
       if (FRAME_TERMCAP_P (it->f) || FRAME_MSDOS_P (it->f))
        return 0;
 
-      value = XCAR (XCDR (prop));
+      value = XCAR (XCDR (spec));
       if (NUMBERP (value) && XFLOATINT (value) > 0)
        it->space_width = value;
+
+      return 0;
     }
-  else if (CONSP (prop)
-          && EQ (XCAR (prop), Qslice))
+
+  /* Handle `(slice X Y WIDTH HEIGHT)'.  */
+  if (CONSP (spec)
+      && EQ (XCAR (spec), Qslice))
     {
-      /* `(slice X Y WIDTH HEIGHT)'.  */
       Lisp_Object tem;
 
       if (FRAME_TERMCAP_P (it->f) || FRAME_MSDOS_P (it->f))
        return 0;
 
-      if (tem = XCDR (prop), CONSP (tem))
+      if (tem = XCDR (spec), CONSP (tem))
        {
          it->slice.x = XCAR (tem);
          if (tem = XCDR (tem), CONSP (tem))
@@ -3524,17 +3668,20 @@ handle_single_display_prop (it, prop, object, position,
                }
            }
        }
+
+      return 0;
     }
-  else if (CONSP (prop)
-          && EQ (XCAR (prop), Qraise)
-          && CONSP (XCDR (prop)))
+
+  /* Handle `(raise FACTOR)'.  */
+  if (CONSP (spec)
+      && EQ (XCAR (spec), Qraise)
+      && CONSP (XCDR (spec)))
     {
-      /* `(raise FACTOR)'.  */
       if (FRAME_TERMCAP_P (it->f) || FRAME_MSDOS_P (it->f))
        return 0;
 
 #ifdef HAVE_WINDOW_SYSTEM
-      value = XCAR (XCDR (prop));
+      value = XCAR (XCDR (spec));
       if (NUMBERP (value))
        {
          struct face *face = FACE_FROM_ID (it->f, it->face_id);
@@ -3542,185 +3689,194 @@ handle_single_display_prop (it, prop, object, position,
                           * (FONT_HEIGHT (face->font)));
        }
 #endif /* HAVE_WINDOW_SYSTEM */
+
+      return 0;
     }
-  else if (!it->string_from_display_prop_p)
-    {
-      /* `((margin left-margin) VALUE)' or `((margin right-margin)
-        VALUE) or `((margin nil) VALUE)' or VALUE.  */
-      Lisp_Object location, value;
-      struct text_pos start_pos;
-      int valid_p;
 
-      /* Characters having this form of property are not displayed, so
-         we have to find the end of the property.  */
-      start_pos = *position;
-      *position = display_prop_end (it, object, start_pos);
-      value = Qnil;
+  /* Don't handle the other kinds of display specifications
+     inside a string that we got from a `display' property.  */
+  if (it->string_from_display_prop_p)
+    return 0;
 
-      /* Let's stop at the new position and assume that all
-        text properties change there.  */
-      it->stop_charpos = position->charpos;
+  /* Characters having this form of property are not displayed, so
+     we have to find the end of the property.  */
+  start_pos = *position;
+  *position = display_prop_end (it, object, start_pos);
+  value = Qnil;
 
-      if (CONSP (prop)
-         && (EQ (XCAR (prop), Qleft_fringe)
-             || EQ (XCAR (prop), Qright_fringe))
-         && CONSP (XCDR (prop)))
-       {
-         unsigned face_id = DEFAULT_FACE_ID;
+  /* Stop the scan at that end position--we assume that all
+     text properties change there.  */
+  it->stop_charpos = position->charpos;
 
-         /* Save current settings of IT so that we can restore them
-            when we are finished with the glyph property value.  */
+  /* Handle `(left-fringe BITMAP [FACE])'
+     and `(right-fringe BITMAP [FACE])'.  */
+  if (CONSP (spec)
+      && (EQ (XCAR (spec), Qleft_fringe)
+         || EQ (XCAR (spec), Qright_fringe))
+      && CONSP (XCDR (spec)))
+    {
+      int face_id = DEFAULT_FACE_ID;
+      int fringe_bitmap;
 
-         /* `(left-fringe BITMAP FACE)'.  */
-         if (FRAME_TERMCAP_P (it->f) || FRAME_MSDOS_P (it->f))
-           return 0;
+      if (FRAME_TERMCAP_P (it->f) || FRAME_MSDOS_P (it->f))
+       /* If we return here, POSITION has been advanced
+          across the text with this property.  */
+       return 0;
 
 #ifdef HAVE_WINDOW_SYSTEM
-         value = XCAR (XCDR (prop));
-         if (!NUMBERP (value)
-             || !valid_fringe_bitmap_id_p (XINT (value)))
-           return 0;
-
-         if (CONSP (XCDR (XCDR (prop))))
-           {
-             Lisp_Object face_name = XCAR (XCDR (XCDR (prop)));
+      value = XCAR (XCDR (spec));
+      if (!SYMBOLP (value)
+         || !(fringe_bitmap = lookup_fringe_bitmap (value)))
+       /* If we return here, POSITION has been advanced
+          across the text with this property.  */
+       return 0;
 
-             face_id = lookup_named_face (it->f, face_name, 'A');
-             if (face_id < 0)
-               return 0;
-           }
+      if (CONSP (XCDR (XCDR (spec))))
+       {
+         Lisp_Object face_name = XCAR (XCDR (XCDR (spec)));
+         int face_id2 = lookup_named_face (it->f, face_name, 'A', 0);
+         if (face_id2 >= 0)
+           face_id = face_id2;
+       }
 
-         push_it (it);
+      /* Save current settings of IT so that we can restore them
+        when we are finished with the glyph property value.  */
 
-         it->area = TEXT_AREA;
-         it->what = IT_IMAGE;
-         it->image_id = -1; /* no image */
-         it->position = start_pos;
-         it->object = NILP (object) ? it->w->buffer : object;
-         it->method = next_element_from_image;
-         it->face_id = face_id;
+      push_it (it);
 
-         /* Say that we haven't consumed the characters with
-            `display' property yet.  The call to pop_it in
-            set_iterator_to_next will clean this up.  */
-         *position = start_pos;
+      it->area = TEXT_AREA;
+      it->what = IT_IMAGE;
+      it->image_id = -1; /* no image */
+      it->position = start_pos;
+      it->object = NILP (object) ? it->w->buffer : object;
+      it->method = GET_FROM_IMAGE;
+      it->face_id = face_id;
 
-         if (EQ (XCAR (prop), Qleft_fringe))
-           {
-             it->left_user_fringe_bitmap = XINT (value);
-             it->left_user_fringe_face_id = face_id;
-           }
-         else
-           {
-             it->right_user_fringe_bitmap = XINT (value);
-             it->right_user_fringe_face_id = face_id;
-           }
-#endif /* HAVE_WINDOW_SYSTEM */
-         return 1;
-       }
+      /* Say that we haven't consumed the characters with
+        `display' property yet.  The call to pop_it in
+        set_iterator_to_next will clean this up.  */
+      *position = start_pos;
 
-      location = Qunbound;
-      if (CONSP (prop) && CONSP (XCAR (prop)))
+      if (EQ (XCAR (spec), Qleft_fringe))
        {
-         Lisp_Object tem;
-
-         value = XCDR (prop);
-         if (CONSP (value))
-           value = XCAR (value);
-
-         tem = XCAR (prop);
-         if (EQ (XCAR (tem), Qmargin)
-             && (tem = XCDR (tem),
-                 tem = CONSP (tem) ? XCAR (tem) : Qnil,
-                 (NILP (tem)
-                  || EQ (tem, Qleft_margin)
-                  || EQ (tem, Qright_margin))))
-           location = tem;
+         it->left_user_fringe_bitmap = fringe_bitmap;
+         it->left_user_fringe_face_id = face_id;
        }
-
-      if (EQ (location, Qunbound))
+      else
        {
-         location = Qnil;
-         value = prop;
+         it->right_user_fringe_bitmap = fringe_bitmap;
+         it->right_user_fringe_face_id = face_id;
        }
+#endif /* HAVE_WINDOW_SYSTEM */
+      return 1;
+    }
 
-      valid_p = (STRINGP (value)
-#ifdef HAVE_WINDOW_SYSTEM
-                || (!FRAME_TERMCAP_P (it->f) && valid_image_p (value))
-#endif /* not HAVE_WINDOW_SYSTEM */
-                || (CONSP (value) && EQ (XCAR (value), Qspace)));
+  /* Prepare to handle `((margin left-margin) ...)',
+     `((margin right-margin) ...)' and `((margin nil) ...)'
+     prefixes for display specifications.  */
+  location = Qunbound;
+  if (CONSP (spec) && CONSP (XCAR (spec)))
+    {
+      Lisp_Object tem;
 
-      if ((EQ (location, Qleft_margin)
-          || EQ (location, Qright_margin)
-          || NILP (location))
-         && valid_p
-         && !display_replaced_before_p)
-       {
-         replaces_text_display_p = 1;
+      value = XCDR (spec);
+      if (CONSP (value))
+       value = XCAR (value);
 
-         /* Save current settings of IT so that we can restore them
-            when we are finished with the glyph property value.  */
-         push_it (it);
+      tem = XCAR (spec);
+      if (EQ (XCAR (tem), Qmargin)
+         && (tem = XCDR (tem),
+             tem = CONSP (tem) ? XCAR (tem) : Qnil,
+             (NILP (tem)
+              || EQ (tem, Qleft_margin)
+              || EQ (tem, Qright_margin))))
+       location = tem;
+    }
 
-         if (NILP (location))
-           it->area = TEXT_AREA;
-         else if (EQ (location, Qleft_margin))
-           it->area = LEFT_MARGIN_AREA;
-         else
-           it->area = RIGHT_MARGIN_AREA;
+  if (EQ (location, Qunbound))
+    {
+      location = Qnil;
+      value = spec;
+    }
 
-         if (STRINGP (value))
-           {
-             it->string = value;
-             it->multibyte_p = STRING_MULTIBYTE (it->string);
-             it->current.overlay_string_index = -1;
-             IT_STRING_CHARPOS (*it) = IT_STRING_BYTEPOS (*it) = 0;
-             it->end_charpos = it->string_nchars = SCHARS (it->string);
-             it->method = next_element_from_string;
-             it->stop_charpos = 0;
-             it->string_from_display_prop_p = 1;
-             /* Say that we haven't consumed the characters with
-                `display' property yet.  The call to pop_it in
-                set_iterator_to_next will clean this up.  */
-             *position = start_pos;
-           }
-         else if (CONSP (value) && EQ (XCAR (value), Qspace))
-           {
-             it->method = next_element_from_stretch;
-             it->object = value;
-             it->current.pos = it->position = start_pos;
-           }
+  /* After this point, VALUE is the property after any
+     margin prefix has been stripped.  It must be a string,
+     an image specification, or `(space ...)'.
+
+     LOCATION specifies where to display: `left-margin',
+     `right-margin' or nil.  */
+
+  valid_p = (STRINGP (value)
 #ifdef HAVE_WINDOW_SYSTEM
-         else
-           {
-             it->what = IT_IMAGE;
-             it->image_id = lookup_image (it->f, value);
-             it->position = start_pos;
-             it->object = NILP (object) ? it->w->buffer : object;
-             it->method = next_element_from_image;
-
-             /* Say that we haven't consumed the characters with
-                `display' property yet.  The call to pop_it in
-                set_iterator_to_next will clean this up.  */
-             *position = start_pos;
-           }
-#endif /* HAVE_WINDOW_SYSTEM */
+            || (!FRAME_TERMCAP_P (it->f) && valid_image_p (value))
+#endif /* not HAVE_WINDOW_SYSTEM */
+            || (CONSP (value) && EQ (XCAR (value), Qspace)));
+
+  if (valid_p && !display_replaced_before_p)
+    {
+      /* Save current settings of IT so that we can restore them
+        when we are finished with the glyph property value.  */
+      push_it (it);
+
+      if (NILP (location))
+       it->area = TEXT_AREA;
+      else if (EQ (location, Qleft_margin))
+       it->area = LEFT_MARGIN_AREA;
+      else
+       it->area = RIGHT_MARGIN_AREA;
+
+      if (STRINGP (value))
+       {
+         it->string = value;
+         it->multibyte_p = STRING_MULTIBYTE (it->string);
+         it->current.overlay_string_index = -1;
+         IT_STRING_CHARPOS (*it) = IT_STRING_BYTEPOS (*it) = 0;
+         it->end_charpos = it->string_nchars = SCHARS (it->string);
+         it->method = GET_FROM_STRING;
+         it->stop_charpos = 0;
+         it->string_from_display_prop_p = 1;
+         /* Say that we haven't consumed the characters with
+            `display' property yet.  The call to pop_it in
+            set_iterator_to_next will clean this up.  */
+         *position = start_pos;
+       }
+      else if (CONSP (value) && EQ (XCAR (value), Qspace))
+       {
+         it->method = GET_FROM_STRETCH;
+         it->object = value;
+         it->current.pos = it->position = start_pos;
        }
+#ifdef HAVE_WINDOW_SYSTEM
       else
-       /* Invalid property or property not supported.  Restore
-          the position to what it was before.  */
-       *position = start_pos;
+       {
+         it->what = IT_IMAGE;
+         it->image_id = lookup_image (it->f, value);
+         it->position = start_pos;
+         it->object = NILP (object) ? it->w->buffer : object;
+         it->method = GET_FROM_IMAGE;
+
+         /* Say that we haven't consumed the characters with
+            `display' property yet.  The call to pop_it in
+            set_iterator_to_next will clean this up.  */
+         *position = start_pos;
+       }
+#endif /* HAVE_WINDOW_SYSTEM */
+
+      return 1;
     }
 
-  return replaces_text_display_p;
+  /* Invalid property or property not supported.  Restore
+     POSITION to what it was before.  */
+  *position = start_pos;
+  return 0;
 }
 
 
-/* Check if PROP is a display sub-property value whose text should be
+/* Check if SPEC is a display specification value whose text should be
    treated as intangible.  */
 
 static int
-single_display_prop_intangible_p (prop)
+single_display_spec_intangible_p (prop)
      Lisp_Object prop;
 {
   /* Skip over `when FORM'.  */
@@ -3773,7 +3929,7 @@ display_prop_intangible_p (prop)
       /* A list of sub-properties.  */
       while (CONSP (prop))
        {
-         if (single_display_prop_intangible_p (XCAR (prop)))
+         if (single_display_spec_intangible_p (XCAR (prop)))
            return 1;
          prop = XCDR (prop);
        }
@@ -3783,11 +3939,11 @@ display_prop_intangible_p (prop)
       /* A vector of sub-properties.  */
       int i;
       for (i = 0; i < ASIZE (prop); ++i)
-       if (single_display_prop_intangible_p (AREF (prop, i)))
+       if (single_display_spec_intangible_p (AREF (prop, i)))
          return 1;
     }
   else
-    return single_display_prop_intangible_p (prop);
+    return single_display_spec_intangible_p (prop);
 
   return 0;
 }
@@ -3796,7 +3952,7 @@ display_prop_intangible_p (prop)
 /* Return 1 if PROP is a display sub-property value containing STRING.  */
 
 static int
-single_display_prop_string_p (prop, string)
+single_display_spec_string_p (prop, string)
      Lisp_Object prop, string;
 {
   if (EQ (string, prop))
@@ -3841,7 +3997,7 @@ display_prop_string_p (prop, string)
       /* A list of sub-properties.  */
       while (CONSP (prop))
        {
-         if (single_display_prop_string_p (XCAR (prop), string))
+         if (single_display_spec_string_p (XCAR (prop), string))
            return 1;
          prop = XCDR (prop);
        }
@@ -3851,11 +4007,11 @@ display_prop_string_p (prop, string)
       /* A vector of sub-properties.  */
       int i;
       for (i = 0; i < ASIZE (prop); ++i)
-       if (single_display_prop_string_p (AREF (prop, i), string))
+       if (single_display_spec_string_p (AREF (prop, i), string))
          return 1;
     }
   else
-    return single_display_prop_string_p (prop, string);
+    return single_display_spec_string_p (prop, string);
 
   return 0;
 }
@@ -3953,7 +4109,7 @@ handle_composition_prop (it)
 
       if (id >= 0)
        {
-         it->method = next_element_from_composition;
+         it->method = GET_FROM_COMPOSITION;
          it->cmp_id = id;
          it->cmp_len = COMPOSITION_LENGTH (prop);
          /* For a terminal, draw only the first character of the
@@ -4028,7 +4184,7 @@ next_overlay_string (it)
       it->current.overlay_string_index = -1;
       SET_TEXT_POS (it->current.string_pos, -1, -1);
       it->n_overlay_strings = 0;
-      it->method = next_element_from_buffer;
+      it->method = GET_FROM_BUFFER;
 
       /* If we're at the end of the buffer, record that we have
         processed the overlay strings there already, so that
@@ -4039,7 +4195,7 @@ next_overlay_string (it)
       /* If we have to display `...' for invisible text, set
         the iterator up for that.  */
       if (display_ellipsis_p)
-       setup_for_ellipsis (it);
+       setup_for_ellipsis (it, 0);
     }
   else
     {
@@ -4057,7 +4213,7 @@ next_overlay_string (it)
       it->string = it->overlay_strings[i];
       it->multibyte_p = STRING_MULTIBYTE (it->string);
       SET_TEXT_POS (it->current.string_pos, 0, 0);
-      it->method = next_element_from_string;
+      it->method = GET_FROM_STRING;
       it->stop_charpos = 0;
     }
 
@@ -4322,13 +4478,13 @@ get_overlay_strings (it, charpos)
       xassert (STRINGP (it->string));
       it->end_charpos = SCHARS (it->string);
       it->multibyte_p = STRING_MULTIBYTE (it->string);
-      it->method = next_element_from_string;
+      it->method = GET_FROM_STRING;
     }
   else
     {
       it->string = Qnil;
       it->current.overlay_string_index = -1;
-      it->method = next_element_from_buffer;
+      it->method = GET_FROM_BUFFER;
     }
 
   CHECK_IT (it);
@@ -4528,46 +4684,57 @@ static void
 back_to_previous_visible_line_start (it)
      struct it *it;
 {
-  int visible_p = 0;
-
-  /* Go back one newline if not on BEGV already.  */
-  if (IT_CHARPOS (*it) > BEGV)
-    back_to_previous_line_start (it);
-
-  /* Move over lines that are invisible because of selective display
-     or text properties.  */
-  while (IT_CHARPOS (*it) > BEGV
-        && !visible_p)
+  while (IT_CHARPOS (*it) > BEGV)
     {
-      visible_p = 1;
+      back_to_previous_line_start (it);
+      if (IT_CHARPOS (*it) <= BEGV)
+       break;
 
       /* If selective > 0, then lines indented more than that values
         are invisible.  */
       if (it->selective > 0
          && indented_beyond_p (IT_CHARPOS (*it), IT_BYTEPOS (*it),
                                (double) it->selective)) /* iftc */
-       visible_p = 0;
-      else
-       {
-         Lisp_Object prop;
+       continue;
 
-         prop = Fget_char_property (make_number (IT_CHARPOS (*it)),
+      /* Check the newline before point for invisibility.  */
+      {
+       Lisp_Object prop;
+       prop = Fget_char_property (make_number (IT_CHARPOS (*it) - 1),
                                     Qinvisible, it->window);
-         if (TEXT_PROP_MEANS_INVISIBLE (prop))
-           visible_p = 0;
-       }
+       if (TEXT_PROP_MEANS_INVISIBLE (prop))
+         continue;
+      }
 
-      if (visible_p)
+      /* If newline has a display property that replaces the newline with something
+        else (image or text), find start of overlay or interval and continue search
+        from that point.  */
+      if (IT_CHARPOS (*it) > BEGV)
        {
          struct it it2 = *it;
-
-         if (handle_display_prop (&it2) == HANDLED_RETURN)
-           visible_p = 0;
+         int pos;
+         int beg, end;
+         Lisp_Object val, overlay;
+
+         pos = --IT_CHARPOS (it2);
+         --IT_BYTEPOS (it2);
+         it2.sp = 0;
+         if (handle_display_prop (&it2) == HANDLED_RETURN
+             && !NILP (val = get_char_property_and_overlay
+                       (make_number (pos), Qdisplay, Qnil, &overlay))
+             && (OVERLAYP (overlay)
+                 ? (beg = OVERLAY_POSITION (OVERLAY_START (overlay)))
+                 : get_property_and_range (pos, Qdisplay, &val, &beg, &end, Qnil)))
+           {
+             if (beg < BEGV)
+               beg = BEGV;
+             IT_CHARPOS (*it) = beg;
+             IT_BYTEPOS (*it) = buf_charpos_to_bytepos (current_buffer, beg);
+             continue;
+           }
        }
 
-      /* Back one more newline if the current one is invisible.  */
-      if (!visible_p)
-       back_to_previous_line_start (it);
+      break;
     }
 
   xassert (IT_CHARPOS (*it) >= BEGV);
@@ -4582,7 +4749,7 @@ back_to_previous_visible_line_start (it)
    selective display.  At the end, update IT's overlay information,
    face information etc.  */
 
-static void
+void
 reseat_at_previous_visible_line_start (it)
      struct it *it;
 {
@@ -4699,7 +4866,7 @@ reseat_1 (it, pos, set_stop_p)
   IT_STRING_CHARPOS (*it) = -1;
   IT_STRING_BYTEPOS (*it) = -1;
   it->string = Qnil;
-  it->method = next_element_from_buffer;
+  it->method = GET_FROM_BUFFER;
   /* RMS: I added this to fix a bug in move_it_vertically_backward
      where it->area continued to relate to the starting point
      for the backward motion.  Bug report from
@@ -4765,7 +4932,7 @@ reseat_to_string (it, s, string, charpos, precision, field_width, multibyte)
       it->string = string;
       it->s = NULL;
       it->end_charpos = it->string_nchars = SCHARS (string);
-      it->method = next_element_from_string;
+      it->method = GET_FROM_STRING;
       it->current.string_pos = string_pos (charpos, string);
     }
   else
@@ -4787,7 +4954,7 @@ reseat_to_string (it, s, string, charpos, precision, field_width, multibyte)
          it->end_charpos = it->string_nchars = strlen (s);
        }
 
-      it->method = next_element_from_c_string;
+      it->method = GET_FROM_C_STRING;
     }
 
   /* PRECISION > 0 means don't return more than PRECISION characters
@@ -4818,6 +4985,20 @@ reseat_to_string (it, s, string, charpos, precision, field_width, multibyte)
                              Iteration
  ***********************************************************************/
 
+/* Map enum it_method value to corresponding next_element_from_* function.  */
+
+static int (* get_next_element[NUM_IT_METHODS]) P_ ((struct it *it)) =
+{
+  next_element_from_buffer,
+  next_element_from_display_vector,
+  next_element_from_composition,
+  next_element_from_string,
+  next_element_from_c_string,
+  next_element_from_image,
+  next_element_from_stretch
+};
+
+
 /* Load IT's display element fields with information about the next
    display element from the current position of IT.  Value is zero if
    end of buffer (or C string) is reached.  */
@@ -4830,7 +5011,10 @@ get_next_display_element (it)
      we hit the end of what we iterate over.  Performance note: the
      function pointer `method' used here turns out to be faster than
      using a sequence of if-statements.  */
-  int success_p = (*it->method) (it);
+  int success_p;
+
+ get_next:
+  success_p = (*get_next_element[it->method]) (it);
 
   if (it->what == IT_CHARACTER)
     {
@@ -4862,14 +5046,16 @@ get_next_display_element (it)
                  it->dpvec = v->contents;
                  it->dpend = v->contents + v->size;
                  it->current.dpvec_index = 0;
-                 it->method = next_element_from_display_vector;
-                 success_p = get_next_display_element (it);
+                 it->dpvec_face_id = -1;
+                 it->saved_face_id = it->face_id;
+                 it->method = GET_FROM_DISPLAY_VECTOR;
+                 it->ellipsis_p = 0;
                }
              else
                {
                  set_iterator_to_next (it, 0);
-                 success_p = get_next_display_element (it);
                }
+             goto get_next;
            }
 
          /* Translate control characters into `\003' or `^C' form.
@@ -4887,13 +5073,19 @@ get_next_display_element (it)
             translated to octal form.  */
          else if ((it->c < ' '
                    && (it->area != TEXT_AREA
+                       /* In mode line, treat \n like other crl chars.  */
+                       || (it->c != '\t'
+                           && it->glyph_row && it->glyph_row->mode_line_p)
                        || (it->c != '\n' && it->c != '\t')))
                   || (it->multibyte_p
                       ? ((it->c >= 127
                           && it->len == 1)
-                         || !CHAR_PRINTABLE_P (it->c))
+                         || !CHAR_PRINTABLE_P (it->c)
+                         || (!NILP (Vshow_nonbreak_escape)
+                             && (it->c == 0x8ad || it->c == 0x8a0)))
                       : (it->c >= 127
-                         && it->c == unibyte_char_to_multibyte (it->c))))
+                         && (!unibyte_display_via_language_environment
+                             || it->c == unibyte_char_to_multibyte (it->c)))))
            {
              /* IT->c is a control character which must be displayed
                 either as '\003' or as `^C' where the '\\' and '^'
@@ -4901,56 +5093,88 @@ get_next_display_element (it)
                 IT->ctl_chars with glyphs for what we have to
                 display.  Then, set IT->dpvec to these glyphs.  */
              GLYPH g;
+             int ctl_len;
+             int face_id, lface_id = 0 ;
+             GLYPH escape_glyph;
 
              if (it->c < 128 && it->ctl_arrow_p)
                {
+                 g = '^';           /* default glyph for Control */
                  /* Set IT->ctl_chars[0] to the glyph for `^'.  */
                  if (it->dp
                      && INTEGERP (DISP_CTRL_GLYPH (it->dp))
                      && GLYPH_CHAR_VALID_P (XINT (DISP_CTRL_GLYPH (it->dp))))
-                   g = XINT (DISP_CTRL_GLYPH (it->dp));
+                   {
+                     g = XINT (DISP_CTRL_GLYPH (it->dp));
+                     lface_id = FAST_GLYPH_FACE (g);
+                   }
+                 if (lface_id)
+                   {
+                      g = FAST_GLYPH_CHAR (g);
+                      face_id = merge_faces (it->f, Qt, lface_id,
+                                             it->face_id);
+                   }
                  else
-                   g = FAST_MAKE_GLYPH ('^', 0);
-                 XSETINT (it->ctl_chars[0], g);
+                   {
+                     /* Merge the escape-glyph face into the current face.  */
+                     face_id = merge_faces (it->f, Qescape_glyph, 0,
+                                            it->face_id);
+                   }
 
-                 g = FAST_MAKE_GLYPH (it->c ^ 0100, 0);
+                 XSETINT (it->ctl_chars[0], g);
+                 g = it->c ^ 0100;
                  XSETINT (it->ctl_chars[1], g);
+                 ctl_len = 2;
+                 goto display_control;
+               }
 
-                 /* Set up IT->dpvec and return first character from it.  */
-                 it->dpvec_char_len = it->len;
-                 it->dpvec = it->ctl_chars;
-                 it->dpend = it->dpvec + 2;
-                 it->current.dpvec_index = 0;
-                 it->method = next_element_from_display_vector;
-                 get_next_display_element (it);
+             escape_glyph = '\\';    /* default for Octal display */
+             if (it->dp
+                 && INTEGERP (DISP_ESCAPE_GLYPH (it->dp))
+                 && GLYPH_CHAR_VALID_P (XFASTINT (DISP_ESCAPE_GLYPH (it->dp))))
+               {
+                 escape_glyph = XFASTINT (DISP_ESCAPE_GLYPH (it->dp));
+                 lface_id = FAST_GLYPH_FACE (escape_glyph);
+               }
+             if (lface_id)
+               {
+                 escape_glyph = FAST_GLYPH_CHAR (escape_glyph);
+                 face_id = merge_faces (it->f, Qt, lface_id,
+                                        it->face_id);
                }
              else
                {
-                 unsigned char str[MAX_MULTIBYTE_LENGTH];
-                 int len;
-                 int i;
-                 GLYPH escape_glyph;
+                 /* Merge the escape-glyph face into the current face.  */
+                 face_id = merge_faces (it->f, Qescape_glyph, 0,
+                                        it->face_id);
+               }
 
-                 /* Set IT->ctl_chars[0] to the glyph for `\\'.  */
-                 if (it->dp
-                     && INTEGERP (DISP_ESCAPE_GLYPH (it->dp))
-                     && GLYPH_CHAR_VALID_P (XFASTINT (DISP_ESCAPE_GLYPH (it->dp))))
-                   escape_glyph = XFASTINT (DISP_ESCAPE_GLYPH (it->dp));
-                 else
-                   escape_glyph = FAST_MAKE_GLYPH ('\\', 0);
+             if (it->c == 0x8a0 || it->c == 0x8ad)
+               {
+                 XSETINT (it->ctl_chars[0], escape_glyph);
+                 g = it->c == 0x8ad ? '-' : ' ';
+                 XSETINT (it->ctl_chars[1], g);
+                 ctl_len = 2;
+                 goto display_control;
+               }
 
-                 if (SINGLE_BYTE_CHAR_P (it->c))
-                   str[0] = it->c, len = 1;
-                 else
-                   {
-                     len = CHAR_STRING_NO_SIGNAL (it->c, str);
-                     if (len < 0)
-                       {
-                         /* It's an invalid character, which
-                            shouldn't happen actually, but due to
-                            bugs it may happen.  Let's print the char
-                            as is, there's not much meaningful we can
-                            do with it.  */
+             {
+               unsigned char str[MAX_MULTIBYTE_LENGTH];
+               int len;
+               int i;
+
+               /* Set IT->ctl_chars[0] to the glyph for `\\'.  */
+               if (SINGLE_BYTE_CHAR_P (it->c))
+                 str[0] = it->c, len = 1;
+               else
+                 {
+                   len = CHAR_STRING_NO_SIGNAL (it->c, str);
+                   if (len < 0)
+                     {
+                       /* It's an invalid character, which shouldn't
+                          happen actually, but due to bugs it may
+                          happen.  Let's print the char as is, there's
+                          not much meaningful we can do with it.  */
                          str[0] = it->c;
                          str[1] = it->c >> 8;
                          str[2] = it->c >> 16;
@@ -4959,28 +5183,32 @@ get_next_display_element (it)
                        }
                    }
 
-                 for (i = 0; i < len; i++)
-                   {
-                     XSETINT (it->ctl_chars[i * 4], escape_glyph);
-                     /* Insert three more glyphs into IT->ctl_chars for
-                        the octal display of the character.  */
-                     g = FAST_MAKE_GLYPH (((str[i] >> 6) & 7) + '0', 0);
-                     XSETINT (it->ctl_chars[i * 4 + 1], g);
-                     g = FAST_MAKE_GLYPH (((str[i] >> 3) & 7) + '0', 0);
-                     XSETINT (it->ctl_chars[i * 4 + 2], g);
-                     g = FAST_MAKE_GLYPH ((str[i] & 7) + '0', 0);
-                     XSETINT (it->ctl_chars[i * 4 + 3], g);
-                   }
+               for (i = 0; i < len; i++)
+                 {
+                   XSETINT (it->ctl_chars[i * 4], escape_glyph);
+                   /* Insert three more glyphs into IT->ctl_chars for
+                      the octal display of the character.  */
+                   g = ((str[i] >> 6) & 7) + '0';
+                   XSETINT (it->ctl_chars[i * 4 + 1], g);
+                   g = ((str[i] >> 3) & 7) + '0';
+                   XSETINT (it->ctl_chars[i * 4 + 2], g);
+                   g = (str[i] & 7) + '0';
+                   XSETINT (it->ctl_chars[i * 4 + 3], g);
+                 }
+               ctl_len = len * 4;
+             }
 
-                 /* Set up IT->dpvec and return the first character
-                     from it.  */
-                 it->dpvec_char_len = it->len;
-                 it->dpvec = it->ctl_chars;
-                 it->dpend = it->dpvec + len * 4;
-                 it->current.dpvec_index = 0;
-                 it->method = next_element_from_display_vector;
-                 get_next_display_element (it);
-               }
+           display_control:
+             /* Set up IT->dpvec and return first character from it.  */
+             it->dpvec_char_len = it->len;
+             it->dpvec = it->ctl_chars;
+             it->dpend = it->dpvec + ctl_len;
+             it->current.dpvec_index = 0;
+             it->dpvec_face_id = face_id;
+             it->saved_face_id = it->face_id;
+             it->method = GET_FROM_DISPLAY_VECTOR;
+             it->ellipsis_p = 0;
+             goto get_next;
            }
        }
 
@@ -5040,8 +5268,9 @@ set_iterator_to_next (it, reseat_p)
      moving the iterator to a new position might set them.  */
   it->start_of_box_run_p = it->end_of_box_run_p = 0;
 
-  if (it->method == next_element_from_buffer)
+  switch (it->method)
     {
+    case GET_FROM_BUFFER:
       /* The current display element of IT is a character from
         current_buffer.  Advance in the buffer, and maybe skip over
         invisible lines that are so because of selective display.  */
@@ -5054,32 +5283,32 @@ set_iterator_to_next (it, reseat_p)
          IT_CHARPOS (*it) += 1;
          xassert (IT_BYTEPOS (*it) == CHAR_TO_BYTE (IT_CHARPOS (*it)));
        }
-    }
-  else if (it->method == next_element_from_composition)
-    {
-      xassert (it->cmp_id >= 0 && it ->cmp_id < n_compositions);
+      break;
+
+    case GET_FROM_COMPOSITION:
+      xassert (it->cmp_id >= 0 && it->cmp_id < n_compositions);
       if (STRINGP (it->string))
        {
          IT_STRING_BYTEPOS (*it) += it->len;
          IT_STRING_CHARPOS (*it) += it->cmp_len;
-         it->method = next_element_from_string;
+         it->method = GET_FROM_STRING;
          goto consider_string_end;
        }
       else
        {
          IT_BYTEPOS (*it) += it->len;
          IT_CHARPOS (*it) += it->cmp_len;
-         it->method = next_element_from_buffer;
+         it->method = GET_FROM_BUFFER;
        }
-    }
-  else if (it->method == next_element_from_c_string)
-    {
+      break;
+
+    case GET_FROM_C_STRING:
       /* Current display element of IT is from a C string.  */
       IT_BYTEPOS (*it) += it->len;
       IT_CHARPOS (*it) += 1;
-    }
-  else if (it->method == next_element_from_display_vector)
-    {
+      break;
+
+    case GET_FROM_DISPLAY_VECTOR:
       /* Current display element of IT is from a display table entry.
         Advance in the display table definition.  Reset it to null if
         end reached, and continue with characters from buffers/
@@ -5093,11 +5322,11 @@ set_iterator_to_next (it, reseat_p)
       if (it->dpvec + it->current.dpvec_index == it->dpend)
        {
          if (it->s)
-           it->method = next_element_from_c_string;
+           it->method = GET_FROM_C_STRING;
          else if (STRINGP (it->string))
-           it->method = next_element_from_string;
+           it->method = GET_FROM_STRING;
          else
-           it->method = next_element_from_buffer;
+           it->method = GET_FROM_BUFFER;
 
          it->dpvec = NULL;
          it->current.dpvec_index = -1;
@@ -5110,10 +5339,13 @@ set_iterator_to_next (it, reseat_p)
              it->len = it->dpvec_char_len;
              set_iterator_to_next (it, reseat_p);
            }
+
+         /* Recheck faces after display vector */
+         it->stop_charpos = IT_CHARPOS (*it);
        }
-    }
-  else if (it->method == next_element_from_string)
-    {
+      break;
+
+    case GET_FROM_STRING:
       /* Current display element is a character from a Lisp string.  */
       xassert (it->s == NULL && STRINGP (it->string));
       IT_STRING_BYTEPOS (*it) += it->len;
@@ -5138,43 +5370,47 @@ set_iterator_to_next (it, reseat_p)
              && it->sp > 0)
            {
              pop_it (it);
-             if (!STRINGP (it->string))
-               it->method = next_element_from_buffer;
-             else
+             if (STRINGP (it->string))
                goto consider_string_end;
+             it->method = GET_FROM_BUFFER;
            }
        }
-    }
-  else if (it->method == next_element_from_image
-          || it->method == next_element_from_stretch)
-    {
+      break;
+
+    case GET_FROM_IMAGE:
+    case GET_FROM_STRETCH:
       /* The position etc with which we have to proceed are on
         the stack.  The position may be at the end of a string,
          if the `display' property takes up the whole string.  */
+      xassert (it->sp > 0);
       pop_it (it);
       it->image_id = 0;
       if (STRINGP (it->string))
        {
-         it->method = next_element_from_string;
+         it->method = GET_FROM_STRING;
          goto consider_string_end;
        }
-      else
-       it->method = next_element_from_buffer;
+      it->method = GET_FROM_BUFFER;
+      break;
+
+    default:
+      /* There are no other methods defined, so this should be a bug.  */
+      abort ();
     }
-  else
-    /* There are no other methods defined, so this should be a bug.  */
-    abort ();
 
-  xassert (it->method != next_element_from_string
+  xassert (it->method != GET_FROM_STRING
           || (STRINGP (it->string)
               && IT_STRING_CHARPOS (*it) >= 0));
 }
 
-
 /* Load IT's display element fields with information about the next
    display element which comes from a display table entry or from the
    result of translating a control character to one of the forms `^C'
-   or `\003'.  IT->dpvec holds the glyphs to return as characters.  */
+   or `\003'.
+
+   IT->dpvec holds the glyphs to return as characters.
+   IT->saved_face_id holds the face id before the display vector--
+   it is restored into IT->face_idin set_iterator_to_next.  */
 
 static int
 next_element_from_display_vector (it)
@@ -5183,14 +5419,9 @@ next_element_from_display_vector (it)
   /* Precondition.  */
   xassert (it->dpvec && it->current.dpvec_index >= 0);
 
-  /* Remember the current face id in case glyphs specify faces.
-     IT's face is restored in set_iterator_to_next.  */
-  it->saved_face_id = it->face_id;
-
   if (INTEGERP (*it->dpvec)
       && GLYPH_CHAR_VALID_P (XFASTINT (*it->dpvec)))
     {
-      int lface_id;
       GLYPH g;
 
       g = XFASTINT (it->dpvec[it->current.dpvec_index]);
@@ -5200,13 +5431,14 @@ next_element_from_display_vector (it)
       /* The entry may contain a face id to use.  Such a face id is
         the id of a Lisp face, not a realized face.  A face id of
         zero means no face is specified.  */
-      lface_id = FAST_GLYPH_FACE (g);
-      if (lface_id)
+      if (it->dpvec_face_id >= 0)
+       it->face_id = it->dpvec_face_id;
+      else
        {
-         /* The function returns -1 if lface_id is invalid.  */
-         int face_id = ascii_face_of_lisp_face (it->f, lface_id);
-         if (face_id >= 0)
-           it->face_id = face_id;
+         int lface_id = FAST_GLYPH_FACE (g);
+         if (lface_id > 0)
+           it->face_id = merge_faces (it->f, Qt, lface_id,
+                                      it->saved_face_id);
        }
     }
   else
@@ -5370,28 +5602,7 @@ next_element_from_ellipsis (it)
      struct it *it;
 {
   if (it->selective_display_ellipsis_p)
-    {
-      if (it->dp && VECTORP (DISP_INVIS_VECTOR (it->dp)))
-       {
-         /* Use the display table definition for `...'.  Invalid glyphs
-            will be handled by the method returning elements from dpvec.  */
-         struct Lisp_Vector *v = XVECTOR (DISP_INVIS_VECTOR (it->dp));
-         it->dpvec_char_len = it->len;
-         it->dpvec = v->contents;
-         it->dpend = v->contents + v->size;
-         it->current.dpvec_index = 0;
-         it->method = next_element_from_display_vector;
-       }
-      else
-       {
-         /* Use default `...' which is stored in default_invis_vector.  */
-         it->dpvec_char_len = it->len;
-         it->dpvec = default_invis_vector;
-         it->dpend = default_invis_vector + 3;
-         it->current.dpvec_index = 0;
-         it->method = next_element_from_display_vector;
-       }
-    }
+    setup_for_ellipsis (it, it->len);
   else
     {
       /* The face at the current position may be different from the
@@ -5399,7 +5610,7 @@ next_element_from_ellipsis (it)
         was in IT->saved_face_id, and signal that it's there by
         setting face_before_selective_p.  */
       it->saved_face_id = it->face_id;
-      it->method = next_element_from_buffer;
+      it->method = GET_FROM_BUFFER;
       reseat_at_next_visible_line_start (it, 1);
       it->face_before_selective_p = 1;
     }
@@ -5640,18 +5851,26 @@ move_it_in_display_line_to (it, to_charpos, to_x, op)
   saved_glyph_row = it->glyph_row;
   it->glyph_row = NULL;
 
-#define BUFFER_POS_REACHED_P()                     \
-  ((op & MOVE_TO_POS) != 0                         \
-   && BUFFERP (it->object)                         \
-   && IT_CHARPOS (*it) >= to_charpos)
+#define BUFFER_POS_REACHED_P()                                 \
+  ((op & MOVE_TO_POS) != 0                                     \
+   && BUFFERP (it->object)                                     \
+   && IT_CHARPOS (*it) >= to_charpos                           \
+   && (it->method == GET_FROM_BUFFER                           \
+       || (it->method == GET_FROM_DISPLAY_VECTOR               \
+          && it->dpvec + it->current.dpvec_index + 1 >= it->dpend)))
+
 
   while (1)
     {
       int x, i, ascent = 0, descent = 0;
 
-      /* Stop when ZV or TO_CHARPOS reached.  */
+      /* Stop when ZV reached.
+         We used to stop here when TO_CHARPOS reached as well, but that is
+         too soon if this glyph does not fit on this line.  So we handle it
+         explicitly below.  */
       if (!get_next_display_element (it)
-         || BUFFER_POS_REACHED_P ())
+         || (it->truncate_lines_p
+             && BUFFER_POS_REACHED_P ()))
        {
          result = MOVE_POS_MATCH_OR_ZV;
          break;
@@ -5711,6 +5930,8 @@ move_it_in_display_line_to (it, to_charpos, to_x, op)
              /* We want to leave anything reaching TO_X to the caller.  */
              if ((op & MOVE_TO_X) && new_x > to_x)
                {
+                 if (BUFFER_POS_REACHED_P ())
+                   goto buffer_pos_reached;
                  it->current_x = x;
                  result = MOVE_X_REACHED;
                  break;
@@ -5772,6 +5993,8 @@ move_it_in_display_line_to (it, to_charpos, to_x, op)
                  result = MOVE_LINE_CONTINUED;
                  break;
                }
+             else if (BUFFER_POS_REACHED_P ())
+               goto buffer_pos_reached;
              else if (new_x > it->first_visible_x)
                {
                  /* Glyph is visible.  Increment number of glyphs that
@@ -5788,6 +6011,15 @@ move_it_in_display_line_to (it, to_charpos, to_x, op)
          if (result != MOVE_UNDEFINED)
            break;
        }
+      else if (BUFFER_POS_REACHED_P ())
+       {
+       buffer_pos_reached:
+         it->current_x = x;
+         it->max_ascent = ascent;
+         it->max_descent = descent;
+         result = MOVE_POS_MATCH_OR_ZV;
+         break;
+       }
       else if ((op & MOVE_TO_X) && it->current_x >= to_x)
        {
          /* Stop when TO_X specified and reached.  This check is
@@ -6042,10 +6274,13 @@ move_it_vertically_backward (it, dy)
 {
   int nlines, h;
   struct it it2, it3;
-  int start_pos = IT_CHARPOS (*it);
+  int start_pos;
 
+ move_further_back:
   xassert (dy >= 0);
 
+  start_pos = IT_CHARPOS (*it);
+
   /* Estimate how many newlines we must move back.  */
   nlines = max (1, dy / FRAME_LINE_HEIGHT (it->f));
 
@@ -6093,7 +6328,11 @@ move_it_vertically_backward (it, dy)
         value of nlines is > 0 if continuation lines were involved.  */
       if (nlines > 0)
        move_it_by_lines (it, nlines, 1);
+#if 0
+      /* I think this assert is bogus if buffer contains
+        invisible text or images.  KFS.  */
       xassert (IT_CHARPOS (*it) <= start_pos);
+#endif
     }
   else
     {
@@ -6111,13 +6350,14 @@ move_it_vertically_backward (it, dy)
             a line height of 13 pixels each, recentering with point
             on the bottom line will try to move -39/2 = 19 pixels
             backward.  Try to avoid moving into the first line.  */
-         && it->current_y - target_y > line_height / 3 * 2
+         && (it->current_y - target_y
+             > min (window_box_height (it->w), line_height * 2 / 3))
          && IT_CHARPOS (*it) > BEGV)
        {
          TRACE_MOVE ((stderr, "  not far enough -> move_vert %d\n",
                       target_y - it->current_y));
-         move_it_vertically (it, target_y - it->current_y);
-         xassert (IT_CHARPOS (*it) >= BEGV);
+         dy = it->current_y - target_y;
+         goto move_further_back;
        }
       else if (target_y >= it->current_y + line_height
               && IT_CHARPOS (*it) < ZV)
@@ -6141,7 +6381,11 @@ move_it_vertically_backward (it, dy)
              while (target_y >= line_bottom_y (it) && IT_CHARPOS (*it) < ZV);
            }
 
+#if 0
+         /* I think this assert is bogus if buffer contains
+            invisible text or images.  KFS.  */
          xassert (IT_CHARPOS (*it) >= BEGV);
+#endif
        }
     }
 }
@@ -6158,7 +6402,7 @@ move_it_vertically (it, dy)
 {
   if (dy <= 0)
     move_it_vertically_backward (it, -dy);
-  else if (dy > 0)
+  else
     {
       TRACE_MOVE ((stderr, "move_it_v: from %d, %d\n", IT_CHARPOS (*it), dy));
       move_it_to (it, ZV, -1, it->current_y + dy, -1,
@@ -6255,6 +6499,8 @@ move_it_by_lines (it, dvpos, need_y_p)
       /* DVPOS == 0 means move to the start of the screen line.  */
       move_it_vertically_backward (it, 0);
       xassert (it->current_x == 0 && it->hpos == 0);
+      /* Let next call to line_bottom_y calculate real line height */
+      last_height = 0;
     }
   else if (dvpos > 0)
     move_it_to (it, -1, -1, -1, it->vpos + dvpos, MOVE_TO_VPOS);
@@ -6283,11 +6529,15 @@ move_it_by_lines (it, dvpos, need_y_p)
       it->current_y -= it2.current_y;
       it->current_x = it->hpos = 0;
 
-      /* If we moved too far, move IT some lines forward.  */
+      /* If we moved too far back, move IT some lines forward.  */
       if (it2.vpos > -dvpos)
        {
          int delta = it2.vpos + dvpos;
+         it2 = *it;
          move_it_to (it, -1, -1, -1, it->vpos + delta, MOVE_TO_VPOS);
+         /* Move back again if we got too far ahead.  */
+         if (IT_CHARPOS (*it) >= start_charpos)
+           *it = it2;
        }
     }
 }
@@ -6298,7 +6548,7 @@ int
 in_display_vector_p (it)
      struct it *it;
 {
-  return (it->method == next_element_from_display_vector
+  return (it->method == GET_FROM_DISPLAY_VECTOR
          && it->current.dpvec_index > 0
          && it->dpvec + it->current.dpvec_index != it->dpend);
 }
@@ -6343,7 +6593,7 @@ add_to_log (format, arg1, arg2)
   bcopy (SDATA (msg), buffer, len);
 
   message_dolog (buffer, len - 1, 1, 0);
-  SAFE_FREE (len);
+  SAFE_FREE ();
 
   UNGCPRO;
 }
@@ -6567,7 +6817,7 @@ message_log_check_duplicate (prev_bol, prev_bol_byte, this_bol, this_bol_byte)
     }
   return 0;
 }
-
+\f
 
 /* Display an echo area message M with a specified length of NBYTES
    bytes.  The string may include null characters.  If M is 0, clear
@@ -6666,6 +6916,7 @@ message3 (m, nbytes, multibyte)
   struct gcpro gcpro1;
 
   GCPRO1 (m);
+  clear_message (1,1);
 
   /* First flush out any partial line written with print.  */
   message_log_maybe_newline ();
@@ -7398,7 +7649,7 @@ resize_mini_window (w, exact_p)
            height = it.current_y + last_height;
          else
            height = it.current_y + it.max_ascent + it.max_descent;
-         height -= it.extra_line_spacing;
+         height -= min (it.extra_line_spacing, it.max_extra_line_spacing);
          height = (height + unit - 1) / unit;
        }
 
@@ -7879,6 +8130,8 @@ echo_area_display (update_frame_p)
 
   /* Last displayed message is now the current message.  */
   echo_area_buffer[1] = echo_area_buffer[0];
+  /* Inform read_char that we're not echoing.  */
+  echo_message_buffer = Qnil;
 
   /* Prevent redisplay optimization in redisplay_internal by resetting
      this_line_start_pos.  This is done because the mini-buffer now
@@ -7954,7 +8207,7 @@ store_frame_title (str, field_width, precision)
 
   /* Copy at most PRECISION chars from STR.  */
   nbytes = strlen (str);
-  n+= c_string_width (str, nbytes, precision, &dummy, &nbytes);
+  n += c_string_width (str, nbytes, precision, &dummy, &nbytes);
   while (nbytes--)
     store_frame_title_char (*str++);
 
@@ -8392,7 +8645,8 @@ update_tool_bar (f, save_match_data)
        {
          struct buffer *prev = current_buffer;
          int count = SPECPDL_INDEX ();
-         Lisp_Object old_tool_bar;
+         Lisp_Object new_tool_bar;
+          int new_n_tool_bar;
          struct gcpro gcpro1;
 
          /* Set current_buffer to the buffer of the selected
@@ -8411,18 +8665,24 @@ update_tool_bar (f, save_match_data)
              specbind (Qoverriding_local_map, Qnil);
            }
 
-         old_tool_bar = f->tool_bar_items;
-         GCPRO1 (old_tool_bar);
+         GCPRO1 (new_tool_bar);
 
          /* Build desired tool-bar items from keymaps.  */
-          BLOCK_INPUT;
-         f->tool_bar_items
-           = tool_bar_items (f->tool_bar_items, &f->n_tool_bar_items);
-          UNBLOCK_INPUT;
+          new_tool_bar = tool_bar_items (Fcopy_sequence (f->tool_bar_items),
+                                         &new_n_tool_bar);
 
          /* Redisplay the tool-bar if we changed it.  */
-         if (! NILP (Fequal (old_tool_bar, f->tool_bar_items)))
-           w->update_mode_line = Qt;
+         if (NILP (Fequal (new_tool_bar, f->tool_bar_items)))
+            {
+              /* Redisplay that happens asynchronously due to an expose event
+                 may access f->tool_bar_items.  Make sure we update both
+                 variables within BLOCK_INPUT so no such event interrupts.  */
+              BLOCK_INPUT;
+              f->tool_bar_items = new_tool_bar;
+              f->n_tool_bar_items = new_n_tool_bar;
+              w->update_mode_line = Qt;
+              UNBLOCK_INPUT;
+            }
 
          UNGCPRO;
 
@@ -8669,6 +8929,7 @@ display_tool_bar_line (it)
     {
       row->height = row->phys_height = it->last_visible_y - row->y;
       row->ascent = row->phys_ascent = 0;
+      row->extra_line_spacing = 0;
     }
 
   row->full_width_p = 1;
@@ -9501,11 +9762,13 @@ update_overlay_arrows (up_to_date)
 }
 
 
-/* Return overlay arrow string at row, or nil.  */
+/* Return overlay arrow string to display at row.
+   Return t if display as bitmap in left fringe.
+   Return nil if no overlay arrow.  */
 
 static Lisp_Object
-overlay_arrow_at_row (f, row, pbitmap)
-     struct frame *f;
+overlay_arrow_at_row (it, row, pbitmap)
+     struct it *it;
      struct glyph_row *row;
      int *pbitmap;
 {
@@ -9528,9 +9791,10 @@ overlay_arrow_at_row (f, row, pbitmap)
          && (MATRIX_ROW_START_CHARPOS (row) == marker_position (val)))
        {
          val = overlay_arrow_string_or_property (var, pbitmap);
-         if (FRAME_WINDOW_P (f))
+         if (FRAME_WINDOW_P (it->f)
+             && WINDOW_LEFT_FRINGE_WIDTH (it->w) > 0)
            return Qt;
-         else if (STRINGP (val))
+         if (STRINGP (val))
            return val;
          break;
        }
@@ -10108,7 +10372,9 @@ redisplay_internal (preserve_echo_area)
   CHARPOS (this_line_start_pos) = 0;
   consider_all_windows_p |= buffer_shared > 1;
   ++clear_face_cache_count;
-
+#ifdef HAVE_WINDOW_SYSTEM
+  ++clear_image_cache_count;
+#endif
 
   /* Build desired matrices, and update the display.  If
      consider_all_windows_p is non-zero, do it for all windows on all
@@ -10121,13 +10387,6 @@ redisplay_internal (preserve_echo_area)
       struct frame **updated
        = (struct frame **) alloca (size * sizeof *updated);
 
-      /* Clear the face cache eventually.  */
-      if (clear_face_cache_count > CLEAR_FACE_CACHE_COUNT)
-       {
-         clear_face_cache (0);
-         clear_face_cache_count = 0;
-       }
-
       /* Recompute # windows showing selected buffer.  This will be
         incremented each time such a window is displayed.  */
       buffer_shared = 0;
@@ -10143,12 +10402,6 @@ redisplay_internal (preserve_echo_area)
                   variables.  */
                select_frame_for_redisplay (frame);
 
-#ifdef HAVE_WINDOW_SYSTEM
-             if (clear_face_cache_count % 50 == 0
-                 && FRAME_WINDOW_P (f))
-               clear_image_cache (f, 0);
-#endif /* HAVE_WINDOW_SYSTEM */
-
              /* Mark all the scroll bars to be removed; we'll redeem
                 the ones we want when we redisplay their windows.  */
              if (condemn_scroll_bars_hook)
@@ -10352,6 +10605,29 @@ redisplay_internal (preserve_echo_area)
   if (windows_or_buffers_changed && !pause)
     goto retry;
 
+  /* Clear the face cache eventually.  */
+  if (consider_all_windows_p)
+    {
+      if (clear_face_cache_count > CLEAR_FACE_CACHE_COUNT)
+       {
+         clear_face_cache (0);
+         clear_face_cache_count = 0;
+       }
+#ifdef HAVE_WINDOW_SYSTEM
+      if (clear_image_cache_count > CLEAR_IMAGE_CACHE_COUNT)
+       {
+         Lisp_Object tail, frame;
+         FOR_EACH_FRAME (tail, frame)
+           {
+             struct frame *f = XFRAME (frame);
+             if (FRAME_WINDOW_P (f))
+               clear_image_cache (f, 0);
+           }
+         clear_image_cache_count = 0;
+       }
+#endif /* HAVE_WINDOW_SYSTEM */
+    }
+
  end_of_redisplay:
   unbind_to (count, Qnil);
   RESUME_POLLING;
@@ -10364,7 +10640,7 @@ redisplay_internal (preserve_echo_area)
    This is useful in situations where you need to redisplay but no
    user action has occurred, making it inappropriate for the message
    area to be cleared.  See tracking_off and
-   wait_reading_process_input for examples of these situations.
+   wait_reading_process_output for examples of these situations.
 
    FROM_WHERE is an integer saying from where this function was
    called.  This is useful for debugging.  */
@@ -10385,6 +10661,9 @@ redisplay_preserve_echo_area (from_where)
     }
   else
     redisplay_internal (1);
+
+  if (rif != NULL && rif->flush_display_optional)
+    rif->flush_display_optional (NULL);
 }
 
 
@@ -10630,6 +10909,7 @@ set_cursor_from_row (w, row, matrix, delta, delta_bytes, dy, dvpos)
 {
   struct glyph *glyph = row->glyphs[TEXT_AREA];
   struct glyph *end = glyph + row->used[TEXT_AREA];
+  struct glyph *cursor = NULL;
   /* The first glyph that starts a sequence of glyphs from string.  */
   struct glyph *string_start;
   /* The X coordinate of string_start.  */
@@ -10639,6 +10919,8 @@ set_cursor_from_row (w, row, matrix, delta, delta_bytes, dy, dvpos)
   /* The last known character position before string_start.  */
   int string_before_pos;
   int x = row->x;
+  int cursor_x = x;
+  int cursor_from_overlay_pos = 0;
   int pt_old = PT - delta;
 
   /* Skip over glyphs not having an object at the start of the row.
@@ -10664,6 +10946,12 @@ set_cursor_from_row (w, row, matrix, delta, delta_bytes, dy, dvpos)
          string_start = NULL;
          x += glyph->pixel_width;
          ++glyph;
+         if (cursor_from_overlay_pos
+             && last_pos > cursor_from_overlay_pos)
+           {
+             cursor_from_overlay_pos = 0;
+             cursor = 0;
+           }
        }
       else
        {
@@ -10671,12 +10959,52 @@ set_cursor_from_row (w, row, matrix, delta, delta_bytes, dy, dvpos)
          string_start = glyph;
          string_start_x = x;
          /* Skip all glyphs from string.  */
-         SKIP_GLYPHS (glyph, end, x, STRINGP (glyph->object));
+         do
+           {
+             int pos;
+             if ((cursor == NULL || glyph > cursor)
+                 && !NILP (Fget_char_property (make_number ((glyph)->charpos),
+                                               Qcursor, (glyph)->object))
+                 && (pos = string_buffer_position (w, glyph->object,
+                                                   string_before_pos),
+                     (pos == 0   /* From overlay */
+                      || pos == pt_old)))
+               {
+                 /* Estimate overlay buffer position from the buffer
+                    positions of the glyphs before and after the overlay.
+                    Add 1 to last_pos so that if point corresponds to the
+                    glyph right after the overlay, we still use a 'cursor'
+                    property found in that overlay.  */
+                 cursor_from_overlay_pos = pos == 0 ? last_pos+1 : 0;
+                 cursor = glyph;
+                 cursor_x = x;
+               }
+             x += glyph->pixel_width;
+             ++glyph;
+           }
+         while (glyph < end && STRINGP (glyph->object));
        }
     }
 
-  if (string_start
-      && (glyph == end || !BUFFERP (glyph->object) || last_pos > pt_old))
+  if (cursor != NULL)
+    {
+      glyph = cursor;
+      x = cursor_x;
+    }
+  else if (row->ends_in_ellipsis_p && glyph == end)
+    {
+      /* Scan back over the ellipsis glyphs, decrementing positions.  */
+      while (glyph > row->glyphs[TEXT_AREA]
+            && (glyph - 1)->charpos == last_pos)
+       glyph--, x -= glyph->pixel_width;
+      /* That loop always goes one position too far,
+        including the glyph before the ellipsis.
+        So scan forward over that one.  */
+      x += glyph->pixel_width;
+      glyph++;
+    }
+  else if (string_start
+          && (glyph == end || !BUFFERP (glyph->object) || last_pos > pt_old))
     {
       /* We may have skipped over point because the previous glyphs
         are from string.  As there's no easy way to know the
@@ -10797,7 +11125,7 @@ run_window_scroll_functions (window, startp)
    as if point had gone off the screen.  */
 
 static int
-make_cursor_line_fully_visible (w, force_p)
+cursor_row_fully_visible_p (w, force_p, current_matrix_p)
      struct window *w;
      int force_p;
 {
@@ -10805,16 +11133,19 @@ make_cursor_line_fully_visible (w, force_p)
   struct glyph_row *row;
   int window_height;
 
+  if (!make_cursor_line_fully_visible_p)
+    return 1;
+
   /* It's not always possible to find the cursor, e.g, when a window
      is full of overlay strings.  Don't do anything in that case.  */
   if (w->cursor.vpos < 0)
     return 1;
 
-  matrix = w->desired_matrix;
+  matrix = current_matrix_p ? w->current_matrix : w->desired_matrix;
   row = MATRIX_ROW (matrix, w->cursor.vpos);
 
   /* If the cursor row is not partially visible, there's nothing to do.  */
-  if (!MATRIX_ROW_PARTIALLY_VISIBLE_P (row))
+  if (!MATRIX_ROW_PARTIALLY_VISIBLE_P (w, row))
     return 1;
 
   /* If the row the cursor is in is taller than the window's height,
@@ -10968,7 +11299,7 @@ try_scrolling (window, just_this_one_p, scroll_conservatively,
     {
       start_display (&it, w, scroll_margin_pos);
       if (this_scroll_margin)
-       move_it_vertically (&it, - this_scroll_margin);
+       move_it_vertically_backward (&it, this_scroll_margin);
       if (extra_scroll_margin_lines)
        move_it_by_lines (&it, - extra_scroll_margin_lines, 0);
       scroll_margin_pos = it.current.pos;
@@ -11068,8 +11399,8 @@ try_scrolling (window, just_this_one_p, scroll_conservatively,
          start_display (&it, w, startp);
 
          if (scroll_conservatively)
-           amount_to_scroll =
-             max (dy, FRAME_LINE_HEIGHT (f) * max (scroll_step, temp_scroll_step));
+           amount_to_scroll
+             max (dy, FRAME_LINE_HEIGHT (f) * max (scroll_step, temp_scroll_step));
          else if (scroll_step || temp_scroll_step)
            amount_to_scroll = scroll_max;
          else
@@ -11088,7 +11419,7 @@ try_scrolling (window, just_this_one_p, scroll_conservatively,
          if (amount_to_scroll <= 0)
            return SCROLLING_FAILED;
 
-         move_it_vertically (&it, - amount_to_scroll);
+         move_it_vertically_backward (&it, amount_to_scroll);
          startp = it.current.pos;
        }
     }
@@ -11115,7 +11446,7 @@ try_scrolling (window, just_this_one_p, scroll_conservatively,
 
       /* If cursor ends up on a partially visible line,
         treat that as being off the bottom of the screen.  */
-      if (! make_cursor_line_fully_visible (w, extra_scroll_margin_lines <= 1))
+      if (! cursor_row_fully_visible_p (w, extra_scroll_margin_lines <= 1, 0))
        {
          clear_glyph_matrix (w->desired_matrix);
          ++extra_scroll_margin_lines;
@@ -11348,8 +11679,7 @@ try_cursor_movement (window, startp, scroll_step)
          else if (PT < XFASTINT (w->last_point))
            {
              /* Cursor has to be moved backward.  Note that PT >=
-                CHARPOS (startp) because of the outer
-                if-statement.  */
+                CHARPOS (startp) because of the outer if-statement.  */
              while (!row->mode_line_p
                     && (MATRIX_ROW_START_CHARPOS (row) > PT
                         || (MATRIX_ROW_START_CHARPOS (row) == PT
@@ -11386,6 +11716,12 @@ try_cursor_movement (window, startp, scroll_step)
                  && CHARPOS (startp) != BEGV)
                scroll_p = 1;
            }
+         else
+           {
+             /* Cursor did not move.  So don't scroll even if cursor line
+                is partially visible, as it was so before.  */
+                rc = CURSOR_MOVEMENT_SUCCESS;
+           }
 
          if (PT < MATRIX_ROW_START_CHARPOS (row)
              || PT > MATRIX_ROW_END_CHARPOS (row))
@@ -11393,7 +11729,9 @@ try_cursor_movement (window, startp, scroll_step)
              /* if PT is not in the glyph row, give up.  */
              rc = CURSOR_MOVEMENT_MUST_SCROLL;
            }
-         else if (MATRIX_ROW_PARTIALLY_VISIBLE_P (row))
+         else if (rc != CURSOR_MOVEMENT_SUCCESS
+                  && MATRIX_ROW_PARTIALLY_VISIBLE_P (w, row)
+                  && make_cursor_line_fully_visible_p)
            {
              if (PT == MATRIX_ROW_END_CHARPOS (row)
                  && !row->ends_at_zv_p
@@ -11411,7 +11749,7 @@ try_cursor_movement (window, startp, scroll_step)
              else
                {
                  set_cursor_from_row (w, row, w->current_matrix, 0, 0, 0, 0);
-                 if (!make_cursor_line_fully_visible (w, 0))
+                 if (!cursor_row_fully_visible_p (w, 0, 1))
                    rc = CURSOR_MOVEMENT_MUST_SCROLL;
                  else
                    rc = CURSOR_MOVEMENT_SUCCESS;
@@ -11496,7 +11834,7 @@ redisplay_window (window, just_this_one_p)
   int temp_scroll_step = 0;
   int count = SPECPDL_INDEX ();
   int rc;
-  int centering_position;
+  int centering_position = -1;
   int last_line_misfit = 0;
 
   SET_TEXT_POS (lpoint, PT, PT_BYTE);
@@ -11742,7 +12080,7 @@ redisplay_window (window, just_this_one_p)
          new_vpos = window_box_height (w) / 2;
        }
 
-      if (!make_cursor_line_fully_visible (w, 0))
+      if (!cursor_row_fully_visible_p (w, 0, 0))
        {
          /* Point does appear, but on a line partly visible at end of window.
             Move it back to a fully-visible line.  */
@@ -11861,8 +12199,8 @@ redisplay_window (window, just_this_one_p)
             buffer.  */
          || !NILP (Vwindow_scroll_functions)
          || MINI_WINDOW_P (w)
-         || !(used_current_matrix_p =
-              try_window_reusing_current_matrix (w)))
+         || !(used_current_matrix_p
+              try_window_reusing_current_matrix (w)))
        {
          IF_DEBUG (debug_method_add (w, "1"));
          try_window (window, startp);
@@ -11879,7 +12217,7 @@ redisplay_window (window, just_this_one_p)
            /* Forget any recorded base line for line number display.  */
            w->base_line_number = Qnil;
 
-         if (!make_cursor_line_fully_visible (w, 1))
+         if (!cursor_row_fully_visible_p (w, 1, 0))
            {
              clear_glyph_matrix (w->desired_matrix);
              last_line_misfit = 1;
@@ -11939,10 +12277,8 @@ redisplay_window (window, just_this_one_p)
   /* Finally, just choose place to start which centers point */
 
  recenter:
-  centering_position = window_box_height (w) / 2;
-
- point_at_top:
-  /* Jump here with centering_position already set to 0.  */
+  if (centering_position < 0)
+    centering_position = window_box_height (w) / 2;
 
 #if GLYPH_DEBUG
   debug_method_add (w, "recenter");
@@ -11968,8 +12304,12 @@ redisplay_window (window, just_this_one_p)
   if (it.current_y <= 0)
     {
       init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID);
-      move_it_vertically (&it, 0);
+      move_it_vertically_backward (&it, 0);
+#if 0
+      /* I think this assert is bogus if buffer contains
+        invisible text or images.  KFS.  */
       xassert (IT_CHARPOS (it) <= PT);
+#endif
       it.current_y = 0;
     }
 
@@ -11991,8 +12331,8 @@ redisplay_window (window, just_this_one_p)
       || !NILP (Vwindow_scroll_functions)
       || !just_this_one_p
       || MINI_WINDOW_P (w)
-      || !(used_current_matrix_p =
-          try_window_reusing_current_matrix (w)))
+      || !(used_current_matrix_p
+          try_window_reusing_current_matrix (w)))
     try_window (window, startp);
 
   /* If new fonts have been loaded (due to fontsets), give up.  We
@@ -12039,7 +12379,7 @@ redisplay_window (window, just_this_one_p)
       set_cursor_from_row (w, row, w->current_matrix, 0, 0, 0, 0);
     }
 
-  if (!make_cursor_line_fully_visible (w, centering_position > 0))
+  if (!cursor_row_fully_visible_p (w, 0, 0))
     {
       /* If vscroll is enabled, disable it and try again.  */
       if (w->vscroll)
@@ -12052,9 +12392,12 @@ redisplay_window (window, just_this_one_p)
       /* If centering point failed to make the whole line visible,
         put point at the top instead.  That has to make the whole line
         visible, if it can be done.  */
+      if (centering_position == 0)
+       goto done;
+
       clear_glyph_matrix (w->desired_matrix);
       centering_position = 0;
-      goto point_at_top;
+      goto recenter;
     }
 
  done:
@@ -12156,14 +12499,16 @@ redisplay_window (window, just_this_one_p)
     }
 
 #ifdef HAVE_WINDOW_SYSTEM
-  if (update_window_fringes (w, 0)
+  if (FRAME_WINDOW_P (f)
+      && update_window_fringes (w, 0)
       && !just_this_one_p
       && (used_current_matrix_p || overlay_arrow_seen)
       && !w->pseudo_window_p)
     {
       update_begin (f);
       BLOCK_INPUT;
-      draw_window_fringes (w);
+      if (draw_window_fringes (w, 1))
+       x_draw_vertical_border (w);
       UNBLOCK_INPUT;
       update_end (f);
     }
@@ -12315,7 +12660,7 @@ try_window_reusing_current_matrix (w)
   /* Give up if old or new display is scrolled vertically.  We could
      make this function handle this, but right now it doesn't.  */
   start_row = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
-  if (w->vscroll || MATRIX_ROW_PARTIALLY_VISIBLE_P (start_row))
+  if (w->vscroll || MATRIX_ROW_PARTIALLY_VISIBLE_P (w, start_row))
     return 0;
 
   /* The variable new_start now holds the new window start.  The old
@@ -12350,10 +12695,36 @@ try_window_reusing_current_matrix (w)
       last_text_row = last_reused_text_row = NULL;
 
       while (it.current_y < it.last_visible_y
-            && IT_CHARPOS (it) < CHARPOS (start)
             && !fonts_changed_p)
-       if (display_line (&it))
-         last_text_row = it.glyph_row - 1;
+       {
+         /* If we have reached into the characters in the START row,
+            that means the line boundaries have changed.  So we
+            can't start copying with the row START.  Maybe it will
+            work to start copying with the following row.  */
+         while (IT_CHARPOS (it) > CHARPOS (start))
+           {
+             /* Advance to the next row as the "start".  */
+             start_row++;
+             start = start_row->start.pos;
+             /* If there are no more rows to try, or just one, give up.  */
+             if (start_row == MATRIX_MODE_LINE_ROW (w->current_matrix) - 1
+                 || w->vscroll || MATRIX_ROW_PARTIALLY_VISIBLE_P (w, start_row)
+                 || CHARPOS (start) == ZV)
+               {
+                 clear_glyph_matrix (w->desired_matrix);
+                 return 0;
+               }
+
+             start_vpos = MATRIX_ROW_VPOS (start_row, w->current_matrix);
+           }
+         /* If we have reached alignment,
+            we can copy the rest of the rows.  */
+         if (IT_CHARPOS (it) == CHARPOS (start))
+           break;
+
+         if (display_line (&it))
+           last_text_row = it.glyph_row - 1;
+       }
 
       /* A value of current_y < last_visible_y means that we stopped
         at the previous window start, which in turn means that we
@@ -12361,12 +12732,12 @@ try_window_reusing_current_matrix (w)
       if (it.current_y < it.last_visible_y)
        {
          /* IT.vpos always starts from 0; it counts text lines.  */
-         nrows_scrolled = it.vpos;
+         nrows_scrolled = it.vpos - (start_row - MATRIX_FIRST_TEXT_ROW (w->current_matrix));
 
          /* Find PT if not already found in the lines displayed.  */
          if (w->cursor.vpos < 0)
            {
-             int dy = it.current_y - first_row_y;
+             int dy = it.current_y - start_row->y;
 
              row = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
              row = row_containing_pos (w, PT, row, NULL, dy);
@@ -12386,7 +12757,7 @@ try_window_reusing_current_matrix (w)
             scroll_run_hook will clear the cursor, and use the
             current matrix to get the height of the row the cursor is
             in.  */
-         run.current_y = first_row_y;
+         run.current_y = start_row->y;
          run.desired_y = it.current_y;
          run.height = it.last_visible_y - it.current_y;
 
@@ -12811,8 +13182,10 @@ find_first_unchanged_at_end_row (w, delta, delta_bytes)
         starts at a minimum position >= last_unchanged_pos_old.  */
       for (; row > first_text_row; --row)
        {
+         /* This used to abort, but it can happen.
+            It is ok to just stop the search instead here.  KFS.  */
          if (!row->enabled_p || !MATRIX_ROW_DISPLAYS_TEXT_P (row))
-           abort ();
+           break;
 
          if (MATRIX_ROW_START_CHARPOS (row) >= last_unchanged_pos_old)
            row_found = row;
@@ -13406,7 +13779,9 @@ try_window_id (w)
         && CHARPOS (start) > BEGV)
        /* Old redisplay didn't take scroll margin into account at the bottom,
           but then global-hl-line-mode doesn't scroll.  KFS 2004-06-14 */
-       || w->cursor.y + cursor_height + this_scroll_margin > it.last_visible_y)
+       || (w->cursor.y + (make_cursor_line_fully_visible_p
+                          ? cursor_height + this_scroll_margin
+                          : 1)) > it.last_visible_y)
       {
        w->cursor.vpos = -1;
        clear_glyph_matrix (w->desired_matrix);
@@ -13517,7 +13892,12 @@ try_window_id (w)
                        bottom_vpos, dy);
 
   if (first_unchanged_at_end_row)
-    first_unchanged_at_end_row += dvpos;
+    {
+      first_unchanged_at_end_row += dvpos;
+      if (first_unchanged_at_end_row->y >= it.last_visible_y
+         || !MATRIX_ROW_DISPLAYS_TEXT_P (first_unchanged_at_end_row))
+       first_unchanged_at_end_row = NULL;
+    }
 
   /* If scrolling up, there may be some lines to display at the end of
      the window.  */
@@ -13574,7 +13954,6 @@ try_window_id (w)
 
   /* Update window_end_pos and window_end_vpos.  */
   if (first_unchanged_at_end_row
-      && first_unchanged_at_end_row->y < it.last_visible_y
       && !last_text_row_at_end)
     {
       /* Window end line if one of the preserved rows from the current
@@ -13984,8 +14363,8 @@ usage: (trace-to-stderr STRING &rest OBJECTS)  */)
                     Building Desired Matrix Rows
  ***********************************************************************/
 
-/* Return a temporary glyph row holding the glyphs of an overlay
-   arrow.  Only used for non-window-redisplay windows.  */
+/* Return a temporary glyph row holding the glyphs of an overlay arrow.
+   Used for non-window-redisplay windows, and for windows w/o left fringe.  */
 
 static struct glyph_row *
 get_overlay_arrow_glyph_row (w, overlay_arrow_string)
@@ -14131,6 +14510,7 @@ compute_line_metrics (it)
          row->height = it->max_ascent + it->max_descent;
          row->phys_ascent = it->max_phys_ascent;
          row->phys_height = it->max_phys_ascent + it->max_phys_descent;
+         row->extra_line_spacing = it->max_extra_line_spacing;
        }
 
       /* Compute the width of this line.  */
@@ -14174,6 +14554,7 @@ compute_line_metrics (it)
        row->pixel_width -= it->truncation_pixel_width;
       row->ascent = row->phys_ascent = 0;
       row->height = row->phys_height = row->visible_height = 1;
+      row->extra_line_spacing = 0;
     }
 
   /* Compute a hash code for this row.  */
@@ -14408,7 +14789,9 @@ highlight_trailing_whitespace (f, row)
                  && glyph->u.ch == ' '))
          && trailing_whitespace_p (glyph->charpos))
        {
-         int face_id = lookup_named_face (f, Qtrailing_whitespace, 0);
+         int face_id = lookup_named_face (f, Qtrailing_whitespace, 0, 0);
+         if (face_id < 0)
+           return;
 
          while (glyph >= start
                 && BUFFERP (glyph->object)
@@ -14436,10 +14819,22 @@ cursor_row_p (w, row)
       /* If the row ends with a newline from a string, we don't want
         the cursor there (if the row is continued it doesn't end in a
         newline).  */
-      if (CHARPOS (row->end.string_pos) >= 0
-         || MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (row))
+      if (CHARPOS (row->end.string_pos) >= 0)
        cursor_row_p = row->continued_p;
-
+      else if (MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (row))
+       {
+         /* If the row ends in middle of a real character,
+            and the line is continued, we want the cursor here.
+            That's because MATRIX_ROW_END_CHARPOS would equal
+            PT if PT is before the character.  */
+         if (!row->ends_in_ellipsis_p)
+           cursor_row_p = row->continued_p;
+         else
+         /* If the row ends in an ellipsis, then
+            MATRIX_ROW_END_CHARPOS will equal point after the invisible text.
+            We want that position to be displayed after the ellipsis.  */
+           cursor_row_p = 0;
+       }
       /* If the row ends at ZV, display the cursor at the end of that
         row instead of at the start of the row below.  */
       else if (row->ends_at_zv_p)
@@ -14501,8 +14896,10 @@ display_line (it)
      hscrolled.  This may stop at an x-position < IT->first_visible_x
      if the first glyph is partially visible or if we hit a line end.  */
   if (it->current_x < it->first_visible_x)
-    move_it_in_display_line_to (it, ZV, it->first_visible_x,
-                               MOVE_TO_POS | MOVE_TO_X);
+    {
+      move_it_in_display_line_to (it, ZV, it->first_visible_x,
+                                 MOVE_TO_POS | MOVE_TO_X);
+    }
 
   /* Get the initial row height.  This is either the height of the
      text hscrolled, if there is any, or zero.  */
@@ -14510,6 +14907,7 @@ display_line (it)
   row->height = it->max_ascent + it->max_descent;
   row->phys_ascent = it->max_phys_ascent;
   row->phys_height = it->max_phys_ascent + it->max_phys_descent;
+  row->extra_line_spacing = it->max_extra_line_spacing;
 
   /* Loop generating characters.  The loop is left with IT on the next
      character to display.  */
@@ -14575,6 +14973,8 @@ display_line (it)
          row->phys_ascent = max (row->phys_ascent, it->max_phys_ascent);
          row->phys_height = max (row->phys_height,
                                  it->max_phys_ascent + it->max_phys_descent);
+         row->extra_line_spacing = max (row->extra_line_spacing,
+                                        it->max_extra_line_spacing);
          set_iterator_to_next (it, 1);
          continue;
        }
@@ -14603,6 +15003,8 @@ display_line (it)
          row->phys_ascent = max (row->phys_ascent, it->max_phys_ascent);
          row->phys_height = max (row->phys_height,
                                  it->max_phys_ascent + it->max_phys_descent);
+         row->extra_line_spacing = max (row->extra_line_spacing,
+                                        it->max_extra_line_spacing);
          if (it->current_x - it->pixel_width < it->first_visible_x)
            row->x = x - it->first_visible_x;
        }
@@ -14754,6 +15156,8 @@ display_line (it)
          row->phys_ascent = max (row->phys_ascent, it->max_phys_ascent);
          row->phys_height = max (row->phys_height,
                                  it->max_phys_ascent + it->max_phys_descent);
+         row->extra_line_spacing = max (row->extra_line_spacing,
+                                        it->max_extra_line_spacing);
 
          /* End of this display line if row is continued.  */
          if (row->continued_p || row->ends_at_zv_p)
@@ -14824,12 +15228,10 @@ display_line (it)
                {
                  if (!get_next_display_element (it))
                    {
-#ifdef HAVE_WINDOW_SYSTEM
                      it->continuation_lines_width = 0;
                      row->ends_at_zv_p = 1;
                      row->exact_window_width_line_p = 1;
                      break;
-#endif /* HAVE_WINDOW_SYSTEM */
                    }
                  if (ITERATOR_AT_END_OF_LINE_P (it))
                    {
@@ -14866,11 +15268,11 @@ display_line (it)
      better to let it be displayed like cursors under X.  */
   if (! overlay_arrow_seen
       && (overlay_arrow_string
-           = overlay_arrow_at_row (it->f, row, &overlay_arrow_bitmap),
+           = overlay_arrow_at_row (it, row, &overlay_arrow_bitmap),
          !NILP (overlay_arrow_string)))
     {
       /* Overlay arrow in window redisplay is a fringe bitmap.  */
-      if (!FRAME_WINDOW_P (it->f))
+      if (STRINGP (overlay_arrow_string))
        {
          struct glyph_row *arrow_row
            = get_overlay_arrow_glyph_row (it->w, overlay_arrow_string);
@@ -14895,10 +15297,12 @@ display_line (it)
              row->used[TEXT_AREA] = p2 - row->glyphs[TEXT_AREA];
            }
        }
-
+      else
+       {
+         it->w->overlay_arrow_bitmap = overlay_arrow_bitmap;
+         row->overlay_arrow_p = 1;
+       }
       overlay_arrow_seen = 1;
-      it->w->overlay_arrow_bitmap = overlay_arrow_bitmap;
-      row->overlay_arrow_p = 1;
     }
 
   /* Compute pixel dimensions of this line.  */
@@ -14907,6 +15311,11 @@ display_line (it)
   /* Remember the position at which this line ends.  */
   row->end = it->current;
 
+  /* Record whether this row ends inside an ellipsis.  */
+  row->ends_in_ellipsis_p
+    = (it->method == GET_FROM_DISPLAY_VECTOR
+       && it->ellipsis_p);
+
   /* Save fringe bitmaps in this row.  */
   row->left_user_fringe_bitmap = it->left_user_fringe_bitmap;
   row->left_user_fringe_face_id = it->left_user_fringe_face_id;
@@ -15281,6 +15690,10 @@ display_mode_element (it, depth, field_width, precision, elt, props, risky)
            Lisp_Object oprops, aelt;
            oprops = Ftext_properties_at (make_number (0), elt);
 
+           /* If the starting string's properties are not what
+              we want, translate the string.  Also, if the string
+              is risky, do that anyway.  */
+
            if (NILP (Fequal (props, oprops)) || risky)
              {
                /* If the starting string has properties,
@@ -15359,14 +15772,15 @@ display_mode_element (it, depth, field_width, precision, elt, props, risky)
 
            if (this - 1 != last)
              {
+               int nchars, nbytes;
+
                /* Output to end of string or up to '%'.  Field width
                   is length of string.  Don't output more than
                   PRECISION allows us.  */
                --this;
 
-               prec = chars_in_text (last, this - last);
-               if (precision > 0 && prec > precision - n)
-                 prec = precision - n;
+               prec = c_string_width (last, this - last, precision - n,
+                                      &nchars, &nbytes);
 
                if (frame_title_ptr)
                  n += store_frame_title (last, 0, prec);
@@ -15374,9 +15788,14 @@ display_mode_element (it, depth, field_width, precision, elt, props, risky)
                  {
                    int bytepos = last - lisp_string;
                    int charpos = string_byte_to_char (elt, bytepos);
+                   int endpos = (precision <= 0
+                                 ? string_byte_to_char (elt,
+                                                        this - lisp_string)
+                                 : charpos + nchars);
+
                    n += store_mode_line_string (NULL,
                                                 Fsubstring (elt, make_number (charpos),
-                                                            make_number (charpos + prec)),
+                                                            make_number (endpos)),
                                                 0, 0, 0, Qnil);
                  }
                else
@@ -15657,7 +16076,8 @@ display_mode_element (it, depth, field_width, precision, elt, props, risky)
    The mode_line_string_face face property is always added to the string.
  */
 
-static int store_mode_line_string (string, lisp_string, copy_string, field_width, precision, props)
+static int
+store_mode_line_string (string, lisp_string, copy_string, field_width, precision, props)
      char *string;
      Lisp_Object lisp_string;
      int copy_string;
@@ -15678,7 +16098,7 @@ static int store_mode_line_string (string, lisp_string, copy_string, field_width
        props = mode_line_string_face_prop;
       else if (!NILP (mode_line_string_face))
        {
-         Lisp_Object face = Fplist_get (props, Qface);
+         Lisp_Object face = Fsafe_plist_get (props, Qface);
          props = Fcopy_sequence (props);
          if (NILP (face))
            face = mode_line_string_face;
@@ -15703,7 +16123,7 @@ static int store_mode_line_string (string, lisp_string, copy_string, field_width
          Lisp_Object face;
          if (NILP (props))
            props = Ftext_properties_at (make_number (0), lisp_string);
-         face = Fplist_get (props, Qface);
+         face = Fsafe_plist_get (props, Qface);
          if (NILP (face))
            face = mode_line_string_face;
          else
@@ -15739,62 +16159,75 @@ static int store_mode_line_string (string, lisp_string, copy_string, field_width
 
 
 DEFUN ("format-mode-line", Fformat_mode_line, Sformat_mode_line,
-       0, 3, 0,
-       doc: /* Return the mode-line of selected window as a string.
-First optional arg FORMAT specifies a different format string (see
-`mode-line-format' for details) to use.  If FORMAT is t, return
-the buffer's header-line.  Second optional arg WINDOW specifies a
-different window to use as the context for the formatting.
-If third optional arg NO-PROPS is non-nil, string is not propertized.  */)
-     (format, window, no_props)
-     Lisp_Object format, window, no_props;
+       1, 4, 0,
+       doc: /* Format a string out of a mode line format specification.
+First arg FORMAT specifies the mode line format (see `mode-line-format'
+for details) to use.
+
+Optional second arg FACE specifies the face property to put
+on all characters for which no face is specified.
+t means whatever face the window's mode line currently uses
+\(either `mode-line' or `mode-line-inactive', depending).
+nil means the default is no face property.
+If FACE is an integer, the value string has no text properties.
+
+Optional third and fourth args WINDOW and BUFFER specify the window
+and buffer to use as the context for the formatting (defaults
+are the selected window and the window's buffer).  */)
+  (format, face, window, buffer)
+     Lisp_Object format, face, window, buffer;
 {
   struct it it;
   int len;
   struct window *w;
   struct buffer *old_buffer = NULL;
-  enum face_id face_id = DEFAULT_FACE_ID;
+  int face_id = -1;
+  int no_props = INTEGERP (face);
 
   if (NILP (window))
     window = selected_window;
   CHECK_WINDOW (window);
   w = XWINDOW (window);
-  CHECK_BUFFER (w->buffer);
 
-  if (XBUFFER (w->buffer) != current_buffer)
+  if (NILP (buffer))
+    buffer = w->buffer;
+  CHECK_BUFFER (buffer);
+
+  if (NILP (format))
+    return build_string ("");
+
+  if (no_props)
+    face = Qnil;
+
+  if (!NILP (face))
     {
-      old_buffer = current_buffer;
-      set_buffer_internal_1 (XBUFFER (w->buffer));
+      if (EQ (face, Qt))
+       face = (EQ (window, selected_window) ? Qmode_line : Qmode_line_inactive);
+      face_id = lookup_named_face (XFRAME (WINDOW_FRAME (w)), face, 0, 0);
     }
 
-  if (NILP (format) || EQ (format, Qt))
+  if (face_id < 0)
+    face_id = DEFAULT_FACE_ID;
+
+  if (XBUFFER (buffer) != current_buffer)
     {
-      face_id = NILP (format)
-       ? CURRENT_MODE_LINE_FACE_ID (w) :
-       HEADER_LINE_FACE_ID;
-      format = NILP (format)
-       ? current_buffer->mode_line_format
-       : current_buffer->header_line_format;
+      old_buffer = current_buffer;
+      set_buffer_internal_1 (XBUFFER (buffer));
     }
 
   init_iterator (&it, w, -1, -1, NULL, face_id);
 
-  if (NILP (no_props))
+  if (!no_props)
     {
-      mode_line_string_face =
-       (face_id == MODE_LINE_FACE_ID ? Qmode_line :
-        face_id == MODE_LINE_INACTIVE_FACE_ID ? Qmode_line_inactive :
-        face_id == HEADER_LINE_FACE_ID ? Qheader_line : Qnil);
-
-      mode_line_string_face_prop =
-       NILP (mode_line_string_face) ? Qnil :
-       Fcons (Qface, Fcons (mode_line_string_face, Qnil));
+      mode_line_string_face = face;
+      mode_line_string_face_prop
+       = (NILP (face) ? Qnil : Fcons (Qface, Fcons (face, Qnil)));
 
       /* We need a dummy last element in mode_line_string_list to
         indicate we are building the propertized mode-line string.
         Using mode_line_string_face_prop here GC protects it.  */
-      mode_line_string_list =
-       Fcons (mode_line_string_face_prop, Qnil);
+      mode_line_string_list
+       Fcons (mode_line_string_face_prop, Qnil);
       frame_title_ptr = NULL;
     }
   else
@@ -15811,7 +16244,7 @@ If third optional arg NO-PROPS is non-nil, string is not propertized.  */)
   if (old_buffer)
     set_buffer_internal_1 (old_buffer);
 
-  if (NILP (no_props))
+  if (!no_props)
     {
       Lisp_Object str;
       mode_line_string_list = Fnreverse (mode_line_string_list);
@@ -15923,27 +16356,31 @@ pint2hrstr (buf, width, d)
        {
          tenths = remainder / 100;
          if (50 <= remainder % 100)
-           if (tenths < 9)
-             tenths++;
-           else
-             {
-               quotient++;
-               if (quotient == 10)
-                 tenths = -1;
-               else
-                 tenths = 0;
-             }
+           {
+             if (tenths < 9)
+               tenths++;
+             else
+               {
+                 quotient++;
+                 if (quotient == 10)
+                   tenths = -1;
+                 else
+                   tenths = 0;
+               }
+           }
        }
       else
        if (500 <= remainder)
-         if (quotient < 999)
-           quotient++;
-         else
-           {
-             quotient = 1;
-             exponent++;
-             tenths = 0;
-           }
+         {
+           if (quotient < 999)
+             quotient++;
+           else
+             {
+               quotient = 1;
+               exponent++;
+               tenths = 0;
+             }
+         }
     }
 
   /* Calculate the LENGTH of QUOTIENT.TENTHS as a string. */
@@ -16067,7 +16504,10 @@ decode_mode_spec_coding (coding_system, buf, eol_flag)
    generated by character C.  PRECISION >= 0 means don't return a
    string longer than that value.  FIELD_WIDTH > 0 means pad the
    string returned with spaces to that value.  Return 1 in *MULTIBYTE
-   if the result is multibyte text.  */
+   if the result is multibyte text.
+
+   Note we operate on the current buffer for most purposes,
+   the exception being w->base_line_pos.  */
 
 static char lots_of_dashes[] = "--------------------------------------------------------------------------------------------------------------------------------------------";
 
@@ -16081,7 +16521,7 @@ decode_mode_spec (w, c, field_width, precision, multibyte)
   Lisp_Object obj;
   struct frame *f = XFRAME (WINDOW_FRAME (w));
   char *decode_mode_spec_buf = f->decode_mode_spec_buffer;
-  struct buffer *b = XBUFFER (w->buffer);
+  struct buffer *b = current_buffer;
 
   obj = Qnil;
   *multibyte = 0;
@@ -16383,7 +16823,7 @@ decode_mode_spec (w, c, field_width, precision, multibyte)
 
     case 's':
       /* status of process */
-      obj = Fget_buffer_process (w->buffer);
+      obj = Fget_buffer_process (Fcurrent_buffer ());
       if (NILP (obj))
        return "no process";
 #ifdef subprocesses
@@ -16642,6 +17082,7 @@ display_string (string, lisp_string, face_string, face_string_pos,
   row->height = it->max_ascent + it->max_descent;
   row->phys_ascent = it->max_phys_ascent;
   row->phys_height = it->max_phys_ascent + it->max_phys_descent;
+  row->extra_line_spacing = it->max_extra_line_spacing;
 
   /* This condition is for the case that we are called with current_x
      past last_visible_x.  */
@@ -16701,6 +17142,8 @@ display_string (string, lisp_string, face_string, face_string_pos,
          row->phys_ascent = max (row->phys_ascent, it->max_phys_ascent);
          row->phys_height = max (row->phys_height,
                                  it->max_phys_ascent + it->max_phys_descent);
+         row->extra_line_spacing = max (row->extra_line_spacing,
+                                        it->max_extra_line_spacing);
          x += glyph->pixel_width;
          ++i;
        }
@@ -17137,7 +17580,8 @@ init_glyph_string (s, OPTIONAL_HDC (hdc) char2b, w, row, area, start, hl)
   s->y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
 
   /* Display the internal border below the tool-bar window.  */
-  if (s->w == XWINDOW (s->f->tool_bar_window))
+  if (WINDOWP (s->f->tool_bar_window)
+      && s->w == XWINDOW (s->f->tool_bar_window))
     s->y -= FRAME_INTERNAL_BORDER_WIDTH (s->f);
 
   s->ybase = s->y + row->ascent;
@@ -17957,6 +18401,7 @@ draw_glyphs (w, x, row, area, start, end, hl, overlaps_p)
 {
   struct glyph_string *head, *tail;
   struct glyph_string *s;
+  struct glyph_string *clip_head = NULL, *clip_tail = NULL;
   int last_x, area_width;
   int x_reached;
   int i, j;
@@ -18025,6 +18470,7 @@ draw_glyphs (w, x, row, area, start, end, hl, overlaps_p)
          start = i;
          compute_overhangs_and_x (t, head->x, 1);
          prepend_glyph_string_lists (&head, &tail, h, t);
+         clip_head = head;
        }
 
       /* Prepend glyph strings for glyphs in front of the first glyph
@@ -18037,6 +18483,7 @@ draw_glyphs (w, x, row, area, start, end, hl, overlaps_p)
       i = left_overwriting (head);
       if (i >= 0)
        {
+         clip_head = head;
          BUILD_GLYPH_STRINGS (i, start, h, t,
                               DRAW_NORMAL_TEXT, dummy_x, last_x);
          for (s = h; s; s = s->next)
@@ -18056,6 +18503,7 @@ draw_glyphs (w, x, row, area, start, end, hl, overlaps_p)
                               DRAW_NORMAL_TEXT, x, last_x);
          compute_overhangs_and_x (h, tail->x + tail->width, 0);
          append_glyph_string_lists (&head, &tail, h, t);
+         clip_tail = tail;
        }
 
       /* Append glyph strings for glyphs following the last glyph
@@ -18066,6 +18514,7 @@ draw_glyphs (w, x, row, area, start, end, hl, overlaps_p)
       i = right_overwriting (tail);
       if (i >= 0)
        {
+         clip_tail = tail;
          BUILD_GLYPH_STRINGS (end, i, h, t,
                               DRAW_NORMAL_TEXT, x, last_x);
          for (s = h; s; s = s->next)
@@ -18073,6 +18522,12 @@ draw_glyphs (w, x, row, area, start, end, hl, overlaps_p)
          compute_overhangs_and_x (h, tail->x + tail->width, 0);
          append_glyph_string_lists (&head, &tail, h, t);
        }
+      if (clip_head || clip_tail)
+       for (s = head; s; s = s->next)
+         {
+           s->clip_head = clip_head;
+           s->clip_tail = clip_tail;
+         }
     }
 
   /* Draw all strings.  */
@@ -18086,8 +18541,9 @@ draw_glyphs (w, x, row, area, start, end, hl, overlaps_p)
         completely. */
       && !overlaps_p)
     {
-      int x0 = head ? head->x : x;
-      int x1 = tail ? tail->x + tail->background_width : x;
+      int x0 = clip_head ? clip_head->x : (head ? head->x : x);
+      int x1 = (clip_tail ? clip_tail->x + clip_tail->background_width
+               : (tail ? tail->x + tail->background_width : x));
 
       int text_left = window_box_left (w, TEXT_AREA);
       x0 -= text_left;
@@ -18109,6 +18565,19 @@ draw_glyphs (w, x, row, area, start, end, hl, overlaps_p)
   return x_reached;
 }
 
+/* Expand row matrix if too narrow.  Don't expand if area
+   is not present.  */
+
+#define IT_EXPAND_MATRIX_WIDTH(it, area)               \
+  {                                                    \
+    if (!fonts_changed_p                               \
+       && (it->glyph_row->glyphs[area]                 \
+           < it->glyph_row->glyphs[area + 1]))         \
+      {                                                        \
+       it->w->ncols_scale_factor++;                    \
+       fonts_changed_p = 1;                            \
+      }                                                        \
+  }
 
 /* Store one glyph for IT->char_to_display in IT->glyph_row.
    Called from x_produce_glyphs when IT->glyph_row is non-null.  */
@@ -18146,11 +18615,8 @@ append_glyph (it)
       glyph->font_type = FONT_TYPE_UNKNOWN;
       ++it->glyph_row->used[area];
     }
-  else if (!fonts_changed_p)
-    {
-      it->w->ncols_scale_factor++;
-      fonts_changed_p = 1;
-    }
+  else
+    IT_EXPAND_MATRIX_WIDTH (it, area);
 }
 
 /* Store one glyph for the composition IT->cmp_id in IT->glyph_row.
@@ -18188,11 +18654,8 @@ append_composite_glyph (it)
       glyph->font_type = FONT_TYPE_UNKNOWN;
       ++it->glyph_row->used[area];
     }
-  else if (!fonts_changed_p)
-    {
-      it->w->ncols_scale_factor++;
-      fonts_changed_p = 1;
-    }
+  else
+    IT_EXPAND_MATRIX_WIDTH (it, area);
 }
 
 
@@ -18227,7 +18690,7 @@ produce_image_glyph (it)
 {
   struct image *img;
   struct face *face;
-  int face_ascent, glyph_ascent;
+  int glyph_ascent;
   struct glyph_slice slice;
 
   xassert (it->what == IT_IMAGE);
@@ -18310,7 +18773,7 @@ produce_image_glyph (it)
 
 #if 0  /* this breaks image tiling */
   /* If this glyph is alone on the last line, adjust it.ascent to minimum row ascent.  */
-  face_ascent = face->font ? FONT_BASE (face->font) : FRAME_BASELINE_OFFSET (it->f);
+  int face_ascent = face->font ? FONT_BASE (face->font) : FRAME_BASELINE_OFFSET (it->f);
   if (face_ascent > it->ascent)
     it->ascent = it->phys_ascent = face_ascent;
 #endif
@@ -18362,11 +18825,8 @@ produce_image_glyph (it)
          glyph->font_type = FONT_TYPE_UNKNOWN;
          ++it->glyph_row->used[area];
        }
-      else if (!fonts_changed_p)
-       {
-         it->w->ncols_scale_factor++;
-         fonts_changed_p = 1;
-       }
+      else
+       IT_EXPAND_MATRIX_WIDTH (it, area);
     }
 }
 
@@ -18410,11 +18870,8 @@ append_stretch_glyph (it, object, width, height, ascent)
       glyph->font_type = FONT_TYPE_UNKNOWN;
       ++it->glyph_row->used[area];
     }
-  else if (!fonts_changed_p)
-    {
-      it->w->ncols_scale_factor++;
-      fonts_changed_p = 1;
-    }
+  else
+    IT_EXPAND_MATRIX_WIDTH (it, area);
 }
 
 
@@ -18469,14 +18926,14 @@ produce_stretch_glyph (it)
   plist = XCDR (it->object);
 
   /* Compute the width of the stretch.  */
-  if ((prop = Fplist_get (plist, QCwidth), !NILP (prop))
+  if ((prop = Fsafe_plist_get (plist, QCwidth), !NILP (prop))
       && calc_pixel_width_or_height (&tem, it, prop, font, 1, 0))
     {
       /* Absolute width `:width WIDTH' specified and valid.  */
       zero_width_ok_p = 1;
       width = (int)tem;
     }
-  else if (prop = Fplist_get (plist, QCrelative_width),
+  else if (prop = Fsafe_plist_get (plist, QCrelative_width),
           NUMVAL (prop) > 0)
     {
       /* Relative width `:relative-width FACTOR' specified and valid.
@@ -18500,7 +18957,7 @@ produce_stretch_glyph (it)
       x_produce_glyphs (&it2);
       width = NUMVAL (prop) * it2.pixel_width;
     }
-  else if ((prop = Fplist_get (plist, QCalign_to), !NILP (prop))
+  else if ((prop = Fsafe_plist_get (plist, QCalign_to), !NILP (prop))
           && calc_pixel_width_or_height (&tem, it, prop, font, 1, &align_to))
     {
       if (it->glyph_row == NULL || !it->glyph_row->mode_line_p)
@@ -18520,13 +18977,13 @@ produce_stretch_glyph (it)
     width = 1;
 
   /* Compute height.  */
-  if ((prop = Fplist_get (plist, QCheight), !NILP (prop))
+  if ((prop = Fsafe_plist_get (plist, QCheight), !NILP (prop))
       && calc_pixel_width_or_height (&tem, it, prop, font, 0, 0))
     {
       height = (int)tem;
       zero_height_ok_p = 1;
     }
-  else if (prop = Fplist_get (plist, QCrelative_height),
+  else if (prop = Fsafe_plist_get (plist, QCrelative_height),
           NUMVAL (prop) > 0)
     height = FONT_HEIGHT (font) * NUMVAL (prop);
   else
@@ -18538,7 +18995,7 @@ produce_stretch_glyph (it)
   /* Compute percentage of height used for ascent.  If
      `:ascent ASCENT' is present and valid, use that.  Otherwise,
      derive the ascent from the font in use.  */
-  if (prop = Fplist_get (plist, QCascent),
+  if (prop = Fsafe_plist_get (plist, QCascent),
       NUMVAL (prop) > 0 && NUMVAL (prop) <= 100)
     ascent = height * NUMVAL (prop) / 100.0;
   else if (!NILP (prop)
@@ -18577,57 +19034,62 @@ produce_stretch_glyph (it)
   take_vertical_position_into_account (it);
 }
 
-/* Calculate line-height and line-spacing properties.
-   An integer value specifies explicit pixel value.
-   A float value specifies relative value to current face height.
-   A cons (float . face-name) specifies relative value to
-   height of specified face font.
-
-   Returns height in pixels, or nil.  */
+/* Get line-height and line-spacing property at point.
+   If line-height has format (HEIGHT TOTAL), return TOTAL
+   in TOTAL_HEIGHT.  */
 
 static Lisp_Object
-calc_line_height_property (it, prop, font, boff, total)
+get_line_height_property (it, prop)
      struct it *it;
      Lisp_Object prop;
-     XFontStruct *font;
-     int boff, *total;
 {
   Lisp_Object position, val;
-  Lisp_Object face_name = Qnil;
-  int ascent, descent, height, override;
 
   if (STRINGP (it->object))
     position = make_number (IT_STRING_CHARPOS (*it));
-  else
+  else if (BUFFERP (it->object))
     position = make_number (IT_CHARPOS (*it));
+  else
+    return Qnil;
 
-  val = Fget_char_property (position, prop, it->object);
+  return Fget_char_property (position, prop, it->object);
+}
 
-  if (NILP (val))
-    return val;
+/* Calculate line-height and line-spacing properties.
+   An integer value specifies explicit pixel value.
+   A float value specifies relative value to current face height.
+   A cons (float . face-name) specifies relative value to
+   height of specified face font.
 
-  if (total && CONSP (val) && EQ (XCAR (val), Qtotal))
-    {
-      *total = 1;
-      val = XCDR (val);
-    }
+   Returns height in pixels, or nil.  */
+
+
+static Lisp_Object
+calc_line_height_property (it, val, font, boff, override)
+     struct it *it;
+     Lisp_Object val;
+     XFontStruct *font;
+     int boff, override;
+{
+  Lisp_Object face_name = Qnil;
+  int ascent, descent, height;
 
-  if (INTEGERP (val))
+  if (NILP (val) || INTEGERP (val) || (override && EQ (val, Qt)))
     return val;
 
   if (CONSP (val))
     {
-      face_name = XCDR (val);
-      val = XCAR (val);
-    }
-  else if (SYMBOLP (val))
-    {
-      face_name = val;
-      val = Qnil;
+      face_name = XCAR (val);
+      val = XCDR (val);
+      if (!NUMBERP (val))
+       val = make_number (1);
+      if (NILP (face_name))
+       {
+         height = it->ascent + it->descent;
+         goto scale;
+       }
     }
 
-  override = EQ (prop, Qline_height);
-
   if (NILP (face_name))
     {
       font = FRAME_FONT (it->f);
@@ -18643,7 +19105,7 @@ calc_line_height_property (it, prop, font, boff, total)
       struct face *face;
       struct font_info *font_info;
 
-      face_id = lookup_named_face (it->f, face_name, ' ');
+      face_id = lookup_named_face (it->f, face_name, ' ', 0);
       if (face_id < 0)
        return make_number (-1);
 
@@ -18669,6 +19131,8 @@ calc_line_height_property (it, prop, font, boff, total)
     }
 
   height = ascent + descent;
+
+ scale:
   if (FLOATP (val))
     height = (int)(XFLOAT_DATA (val) * height);
   else if (INTEGERP (val))
@@ -18881,12 +19345,22 @@ x_produce_glyphs (it)
             increase that height */
 
          Lisp_Object height;
+         Lisp_Object total_height = Qnil;
 
          it->override_ascent = -1;
          it->pixel_width = 0;
          it->nglyphs = 0;
 
-         height = calc_line_height_property(it, Qline_height, font, boff, 0);
+         height = get_line_height_property(it, Qline_height);
+         /* Split (line-height total-height) list */
+         if (CONSP (height)
+             && CONSP (XCDR (height))
+             && NILP (XCDR (XCDR (height))))
+           {
+             total_height = XCAR (XCDR (height));
+             height = XCAR (height);
+           }
+         height = calc_line_height_property(it, height, font, boff, 1);
 
          if (it->override_ascent >= 0)
            {
@@ -18900,7 +19374,7 @@ x_produce_glyphs (it)
              it->descent = FONT_DESCENT (font) - boff;
            }
 
-         if (EQ (height, make_number(0)))
+         if (EQ (height, Qt))
            {
              if (it->descent > it->max_descent)
                {
@@ -18936,25 +19410,31 @@ x_produce_glyphs (it)
                  && XINT (height) > it->ascent + it->descent)
                it->ascent = XINT (height) - it->descent;
 
-             spacing = calc_line_height_property(it, Qline_spacing, font, boff, &total);
+             if (!NILP (total_height))
+               spacing = calc_line_height_property(it, total_height, font, boff, 0);
+             else
+               {
+                 spacing = get_line_height_property(it, Qline_spacing);
+                 spacing = calc_line_height_property(it, spacing, font, boff, 0);
+               }
              if (INTEGERP (spacing))
                {
                  extra_line_spacing = XINT (spacing);
-                 if (total)
+                 if (!NILP (total_height))
                    extra_line_spacing -= (it->phys_ascent + it->phys_descent);
                }
            }
        }
       else if (it->char_to_display == '\t')
        {
-         int tab_width = it->tab_width * FRAME_COLUMN_WIDTH (it->f);
+         int tab_width = it->tab_width * FRAME_SPACE_WIDTH (it->f);
          int x = it->current_x + it->continuation_lines_width;
          int next_tab_x = ((1 + x + tab_width - 1) / tab_width) * tab_width;
 
          /* If the distance from the current position to the next tab
-            stop is less than a canonical character width, use the
+            stop is less than a space character width, use the
             tab stop after that.  */
-         if (next_tab_x - x < FRAME_COLUMN_WIDTH (it->f))
+         if (next_tab_x - x < FRAME_SPACE_WIDTH (it->f))
            next_tab_x += tab_width;
 
          it->pixel_width = next_tab_x - x;
@@ -19321,7 +19801,11 @@ x_produce_glyphs (it)
     it->current_x += it->pixel_width;
 
   if (extra_line_spacing > 0)
-    it->descent += extra_line_spacing;
+    {
+      it->descent += extra_line_spacing;
+      if (extra_line_spacing > it->max_extra_line_spacing)
+       it->max_extra_line_spacing = extra_line_spacing;
+    }
 
   it->max_ascent = max (it->max_ascent, it->ascent);
   it->max_descent = max (it->max_descent, it->descent);
@@ -19736,8 +20220,10 @@ notice_overwritten_cursor (w, area, x0, x1, y0, y1)
   if (area != TEXT_AREA)
     return;
 
-  row = w->current_matrix->rows + w->phys_cursor.vpos;
-  if (!row->displays_text_p)
+  if (w->phys_cursor.vpos < 0
+      || w->phys_cursor.vpos >= w->current_matrix->nrows
+      || (row = w->current_matrix->rows + w->phys_cursor.vpos,
+         !(row->enabled_p && row->displays_text_p)))
     return;
 
   if (row->cursor_in_fringe_p)
@@ -19903,6 +20389,11 @@ erase_phys_cursor (w)
   if (!cursor_row->enabled_p)
     goto mark_cursor_off;
 
+  /* If line spacing is > 0, old cursor may only be partially visible in
+     window after split-window.  So adjust visible height.  */
+  cursor_row->visible_height = min (cursor_row->visible_height,
+                                   window_text_bottom_y (w) - cursor_row->y);
+
   /* If row is completely invisible, don't attempt to delete a cursor which
      isn't there.  This can happen if cursor is at top of a window, and
      we switch to a buffer with a header line in that window.  */
@@ -19946,6 +20437,7 @@ erase_phys_cursor (w)
     {
       int x, y;
       int header_line_height = WINDOW_HEADER_LINE_HEIGHT (w);
+      int width;
 
       cursor_glyph = get_phys_cursor_glyph (w);
       if (cursor_glyph == NULL)
@@ -19953,9 +20445,10 @@ erase_phys_cursor (w)
 
       x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
       y = WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height, cursor_row->y));
+      width = min (cursor_glyph->pixel_width,
+                  window_box_width (w, TEXT_AREA) - w->phys_cursor.x);
 
-      rif->clear_frame_area (f, x, y,
-                            cursor_glyph->pixel_width, cursor_row->visible_height);
+      rif->clear_frame_area (f, x, y, width, cursor_row->visible_height);
     }
 
   /* Erase the cursor by redrawing the character underneath it.  */
@@ -20288,18 +20781,43 @@ fast_find_position (w, charpos, hpos, vpos, x, y, stop)
   int past_end = 0;
 
   first = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
+  if (charpos < MATRIX_ROW_START_CHARPOS (first))
+    {
+      *x = first->x;
+      *y = first->y;
+      *hpos = 0;
+      *vpos = MATRIX_ROW_VPOS (first, w->current_matrix);
+      return 1;
+    }
+
   row = row_containing_pos (w, charpos, first, NULL, 0);
   if (row == NULL)
     {
-      if (charpos < MATRIX_ROW_START_CHARPOS (first))
-       {
-         *x = *y = *hpos = *vpos = 0;
-         return 1;
-       }
-      else
+      row = MATRIX_ROW (w->current_matrix, XFASTINT (w->window_end_vpos));
+      past_end = 1;
+    }
+
+  /* If whole rows or last part of a row came from a display overlay,
+     row_containing_pos will skip over such rows because their end pos
+     equals the start pos of the overlay or interval.
+
+     Move back if we have a STOP object and previous row's
+     end glyph came from STOP.  */
+  if (!NILP (stop))
+    {
+      struct glyph_row *prev;
+      while ((prev = row - 1, prev >= first)
+            && MATRIX_ROW_END_CHARPOS (prev) == charpos
+            && prev->used[TEXT_AREA] > 0)
        {
-         row = MATRIX_ROW (w->current_matrix, XFASTINT (w->window_end_vpos));
-         past_end = 1;
+         struct glyph *beg = prev->glyphs[TEXT_AREA];
+         glyph = beg + prev->used[TEXT_AREA];
+         while (--glyph >= beg
+                && INTEGERP (glyph->object));
+         if (glyph < beg
+             || !EQ (stop, glyph->object))
+           break;
+         row = prev;
        }
     }
 
@@ -20670,6 +21188,10 @@ define_frame_cursor1 (f, cursor, pointer)
      Cursor cursor;
      Lisp_Object pointer;
 {
+  /* Do not change cursor shape while dragging mouse.  */
+  if (!NILP (do_mouse_tracking))
+    return;
+
   if (!NILP (pointer))
     {
       if (EQ (pointer, Qarrow))
@@ -20731,7 +21253,7 @@ note_mode_line_or_margin_highlight (w, x, y, area)
   if (IMAGEP (object))
     {
       Lisp_Object image_map, hotspot;
-      if ((image_map = Fplist_get (XCDR (object), QCmap),
+      if ((image_map = Fsafe_plist_get (XCDR (object), QCmap),
           !NILP (image_map))
          && (hotspot = find_hot_spot (image_map, dx, dy),
              CONSP (hotspot))
@@ -20743,12 +21265,14 @@ note_mode_line_or_margin_highlight (w, x, y, area)
          /* Could check AREA_ID to see if we enter/leave this hot-spot.
             If so, we could look for mouse-enter, mouse-leave
             properties in PLIST (and do something...).  */
-         if ((plist = XCDR (hotspot), CONSP (plist)))
+         hotspot = XCDR (hotspot);
+         if (CONSP (hotspot)
+             && (plist = XCAR (hotspot), CONSP (plist)))
            {
-             pointer = Fplist_get (plist, Qpointer);
+             pointer = Fsafe_plist_get (plist, Qpointer);
              if (NILP (pointer))
                pointer = Qhand;
-             help = Fplist_get (plist, Qhelp_echo);
+             help = Fsafe_plist_get (plist, Qhelp_echo);
              if (!NILP (help))
                {
                  help_echo_string = help;
@@ -20758,9 +21282,9 @@ note_mode_line_or_margin_highlight (w, x, y, area)
                  help_echo_pos = charpos;
                }
            }
-         if (NILP (pointer))
-           pointer = Fplist_get (XCDR (object), QCpointer);
        }
+      if (NILP (pointer))
+       pointer = Fsafe_plist_get (XCDR (object), QCpointer);
     }
 
   if (STRINGP (string))
@@ -20769,13 +21293,16 @@ note_mode_line_or_margin_highlight (w, x, y, area)
       /* If we're on a string with `help-echo' text property, arrange
         for the help to be displayed.  This is done by setting the
         global variable help_echo_string to the help string.  */
-      help = Fget_text_property (pos, Qhelp_echo, string);
-      if (!NILP (help))
+      if (NILP (help))
        {
-         help_echo_string = help;
-         XSETWINDOW (help_echo_window, w);
-         help_echo_object = string;
-         help_echo_pos = charpos;
+         help = Fget_text_property (pos, Qhelp_echo, string);
+         if (!NILP (help))
+           {
+             help_echo_string = help;
+             XSETWINDOW (help_echo_window, w);
+             help_echo_object = string;
+             help_echo_pos = charpos;
+           }
        }
 
       if (NILP (pointer))
@@ -20842,8 +21369,10 @@ note_mouse_highlight (f, x, y)
   /* Which window is that in?  */
   window = window_from_coordinates (f, x, y, &part, 0, 0, 1);
 
-  /* If we were displaying active text in another window, clear that.  */
-  if (! EQ (window, dpyinfo->mouse_face_window))
+  /* If we were displaying active text in another window, clear that.
+     Also clear if we move out of text area in same window.  */
+  if (! EQ (window, dpyinfo->mouse_face_window)
+      || (part != ON_TEXT && !NILP (dpyinfo->mouse_face_window)))
     clear_mouse_face (dpyinfo);
 
   /* Not on a window -> return.  */
@@ -20875,7 +21404,8 @@ note_mouse_highlight (f, x, y)
 
   if (part == ON_VERTICAL_BORDER)
     cursor = FRAME_X_OUTPUT (f)->horizontal_drag_cursor;
-  else if (part == ON_LEFT_FRINGE || part == ON_RIGHT_FRINGE)
+  else if (part == ON_LEFT_FRINGE || part == ON_RIGHT_FRINGE
+          || part == ON_SCROLL_BAR)
     cursor = FRAME_X_OUTPUT (f)->nontext_cursor;
   else
     cursor = FRAME_X_OUTPUT (f)->text_cursor;
@@ -20907,7 +21437,7 @@ note_mouse_highlight (f, x, y)
          if (img != NULL && IMAGEP (img->spec))
            {
              Lisp_Object image_map, hotspot;
-             if ((image_map = Fplist_get (XCDR (img->spec), QCmap),
+             if ((image_map = Fsafe_plist_get (XCDR (img->spec), QCmap),
                   !NILP (image_map))
                  && (hotspot = find_hot_spot (image_map,
                                               glyph->slice.x + dx,
@@ -20921,12 +21451,14 @@ note_mouse_highlight (f, x, y)
                  /* Could check AREA_ID to see if we enter/leave this hot-spot.
                     If so, we could look for mouse-enter, mouse-leave
                     properties in PLIST (and do something...).  */
-                 if ((plist = XCDR (hotspot), CONSP (plist)))
+                 hotspot = XCDR (hotspot);
+                 if (CONSP (hotspot)
+                     && (plist = XCAR (hotspot), CONSP (plist)))
                    {
-                     pointer = Fplist_get (plist, Qpointer);
+                     pointer = Fsafe_plist_get (plist, Qpointer);
                      if (NILP (pointer))
                        pointer = Qhand;
-                     help_echo_string = Fplist_get (plist, Qhelp_echo);
+                     help_echo_string = Fsafe_plist_get (plist, Qhelp_echo);
                      if (!NILP (help_echo_string))
                        {
                          help_echo_window = window;
@@ -20936,7 +21468,7 @@ note_mouse_highlight (f, x, y)
                    }
                }
              if (NILP (pointer))
-               pointer = Fplist_get (XCDR (img->spec), QCpointer);
+               pointer = Fsafe_plist_get (XCDR (img->spec), QCpointer);
            }
        }
 
@@ -21530,6 +22062,9 @@ x_draw_vertical_border (w)
      do it for frames with vertical scroll bars because either the
      right scroll bar of a window, or the left scroll bar of its
      neighbor will suffice as a border.  */
+  if (FRAME_HAS_VERTICAL_SCROLL_BARS (XFRAME (w->frame)))
+    return;
+
   if (!WINDOW_RIGHTMOST_P (w)
       && !WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w))
     {
@@ -21627,7 +22162,9 @@ expose_window (w, fr)
              || (r.y >= y0 && r.y < y1)
              || (r.y + r.height > y0 && r.y + r.height < y1))
            {
-             if (row->overlapping_p)
+             /* A header line may be overlapping, but there is no need
+                to fix overlapping areas for them.  KFS 2005-02-12 */
+             if (row->overlapping_p && !row->mode_line_p)
                {
                  if (first_overlapping_row == NULL)
                    first_overlapping_row = row;
@@ -21667,20 +22204,6 @@ expose_window (w, fr)
        }
     }
 
-#ifdef HAVE_CARBON
-  /* Display scroll bar for this window.  */
-  if (!NILP (w->vertical_scroll_bar))
-    {
-      /* ++KFS:
-        If this doesn't work here (maybe some header files are missing),
-        make a function in macterm.c and call it to do the job! */
-      ControlHandle ch
-       = SCROLL_BAR_CONTROL_HANDLE (XSCROLL_BAR (w->vertical_scroll_bar));
-
-      Draw1Control (ch);
-    }
-#endif
-
   return mouse_face_overwritten_p;
 }
 
@@ -21739,16 +22262,6 @@ expose_frame (f, x, y, w, h)
       return;
     }
 
-#ifdef HAVE_CARBON
-  /* MAC_TODO: this is a kludge, but if scroll bars are not activated
-     or deactivated here, for unknown reasons, activated scroll bars
-     are shown in deactivated frames in some instances.  */
-  if (f == FRAME_MAC_DISPLAY_INFO (f)->x_focus_frame)
-    activate_scroll_bars (f);
-  else
-    deactivate_scroll_bars (f);
-#endif
-
   /* If basic faces haven't been realized yet, there is no point in
      trying to redraw anything.  This can happen when we get an expose
      event while Emacs is starting, e.g. by moving another window.  */
@@ -21953,8 +22466,6 @@ syms_of_xdisp ()
   staticpro (&Qcenter);
   Qline_height = intern ("line-height");
   staticpro (&Qline_height);
-  Qtotal = intern ("total");
-  staticpro (&Qtotal);
   QCalign_to = intern (":align-to");
   staticpro (&QCalign_to);
   QCrelative_width = intern (":relative-width");
@@ -21973,6 +22484,8 @@ syms_of_xdisp ()
   staticpro (&Qfontification_functions);
   Qtrailing_whitespace = intern ("trailing-whitespace");
   staticpro (&Qtrailing_whitespace);
+  Qescape_glyph = intern ("escape-glyph");
+  staticpro (&Qescape_glyph);
   Qimage = intern ("image");
   staticpro (&Qimage);
   QCmap = intern (":map");
@@ -22075,6 +22588,10 @@ wide as that tab on the display.  */);
 The face used for trailing whitespace is `trailing-whitespace'.  */);
   Vshow_trailing_whitespace = Qnil;
 
+  DEFVAR_LISP ("show-nonbreak-escape", &Vshow_nonbreak_escape,
+    doc: /* *Non-nil means display escape character before non-break space and hyphen.  */);
+  Vshow_nonbreak_escape = Qt;
+
   DEFVAR_LISP ("void-text-area-pointer", &Vvoid_text_area_pointer,
     doc: /* *The pointer shape to show in void text areas.
 Nil means to show the text pointer.  Other options are `arrow', `text',
@@ -22230,6 +22747,10 @@ otherwise.  */);
     doc: /* *Non-nil means raise tool-bar buttons when the mouse moves over them.  */);
   auto_raise_tool_bar_buttons_p = 1;
 
+  DEFVAR_BOOL ("make-cursor-line-fully-visible", &make_cursor_line_fully_visible_p,
+    doc: /* *Non-nil means to scroll (recenter) cursor line if it is not fully visible.  */);
+  make_cursor_line_fully_visible_p = 1;
+
   DEFVAR_LISP ("tool-bar-button-margin", &Vtool_bar_button_margin,
     doc: /* *Margin around tool-bar buttons in pixels.
 If an integer, use that for both horizontal and vertical margins.
@@ -22321,8 +22842,10 @@ Bind this around calls to `message' to let it take effect.  */);
   message_truncate_lines = 0;
 
   DEFVAR_LISP ("menu-bar-update-hook",  &Vmenu_bar_update_hook,
-    doc: /* Normal hook run for clicks on menu bar, before displaying a submenu.
-Can be used to update submenus whose contents should vary.  */);
+    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.  */);
   Vmenu_bar_update_hook = Qnil;
 
   DEFVAR_BOOL ("inhibit-menubar-update", &inhibit_menubar_update,