]> code.delx.au - gnu-emacs/blobdiff - src/xdisp.c
(pos_visible_p): CHARPOS < 0 means return info for
[gnu-emacs] / src / xdisp.c
index 2b97866592e98c23909674e1ed87df4af49f3405..c766f714335778540ae2bfcfaac1154514c2d817 100644 (file)
@@ -1,6 +1,7 @@
 /* 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, 2006 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -16,8 +17,8 @@ GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
 along with GNU Emacs; see the file COPYING.  If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA.  */
+the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA.  */
 
 /* New redisplay written by Gerd Moellmann <gerd@gnu.org>.
 
@@ -231,7 +232,7 @@ extern Lisp_Object Qhelp_echo;
 
 Lisp_Object Qoverriding_local_map, Qoverriding_terminal_local_map;
 Lisp_Object Qwindow_scroll_functions, Vwindow_scroll_functions;
-Lisp_Object Qredisplay_end_trigger_functions;
+Lisp_Object Qredisplay_end_trigger_functions, Vredisplay_end_trigger_functions;
 Lisp_Object Qinhibit_point_motion_hooks;
 Lisp_Object QCeval, QCfile, QCdata, QCpropertize;
 Lisp_Object Qfontified;
@@ -255,9 +256,9 @@ Lisp_Object list_of_error;
 Lisp_Object Vfontification_functions;
 Lisp_Object Qfontification_functions;
 
-/* Non-zero means automatically select any window when the mouse
+/* Non-nil means automatically select any window when the mouse
    cursor moves into it.  */
-int mouse_autoselect_window;
+Lisp_Object Vmouse_autoselect_window;
 
 /* Non-zero means draw tool bar buttons raised when the mouse moves
    over them.  */
@@ -268,6 +269,12 @@ int auto_raise_tool_bar_buttons_p;
 
 int make_cursor_line_fully_visible_p;
 
+/* Margin below tool bar in pixels.  0 or nil means no margin.
+   If value is `internal-border-width' or `border-width',
+   the corresponding frame parameter is used.  */
+
+Lisp_Object Vtool_bar_border;
+
 /* Margin around tool bar buttons in pixels.  */
 
 Lisp_Object Vtool_bar_button_margin;
@@ -308,7 +315,7 @@ 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;
@@ -318,6 +325,10 @@ extern Lisp_Object Qcursor;
 
 Lisp_Object Vshow_trailing_whitespace;
 
+/* Non-nil means escape non-break space and hyphens.  */
+
+Lisp_Object Vnobreak_char_display;
+
 #ifdef HAVE_WINDOW_SYSTEM
 extern Lisp_Object Voverflow_newline_into_fringe;
 
@@ -345,7 +356,10 @@ Lisp_Object Qtrailing_whitespace;
 /* Name and number of the face used to highlight escape glyphs.  */
 
 Lisp_Object Qescape_glyph;
-int escape_glyph_face;
+
+/* Name and number of the face used to highlight non-breaking spaces.  */
+
+Lisp_Object Qnobreak_space;
 
 /* The symbol `image' which is the car of the lists used to represent
    images in Lisp.  */
@@ -459,7 +473,7 @@ static Lisp_Object Vwindow_size_change_functions;
 
 Lisp_Object Qmenu_bar_update_hook, Vmenu_bar_update_hook;
 
-/* Nonzero if overlay arrow has been displayed once in this window.  */
+/* Nonzero if an overlay arrow has been displayed in this window.  */
 
 static int overlay_arrow_seen;
 
@@ -564,12 +578,21 @@ Lisp_Object Vmessage_log_max;
 
 static Lisp_Object Vmessages_buffer_name;
 
-/* Current, index 0, and last displayed echo area message.  Either
-   buffers from echo_buffers, or nil to indicate no message.  */
+/* Index 0 is the buffer that holds the current (desired) echo area message,
+   or nil if none is desired right now.
+
+   Index 1 is the buffer that holds the previously displayed echo area message,
+   or nil to indicate no message.  This is normally what's on the screen now.
+
+   These two can point to the same buffer.  That happens when the last
+   message output by the user (or made by echoing) has been displayed.  */
 
 Lisp_Object echo_area_buffer[2];
 
-/* The buffers referenced from echo_area_buffer.  */
+/* Permanent pointers to the two buffers that are used for echo area
+   purposes.  Once the two buffers are made, and their pointers are
+   placed here, these two slots remain unchanged unless those buffers
+   need to be created afresh.  */
 
 static Lisp_Object echo_buffer[2];
 
@@ -592,6 +615,11 @@ int message_buf_print;
 Lisp_Object Qinhibit_menubar_update;
 int inhibit_menubar_update;
 
+/* When evaluating expressions from menu bar items (enable conditions,
+   for instance), this is the frame they are being processed for.  */
+
+Lisp_Object Vmenu_updating_frame;
+
 /* Maximum height for resizing mini-windows.  Either a float
    specifying a fraction of the available height, or an integer
    specifying a number of lines.  */
@@ -609,12 +637,6 @@ Lisp_Object Qmessage_truncate_lines;
 
 static int message_cleared_p;
 
-/* Non-zero means we want a hollow cursor in windows that are not
-   selected.  Zero means there's no cursor in such windows.  */
-
-Lisp_Object Vcursor_in_non_selected_windows;
-Lisp_Object Qcursor_in_non_selected_windows;
-
 /* How to blink the default frame cursor off.  */
 Lisp_Object Vblink_cursor_alist;
 
@@ -693,6 +715,10 @@ Lisp_Object Vresize_mini_windows;
 
 struct buffer *displayed_buffer;
 
+/* Space between overline and text. */
+
+EMACS_INT overline_margin;
+
 /* Value returned from text property handlers (see below).  */
 
 enum prop_handled
@@ -778,6 +804,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;
@@ -814,7 +847,7 @@ static struct glyph_slice null_glyph_slice = { 0, 0, 0, 0 };
 
 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));
@@ -824,19 +857,18 @@ 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,
                                                        struct text_pos));
 static void reconsider_clip_changes P_ ((struct window *, struct buffer *));
 static int text_outside_line_unchanged_p P_ ((struct window *, int, int));
-static void store_frame_title_char P_ ((char));
-static int store_frame_title P_ ((const unsigned char *, int, int));
+static void store_mode_line_noprop_char P_ ((char));
+static int store_mode_line_noprop 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 tool_bar_lines_needed P_ ((struct frame *, int *));
+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 *));
@@ -861,7 +893,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));
@@ -877,7 +909,7 @@ static void redisplay_window P_ ((Lisp_Object, int));
 static Lisp_Object redisplay_window_error ();
 static Lisp_Object redisplay_window_0 P_ ((Lisp_Object));
 static Lisp_Object redisplay_window_1 P_ ((Lisp_Object));
-static void update_menu_bar P_ ((struct frame *, int));
+static int update_menu_bar P_ ((struct frame *, int, int));
 static int try_window_reusing_current_matrix P_ ((struct window *));
 static int try_window_id P_ ((struct window *));
 static int display_line P_ ((struct it *));
@@ -893,12 +925,14 @@ static int display_string P_ ((unsigned char *, Lisp_Object, Lisp_Object,
 static void compute_line_metrics P_ ((struct it *));
 static void run_redisplay_end_trigger_hook P_ ((struct it *));
 static int get_overlay_strings P_ ((struct it *, int));
+static int get_overlay_strings_1 P_ ((struct it *, int, int));
 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 *));
 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 *));
@@ -930,7 +964,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 *));
@@ -945,7 +979,7 @@ static int in_ellipses_for_invisible_text_p P_ ((struct display_pos *,
 static void update_tool_bar P_ ((struct frame *, int));
 static void build_desired_tool_bar_string P_ ((struct frame *f));
 static int redisplay_tool_bar P_ ((struct frame *));
-static void display_tool_bar_line P_ ((struct it *));
+static void display_tool_bar_line P_ ((struct it *, int));
 static void notice_overwritten_cursor P_ ((struct window *,
                                           enum glyph_row_area,
                                           int, int, int, int));
@@ -1240,83 +1274,92 @@ 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.
-   EXACT_MODE_LINE_HEIGHTS_P non-zero means compute exact mode-line
-   and header-lines heights.  */
+/* Return 1 if position CHARPOS is visible in window W.
+   CHARPOS < 0 means return info about WINDOW_END position.
+   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.
+   Set *ROWH and *VPOS to row's visible height and VPOS (row number).  */
 
 int
-pos_visible_p (w, charpos, fully, x, y, exact_mode_line_heights_p)
+pos_visible_p (w, charpos, x, y, rtop, rbot, rowh, vpos)
      struct window *w;
-     int charpos, *fully, *x, *y, exact_mode_line_heights_p;
+     int charpos, *x, *y, *rtop, *rbot, *rowh, *vpos;
 {
   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.  */
-  if (exact_mode_line_heights_p)
-    {
-      if (WINDOW_WANTS_MODELINE_P (w))
-       current_mode_line_height
-         = display_mode_line (w, CURRENT_MODE_LINE_FACE_ID (w),
-                              current_buffer->mode_line_format);
+  /* Compute exact mode line heights.  */
+  if (WINDOW_WANTS_MODELINE_P (w))
+    current_mode_line_height
+      = display_mode_line (w, CURRENT_MODE_LINE_FACE_ID (w),
+                          current_buffer->mode_line_format);
 
-      if (WINDOW_WANTS_HEADER_LINE_P (w))
-       current_header_line_height
-         = display_mode_line (w, HEADER_LINE_FACE_ID,
+  if (WINDOW_WANTS_HEADER_LINE_P (w))
+    current_header_line_height
+      = display_mode_line (w, HEADER_LINE_FACE_ID,
                               current_buffer->header_line_format);
-    }
 
   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, -1,
+             (charpos >= 0 ? MOVE_TO_POS : 0) | MOVE_TO_Y);
 
   /* Note that we may overshoot because of invisible text.  */
-  if (IT_CHARPOS (it) >= charpos)
+  if (charpos >= 0 && IT_CHARPOS (it) >= charpos)
     {
+      int top_x = it.current_x;
       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)
+      if (visible_p)
        {
-         *x = it.current_x;
-         *y = max (top_y + it.max_ascent - it.ascent, window_top_y);
+         *x = top_x;
+         *y = max (top_y + max (0, it.max_ascent - it.ascent), window_top_y);
+         *rtop = max (0, window_top_y - top_y);
+         *rbot = max (0, bottom_y - it.last_visible_y);
+         *rowh = max (0, (min (bottom_y, it.last_visible_y)
+                          - max (top_y, window_top_y)));
+         *vpos = it.vpos;
        }
     }
-  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;
-         if (x)
-           {
-             move_it_to (&it2, charpos, -1, -1, -1, MOVE_TO_POS);
-             *x = it2.current_x;
-             *y = it2.current_y + it2.max_ascent - it2.ascent;
-           }
+         move_it_to (&it2, charpos, -1, -1, -1, MOVE_TO_POS);
+         *x = it2.current_x;
+         *y = it2.current_y + it2.max_ascent - it2.ascent;
+         *rtop = max (0, -it2.current_y);
+         *rbot = max (0, ((it2.current_y + it2.max_ascent + it2.max_descent)
+                          - it.last_visible_y));
+         *rowh = max (0, (min (it2.current_y + it2.max_ascent + it2.max_descent,
+                               it.last_visible_y)
+                          - max (it2.current_y,
+                                 WINDOW_HEADER_LINE_HEIGHT (w))));
+         *vpos = it2.vpos;
        }
     }
 
@@ -1325,6 +1368,18 @@ pos_visible_p (w, charpos, fully, x, y, exact_mode_line_heights_p)
 
   current_header_line_height = current_mode_line_height = -1;
 
+  if (visible_p && XFASTINT (w->hscroll) > 0)
+    *x -= XFASTINT (w->hscroll) * WINDOW_FRAME_COLUMN_WIDTH (w);
+
+#if 0
+  /* Debugging code.  */
+  if (visible_p)
+    fprintf (stderr, "+pv pt=%d vs=%d --> x=%d y=%d rt=%d rb=%d rh=%d vp=%d\n",
+            charpos, w->vscroll, *x, *y, *rtop, *rbot, *rowh, *vpos);
+  else
+    fprintf (stderr, "-pv pt=%d vs=%d\n", charpos, w->vscroll);
+#endif
+
   return visible_p;
 }
 
@@ -1743,15 +1798,20 @@ frame_to_window_pixel_xy (w, x, y)
 }
 
 /* EXPORT:
-   Return in *R the clipping rectangle for glyph string S.  */
+   Return in RECTS[] at most N clipping rectangles for glyph string S.
+   Return the number of stored rectangles.  */
 
-void
-get_glyph_string_clip_rect (s, nr)
+int
+get_glyph_string_clip_rects (s, rects, n)
      struct glyph_string *s;
-     NativeRectangle *nr;
+     NativeRectangle *rects;
+     int n;
 {
   XRectangle r;
 
+  if (n <= 0)
+    return 0;
+
   if (s->row->full_width_p)
     {
       /* Draw full-width.  X coordinates are relative to S->w->left_col.  */
@@ -1773,13 +1833,48 @@ 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.  */
-  if (s->for_overlaps_p)
+  if (s->for_overlaps)
     {
       r.y = WINDOW_HEADER_LINE_HEIGHT (s->w);
       r.height = window_text_bottom_y (s->w) - r.y;
+
+      /* Alas, the above simple strategy does not work for the
+        environments with anti-aliased text: if the same text is
+        drawn onto the same place multiple times, it gets thicker.
+        If the overlap we are processing is for the erased cursor, we
+        take the intersection with the rectagle of the cursor.  */
+      if (s->for_overlaps & OVERLAPS_ERASED_CURSOR)
+       {
+         XRectangle rc, r_save = r;
+
+         rc.x = WINDOW_TEXT_TO_FRAME_PIXEL_X (s->w, s->w->phys_cursor.x);
+         rc.y = s->w->phys_cursor.y;
+         rc.width = s->w->phys_cursor_width;
+         rc.height = s->w->phys_cursor_height;
+
+         x_intersect_rectangles (&r_save, &rc, &r);
+       }
     }
   else
     {
@@ -1806,7 +1901,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)
        {
@@ -1815,23 +1910,359 @@ 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)
        {
-         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);
+         r.y = max_y;
+         r.height = height;
+       }
+      else
+       {
+         /* 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);
+           }
        }
     }
 
+  if ((s->for_overlaps & OVERLAPS_BOTH) == 0
+      || ((s->for_overlaps & OVERLAPS_BOTH) == OVERLAPS_BOTH && n == 1))
+    {
 #ifdef CONVERT_FROM_XRECT
-  CONVERT_FROM_XRECT (r, *nr);
+      CONVERT_FROM_XRECT (r, *rects);
 #else
-  *nr = r;
+      *rects = r;
+#endif
+      return 1;
+    }
+  else
+    {
+      /* If we are processing overlapping and allowed to return
+        multiple clipping rectangles, we exclude the row of the glyph
+        string from the clipping rectangle.  This is to avoid drawing
+        the same text on the environment with anti-aliasing.  */
+#ifdef CONVERT_FROM_XRECT
+      XRectangle rs[2];
+#else
+      XRectangle *rs = rects;
+#endif
+      int i = 0, row_y = WINDOW_TO_FRAME_PIXEL_Y (s->w, s->row->y);
+
+      if (s->for_overlaps & OVERLAPS_PRED)
+       {
+         rs[i] = r;
+         if (r.y + r.height > row_y)
+           {
+             if (r.y < row_y)
+               rs[i].height = row_y - r.y;
+             else
+               rs[i].height = 0;
+           }
+         i++;
+       }
+      if (s->for_overlaps & OVERLAPS_SUCC)
+       {
+         rs[i] = r;
+         if (r.y < row_y + s->row->visible_height)
+           {
+             if (r.y + r.height > row_y + s->row->visible_height)
+               {
+                 rs[i].y = row_y + s->row->visible_height;
+                 rs[i].height = r.y + r.height - rs[i].y;
+               }
+             else
+               rs[i].height = 0;
+           }
+         i++;
+       }
+
+      n = i;
+#ifdef CONVERT_FROM_XRECT
+      for (i = 0; i < n; i++)
+       CONVERT_FROM_XRECT (rs[i], rects[i]);
 #endif
+      return n;
+    }
+}
+
+/* EXPORT:
+   Return in *NR the clipping rectangle for glyph string S.  */
+
+void
+get_glyph_string_clip_rect (s, nr)
+     struct glyph_string *s;
+     NativeRectangle *nr;
+{
+  get_glyph_string_clip_rects (s, nr, 1);
+}
+
+
+/* EXPORT:
+   Return the position and height of the phys cursor in window W.
+   Set w->phys_cursor_width to width of phys cursor.
+*/
+
+void
+get_phys_cursor_geometry (w, row, glyph, xp, yp, heightp)
+     struct window *w;
+     struct glyph_row *row;
+     struct glyph *glyph;
+     int *xp, *yp, *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
+
+  x = w->phys_cursor.x;
+  if (x < 0)
+    {
+      wd += x;
+      x = 0;
+    }
+
+  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;
+       }
+    }
+
+  *xp = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, x);
+  *yp = WINDOW_TO_FRAME_PIXEL_Y (w, y);
+  *heightp = h;
 }
 
+/*
+ * Remember which glyph the mouse is over.
+ */
+
+void
+remember_mouse_glyph (f, gx, gy, rect)
+     struct frame *f;
+     int gx, gy;
+     NativeRectangle *rect;
+{
+  Lisp_Object window;
+  struct window *w;
+  struct glyph_row *r, *gr, *end_row;
+  enum window_part part;
+  enum glyph_row_area area;
+  int x, y, width, height;
+
+  /* Try to determine frame pixel position and size of the glyph under
+     frame pixel coordinates X/Y on frame F.  */
+
+  window = window_from_coordinates (f, gx, gy, &part, &x, &y, 0);
+  if (NILP (window))
+    {
+      width = FRAME_SMALLEST_CHAR_WIDTH (f);
+      height = FRAME_SMALLEST_FONT_HEIGHT (f);
+      goto virtual_glyph;
+    }
+
+  w = XWINDOW (window);
+  width = WINDOW_FRAME_COLUMN_WIDTH (w);
+  height = WINDOW_FRAME_LINE_HEIGHT (w);
+
+  r = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
+  end_row = MATRIX_BOTTOM_TEXT_ROW (w->current_matrix, w);
+
+  if (w->pseudo_window_p)
+    {
+      area = TEXT_AREA;
+      part = ON_MODE_LINE; /* Don't adjust margin. */
+      goto text_glyph;
+    }
+
+  switch (part)
+    {
+    case ON_LEFT_MARGIN:
+      area = LEFT_MARGIN_AREA;
+      goto text_glyph;
+
+    case ON_RIGHT_MARGIN:
+      area = RIGHT_MARGIN_AREA;
+      goto text_glyph;
+
+    case ON_HEADER_LINE:
+    case ON_MODE_LINE:
+      gr = (part == ON_HEADER_LINE
+           ? MATRIX_HEADER_LINE_ROW (w->current_matrix)
+           : MATRIX_MODE_LINE_ROW (w->current_matrix));
+      gy = gr->y;
+      area = TEXT_AREA;
+      goto text_glyph_row_found;
+
+    case ON_TEXT:
+      area = TEXT_AREA;
+
+    text_glyph:
+      gr = 0; gy = 0;
+      for (; r <= end_row && r->enabled_p; ++r)
+       if (r->y + r->height > y)
+         {
+           gr = r; gy = r->y;
+           break;
+         }
+
+    text_glyph_row_found:
+      if (gr && gy <= y)
+       {
+         struct glyph *g = gr->glyphs[area];
+         struct glyph *end = g + gr->used[area];
+
+         height = gr->height;
+         for (gx = gr->x; g < end; gx += g->pixel_width, ++g)
+           if (gx + g->pixel_width > x)
+             break;
+
+         if (g < end)
+           {
+             if (g->type == IMAGE_GLYPH)
+               {
+                 /* Don't remember when mouse is over image, as
+                    image may have hot-spots.  */
+                 STORE_NATIVE_RECT (*rect, 0, 0, 0, 0);
+                 return;
+               }
+             width = g->pixel_width;
+           }
+         else
+           {
+             /* Use nominal char spacing at end of line.  */
+             x -= gx;
+             gx += (x / width) * width;
+           }
+
+         if (part != ON_MODE_LINE && part != ON_HEADER_LINE)
+           gx += window_box_left_offset (w, area);
+       }
+      else
+       {
+         /* Use nominal line height at end of window.  */
+         gx = (x / width) * width;
+         y -= gy;
+         gy += (y / height) * height;
+       }
+      break;
+
+    case ON_LEFT_FRINGE:
+      gx = (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
+           ? WINDOW_LEFT_SCROLL_BAR_AREA_WIDTH (w)
+           : window_box_right_offset (w, LEFT_MARGIN_AREA));
+      width = WINDOW_LEFT_FRINGE_WIDTH (w);
+      goto row_glyph;
+
+    case ON_RIGHT_FRINGE:
+      gx = (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
+           ? window_box_right_offset (w, RIGHT_MARGIN_AREA)
+           : window_box_right_offset (w, TEXT_AREA));
+      width = WINDOW_RIGHT_FRINGE_WIDTH (w);
+      goto row_glyph;
+
+    case ON_SCROLL_BAR:
+      gx = (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w)
+           ? 0
+           : (window_box_right_offset (w, RIGHT_MARGIN_AREA)
+              + (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
+                 ? WINDOW_RIGHT_FRINGE_WIDTH (w)
+                 : 0)));
+      width = WINDOW_SCROLL_BAR_AREA_WIDTH (w);
+
+    row_glyph:
+      gr = 0, gy = 0;
+      for (; r <= end_row && r->enabled_p; ++r)
+       if (r->y + r->height > y)
+         {
+           gr = r; gy = r->y;
+           break;
+         }
+
+      if (gr && gy <= y)
+       height = gr->height;
+      else
+       {
+         /* Use nominal line height at end of window.  */
+         y -= gy;
+         gy += (y / height) * height;
+       }
+      break;
+
+    default:
+      ;
+    virtual_glyph:
+      /* If there is no glyph under the mouse, then we divide the screen
+        into a grid of the smallest glyph in the frame, and use that
+        as our "glyph".  */
+
+      /* Arrange for the division in FRAME_PIXEL_X_TO_COL etc. to
+        round down even for negative values.  */
+      if (gx < 0)
+       gx -= width - 1;
+      if (gy < 0)
+       gy -= height - 1;
+
+      gx = (gx / width) * width;
+      gy = (gy / height) * height;
+
+      goto store_rect;
+    }
+
+  gx += WINDOW_LEFT_EDGE_X (w);
+  gy += WINDOW_TOP_EDGE_Y (w);
+
+ store_rect:
+  STORE_NATIVE_RECT (*rect, gx, gy, width, height);
+
+  /* Visible feedback for debugging.  */
+#if 0
+#if HAVE_X_WINDOWS
+  XDrawRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
+                 f->output_data.x->normal_gc,
+                 gx, gy, width, height);
+#endif
+#endif
+}
+
+
 #endif /* HAVE_WINDOW_SYSTEM */
 
 \f
@@ -1941,7 +2372,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);
@@ -1949,7 +2380,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)));
@@ -2298,7 +2729,9 @@ start_display (it, w, pos)
   init_iterator (it, w, CHARPOS (pos), BYTEPOS (pos), row, DEFAULT_FACE_ID);
   it->first_vpos = first_vpos;
 
-  if (!it->truncate_lines_p)
+  /* Don't reseat to previous visible line start if current start
+     position is in a string or image.  */
+  if (it->method == GET_FROM_BUFFER && !it->truncate_lines_p)
     {
       int start_at_line_beg_p;
       int first_y = it->current_y;
@@ -2434,7 +2867,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]);
@@ -2459,7 +2895,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
@@ -2482,7 +2918,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
@@ -2497,8 +2933,8 @@ init_from_display_pos (it, w, pos)
         also ``processed'' overlay strings at ZV.  */
       while (it->sp)
        pop_it (it);
-      it->current.overlay_string_index = -1;
-      it->method = next_element_from_buffer;
+      xassert (it->current.overlay_string_index == -1);
+      xassert (it->method == GET_FROM_BUFFER);
       if (CHARPOS (pos->pos) == ZV)
        it->overlay_strings_at_end_processed_p = 1;
     }
@@ -2585,11 +3021,17 @@ handle_stop (it)
      struct it *it;
 {
   enum prop_handled handled;
-  int handle_overlay_change_p = 1;
+  int handle_overlay_change_p;
   struct props *p;
 
   it->dpvec = NULL;
   it->current.dpvec_index = -1;
+  handle_overlay_change_p = !it->ignore_overlay_strings_at_pos_p;
+  it->ignore_overlay_strings_at_pos_p = 0;
+
+  /* Use face of preceding text for ellipsis (if invisible) */
+  if (it->selective_display_ellipsis_p)
+    it->saved_face_id = it->face_id;
 
   do
     {
@@ -2603,7 +3045,19 @@ handle_stop (it)
          if (handled == HANDLED_RECOMPUTE_PROPS)
            break;
          else if (handled == HANDLED_RETURN)
-           return;
+           {
+             /* We still want to show before and after strings from
+                overlays even if the actual buffer text is replaced.  */
+             if (!handle_overlay_change_p || it->sp > 1)
+               return;
+             if (!get_overlay_strings_1 (it, 0, 0))
+               return;
+             it->ignore_overlay_strings_at_pos_p = 1;
+             it->string_from_display_prop_p = 0;
+             handle_overlay_change_p = 0;
+             handled = HANDLED_RECOMPUTE_PROPS;
+             break;
+           }
          else if (handled == HANDLED_OVERLAY_STRING_CONSUMED)
            handle_overlay_change_p = 0;
        }
@@ -2612,7 +3066,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.  */
@@ -2779,6 +3233,9 @@ handle_fontified_prop (it)
   Lisp_Object prop, pos;
   enum prop_handled handled = HANDLED_NORMALLY;
 
+  if (!NILP (Vmemory_full))
+    return handled;
+
   /* Get the value of the `fontified' property at IT's current buffer
      position.  (The `fontified' property doesn't have a special
      meaning in strings.)  If the value is nil, call functions from
@@ -3212,6 +3669,11 @@ handle_invisible_prop (it)
                 skip starting with next_stop.  */
              if (invis_p)
                IT_CHARPOS (*it) = next_stop;
+
+              /* If there are adjacent invisible texts, don't lose the
+                 second one's ellipsis. */
+              if (invis_p == 2)
+                display_ellipsis_p = 1;
            }
          while (invis_p);
 
@@ -3232,7 +3694,26 @@ handle_invisible_prop (it)
              it->stack[it->sp - 1].display_ellipsis_p = display_ellipsis_p;
            }
          else if (display_ellipsis_p)
-           setup_for_ellipsis (it, 0);
+            {
+              /* Make sure that the glyphs of the ellipsis will get
+                 correct `charpos' values.  If we would not update
+                 it->position here, the glyphs would belong to the
+                 last visible character _before_ the invisible
+                 text, which confuses `set_cursor_from_row'.
+
+                 We use the last invisible position instead of the
+                 first because this way the cursor is always drawn on
+                 the first "." of the ellipsis, whenever PT is inside
+                 the invisible text.  Otherwise the cursor would be
+                 placed _after_ the ellipsis when the point is after the
+                 first invisible character.  */
+             if (!STRINGP (it->object))
+               {
+                 it->position.charpos = IT_CHARPOS (*it) - 1;
+                 it->position.bytepos = CHAR_TO_BYTE (it->position.charpos);
+               }
+              setup_for_ellipsis (it, 0);
+            }
        }
     }
 
@@ -3265,11 +3746,16 @@ setup_for_ellipsis (it, len)
 
   it->dpvec_char_len = len;
   it->current.dpvec_index = 0;
+  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 = next_element_from_display_vector;
+     IT's face is restored in set_iterator_to_next.
+     saved_face_id was set to preceding char's face in handle_stop.  */
+  if (it->saved_face_id < 0 || it->saved_face_id != it->face_id)
+    it->saved_face_id = it->face_id = DEFAULT_FACE_ID;
+
+  it->method = GET_FROM_DISPLAY_VECTOR;
+  it->ellipsis_p = 1;
 }
 
 
@@ -3279,7 +3765,10 @@ setup_for_ellipsis (it, len)
  ***********************************************************************/
 
 /* 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)
@@ -3287,6 +3776,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))
@@ -3296,7 +3786,7 @@ handle_display_prop (it)
     }
   else
     {
-      object = it->w->buffer;
+      XSETWINDOW (object, it->w);
       position = &it->current.pos;
     }
 
@@ -3317,6 +3807,9 @@ handle_display_prop (it)
   if (NILP (prop))
     return HANDLED_NORMALLY;
 
+  if (!STRINGP (it->string))
+    object = it->w->buffer;
+
   if (CONSP (prop)
       /* Simple properties.  */
       && !EQ (XCAR (prop), Qimage)
@@ -3334,7 +3827,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;
        }
@@ -3343,13 +3836,16 @@ 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))
+      int ret = handle_single_display_spec (it, prop, object, position, 0);
+      if (ret < 0)  /* Replaced by "", i.e. nothing. */
+       return HANDLED_RECOMPUTE_PROPS;
+      if (ret)
        display_replaced_p = 1;
     }
 
@@ -3381,42 +3877,45 @@ 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.  */
+   of buffer or string text.  Specifically, the value is -1 if that
+   "something" is "nothing". */
 
 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, save_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))
@@ -3442,15 +3941,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);
@@ -3491,7 +3990,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]);
@@ -3505,29 +4003,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))
@@ -3541,17 +4045,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);
@@ -3559,185 +4066,206 @@ 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)))
-       {
-         int face_id = DEFAULT_FACE_ID;
-         int fringe_bitmap;
+  /* 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 (!SYMBOLP (value)
-             || !(fringe_bitmap = lookup_fringe_bitmap (value)))
-           return 0;
+      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;
 
-         if (CONSP (XCDR (XCDR (prop))))
-           {
-             Lisp_Object face_name = XCAR (XCDR (XCDR (prop)));
-             int face_id2 = lookup_named_face (it->f, face_name, 'A', 0);
-             if (face_id2 >= 0)
-               face_id = face_id2;
-           }
+      if (CONSP (XCDR (XCDR (spec))))
+       {
+         Lisp_Object face_name = XCAR (XCDR (XCDR (spec)));
+         int face_id2 = lookup_derived_face (it->f, face_name,
+                                             'A', FRINGE_FACE_ID, 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;
+      save_pos = it->position;
+      it->position = *position;
+      push_it (it);
+      it->position = save_pos;
 
-         /* 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 = fringe_bitmap;
-             it->left_user_fringe_face_id = face_id;
-           }
-         else
-           {
-             it->right_user_fringe_bitmap = fringe_bitmap;
-             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)
+  /* 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;
+
+      value = XCDR (spec);
+      if (CONSP (value))
+       value = XCAR (value);
+
+      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 (EQ (location, Qunbound))
+    {
+      location = Qnil;
+      value = spec;
+    }
+
+  /* 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
-                || (!FRAME_TERMCAP_P (it->f) && valid_image_p (value))
+            || (!FRAME_TERMCAP_P (it->f) && valid_image_p (value))
 #endif /* not HAVE_WINDOW_SYSTEM */
-                || (CONSP (value) && EQ (XCAR (value), Qspace)));
+            || (CONSP (value) && EQ (XCAR (value), Qspace)));
 
-      if ((EQ (location, Qleft_margin)
-          || EQ (location, Qright_margin)
-          || NILP (location))
-         && valid_p
-         && !display_replaced_before_p)
-       {
-         replaces_text_display_p = 1;
-
-         /* Save current settings of IT so that we can restore them
-            when we are finished with the glyph property value.  */
-         push_it (it);
+  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.  */
+      save_pos = it->position;
+      it->position = *position;
+      push_it (it);
+      it->position = save_pos;
 
-         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 (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 = 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))
+      if (STRINGP (value))
+       {
+         if (SCHARS (value) == 0)
            {
-             it->method = next_element_from_stretch;
-             it->object = value;
-             it->current.pos = it->position = start_pos;
+             pop_it (it);
+             return -1;  /* Replaced by "", i.e. nothing.  */
            }
+         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;
+         *position = it->position = start_pos;
+       }
 #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 */
+      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 = 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;
        }
-      else
-       /* Invalid property or property not supported.  Restore
-          the position to what it was before.  */
-       *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'.  */
@@ -3790,7 +4318,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);
        }
@@ -3800,11 +4328,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;
 }
@@ -3813,7 +4341,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))
@@ -3858,7 +4386,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);
        }
@@ -3868,11 +4396,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;
 }
@@ -3970,7 +4498,29 @@ handle_composition_prop (it)
 
       if (id >= 0)
        {
-         it->method = next_element_from_composition;
+         struct composition *cmp = composition_table[id];
+
+         if (cmp->glyph_len == 0)
+           {
+             /* No glyph.  */
+             if (STRINGP (it->string))
+               {
+                 IT_STRING_CHARPOS (*it) = end;
+                 IT_STRING_BYTEPOS (*it) = string_char_to_byte (it->string,
+                                                                end);
+               }
+             else
+               {
+                 IT_CHARPOS (*it) = end;
+                 IT_BYTEPOS (*it) = CHAR_TO_BYTE (end);
+               }
+             return HANDLED_RECOMPUTE_PROPS;
+           }
+
+         it->stop_charpos = end;
+         push_it (it);
+
+         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
@@ -3979,7 +4529,6 @@ handle_composition_prop (it)
          it->len = (STRINGP (it->string)
                     ? string_char_to_byte (it->string, end)
                     : CHAR_TO_BYTE (end)) - pos_byte;
-         it->stop_charpos = end;
          handled = HANDLED_RETURN;
        }
     }
@@ -4039,13 +4588,14 @@ next_overlay_string (it)
       int display_ellipsis_p = it->stack[it->sp - 1].display_ellipsis_p;
 
       pop_it (it);
-      xassert (it->stop_charpos >= BEGV
-              && it->stop_charpos <= it->end_charpos);
-      it->string = Qnil;
+      xassert (it->sp > 0
+              || it->method == GET_FROM_COMPOSITION
+              || (NILP (it->string)
+                  && it->method == GET_FROM_BUFFER
+                  && it->stop_charpos >= BEGV
+                  && it->stop_charpos <= it->end_charpos));
       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;
 
       /* If we're at the end of the buffer, record that we have
         processed the overlay strings there already, so that
@@ -4074,7 +4624,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;
     }
 
@@ -4301,7 +4851,7 @@ load_overlay_strings (it, charpos)
    least one overlay string was found.  */
 
 static int
-get_overlay_strings (it, charpos)
+get_overlay_strings_1 (it, charpos, compute_stop_p)
      struct it *it;
      int charpos;
 {
@@ -4323,12 +4873,13 @@ get_overlay_strings (it, charpos)
       /* Make sure we know settings in current_buffer, so that we can
         restore meaningful values when we're done with the overlay
         strings.  */
-      compute_stop_pos (it);
+      if (compute_stop_p)
+       compute_stop_pos (it);
       xassert (it->face_id >= 0);
 
       /* Save IT's settings.  They are restored after all overlay
         strings have been processed.  */
-      xassert (it->sp == 0);
+      xassert (!compute_stop_p || it->sp == 0);
       push_it (it);
 
       /* Set up IT to deliver display elements from the first overlay
@@ -4339,15 +4890,24 @@ 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;
-    }
-  else
-    {
-      it->string = Qnil;
-      it->current.overlay_string_index = -1;
-      it->method = next_element_from_buffer;
+      it->method = GET_FROM_STRING;
+      return 1;
     }
 
+  it->current.overlay_string_index = -1;
+  return 0;
+}
+
+static int
+get_overlay_strings (it, charpos)
+     struct it *it;
+     int charpos;
+{
+  it->string = Qnil;
+  it->method = GET_FROM_BUFFER;
+
+  (void) get_overlay_strings_1 (it, charpos, 1);
+
   CHECK_IT (it);
 
   /* Value is non-zero if we found at least one overlay string.  */
@@ -4371,19 +4931,38 @@ push_it (it)
 {
   struct iterator_stack_entry *p;
 
-  xassert (it->sp < 2);
+  xassert (it->sp < IT_STACK_SIZE);
   p = it->stack + it->sp;
 
   p->stop_charpos = it->stop_charpos;
   xassert (it->face_id >= 0);
   p->face_id = it->face_id;
   p->string = it->string;
-  p->pos = it->current;
+  p->method = it->method;
+  switch (p->method)
+    {
+    case GET_FROM_IMAGE:
+      p->u.image.object = it->object;
+      p->u.image.image_id = it->image_id;
+      p->u.image.slice = it->slice;
+      break;
+    case GET_FROM_COMPOSITION:
+      p->u.comp.object = it->object;
+      p->u.comp.c = it->c;
+      p->u.comp.len = it->len;
+      p->u.comp.cmp_id = it->cmp_id;
+      p->u.comp.cmp_len = it->cmp_len;
+      break;
+    case GET_FROM_STRETCH:
+      p->u.stretch.object = it->object;
+      break;
+    }
+  p->position = it->position;
+  p->current = it->current;
   p->end_charpos = it->end_charpos;
   p->string_nchars = it->string_nchars;
   p->area = it->area;
   p->multibyte_p = it->multibyte_p;
-  p->slice = it->slice;
   p->space_width = it->space_width;
   p->font_height = it->font_height;
   p->voffset = it->voffset;
@@ -4410,13 +4989,40 @@ pop_it (it)
   p = it->stack + it->sp;
   it->stop_charpos = p->stop_charpos;
   it->face_id = p->face_id;
+  it->current = p->current;
+  it->position = p->position;
   it->string = p->string;
-  it->current = p->pos;
+  if (NILP (it->string))
+    SET_TEXT_POS (it->current.string_pos, -1, -1);
+  it->method = p->method;
+  switch (it->method)
+    {
+    case GET_FROM_IMAGE:
+      it->image_id = p->u.image.image_id;
+      it->object = p->u.image.object;
+      it->slice = p->u.image.slice;
+      break;
+    case GET_FROM_COMPOSITION:
+      it->object = p->u.comp.object;
+      it->c = p->u.comp.c;
+      it->len = p->u.comp.len;
+      it->cmp_id = p->u.comp.cmp_id;
+      it->cmp_len = p->u.comp.cmp_len;
+      break;
+    case GET_FROM_STRETCH:
+      it->object = p->u.comp.object;
+      break;
+    case GET_FROM_BUFFER:
+      it->object = it->w->buffer;
+      break;
+    case GET_FROM_STRING:
+      it->object = it->string;
+      break;
+    }
   it->end_charpos = p->end_charpos;
   it->string_nchars = p->string_nchars;
   it->area = p->area;
   it->multibyte_p = p->multibyte_p;
-  it->slice = p->slice;
   it->space_width = p->space_width;
   it->font_height = p->font_height;
   it->voffset = p->voffset;
@@ -4545,49 +5151,70 @@ 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;
 
-         /* Check the newline before point for invisibility.  */
-         prop = Fget_char_property (make_number (IT_CHARPOS (*it) - 1),
+      /* 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)
-       {
-         struct it it2 = *it;
+      if (IT_CHARPOS (*it) <= BEGV)
+       break;
 
-         if (handle_display_prop (&it2) == HANDLED_RETURN)
-           visible_p = 0;
-       }
+      {
+       struct it it2;
+       int pos;
+       int beg, end;
+       Lisp_Object val, overlay;
+
+       /* If newline is part of a composition, continue from start of composition */
+       if (find_composition (IT_CHARPOS (*it), -1, &beg, &end, &val, Qnil)
+           && beg < IT_CHARPOS (*it))
+         goto replaced;
+
+       /* If newline is replaced by a display property, find start of overlay
+          or interval and continue search from that point.  */
+       it2 = *it;
+       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)))
+         goto replaced;
+
+       /* Newline is not replaced by anything -- so we are done.  */
+       break;
 
-      /* Back one more newline if the current one is invisible.  */
-      if (!visible_p)
-       back_to_previous_line_start (it);
+      replaced:
+       if (beg < BEGV)
+         beg = BEGV;
+       IT_CHARPOS (*it) = beg;
+       IT_BYTEPOS (*it) = buf_charpos_to_bytepos (current_buffer, beg);
+      }
     }
 
+  it->continuation_lines_width = 0;
+
   xassert (IT_CHARPOS (*it) >= BEGV);
   xassert (IT_CHARPOS (*it) == BEGV
           || FETCH_BYTE (IT_BYTEPOS (*it) - 1) == '\n');
@@ -4633,7 +5260,8 @@ reseat_at_next_visible_line_start (it, on_newline_p)
           && indented_beyond_p (IT_CHARPOS (*it), IT_BYTEPOS (*it),
                                 (double) it->selective)) /* iftc */
       {
-       xassert (FETCH_BYTE (IT_BYTEPOS (*it) - 1) == '\n');
+       xassert (IT_BYTEPOS (*it) == BEGV
+                || FETCH_BYTE (IT_BYTEPOS (*it) - 1) == '\n');
        newline_found_p = forward_to_next_line_start (it, &skipped_p);
       }
 
@@ -4709,7 +5337,6 @@ reseat_1 (it, pos, set_stop_p)
   xassert (CHARPOS (pos) >= BEGV && CHARPOS (pos) <= ZV);
 
   it->current.pos = it->position = pos;
-  XSETBUFFER (it->object, current_buffer);
   it->end_charpos = ZV;
   it->dpvec = NULL;
   it->current.dpvec_index = -1;
@@ -4717,16 +5344,12 @@ 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;
-  /* 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
-     Nick Roberts <nick@nick.uklinux.net> on 19 May 2003.
-     However, I am not sure whether reseat still does the right thing
-     in general after this change.  */
+  it->method = GET_FROM_BUFFER;
+  it->object = it->w->buffer;
   it->area = TEXT_AREA;
   it->multibyte_p = !NILP (current_buffer->enable_multibyte_characters);
   it->sp = 0;
+  it->string_from_display_prop_p = 0;
   it->face_before_selective_p = 0;
 
   if (set_stop_p)
@@ -4783,7 +5406,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
@@ -4805,7 +5428,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
@@ -4836,10 +5459,28 @@ 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.  */
 
+static struct frame *last_escape_glyph_frame = NULL;
+static unsigned last_escape_glyph_face_id = (1 << FACE_ID_BITS);
+static int last_escape_glyph_merged_face_id = 0;
+
 int
 get_next_display_element (it)
      struct it *it;
@@ -4851,7 +5492,7 @@ get_next_display_element (it)
   int success_p;
 
  get_next:
-  success_p = (*it->method) (it);
+  success_p = (*get_next_element[it->method]) (it);
 
   if (it->what == IT_CHARACTER)
     {
@@ -4883,8 +5524,10 @@ get_next_display_element (it)
                  it->dpvec = v->contents;
                  it->dpend = v->contents + v->size;
                  it->current.dpvec_index = 0;
+                 it->dpvec_face_id = -1;
                  it->saved_face_id = it->face_id;
-                 it->method = next_element_from_display_vector;
+                 it->method = GET_FROM_DISPLAY_VECTOR;
+                 it->ellipsis_p = 0;
                }
              else
                {
@@ -4909,15 +5552,18 @@ get_next_display_element (it)
          else if ((it->c < ' '
                    && (it->area != TEXT_AREA
                        /* In mode line, treat \n like other crl chars.  */
-                       || (it->c != '\n'
+                       || (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)
-                         || it->c == 0x8ad
-                         || it->c == 0x8a0)
+                         || (!NILP (Vnobreak_char_display)
+                             && (it->c == 0x8a0 || it->c == 0x8ad
+                                 || it->c == 0x920 || it->c == 0x92d
+                                 || it->c == 0xe20 || it->c == 0xe2d
+                                 || it->c == 0xf20 || it->c == 0xf2d)))
                       : (it->c >= 127
                          && (!unibyte_display_via_language_environment
                              || it->c == unibyte_char_to_multibyte (it->c)))))
@@ -4929,79 +5575,147 @@ get_next_display_element (it)
                 display.  Then, set IT->dpvec to these glyphs.  */
              GLYPH g;
              int ctl_len;
-             int face_id = escape_glyph_face;
+             int face_id, lface_id = 0 ;
+             GLYPH escape_glyph;
 
-             /* Find the face id if `escape-glyph' unless we recently did.  */
-             if (face_id < 0)
-               {
-                 Lisp_Object tem = Fget (Qescape_glyph, Qface);
-                 if (INTEGERP (tem))
-                   face_id = XINT (tem);
-                 else
-                   face_id = 0;
-                 /* If there's overflow, use 0 instead.  */
-                 if (FAST_GLYPH_FACE (FAST_MAKE_GLYPH (0, face_id)) != face_id)
-                   face_id = 0;
-                 escape_glyph_face = face_id;
-               }
+             /* Handle control characters with ^.  */
 
              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 if (it->f == last_escape_glyph_frame
+                          && it->face_id == last_escape_glyph_face_id)
+                   {
+                     face_id = last_escape_glyph_merged_face_id;
+                   }
                  else
-                   g = FAST_MAKE_GLYPH ('^', face_id);
-                 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);
+                     last_escape_glyph_frame = it->f;
+                     last_escape_glyph_face_id = it->face_id;
+                     last_escape_glyph_merged_face_id = face_id;
+                   }
 
-                 g = FAST_MAKE_GLYPH (it->c ^ 0100, face_id);
+                 XSETINT (it->ctl_chars[0], g);
+                 g = it->c ^ 0100;
                  XSETINT (it->ctl_chars[1], g);
                  ctl_len = 2;
+                 goto display_control;
+               }
+
+             /* Handle non-break space in the mode where it only gets
+                highlighting.  */
+
+             if (EQ (Vnobreak_char_display, Qt)
+                 && (it->c == 0x8a0 || it->c == 0x920
+                     || it->c == 0xe20 || it->c == 0xf20))
+               {
+                 /* Merge the no-break-space face into the current face.  */
+                 face_id = merge_faces (it->f, Qnobreak_space, 0,
+                                        it->face_id);
+
+                 g = it->c = ' ';
+                 XSETINT (it->ctl_chars[0], g);
+                 ctl_len = 1;
+                 goto display_control;
                }
-             else if (it->c == 0x8a0 || it->c == 0x8ad)
+
+             /* Handle sequences that start with the "escape glyph".  */
+
+             /* the default escape glyph is \.  */
+             escape_glyph = '\\';
+
+             if (it->dp
+                 && INTEGERP (DISP_ESCAPE_GLYPH (it->dp))
+                 && GLYPH_CHAR_VALID_P (XFASTINT (DISP_ESCAPE_GLYPH (it->dp))))
                {
-                 /* Set IT->ctl_chars[0] to the glyph for `\\'.  */
-                 if (it->dp
-                     && INTEGERP (DISP_ESCAPE_GLYPH (it->dp))
-                     && GLYPH_CHAR_VALID_P (XINT (DISP_ESCAPE_GLYPH (it->dp))))
-                   g = XINT (DISP_ESCAPE_GLYPH (it->dp));
-                 else
-                   g = FAST_MAKE_GLYPH ('\\', face_id);
+                 escape_glyph = XFASTINT (DISP_ESCAPE_GLYPH (it->dp));
+                 lface_id = FAST_GLYPH_FACE (escape_glyph);
+               }
+             if (lface_id)
+               {
+                 /* The display table specified a face.
+                    Merge it into face_id and also into escape_glyph.  */
+                 escape_glyph = FAST_GLYPH_CHAR (escape_glyph);
+                 face_id = merge_faces (it->f, Qt, lface_id,
+                                        it->face_id);
+               }
+             else if (it->f == last_escape_glyph_frame
+                      && it->face_id == last_escape_glyph_face_id)
+               {
+                 face_id = last_escape_glyph_merged_face_id;
+               }
+             else
+               {
+                 /* Merge the escape-glyph face into the current face.  */
+                 face_id = merge_faces (it->f, Qescape_glyph, 0,
+                                        it->face_id);
+                 last_escape_glyph_frame = it->f;
+                 last_escape_glyph_face_id = it->face_id;
+                 last_escape_glyph_merged_face_id = face_id;
+               }
+
+             /* Handle soft hyphens in the mode where they only get
+                highlighting.  */
+
+             if (EQ (Vnobreak_char_display, Qt)
+                 && (it->c == 0x8ad || it->c == 0x92d
+                     || it->c == 0xe2d || it->c == 0xf2d))
+               {
+                 g = it->c = '-';
                  XSETINT (it->ctl_chars[0], g);
+                 ctl_len = 1;
+                 goto display_control;
+               }
+
+             /* Handle non-break space and soft hyphen
+                with the escape glyph.  */
 
-                 g = FAST_MAKE_GLYPH (it->c == 0x8ad ? '-' : ' ', face_id);
+             if (it->c == 0x8a0 || it->c == 0x8ad
+                 || it->c == 0x920 || it->c == 0x92d
+                 || it->c == 0xe20 || it->c == 0xe2d
+                 || it->c == 0xf20 || it->c == 0xf2d)
+               {
+                 XSETINT (it->ctl_chars[0], escape_glyph);
+                 g = it->c = ((it->c & 0xf) == 0 ? ' ' : '-');
                  XSETINT (it->ctl_chars[1], g);
                  ctl_len = 2;
+                 goto display_control;
                }
-             else
-               {
-                 unsigned char str[MAX_MULTIBYTE_LENGTH];
-                 int len;
-                 int i;
-                 GLYPH escape_glyph;
 
-                 /* 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 ('\\', face_id);
+             {
+               unsigned char str[MAX_MULTIBYTE_LENGTH];
+               int len;
+               int i;
 
-                 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.  */
+               /* 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;
@@ -5010,31 +5724,31 @@ 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',
-                                          face_id);
-                     XSETINT (it->ctl_chars[i * 4 + 1], g);
-                     g = FAST_MAKE_GLYPH (((str[i] >> 3) & 7) + '0',
-                                          face_id);
-                     XSETINT (it->ctl_chars[i * 4 + 2], g);
-                     g = FAST_MAKE_GLYPH ((str[i] & 7) + '0',
-                                          face_id);
-                     XSETINT (it->ctl_chars[i * 4 + 3], g);
-                   }
-                 ctl_len = len * 4;
-               }
+               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;
+             }
 
+           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 = next_element_from_display_vector;
+             it->method = GET_FROM_DISPLAY_VECTOR;
+             it->ellipsis_p = 0;
              goto get_next;
            }
        }
@@ -5095,8 +5809,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.  */
@@ -5109,32 +5824,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);
-      if (STRINGP (it->string))
+      break;
+
+    case GET_FROM_COMPOSITION:
+      xassert (it->cmp_id >= 0 && it->cmp_id < n_compositions);
+      xassert (it->sp > 0);
+      pop_it (it);
+      if (it->method == GET_FROM_STRING)
        {
          IT_STRING_BYTEPOS (*it) += it->len;
          IT_STRING_CHARPOS (*it) += it->cmp_len;
-         it->method = next_element_from_string;
          goto consider_string_end;
        }
-      else
+      else if (it->method == GET_FROM_BUFFER)
        {
          IT_BYTEPOS (*it) += it->len;
          IT_CHARPOS (*it) += it->cmp_len;
-         it->method = next_element_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/
@@ -5147,31 +5862,40 @@ set_iterator_to_next (it, reseat_p)
 
       if (it->dpvec + it->current.dpvec_index == it->dpend)
        {
+         int recheck_faces = it->ellipsis_p;
+
          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->object = it->w->buffer;
+           }
 
          it->dpvec = NULL;
          it->current.dpvec_index = -1;
 
-         /* Recheck faces after display vector */
-         it->stop_charpos = 0;
-
          /* Skip over characters which were displayed via IT->dpvec.  */
          if (it->dpvec_char_len < 0)
            reseat_at_next_visible_line_start (it, 1);
          else if (it->dpvec_char_len > 0)
            {
+             if (it->method == GET_FROM_STRING
+                 && it->n_overlay_strings > 0)
+               it->ignore_overlay_strings_at_pos_p = 1;
              it->len = it->dpvec_char_len;
              set_iterator_to_next (it, reseat_p);
            }
+
+         /* Maybe recheck faces after display vector */
+         if (recheck_faces)
+           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;
@@ -5196,34 +5920,29 @@ 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 (it->method == GET_FROM_STRING)
                goto consider_string_end;
            }
        }
-    }
-  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;
-         goto consider_string_end;
-       }
-      else
-       it->method = next_element_from_buffer;
+      if (it->method == GET_FROM_STRING)
+       goto consider_string_end;
+      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));
 }
@@ -5244,10 +5963,11 @@ next_element_from_display_vector (it)
   /* Precondition.  */
   xassert (it->dpvec && it->current.dpvec_index >= 0);
 
+  it->face_id = it->saved_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]);
@@ -5257,13 +5977,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
@@ -5358,9 +6079,7 @@ next_element_from_string (it)
        }
     }
 
-  /* Record what we have and where it came from.  Note that we store a
-     buffer position in IT->position although it could arguably be a
-     string position.  */
+  /* Record what we have and where it came from.  */
   it->what = IT_CHARACTER;
   it->object = it->string;
   it->position = position;
@@ -5435,7 +6154,8 @@ 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;
+      it->object = it->w->buffer;
       reseat_at_next_visible_line_start (it, 1);
       it->face_before_selective_p = 1;
     }
@@ -5622,6 +6342,10 @@ next_element_from_composition (it)
   it->position = (STRINGP (it->string)
                  ? it->current.string_pos
                  : it->current.pos);
+  if (STRINGP (it->string))
+    it->object = it->string;
+  else
+    it->object = it->w->buffer;
   return 1;
 }
 
@@ -5631,6 +6355,15 @@ next_element_from_composition (it)
             Moving an iterator without producing glyphs
  ***********************************************************************/
 
+/* Check if iterator is at a position corresponding to a valid buffer
+   position after some move_it_ call.  */
+
+#define IT_POS_VALID_AFTER_MOVE_P(it)                  \
+  ((it)->method == GET_FROM_STRING                     \
+   ? IT_STRING_CHARPOS (*it) == 0                      \
+   : 1)
+
+
 /* Move iterator IT to a specified buffer or X position within one
    line on the display without producing glyphs.
 
@@ -5676,15 +6409,29 @@ 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 if we move beyond TO_CHARPOS (after an image or stretch glyph).  */
+      if ((op & MOVE_TO_POS) != 0
+         && BUFFERP (it->object)
+         && it->method == GET_FROM_BUFFER
+         && IT_CHARPOS (*it) > to_charpos)
+       {
+         result = MOVE_POS_MATCH_OR_ZV;
+         break;
+       }
+
       /* 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
@@ -5743,6 +6490,8 @@ move_it_in_display_line_to (it, to_charpos, to_x, op)
             glyphs have the same width.  */
          int single_glyph_width = it->pixel_width / it->nglyphs;
          int new_x;
+         int x_before_this_char = x;
+         int hpos_before_this_char = it->hpos;
 
          for (i = 0; i < it->nglyphs; ++i, x = new_x)
            {
@@ -5774,8 +6523,22 @@ move_it_in_display_line_to (it, to_charpos, to_x, op)
                    {
                      ++it->hpos;
                      it->current_x = new_x;
+
+                     /* The character's last glyph just barely fits
+                        in this row.  */
                      if (i == it->nglyphs - 1)
                        {
+                         /* If this is the destination position,
+                            return a position *before* it in this row,
+                            now that we know it fits in this row.  */
+                         if (BUFFER_POS_REACHED_P ())
+                           {
+                             it->hpos = hpos_before_this_char;
+                             it->current_x = x_before_this_char;
+                             result = MOVE_POS_MATCH_OR_ZV;
+                             break;
+                           }
+
                          set_iterator_to_next (it, 1);
 #ifdef HAVE_WINDOW_SYSTEM
                          if (IT_OVERFLOW_NEWLINE_INTO_FRINGE (it))
@@ -6031,6 +6794,10 @@ move_it_to (it, to_charpos, to_x, to_y, to_vpos, op)
          if (reached)
            break;
        }
+      else if (BUFFERP (it->object)
+              && it->method == GET_FROM_BUFFER
+              && IT_CHARPOS (*it) >= to_charpos)
+       skip = MOVE_POS_MATCH_OR_ZV;
       else
        skip = move_it_in_display_line_to (it, to_charpos, -1, MOVE_TO_POS);
 
@@ -6125,8 +6892,12 @@ move_it_vertically_backward (it, dy)
      y-distance.  */
   it2 = *it;
   it2.max_ascent = it2.max_descent = 0;
-  move_it_to (&it2, start_pos, -1, -1, it2.vpos + 1,
-             MOVE_TO_POS | MOVE_TO_VPOS);
+  do
+    {
+      move_it_to (&it2, start_pos, -1, -1, it2.vpos + 1,
+                 MOVE_TO_POS | MOVE_TO_VPOS);
+    }
+  while (!IT_POS_VALID_AFTER_MOVE_P (&it2));
   xassert (IT_CHARPOS (*it) >= BEGV);
   it3 = it2;
 
@@ -6149,7 +6920,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
     {
@@ -6167,7 +6942,8 @@ 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 * 2 / 3
+         && (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",
@@ -6197,7 +6973,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
        }
     }
 }
@@ -6224,6 +7004,7 @@ move_it_vertically (it, dy)
       /* If buffer ends in ZV without a newline, move to the start of
         the line to satisfy the post-condition.  */
       if (IT_CHARPOS (*it) == ZV
+         && ZV > BEGV
          && FETCH_BYTE (IT_BYTEPOS (*it) - 1) != '\n')
        move_it_by_lines (it, 0, 0);
     }
@@ -6315,21 +7096,45 @@ move_it_by_lines (it, dvpos, need_y_p)
       last_height = 0;
     }
   else if (dvpos > 0)
-    move_it_to (it, -1, -1, -1, it->vpos + dvpos, MOVE_TO_VPOS);
+    {
+      move_it_to (it, -1, -1, -1, it->vpos + dvpos, MOVE_TO_VPOS);
+      if (!IT_POS_VALID_AFTER_MOVE_P (it))
+       move_it_to (it, IT_CHARPOS (*it) + 1, -1, -1, -1, MOVE_TO_POS);
+    }
   else
     {
       struct it it2;
       int start_charpos, i;
 
       /* Start at the beginning of the screen line containing IT's
-        position.  */
+        position.  This may actually move vertically backwards,
+         in case of overlays, so adjust dvpos accordingly.  */
+      dvpos += it->vpos;
       move_it_vertically_backward (it, 0);
+      dvpos -= it->vpos;
 
       /* Go back -DVPOS visible lines and reseat the iterator there.  */
       start_charpos = IT_CHARPOS (*it);
-      for (i = -dvpos; i && IT_CHARPOS (*it) > BEGV; --i)
+      for (i = -dvpos; i > 0 && IT_CHARPOS (*it) > BEGV; --i)
        back_to_previous_visible_line_start (it);
       reseat (it, it->current.pos, 1);
+
+      /* Move further back if we end up in a string or an image.  */
+      while (!IT_POS_VALID_AFTER_MOVE_P (it))
+       {
+         /* First try to move to start of display line.  */
+         dvpos += it->vpos;
+         move_it_vertically_backward (it, 0);
+         dvpos -= it->vpos;
+         if (IT_POS_VALID_AFTER_MOVE_P (it))
+           break;
+         /* If start of line is still in string or image,
+            move further back.  */
+         back_to_previous_visible_line_start (it);
+         reseat (it, it->current.pos, 1);
+         dvpos--;
+       }
+
       it->current_x = it->hpos = 0;
 
       /* Above call may have moved too far if continuation lines
@@ -6341,11 +7146,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;
        }
     }
 }
@@ -6356,7 +7165,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);
 }
@@ -6421,7 +7230,10 @@ message_log_maybe_newline ()
    terminated with a newline when NLFLAG is non-zero.  MULTIBYTE, if
    nonzero, means interpret the contents of M as multibyte.  This
    function calls low-level routines in order to bypass text property
-   hooks, etc. which might not be safe to run.  */
+   hooks, etc. which might not be safe to run.
+
+   This may GC (insert may run before/after change hooks),
+   so the buffer M must NOT point to a Lisp string.  */
 
 void
 message_dolog (m, nbytes, nlflag, multibyte)
@@ -6625,17 +7437,14 @@ 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
    out any existing message, and let the mini-buffer text show
    through.
 
-   The buffer M must continue to exist until after the echo area gets
-   cleared or some other message gets displayed there.  This means do
-   not pass text that is stored in a Lisp string; do not pass text in
-   a buffer that was alloca'd.  */
+   This may GC, so the buffer M must NOT point to a Lisp string.  */
 
 void
 message2 (m, nbytes, multibyte)
@@ -6713,7 +7522,9 @@ message2_nolog (m, nbytes, multibyte)
 /* Display an echo area message M with a specified length of NBYTES
    bytes.  The string may include null characters.  If M is not a
    string, clear out any existing message, and let the mini-buffer
-   text show through.  */
+   text show through.
+
+   This function cancels echoing.  */
 
 void
 message3 (m, nbytes, multibyte)
@@ -6725,18 +7536,30 @@ message3 (m, nbytes, multibyte)
 
   GCPRO1 (m);
   clear_message (1,1);
+  cancel_echoing ();
 
   /* First flush out any partial line written with print.  */
   message_log_maybe_newline ();
   if (STRINGP (m))
-    message_dolog (SDATA (m), nbytes, 1, multibyte);
+    {
+      char *buffer;
+      USE_SAFE_ALLOCA;
+
+      SAFE_ALLOCA (buffer, char *, nbytes);
+      bcopy (SDATA (m), buffer, nbytes);
+      message_dolog (buffer, nbytes, 1, multibyte);
+      SAFE_FREE ();
+    }
   message3_nolog (m, nbytes, multibyte);
 
   UNGCPRO;
 }
 
 
-/* The non-logging version of message3.  */
+/* The non-logging version of message3.
+   This does not cancel echoing, because it is used for echoing.
+   Perhaps we need to make a separate function for echoing
+   and make this cancel echoing.  */
 
 void
 message3_nolog (m, nbytes, multibyte)
@@ -6784,6 +7607,9 @@ message3_nolog (m, nbytes, multibyte)
          set_message (NULL, m, nbytes, multibyte);
          if (minibuffer_auto_raise)
            Fraise_frame (frame);
+         /* Assume we are not echoing.
+            (If we are, echo_now will override this.)  */
+         echo_message_buffer = Qnil;
        }
       else
        clear_message (1, 1);
@@ -7030,10 +7856,6 @@ ensure_echo_area_buffers ()
    WHICH > 0 means use echo_area_buffer[1].  If that is nil, choose a
    suitable buffer from echo_buffer[] and clear it.
 
-   If WHICH < 0, set echo_area_buffer[1] to echo_area_buffer[0], so
-   that the current message becomes the last displayed one, make
-   choose a suitable buffer for echo_area_buffer[0], and clear it.
-
    Value is what FN returns.  */
 
 static int
@@ -7058,17 +7880,6 @@ with_echo_area_buffer (w, which, fn, a1, a2, a3, a4)
     this_one = 0, the_other = 1;
   else if (which > 0)
     this_one = 1, the_other = 0;
-  else
-    {
-      this_one = 0, the_other = 1;
-      clear_buffer_p = 1;
-
-      /* We need a fresh one in case the current echo buffer equals
-        the one containing the last displayed echo area message.  */
-      if (!NILP (echo_area_buffer[this_one])
-         && EQ (echo_area_buffer[this_one], echo_area_buffer[the_other]))
-       echo_area_buffer[this_one] = Qnil;
-    }
 
   /* Choose a suitable buffer from echo_buffer[] is we don't
      have one.  */
@@ -7327,14 +8138,17 @@ display_echo_area_1 (a1, a2, a3, a4)
   int window_height_changed_p = 0;
 
   /* Do this before displaying, so that we have a large enough glyph
-     matrix for the display.  */
+     matrix for the display.  If we can't get enough space for the
+     whole text, display the last N lines.  That works by setting w->start.  */
   window_height_changed_p = resize_mini_window (w, 0);
 
+  /* Use the starting position chosen by resize_mini_window.  */
+  SET_TEXT_POS_FROM_MARKER (start, w->start);
+
   /* Display.  */
   clear_glyph_matrix (w->desired_matrix);
   XSETWINDOW (window, w);
-  SET_TEXT_POS (start, BEG, BEG_BYTE);
-  try_window (window, start);
+  try_window (window, start, 0);
 
   return window_height_changed_p;
 }
@@ -7389,8 +8203,14 @@ resize_mini_window_1 (a1, exactly, a3, a4)
 
 /* Resize mini-window W to fit the size of its contents.  EXACT:P
    means size the window exactly to the size needed.  Otherwise, it's
-   only enlarged until W's buffer is empty.  Value is non-zero if
-   the window height has been changed.  */
+   only enlarged until W's buffer is empty.
+
+   Set W->start to the right place to begin display.  If the whole
+   contents fit, start at the beginning.  Otherwise, start so as
+   to make the end of the contents appear.  This is particularly
+   important for y-or-n-p, but seems desirable generally.
+
+   Value is non-zero if the window height has been changed.  */
 
 int
 resize_mini_window (w, exact_p)
@@ -7402,6 +8222,11 @@ resize_mini_window (w, exact_p)
 
   xassert (MINI_WINDOW_P (w));
 
+  /* By default, start display at the beginning.  */
+  set_marker_both (w->start, w->buffer,
+                  BUF_BEGV (XBUFFER (w->buffer)),
+                  BUF_BEGV_BYTE (XBUFFER (w->buffer)));
+
   /* Don't resize windows while redisplaying a window; it would
      confuse redisplay functions when the size of the window they are
      displaying changes from under them.  Such a resizing can happen,
@@ -7465,7 +8290,7 @@ resize_mini_window (w, exact_p)
       if (height > max_height)
        {
          height = max_height;
-         init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID);
+         init_iterator (&it, w, ZV, ZV_BYTE, NULL, DEFAULT_FACE_ID);
          move_it_vertically_backward (&it, (height - 1) * unit);
          start = it.current.pos;
        }
@@ -7676,7 +8501,11 @@ truncate_message_1 (nchars, a2, a3, a4)
 
    If S is not null, set the message to the first LEN bytes of S.  LEN
    zero means use the whole string.  MULTIBYTE_P non-zero means S is
-   multibyte.  Display the message multibyte in that case.  */
+   multibyte.  Display the message multibyte in that case.
+
+   Doesn't GC, as with_echo_area_buffer binds Qinhibit_modification_hooks
+   to t before calling set_message_1 (which calls insert).
+  */
 
 void
 set_message (s, string, nbytes, multibyte_p)
@@ -7688,7 +8517,7 @@ set_message (s, string, nbytes, multibyte_p)
     = ((s && multibyte_p)
        || (STRINGP (string) && STRING_MULTIBYTE (string)));
 
-  with_echo_area_buffer (0, -1, set_message_1,
+  with_echo_area_buffer (0, 0, set_message_1,
                         (EMACS_INT) s, string, nbytes, multibyte_p);
   message_buf_print = 0;
   help_echo_showing_p = 0;
@@ -7709,8 +8538,6 @@ set_message_1 (a1, a2, nbytes, multibyte_p)
   const char *s = (const char *) a1;
   Lisp_Object string = a2;
 
-  xassert (BEG == Z);
-
   /* Change multibyteness of the echo buffer appropriately.  */
   if (message_enable_multibyte
       != !NILP (current_buffer->enable_multibyte_characters))
@@ -7720,6 +8547,7 @@ set_message_1 (a1, a2, nbytes, multibyte_p)
 
   /* Insert new message at BEG.  */
   TEMP_SET_PT_BOTH (BEG, BEG_BYTE);
+  Ferase_buffer ();
 
   if (STRINGP (string))
     {
@@ -7936,7 +8764,7 @@ echo_area_display (update_frame_p)
   else if (!EQ (mini_window, selected_window))
     windows_or_buffers_changed++;
 
-  /* Last displayed message is now the current message.  */
+  /* The current message is now also the last one displayed.  */
   echo_area_buffer[1] = echo_area_buffer[0];
 
   /* Prevent redisplay optimization in redisplay_internal by resetting
@@ -7951,52 +8779,126 @@ echo_area_display (update_frame_p)
 
 \f
 /***********************************************************************
-                            Frame Titles
+                    Mode Lines and Frame Titles
  ***********************************************************************/
 
+/* A buffer for constructing non-propertized mode-line strings and
+   frame titles in it; allocated from the heap in init_xdisp and
+   resized as needed in store_mode_line_noprop_char.  */
+
+static char *mode_line_noprop_buf;
+
+/* The buffer's end, and a current output position in it.  */
+
+static char *mode_line_noprop_buf_end;
+static char *mode_line_noprop_ptr;
+
+#define MODE_LINE_NOPROP_LEN(start) \
+  ((mode_line_noprop_ptr - mode_line_noprop_buf) - start)
+
+static enum {
+  MODE_LINE_DISPLAY = 0,
+  MODE_LINE_TITLE,
+  MODE_LINE_NOPROP,
+  MODE_LINE_STRING
+} mode_line_target;
+
+/* Alist that caches the results of :propertize.
+   Each element is (PROPERTIZED-STRING . PROPERTY-LIST).  */
+static Lisp_Object mode_line_proptrans_alist;
+
+/* List of strings making up the mode-line.  */
+static Lisp_Object mode_line_string_list;
+
+/* Base face property when building propertized mode line string.  */
+static Lisp_Object mode_line_string_face;
+static Lisp_Object mode_line_string_face_prop;
+
+
+/* Unwind data for mode line strings */
+
+static Lisp_Object Vmode_line_unwind_vector;
+
+static Lisp_Object
+format_mode_line_unwind_data (obuf, save_proptrans)
+     struct buffer *obuf;
+{
+  Lisp_Object vector;
+
+  /* Reduce consing by keeping one vector in
+     Vwith_echo_area_save_vector.  */
+  vector = Vmode_line_unwind_vector;
+  Vmode_line_unwind_vector = Qnil;
+
+  if (NILP (vector))
+    vector = Fmake_vector (make_number (7), Qnil);
 
-/* The frame title buffering code is also used by Fformat_mode_line.
-   So it is not conditioned by HAVE_WINDOW_SYSTEM.  */
+  AREF (vector, 0) = make_number (mode_line_target);
+  AREF (vector, 1) = make_number (MODE_LINE_NOPROP_LEN (0));
+  AREF (vector, 2) = mode_line_string_list;
+  AREF (vector, 3) = (save_proptrans ? mode_line_proptrans_alist : Qt);
+  AREF (vector, 4) = mode_line_string_face;
+  AREF (vector, 5) = mode_line_string_face_prop;
 
-/* A buffer for constructing frame titles in it; allocated from the
-   heap in init_xdisp and resized as needed in store_frame_title_char.  */
+  if (obuf)
+    XSETBUFFER (AREF (vector, 6), obuf);
+  else
+    AREF (vector, 6) = Qnil;
 
-static char *frame_title_buf;
+  return vector;
+}
 
-/* The buffer's end, and a current output position in it.  */
+static Lisp_Object
+unwind_format_mode_line (vector)
+     Lisp_Object vector;
+{
+  mode_line_target = XINT (AREF (vector, 0));
+  mode_line_noprop_ptr = mode_line_noprop_buf + XINT (AREF (vector, 1));
+  mode_line_string_list = AREF (vector, 2);
+  if (! EQ (AREF (vector, 3), Qt))
+    mode_line_proptrans_alist = AREF (vector, 3);
+  mode_line_string_face = AREF (vector, 4);
+  mode_line_string_face_prop = AREF (vector, 5);
+
+  if (!NILP (AREF (vector, 6)))
+    {
+      set_buffer_internal_1 (XBUFFER (AREF (vector, 6)));
+      AREF (vector, 6) = Qnil;
+    }
 
-static char *frame_title_buf_end;
-static char *frame_title_ptr;
+  Vmode_line_unwind_vector = vector;
+  return Qnil;
+}
 
 
-/* Store a single character C for the frame title in frame_title_buf.
-   Re-allocate frame_title_buf if necessary.  */
+/* Store a single character C for the frame title in mode_line_noprop_buf.
+   Re-allocate mode_line_noprop_buf if necessary.  */
 
 static void
 #ifdef PROTOTYPES
-store_frame_title_char (char c)
+store_mode_line_noprop_char (char c)
 #else
-store_frame_title_char (c)
+store_mode_line_noprop_char (c)
     char c;
 #endif
 {
   /* If output position has reached the end of the allocated buffer,
      double the buffer's size.  */
-  if (frame_title_ptr == frame_title_buf_end)
+  if (mode_line_noprop_ptr == mode_line_noprop_buf_end)
     {
-      int len = frame_title_ptr - frame_title_buf;
-      int new_size = 2 * len * sizeof *frame_title_buf;
-      frame_title_buf = (char *) xrealloc (frame_title_buf, new_size);
-      frame_title_buf_end = frame_title_buf + new_size;
-      frame_title_ptr = frame_title_buf + len;
+      int len = MODE_LINE_NOPROP_LEN (0);
+      int new_size = 2 * len * sizeof *mode_line_noprop_buf;
+      mode_line_noprop_buf = (char *) xrealloc (mode_line_noprop_buf, new_size);
+      mode_line_noprop_buf_end = mode_line_noprop_buf + new_size;
+      mode_line_noprop_ptr = mode_line_noprop_buf + len;
     }
 
-  *frame_title_ptr++ = c;
+  *mode_line_noprop_ptr++ = c;
 }
 
 
-/* Store part of a frame title in frame_title_buf, beginning at
-   frame_title_ptr.  STR is the string to store.  Do not copy
+/* Store part of a frame title in mode_line_noprop_buf, beginning at
+   mode_line_noprop_ptr.  STR is the string to store.  Do not copy
    characters that yield more columns than PRECISION; PRECISION <= 0
    means copy the whole string.  Pad with spaces until FIELD_WIDTH
    number of characters have been copied; FIELD_WIDTH <= 0 means don't
@@ -8004,7 +8906,7 @@ store_frame_title_char (c)
    frame title.  */
 
 static int
-store_frame_title (str, field_width, precision)
+store_mode_line_noprop (str, field_width, precision)
      const unsigned char *str;
      int field_width, precision;
 {
@@ -8015,19 +8917,23 @@ store_frame_title (str, field_width, precision)
   nbytes = strlen (str);
   n += c_string_width (str, nbytes, precision, &dummy, &nbytes);
   while (nbytes--)
-    store_frame_title_char (*str++);
+    store_mode_line_noprop_char (*str++);
 
   /* Fill up with spaces until FIELD_WIDTH reached.  */
   while (field_width > 0
         && n < field_width)
     {
-      store_frame_title_char (' ');
+      store_mode_line_noprop_char (' ');
       ++n;
     }
 
   return n;
 }
 
+/***********************************************************************
+                            Frame Titles
+ ***********************************************************************/
+
 #ifdef HAVE_WINDOW_SYSTEM
 
 /* Set the title of FRAME, if it has changed.  The title format is
@@ -8047,9 +8953,11 @@ x_consider_frame_title (frame)
       /* Do we have more than one visible frame on this X display?  */
       Lisp_Object tail;
       Lisp_Object fmt;
-      struct buffer *obuf;
+      int title_start;
+      char *title;
       int len;
       struct it it;
+      int count = SPECPDL_INDEX ();
 
       for (tail = Vframe_list; CONSP (tail); tail = XCDR (tail))
        {
@@ -8068,18 +8976,22 @@ x_consider_frame_title (frame)
       multiple_frames = CONSP (tail);
 
       /* Switch to the buffer of selected window of the frame.  Set up
-        frame_title_ptr so that display_mode_element will output into it;
-        then display the title.  */
-      obuf = current_buffer;
+        mode_line_target so that display_mode_element will output into
+        mode_line_noprop_buf; then display the title.  */
+      record_unwind_protect (unwind_format_mode_line,
+                            format_mode_line_unwind_data (current_buffer, 0));
+
       set_buffer_internal_1 (XBUFFER (XWINDOW (f->selected_window)->buffer));
       fmt = FRAME_ICONIFIED_P (f) ? Vicon_title_format : Vframe_title_format;
-      frame_title_ptr = frame_title_buf;
+
+      mode_line_target = MODE_LINE_TITLE;
+      title_start = MODE_LINE_NOPROP_LEN (0);
       init_iterator (&it, XWINDOW (f->selected_window), -1, -1,
                     NULL, DEFAULT_FACE_ID);
       display_mode_element (&it, 0, -1, -1, fmt, Qnil, 0);
-      len = frame_title_ptr - frame_title_buf;
-      frame_title_ptr = NULL;
-      set_buffer_internal_1 (obuf);
+      len = MODE_LINE_NOPROP_LEN (title_start);
+      title = mode_line_noprop_buf + title_start;
+      unbind_to (count, Qnil);
 
       /* Set the title only if it's changed.  This avoids consing in
         the common case where it hasn't.  (If it turns out that we've
@@ -8088,8 +9000,8 @@ x_consider_frame_title (frame)
         higher level than this.)  */
       if (! STRINGP (f->name)
          || SBYTES (f->name) != len
-         || bcmp (frame_title_buf, SDATA (f->name), len) != 0)
-       x_implicitly_set_name (f, make_string (frame_title_buf, len), Qnil);
+         || bcmp (title, SDATA (f->name), len) != 0)
+       x_implicitly_set_name (f, make_string (title, len), Qnil);
     }
 }
 
@@ -8147,8 +9059,11 @@ prepare_menu_bars ()
     {
       Lisp_Object tail, frame;
       int count = SPECPDL_INDEX ();
+      /* 1 means that update_menu_bar has run its hooks
+        so any further calls to update_menu_bar shouldn't do so again.  */
+      int menu_bar_hooks_run = 0;
 
-      record_unwind_protect (Fset_match_data, Fmatch_data (Qnil, Qnil));
+      record_unwind_save_match_data ();
 
       FOR_EACH_FRAME (tail, frame)
        {
@@ -8178,9 +9093,12 @@ prepare_menu_bars ()
            }
 
          GCPRO1 (tail);
-         update_menu_bar (f, 0);
+         menu_bar_hooks_run = update_menu_bar (f, 0, menu_bar_hooks_run);
 #ifdef HAVE_WINDOW_SYSTEM
          update_tool_bar (f, 0);
+#ifdef MAC_OS
+         mac_update_title_bar (f, 0);
+#endif
 #endif
          UNGCPRO;
        }
@@ -8190,9 +9108,12 @@ prepare_menu_bars ()
   else
     {
       struct frame *sf = SELECTED_FRAME ();
-      update_menu_bar (sf, 1);
+      update_menu_bar (sf, 1, 0);
 #ifdef HAVE_WINDOW_SYSTEM
       update_tool_bar (sf, 1);
+#ifdef MAC_OS
+      mac_update_title_bar (sf, 1);
+#endif
 #endif
     }
 
@@ -8208,12 +9129,18 @@ prepare_menu_bars ()
    before we start to fill in any display lines, because it can call
    eval.
 
-   If SAVE_MATCH_DATA is non-zero, we must save and restore it here.  */
+   If SAVE_MATCH_DATA is non-zero, we must save and restore it here.
 
-static void
-update_menu_bar (f, save_match_data)
+   If HOOKS_RUN is 1, that means a previous call to update_menu_bar
+   already ran the menu bar hooks for this redisplay, so there
+   is no need to run them again.  The return value is the
+   updated value of this flag, to pass to the next call.  */
+
+static int
+update_menu_bar (f, save_match_data, hooks_run)
      struct frame *f;
      int save_match_data;
+     int hooks_run;
 {
   Lisp_Object window;
   register struct window *w;
@@ -8222,7 +9149,7 @@ update_menu_bar (f, save_match_data)
      happen when, for instance, an activate-menubar-hook causes a
      redisplay.  */
   if (inhibit_menubar_update)
-    return;
+    return hooks_run;
 
   window = FRAME_SELECTED_WINDOW (f);
   w = XWINDOW (window);
@@ -8271,35 +9198,43 @@ update_menu_bar (f, save_match_data)
 
          set_buffer_internal_1 (XBUFFER (w->buffer));
          if (save_match_data)
-           record_unwind_protect (Fset_match_data, Fmatch_data (Qnil, Qnil));
+           record_unwind_save_match_data ();
          if (NILP (Voverriding_local_map_menu_flag))
            {
              specbind (Qoverriding_terminal_local_map, Qnil);
              specbind (Qoverriding_local_map, Qnil);
            }
 
-         /* Run the Lucid hook.  */
-         safe_run_hooks (Qactivate_menubar_hook);
+         if (!hooks_run)
+           {
+             /* Run the Lucid hook.  */
+             safe_run_hooks (Qactivate_menubar_hook);
+
+             /* If it has changed current-menubar from previous value,
+                really recompute the menu-bar from the value.  */
+             if (! NILP (Vlucid_menu_bar_dirty_flag))
+               call0 (Qrecompute_lucid_menubar);
+
+             safe_run_hooks (Qmenu_bar_update_hook);
 
-         /* If it has changed current-menubar from previous value,
-            really recompute the menu-bar from the value.  */
-         if (! NILP (Vlucid_menu_bar_dirty_flag))
-           call0 (Qrecompute_lucid_menubar);
+             hooks_run = 1;
+           }
 
-         safe_run_hooks (Qmenu_bar_update_hook);
+         XSETFRAME (Vmenu_updating_frame, f);
          FRAME_MENU_BAR_ITEMS (f) = menu_bar_items (FRAME_MENU_BAR_ITEMS (f));
 
          /* Redisplay the menu bar in case we changed it.  */
 #if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) || defined (MAC_OS) \
     || defined (USE_GTK)
-         if (FRAME_WINDOW_P (f)
-#if defined (MAC_OS)
-              /* All frames on Mac OS share the same menubar.  So only the
-                 selected frame should be allowed to set it.  */
-              && f == SELECTED_FRAME ()
+         if (FRAME_WINDOW_P (f))
+           {
+#ifdef MAC_OS
+              /* All frames on Mac OS share the same menubar.  So only
+                 the selected frame should be allowed to set it.  */
+              if (f == SELECTED_FRAME ())
 #endif
-            )
-           set_frame_menubar (f, 0, 0);
+               set_frame_menubar (f, 0, 0);
+           }
          else
            /* On a terminal screen, the menu bar is an ordinary screen
               line, and this makes it get updated.  */
@@ -8314,6 +9249,8 @@ update_menu_bar (f, save_match_data)
          set_buffer_internal_1 (prev);
        }
     }
+
+  return hooks_run;
 }
 
 
@@ -8462,7 +9399,7 @@ update_tool_bar (f, save_match_data)
 
          /* Save match data, if we must.  */
          if (save_match_data)
-           record_unwind_protect (Fset_match_data, Fmatch_data (Qnil, Qnil));
+           record_unwind_save_match_data ();
 
          /* Make sure that we don't accidentally use bogus keymaps.  */
          if (NILP (Voverriding_local_map_menu_flag))
@@ -8478,7 +9415,8 @@ update_tool_bar (f, save_match_data)
                                          &new_n_tool_bar);
 
          /* Redisplay the tool-bar if we changed it.  */
-         if (NILP (Fequal (new_tool_bar, f->tool_bar_items)))
+         if (new_n_tool_bar != f->n_tool_bar_items
+             || 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
@@ -8663,11 +9601,22 @@ build_desired_tool_bar_string (f)
 }
 
 
-/* Display one line of the tool-bar of frame IT->f.  */
+/* Display one line of the tool-bar of frame IT->f.
+
+   HEIGHT specifies the desired height of the tool-bar line.
+   If the actual height of the glyph row is less than HEIGHT, the
+   row's height is increased to HEIGHT, and the icons are centered
+   vertically in the new height.
+
+   If HEIGHT is -1, we are counting needed tool-bar lines, so don't
+   count a final empty row in case the tool-bar width exactly matches
+   the window width.
+*/
 
 static void
-display_tool_bar_line (it)
+display_tool_bar_line (it, height)
      struct it *it;
+     int height;
 {
   struct glyph_row *row = it->glyph_row;
   int max_x = it->last_visible_x;
@@ -8682,29 +9631,42 @@ display_tool_bar_line (it)
 
   while (it->current_x < max_x)
     {
-      int x_before, x, n_glyphs_before, i, nglyphs;
+      int x, n_glyphs_before, i, nglyphs;
+      struct it it_before;
 
       /* Get the next display element.  */
       if (!get_next_display_element (it))
-       break;
+       {
+         /* Don't count empty row if we are counting needed tool-bar lines.  */
+         if (height < 0 && !it->hpos)
+           return;
+         break;
+       }
 
       /* Produce glyphs.  */
-      x_before = it->current_x;
-      n_glyphs_before = it->glyph_row->used[TEXT_AREA];
+      n_glyphs_before = row->used[TEXT_AREA];
+      it_before = *it;
+
       PRODUCE_GLYPHS (it);
 
-      nglyphs = it->glyph_row->used[TEXT_AREA] - n_glyphs_before;
+      nglyphs = row->used[TEXT_AREA] - n_glyphs_before;
       i = 0;
-      x = x_before;
+      x = it_before.current_x;
       while (i < nglyphs)
        {
          struct glyph *glyph = row->glyphs[TEXT_AREA] + n_glyphs_before + i;
 
          if (x + glyph->pixel_width > max_x)
            {
-             /* Glyph doesn't fit on line.  */
-             it->glyph_row->used[TEXT_AREA] = n_glyphs_before + i;
-             it->current_x = x;
+             /* Glyph doesn't fit on line.  Backtrack.  */
+             row->used[TEXT_AREA] = n_glyphs_before;
+             *it = it_before;
+             /* If this is the only glyph on this line, it will never fit on the
+                toolbar, so skip it.   But ensure there is at least one glyph,
+                so we don't accidentally disable the tool-bar.  */
+             if (n_glyphs_before == 0
+                 && (it->vpos > 0 || IT_STRING_CHARPOS (*it) < it->end_charpos-1))
+               break;
              goto out;
            }
 
@@ -8723,11 +9685,24 @@ display_tool_bar_line (it)
  out:;
 
   row->displays_text_p = row->used[TEXT_AREA] != 0;
+  /* Use default face for the border below the tool bar.  */
+  if (!row->displays_text_p)
+    it->face_id = DEFAULT_FACE_ID;
   extend_face_to_end_of_line (it);
   last = row->glyphs[TEXT_AREA] + row->used[TEXT_AREA] - 1;
   last->right_box_line_p = 1;
   if (last == row->glyphs[TEXT_AREA])
     last->left_box_line_p = 1;
+
+  /* Make line the desired height and center it vertically.  */
+  if ((height -= it->max_ascent + it->max_descent) > 0)
+    {
+      /* Don't add more than one line height.  */
+      height %= FRAME_LINE_HEIGHT (it->f);
+      it->max_ascent += height / 2;
+      it->max_descent += (height + 1) / 2;
+    }
+
   compute_line_metrics (it);
 
   /* If line is empty, make it occupy the rest of the tool-bar.  */
@@ -8750,29 +9725,45 @@ display_tool_bar_line (it)
 }
 
 
+/* Max tool-bar height.  */
+
+#define MAX_FRAME_TOOL_BAR_HEIGHT(f) \
+  ((FRAME_LINE_HEIGHT (f) * FRAME_LINES (f)))
+
 /* Value is the number of screen lines needed to make all tool-bar
-   items of frame F visible.  */
+   items of frame F visible.  The number of actual rows needed is
+   returned in *N_ROWS if non-NULL.  */
 
 static int
-tool_bar_lines_needed (f)
+tool_bar_lines_needed (f, n_rows)
      struct frame *f;
+     int *n_rows;
 {
   struct window *w = XWINDOW (f->tool_bar_window);
   struct it it;
+  /* tool_bar_lines_needed is called from redisplay_tool_bar after building
+     the desired matrix, so use (unused) mode-line row as temporary row to
+     avoid destroying the first tool-bar row.  */
+  struct glyph_row *temp_row = MATRIX_MODE_LINE_ROW (w->desired_matrix);
 
   /* Initialize an iterator for iteration over
      F->desired_tool_bar_string in the tool-bar window of frame F.  */
-  init_iterator (&it, w, -1, -1, w->desired_matrix->rows, TOOL_BAR_FACE_ID);
+  init_iterator (&it, w, -1, -1, temp_row, TOOL_BAR_FACE_ID);
   it.first_visible_x = 0;
   it.last_visible_x = FRAME_TOTAL_COLS (f) * FRAME_COLUMN_WIDTH (f);
   reseat_to_string (&it, NULL, f->desired_tool_bar_string, 0, 0, 0, -1);
 
   while (!ITERATOR_AT_END_P (&it))
     {
-      it.glyph_row = w->desired_matrix->rows;
-      clear_glyph_row (it.glyph_row);
-      display_tool_bar_line (&it);
+      clear_glyph_row (temp_row);
+      it.glyph_row = temp_row;
+      display_tool_bar_line (&it, -1);
     }
+  clear_glyph_row (temp_row);
+
+  /* f->n_tool_bar_rows == 0 means "unknown"; -1 means no tool-bar.  */
+  if (n_rows)
+    *n_rows = it.vpos > 0 ? it.vpos : -1;
 
   return (it.current_y + FRAME_LINE_HEIGHT (f) - 1) / FRAME_LINE_HEIGHT (f);
 }
@@ -8802,7 +9793,7 @@ DEFUN ("tool-bar-lines-needed", Ftool_bar_lines_needed, Stool_bar_lines_needed,
       if (f->n_tool_bar_items)
        {
          build_desired_tool_bar_string (f);
-         nlines = tool_bar_lines_needed (f);
+         nlines = tool_bar_lines_needed (f, NULL);
        }
     }
 
@@ -8847,9 +9838,68 @@ redisplay_tool_bar (f)
   build_desired_tool_bar_string (f);
   reseat_to_string (&it, NULL, f->desired_tool_bar_string, 0, 0, 0, -1);
 
+  if (f->n_tool_bar_rows == 0)
+    {
+      int nlines;
+
+      if ((nlines = tool_bar_lines_needed (f, &f->n_tool_bar_rows),
+          nlines != WINDOW_TOTAL_LINES (w)))
+       {
+         extern Lisp_Object Qtool_bar_lines;
+         Lisp_Object frame;
+         int old_height = WINDOW_TOTAL_LINES (w);
+
+         XSETFRAME (frame, f);
+         Fmodify_frame_parameters (frame,
+                                   Fcons (Fcons (Qtool_bar_lines,
+                                                 make_number (nlines)),
+                                          Qnil));
+         if (WINDOW_TOTAL_LINES (w) != old_height)
+           {
+             clear_glyph_matrix (w->desired_matrix);
+             fonts_changed_p = 1;
+             return 1;
+           }
+       }
+    }
+
   /* Display as many lines as needed to display all tool-bar items.  */
-  while (it.current_y < it.last_visible_y)
-    display_tool_bar_line (&it);
+
+  if (f->n_tool_bar_rows > 0)
+    {
+      int border, rows, height, extra;
+
+      if (INTEGERP (Vtool_bar_border))
+       border = XINT (Vtool_bar_border);
+      else if (EQ (Vtool_bar_border, Qinternal_border_width))
+       border = FRAME_INTERNAL_BORDER_WIDTH (f);
+      else if (EQ (Vtool_bar_border, Qborder_width))
+       border = f->border_width;
+      else
+       border = 0;
+      if (border < 0)
+       border = 0;
+
+      rows = f->n_tool_bar_rows;
+      height = max (1, (it.last_visible_y - border) / rows);
+      extra = it.last_visible_y - border - height * rows;
+
+      while (it.current_y < it.last_visible_y)
+       {
+         int h = 0;
+         if (extra > 0 && rows-- > 0)
+           {
+             h = (extra + rows - 1) / rows;
+             extra -= h;
+           }
+         display_tool_bar_line (&it, height + h);
+       }
+    }
+  else
+    {
+      while (it.current_y < it.last_visible_y)
+       display_tool_bar_line (&it, 0);
+    }
 
   /* It doesn't make much sense to try scrolling in the tool-bar
      window, so don't do it.  */
@@ -8858,17 +9908,20 @@ redisplay_tool_bar (f)
 
   if (auto_resize_tool_bars_p)
     {
-      int nlines;
+      int nlines, nrows;
+      int max_tool_bar_height = MAX_FRAME_TOOL_BAR_HEIGHT (f);
 
       /* If we couldn't display everything, change the tool-bar's
-        height.  */
-      if (IT_STRING_CHARPOS (it) < it.end_charpos)
+        height if there is room for more.  */
+      if (IT_STRING_CHARPOS (it) < it.end_charpos
+         && it.current_y < max_tool_bar_height)
        change_height_p = 1;
 
+      row = it.glyph_row - 1;
+
       /* If there are blank lines at the end, except for a partially
         visible blank line at the end that is smaller than
         FRAME_LINE_HEIGHT, change the tool-bar's height.  */
-      row = it.glyph_row - 1;
       if (!row->displays_text_p
          && row->height >= FRAME_LINE_HEIGHT (f))
        change_height_p = 1;
@@ -8876,13 +9929,14 @@ redisplay_tool_bar (f)
       /* If row displays tool-bar items, but is partially visible,
         change the tool-bar's height.  */
       if (row->displays_text_p
-         && MATRIX_ROW_BOTTOM_Y (row) > it.last_visible_y)
+         && MATRIX_ROW_BOTTOM_Y (row) > it.last_visible_y
+         && MATRIX_ROW_BOTTOM_Y (row) < max_tool_bar_height)
        change_height_p = 1;
 
       /* Resize windows as needed by changing the `tool-bar-lines'
         frame parameter.  */
       if (change_height_p
-         && (nlines = tool_bar_lines_needed (f),
+         && (nlines = tool_bar_lines_needed (f, &nrows),
              nlines != WINDOW_TOTAL_LINES (w)))
        {
          extern Lisp_Object Qtool_bar_lines;
@@ -8890,13 +9944,16 @@ redisplay_tool_bar (f)
          int old_height = WINDOW_TOTAL_LINES (w);
 
          XSETFRAME (frame, f);
-         clear_glyph_matrix (w->desired_matrix);
          Fmodify_frame_parameters (frame,
                                    Fcons (Fcons (Qtool_bar_lines,
                                                  make_number (nlines)),
                                           Qnil));
          if (WINDOW_TOTAL_LINES (w) != old_height)
-           fonts_changed_p = 1;
+           {
+             clear_glyph_matrix (w->desired_matrix);
+             f->n_tool_bar_rows = nrows;
+             fonts_changed_p = 1;
+           }
        }
     }
 
@@ -9461,22 +10518,14 @@ redisplay ()
 
 
 static Lisp_Object
-overlay_arrow_string_or_property (var, pbitmap)
+overlay_arrow_string_or_property (var)
      Lisp_Object var;
-     int *pbitmap;
 {
-  Lisp_Object pstr = Fget (var, Qoverlay_arrow_string);
-  Lisp_Object bitmap;
+  Lisp_Object val;
 
-  if (pbitmap)
-    {
-      *pbitmap = 0;
-      if (bitmap  = Fget (var, Qoverlay_arrow_bitmap), INTEGERP (bitmap))
-       *pbitmap = XINT (bitmap);
-    }
+  if (val = Fget (var, Qoverlay_arrow_string), STRINGP (val))
+    return val;
 
-  if (!NILP (pstr))
-    return pstr;
   return Voverlay_arrow_string;
 }
 
@@ -9526,7 +10575,7 @@ overlay_arrows_changed_p ()
        continue;
       if (! EQ (COERCE_MARKER (val),
                Fget (var, Qlast_arrow_position))
-         || ! (pstr = overlay_arrow_string_or_property (var, 0),
+         || ! (pstr = overlay_arrow_string_or_property (var),
                EQ (pstr, Fget (var, Qlast_arrow_string))))
        return 1;
     }
@@ -9556,7 +10605,7 @@ update_overlay_arrows (up_to_date)
          Fput (var, Qlast_arrow_position,
                COERCE_MARKER (val));
          Fput (var, Qlast_arrow_string,
-               overlay_arrow_string_or_property (var, 0));
+               overlay_arrow_string_or_property (var));
        }
       else if (up_to_date < 0
               || !NILP (Fget (var, Qlast_arrow_position)))
@@ -9569,14 +10618,13 @@ update_overlay_arrows (up_to_date)
 
 
 /* Return overlay arrow string to display at row.
-   Return t if display as bitmap in left fringe.
+   Return integer (bitmap number) for arrow bitmap in left fringe.
    Return nil if no overlay arrow.  */
 
 static Lisp_Object
-overlay_arrow_at_row (it, row, pbitmap)
+overlay_arrow_at_row (it, row)
      struct it *it;
      struct glyph_row *row;
-     int *pbitmap;
 {
   Lisp_Object vlist;
 
@@ -9596,17 +10644,23 @@ overlay_arrow_at_row (it, row, pbitmap)
          && current_buffer == XMARKER (val)->buffer
          && (MATRIX_ROW_START_CHARPOS (row) == marker_position (val)))
        {
-         val = overlay_arrow_string_or_property (var, pbitmap);
          if (FRAME_WINDOW_P (it->f)
              && WINDOW_LEFT_FRINGE_WIDTH (it->w) > 0)
-           return Qt;
-         if (STRINGP (val))
-           return val;
-         break;
+           {
+#ifdef HAVE_WINDOW_SYSTEM
+             if (val = Fget (var, Qoverlay_arrow_bitmap), SYMBOLP (val))
+               {
+                 int fringe_bitmap;
+                 if ((fringe_bitmap = lookup_fringe_bitmap (val)) != 0)
+                   return make_number (fringe_bitmap);
+               }
+#endif
+             return make_number (-1); /* Use default arrow bitmap */
+           }
+         return overlay_arrow_string_or_property (var);
        }
     }
 
-  *pbitmap = 0;
   return Qnil;
 }
 
@@ -9711,7 +10765,9 @@ select_frame_for_redisplay (frame)
            (BUFFER_LOCAL_VALUEP (val)
             || SOME_BUFFER_LOCAL_VALUEP (val)))
        && XBUFFER_LOCAL_VALUE (val)->check_frame)
-      Fsymbol_value (sym);
+      /* Use find_symbol_value rather than Fsymbol_value
+        to avoid an error if it is void.  */
+      find_symbol_value (sym);
 
   for (tail = XFRAME (old)->param_alist; CONSP (tail); tail = XCDR (tail))
     if (CONSP (XCAR (tail))
@@ -9722,7 +10778,7 @@ select_frame_for_redisplay (frame)
            (BUFFER_LOCAL_VALUEP (val)
             || SOME_BUFFER_LOCAL_VALUEP (val)))
        && XBUFFER_LOCAL_VALUE (val)->check_frame)
-      Fsymbol_value (sym);
+      find_symbol_value (sym);
 }
 
 
@@ -9746,13 +10802,13 @@ redisplay_internal (preserve_echo_area)
      int preserve_echo_area;
 {
   struct window *w = XWINDOW (selected_window);
-  struct frame *f = XFRAME (w->frame);
+  struct frame *f;
   int pause;
   int must_finish = 0;
   struct text_pos tlbufpos, tlendpos;
   int number_of_visible_frames;
   int count;
-  struct frame *sf = SELECTED_FRAME ();
+  struct frame *sf;
   int polling_stopped_here = 0;
 
   /* Non-zero means redisplay has to consider all windows on all
@@ -9765,8 +10821,16 @@ redisplay_internal (preserve_echo_area)
      initialized, or redisplay is explicitly turned off by setting
      Vinhibit_redisplay.  */
   if (noninteractive
-      || !NILP (Vinhibit_redisplay)
-      || !f->glyphs_initialized_p)
+      || !NILP (Vinhibit_redisplay))
+    return;
+
+  /* Don't examine these until after testing Vinhibit_redisplay.
+     When Emacs is shutting down, perhaps because its connection to
+     X has dropped, we should not look at them at all.  */
+  f = XFRAME (w->frame);
+  sf = SELECTED_FRAME ();
+
+  if (!f->glyphs_initialized_p)
     return;
 
   /* The flag redisplay_performed_directly_p is set by
@@ -9796,9 +10860,21 @@ redisplay_internal (preserve_echo_area)
   ++redisplaying_p;
   specbind (Qinhibit_free_realized_faces, Qnil);
 
+  {
+    Lisp_Object tail, frame;
+
+    FOR_EACH_FRAME (tail, frame)
+      {
+       struct frame *f = XFRAME (frame);
+       f->already_hscrolled_p = 0;
+      }
+  }
+
  retry:
   pause = 0;
   reconsider_clip_changes (w, current_buffer);
+  last_escape_glyph_frame = NULL;
+  last_escape_glyph_face_id = (1 << FACE_ID_BITS);
 
   /* If new fonts have been loaded that make a glyph matrix adjustment
      necessary, do it.  */
@@ -9855,7 +10931,8 @@ redisplay_internal (preserve_echo_area)
     clear_garbaged_frames ();
 
   /* Build menubar and tool-bar items.  */
-  prepare_menu_bars ();
+  if (NILP (Vmemory_full))
+    prepare_menu_bars ();
 
   if (windows_or_buffers_changed)
     update_mode_lines++;
@@ -10178,7 +11255,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
@@ -10187,16 +11266,9 @@ redisplay_internal (preserve_echo_area)
   if (consider_all_windows_p)
     {
       Lisp_Object tail, frame;
-      int i, n = 0, size = 50;
-      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;
-       }
+      FOR_EACH_FRAME (tail, frame)
+       XFRAME (frame)->updated_p = 0;
 
       /* Recompute # windows showing selected buffer.  This will be
         incremented each time such a window is displayed.  */
@@ -10213,12 +11285,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)
@@ -10241,8 +11307,12 @@ redisplay_internal (preserve_echo_area)
              if (FRAME_VISIBLE_P (f) && !FRAME_OBSCURED_P (f))
                {
                  /* See if we have to hscroll.  */
-                 if (hscroll_windows (f->root_window))
-                   goto retry;
+                 if (!f->already_hscrolled_p)
+                   {
+                     f->already_hscrolled_p = 1;
+                     if (hscroll_windows (f->root_window))
+                       goto retry;
+                   }
 
                  /* Prevent various kinds of signals during display
                     update.  stdio is not robust about handling
@@ -10260,15 +11330,7 @@ redisplay_internal (preserve_echo_area)
                    break;
 #endif
 
-                 if (n == size)
-                   {
-                     int nbytes = size * sizeof *updated;
-                     struct frame **p = (struct frame **) alloca (2 * nbytes);
-                     bcopy (updated, p, nbytes);
-                     size *= 2;
-                   }
-
-                 updated[n++] = f;
+                 f->updated_p = 1;
                }
            }
        }
@@ -10278,12 +11340,15 @@ redisplay_internal (preserve_echo_area)
          /* Do the mark_window_display_accurate after all windows have
             been redisplayed because this call resets flags in buffers
             which are needed for proper redisplay.  */
-         for (i = 0; i < n; ++i)
+         FOR_EACH_FRAME (tail, frame)
            {
-             struct frame *f = updated[i];
-             mark_window_display_accurate (f->root_window, 1);
-             if (frame_up_to_date_hook)
-               frame_up_to_date_hook (f);
+             struct frame *f = XFRAME (frame);
+             if (f->updated_p)
+               {
+                 mark_window_display_accurate (f->root_window, 1);
+                 if (frame_up_to_date_hook)
+                   frame_up_to_date_hook (f);
+               }
            }
        }
     }
@@ -10422,6 +11487,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;
@@ -10692,9 +11780,11 @@ redisplay_window_1 (window)
 
 /* Set cursor position of W.  PT is assumed to be displayed in ROW.
    DELTA is the number of bytes by which positions recorded in ROW
-   differ from current buffer positions.  */
+   differ from current buffer positions.
 
-void
+   Return 0 if cursor is not on this row.  1 otherwise.  */
+
+int
 set_cursor_from_row (w, row, matrix, delta, delta_bytes, dy, dvpos)
      struct window *w;
      struct glyph_row *row;
@@ -10741,7 +11831,7 @@ set_cursor_from_row (w, row, matrix, delta, delta_bytes, dy, dvpos)
          x += glyph->pixel_width;
          ++glyph;
          if (cursor_from_overlay_pos
-             && last_pos > cursor_from_overlay_pos)
+             && last_pos >= cursor_from_overlay_pos)
            {
              cursor_from_overlay_pos = 0;
              cursor = 0;
@@ -10749,16 +11839,21 @@ set_cursor_from_row (w, row, matrix, delta, delta_bytes, dy, dvpos)
        }
       else
        {
-         string_before_pos = last_pos;
-         string_start = glyph;
-         string_start_x = x;
+         if (string_start == NULL)
+           {
+             string_before_pos = last_pos;
+             string_start = glyph;
+             string_start_x = x;
+           }
          /* Skip all glyphs from string.  */
          do
            {
+             Lisp_Object cprop;
              int pos;
              if ((cursor == NULL || glyph > cursor)
-                 && !NILP (Fget_char_property (make_number ((glyph)->charpos),
-                                               Qcursor, (glyph)->object))
+                 && (cprop = Fget_char_property (make_number ((glyph)->charpos),
+                                                 Qcursor, (glyph)->object),
+                     !NILP (cprop))
                  && (pos = string_buffer_position (w, glyph->object,
                                                    string_before_pos),
                      (pos == 0   /* From overlay */
@@ -10769,14 +11864,15 @@ set_cursor_from_row (w, row, matrix, delta, delta_bytes, dy, dvpos)
                     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_from_overlay_pos = (pos ? 0 : last_pos
+                                            + (INTEGERP (cprop) ? XINT (cprop) : 0));
                  cursor = glyph;
                  cursor_x = x;
                }
              x += glyph->pixel_width;
              ++glyph;
            }
-         while (glyph < end && STRINGP (glyph->object));
+         while (glyph < end && EQ (glyph->object, string_start->object));
        }
     }
 
@@ -10785,6 +11881,18 @@ set_cursor_from_row (w, row, matrix, delta, delta_bytes, dy, dvpos)
       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))
     {
@@ -10794,25 +11902,25 @@ set_cursor_from_row (w, row, matrix, delta, delta_bytes, dy, dvpos)
         glyph on point by scanning from string_start again.  */
       Lisp_Object limit;
       Lisp_Object string;
+      struct glyph *stop = glyph;
       int pos;
 
       limit = make_number (pt_old + 1);
-      end = glyph;
       glyph = string_start;
       x = string_start_x;
       string = glyph->object;
       pos = string_buffer_position (w, string, string_before_pos);
       /* If STRING is from overlay, LAST_POS == 0.  We skip such glyphs
         because we always put cursor after overlay strings.  */
-      while (pos == 0 && glyph < end)
+      while (pos == 0 && glyph < stop)
        {
          string = glyph->object;
-         SKIP_GLYPHS (glyph, end, x, EQ (glyph->object, string));
-         if (glyph < end)
+         SKIP_GLYPHS (glyph, stop, x, EQ (glyph->object, string));
+         if (glyph < stop)
            pos = string_buffer_position (w, glyph->object, string_before_pos);
        }
 
-      while (glyph < end)
+      while (glyph < stop)
        {
          pos = XINT (Fnext_single_char_property_change
                      (make_number (pos), Qdisplay, Qnil, limit));
@@ -10820,15 +11928,20 @@ set_cursor_from_row (w, row, matrix, delta, delta_bytes, dy, dvpos)
            break;
          /* Skip glyphs from the same string.  */
          string = glyph->object;
-         SKIP_GLYPHS (glyph, end, x, EQ (glyph->object, string));
+         SKIP_GLYPHS (glyph, stop, x, EQ (glyph->object, string));
          /* Skip glyphs from an overlay.  */
-         while (glyph < end
+         while (glyph < stop
                 && ! string_buffer_position (w, glyph->object, pos))
            {
              string = glyph->object;
-             SKIP_GLYPHS (glyph, end, x, EQ (glyph->object, string));
+             SKIP_GLYPHS (glyph, stop, x, EQ (glyph->object, string));
            }
        }
+
+      /* If we reached the end of the line, and end was from a string,
+        cursor is not on this line.  */
+      if (glyph == end && row->continued_p)
+       return 0;
     }
 
   w->cursor.hpos = glyph - row->glyphs[TEXT_AREA];
@@ -10862,6 +11975,8 @@ set_cursor_from_row (w, row, matrix, delta, delta_bytes, dy, dvpos)
       else
        CHARPOS (this_line_start_pos) = 0;
     }
+
+  return 1;
 }
 
 
@@ -10907,9 +12022,10 @@ 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;
+     int current_matrix_p;
 {
   struct glyph_matrix *matrix;
   struct glyph_row *row;
@@ -10923,7 +12039,7 @@ make_cursor_line_fully_visible (w, force_p)
   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.  */
@@ -10935,7 +12051,8 @@ make_cursor_line_fully_visible (w, force_p)
   window_height = window_box_height (w);
   if (row->height >= window_height)
     {
-      if (!force_p || w->vscroll)
+      if (!force_p || MINI_WINDOW_P (w)
+         || w->vscroll || w->cursor.vpos == 0)
        return 1;
     }
   return 0;
@@ -11211,7 +12328,7 @@ try_scrolling (window, just_this_one_p, scroll_conservatively,
 
   /* Display the window.  Give up if new fonts are loaded, or if point
      doesn't appear.  */
-  if (!try_window (window, startp))
+  if (!try_window (window, startp, 0))
     rc = SCROLLING_NEED_LARGER_MATRICES;
   else if (w->cursor.vpos < 0)
     {
@@ -11228,7 +12345,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;
@@ -11465,7 +12582,10 @@ try_cursor_movement (window, startp, scroll_step)
              while (!row->mode_line_p
                     && (MATRIX_ROW_START_CHARPOS (row) > PT
                         || (MATRIX_ROW_START_CHARPOS (row) == PT
-                            && MATRIX_ROW_STARTS_IN_MIDDLE_OF_CHAR_P (row)))
+                            && (MATRIX_ROW_STARTS_IN_MIDDLE_OF_CHAR_P (row)
+                                || (/* STARTS_IN_MIDDLE_OF_STRING_P (row) */
+                                    row > w->current_matrix->rows
+                                    && (row-1)->ends_in_newline_from_string_p))))
                     && (row->y > top_scroll_margin
                         || CHARPOS (startp) == BEGV))
                {
@@ -11498,6 +12618,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))
@@ -11505,7 +12631,8 @@ 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 (w, 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)
@@ -11524,7 +12651,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;
@@ -11534,8 +12661,18 @@ try_cursor_movement (window, startp, scroll_step)
            rc = CURSOR_MOVEMENT_MUST_SCROLL;
          else
            {
-             set_cursor_from_row (w, row, w->current_matrix, 0, 0, 0, 0);
-             rc = CURSOR_MOVEMENT_SUCCESS;
+             do
+               {
+                 if (set_cursor_from_row (w, row, w->current_matrix, 0, 0, 0, 0))
+                   {
+                     rc = CURSOR_MOVEMENT_SUCCESS;
+                     break;
+                   }
+                 ++row;
+               }
+             while (MATRIX_ROW_BOTTOM_Y (row) < last_y
+                    && MATRIX_ROW_START_CHARPOS (row) == PT
+                    && cursor_row_p (w, row));
            }
        }
     }
@@ -11609,7 +12746,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);
@@ -11621,9 +12758,6 @@ redisplay_window (window, just_this_one_p)
   *w->desired_matrix->method = 0;
 #endif
 
-  /* Force this to be looked up again for each redisp of each window.  */
-  escape_glyph_face = -1;
-
   specbind (Qinhibit_point_motion_hooks, Qt);
 
   reconsider_clip_changes (w, buffer);
@@ -11799,8 +12933,6 @@ redisplay_window (window, just_this_one_p)
       /* IT may overshoot PT if text at PT is invisible.  */
       else if (IT_CHARPOS (it) > PT && CHARPOS (startp) <= PT)
        w->force_start = Qt;
-
-
     }
 
   /* Handle case where place to start displaying has been specified,
@@ -11810,6 +12942,7 @@ redisplay_window (window, just_this_one_p)
     {
       /* We set this later on if we have to adjust point.  */
       int new_vpos = -1;
+      int val;
 
       w->force_start = Qnil;
       w->vscroll = 0;
@@ -11843,12 +12976,16 @@ redisplay_window (window, just_this_one_p)
 
       /* Redisplay, then check if cursor has been set during the
         redisplay.  Give up if new fonts were loaded.  */
-      if (!try_window (window, startp))
+      val = try_window (window, startp, 1);
+      if (!val)
        {
          w->force_start = Qt;
          clear_glyph_matrix (w->desired_matrix);
          goto need_larger_matrices;
        }
+      /* Point was outside the scroll margins.  */
+      if (val < 0)
+       new_vpos = window_box_height (w) / 2;
 
       if (w->cursor.vpos < 0 && !w->frozen_window_start_p)
        {
@@ -11858,7 +12995,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.  */
@@ -11891,7 +13028,7 @@ redisplay_window (window, just_this_one_p)
              && !NILP (current_buffer->mark_active))
            {
              clear_glyph_matrix (w->desired_matrix);
-             if (!try_window (window, startp))
+             if (!try_window (window, startp, 0))
                goto need_larger_matrices;
            }
        }
@@ -11965,6 +13102,36 @@ redisplay_window (window, just_this_one_p)
               || (XFASTINT (w->last_modified) >= MODIFF
                   && XFASTINT (w->last_overlay_modified) >= OVERLAY_MODIFF)))
     {
+
+      /* If first window line is a continuation line, and window start
+        is inside the modified region, but the first change is before
+        current window start, we must select a new window start.*/
+      if (NILP (w->start_at_line_beg)
+         && CHARPOS (startp) > BEGV)
+       {
+         /* Make sure beg_unchanged and end_unchanged are up to date.
+            Do it only if buffer has really changed.  This may or may
+            not have been done by try_window_id (see which) already. */
+         if (MODIFF > SAVE_MODIFF
+             /* This seems to happen sometimes after saving a buffer.  */
+             || BEG_UNCHANGED + END_UNCHANGED > Z_BYTE)
+           {
+             if (GPT - BEG < BEG_UNCHANGED)
+               BEG_UNCHANGED = GPT - BEG;
+             if (Z - GPT < END_UNCHANGED)
+               END_UNCHANGED = Z - GPT;
+           }
+
+         if (CHARPOS (startp) > BEG + BEG_UNCHANGED
+             && CHARPOS (startp) <= Z - END_UNCHANGED)
+           {
+             /* There doesn't seems to be a simple way to find a new
+                window start that is near the old window start, so
+                we just recenter.  */
+             goto recenter;
+           }
+       }
+
 #if GLYPH_DEBUG
       debug_method_add (w, "same window start");
 #endif
@@ -11981,7 +13148,11 @@ redisplay_window (window, just_this_one_p)
               = try_window_reusing_current_matrix (w)))
        {
          IF_DEBUG (debug_method_add (w, "1"));
-         try_window (window, startp);
+         if (try_window (window, startp, 1) < 0)
+           /* -1 means we need to scroll.
+              0 means we need new matrices, but fonts_changed_p
+              is set in that case, so we will detect it below.  */
+           goto try_to_scroll;
        }
 
       if (fonts_changed_p)
@@ -11995,7 +13166,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;
@@ -12055,10 +13226,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");
@@ -12085,7 +13254,11 @@ redisplay_window (window, just_this_one_p)
     {
       init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID);
       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;
     }
 
@@ -12109,7 +13282,7 @@ redisplay_window (window, just_this_one_p)
       || MINI_WINDOW_P (w)
       || !(used_current_matrix_p
           = try_window_reusing_current_matrix (w)))
-    try_window (window, startp);
+    try_window (window, startp, 0);
 
   /* If new fonts have been loaded (due to fontsets), give up.  We
      have to start a new redisplay since we need to re-adjust glyph
@@ -12129,13 +13302,13 @@ redisplay_window (window, just_this_one_p)
        {
          clear_glyph_matrix (w->desired_matrix);
          move_it_by_lines (&it, 1, 0);
-         try_window (window, it.current.pos);
+         try_window (window, it.current.pos, 0);
        }
       else if (PT < IT_CHARPOS (it))
        {
          clear_glyph_matrix (w->desired_matrix);
          move_it_by_lines (&it, -1, 0);
-         try_window (window, it.current.pos);
+         try_window (window, it.current.pos, 0);
        }
       else
        {
@@ -12155,7 +13328,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)
@@ -12168,9 +13341,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:
@@ -12273,10 +13449,9 @@ redisplay_window (window, just_this_one_p)
 
 #ifdef HAVE_WINDOW_SYSTEM
   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_window_fringes (w, (just_this_one_p
+                                   || (!used_current_matrix_p && !overlay_arrow_seen)
+                                   || w->pseudo_window_p)))
     {
       update_begin (f);
       BLOCK_INPUT;
@@ -12315,14 +13490,18 @@ redisplay_window (window, just_this_one_p)
 
 
 /* Build the complete desired matrix of WINDOW with a window start
-   buffer position POS.  Value is non-zero if successful.  It is zero
-   if fonts were loaded during redisplay which makes re-adjusting
-   glyph matrices necessary.  */
+   buffer position POS.
+
+   Value is 1 if successful.  It is zero if fonts were loaded during
+   redisplay which makes re-adjusting glyph matrices necessary, and -1
+   if point would appear in the scroll margins.
+   (We check that only if CHECK_MARGINS is nonzero.  */
 
 int
-try_window (window, pos)
+try_window (window, pos, check_margins)
      Lisp_Object window;
      struct text_pos pos;
+     int check_margins;
 {
   struct window *w = XWINDOW (window);
   struct it it;
@@ -12347,6 +13526,32 @@ try_window (window, pos)
        return 0;
     }
 
+  /* Don't let the cursor end in the scroll margins.  */
+  if (check_margins
+      && !MINI_WINDOW_P (w))
+    {
+      int this_scroll_margin;
+
+      this_scroll_margin = max (0, scroll_margin);
+      this_scroll_margin = min (this_scroll_margin, WINDOW_TOTAL_LINES (w) / 4);
+      this_scroll_margin *= FRAME_LINE_HEIGHT (it.f);
+
+      if ((w->cursor.y >= 0    /* not vscrolled */
+          && w->cursor.y < this_scroll_margin
+          && CHARPOS (pos) > BEGV
+          && IT_CHARPOS (it) < ZV)
+         /* rms: considering make_cursor_line_fully_visible_p here
+            seems to give wrong results.  We don't want to recenter
+            when the last line is partly visible, we want to allow
+            that case to be handled in the usual way.  */
+         || (w->cursor.y + 1) > it.last_visible_y)
+       {
+         w->cursor.vpos = -1;
+         clear_glyph_matrix (w->desired_matrix);
+         return -1;
+       }
+    }
+
   /* If bottom moved off end of frame, change mode line percentage.  */
   if (XFASTINT (w->window_end_pos) <= 0
       && Z != IT_CHARPOS (it))
@@ -12582,7 +13787,7 @@ try_window_reusing_current_matrix (w)
          /* Disable lines in the current matrix which are now
             below the window.  */
          for (++row; row < bottom_row; ++row)
-           row->enabled_p = 0;
+           row->enabled_p = row->mode_line_p = 0;
        }
 
       /* Update window_end_pos etc.; last_reused_text_row is the last
@@ -12955,8 +14160,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;
@@ -13663,7 +14870,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.  */
@@ -13720,7 +14932,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
@@ -13915,6 +15126,25 @@ dump_glyph (row, glyph, area)
               glyph->left_box_line_p,
               glyph->right_box_line_p);
     }
+  else if (glyph->type == COMPOSITE_GLYPH)
+    {
+      fprintf (stderr,
+              "  %5d %4c %6d %c %3d 0x%05x %c %4d %1.1d%1.1d\n",
+              glyph - row->glyphs[TEXT_AREA],
+              '+',
+              glyph->charpos,
+              (BUFFERP (glyph->object)
+               ? 'B'
+               : (STRINGP (glyph->object)
+                  ? 'S'
+                  : '-')),
+              glyph->pixel_width,
+              glyph->u.cmp_id,
+              '.',
+              glyph->face_id,
+              glyph->left_box_line_p,
+              glyph->right_box_line_p);
+    }
 }
 
 
@@ -13930,10 +15160,10 @@ dump_glyph_row (row, vpos, glyphs)
 {
   if (glyphs != 1)
     {
-      fprintf (stderr, "Row Start   End Used oEI><O\\CTZFesm     X    Y    W    H    V    A    P\n");
-      fprintf (stderr, "=======================================================================\n");
+      fprintf (stderr, "Row Start   End Used oE><\\CTZFesm     X    Y    W    H    V    A    P\n");
+      fprintf (stderr, "======================================================================\n");
 
-      fprintf (stderr, "%3d %5d %5d %4d %1.1d%1.1d%1.1d%1.1d%1.1d\
+      fprintf (stderr, "%3d %5d %5d %4d %1.1d%1.1d%1.1d%1.1d\
 %1.1d%1.1d%1.1d%1.1d%1.1d%1.1d%1.1d%1.1d  %4d %4d %4d %4d %4d %4d %4d\n",
               vpos,
               MATRIX_ROW_START_CHARPOS (row),
@@ -13943,7 +15173,6 @@ dump_glyph_row (row, vpos, glyphs)
               row->enabled_p,
               row->truncated_on_left_p,
               row->truncated_on_right_p,
-              row->overlay_arrow_p,
               row->continued_p,
               MATRIX_ROW_CONTINUATION_LINE_P (row),
               row->displays_text_p,
@@ -14435,6 +15664,7 @@ extend_face_to_end_of_line (it)
     face = FACE_FROM_ID (f, it->face_id);
 
   if (FRAME_WINDOW_P (f)
+      && it->glyph_row->displays_text_p
       && face->box == FACE_NO_BOX
       && face->background == FRAME_BACKGROUND_PIXEL (f)
       && !face->stipple)
@@ -14584,12 +15814,26 @@ cursor_row_p (w, row)
   if (PT == MATRIX_ROW_END_CHARPOS (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))
-       cursor_row_p = row->continued_p;
-
+        the cursor there, but we still want it at the start of the
+        string if the string starts in this row.
+        If the row is continued it doesn't end in a newline.  */
+      if (CHARPOS (row->end.string_pos) >= 0)
+       cursor_row_p = (row->continued_p
+                       || PT >= MATRIX_ROW_START_CHARPOS (row));
+      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)
@@ -14613,7 +15857,6 @@ display_line (it)
      struct it *it;
 {
   struct glyph_row *row = it->glyph_row;
-  int overlay_arrow_bitmap;
   Lisp_Object overlay_arrow_string;
 
   /* We always start displaying at hpos zero even if hscrolled.  */
@@ -14867,7 +16110,9 @@ display_line (it)
                        produce_special_glyphs (it, IT_CONTINUATION);
                      row->continued_p = 1;
 
+                     it->current_x = x_before;
                      it->continuation_lines_width += x;
+                     extend_face_to_end_of_line (it);
 
                      if (nglyphs > 1 && i > 0)
                        {
@@ -15021,9 +16266,8 @@ display_line (it)
      mark this glyph row as the one containing the overlay arrow.
      This is clearly a mess with variable size fonts.  It would be
      better to let it be displayed like cursors under X.  */
-  if (! overlay_arrow_seen
-      && (overlay_arrow_string
-           = overlay_arrow_at_row (it, row, &overlay_arrow_bitmap),
+  if ((row->displays_text_p || !overlay_arrow_seen)
+      && (overlay_arrow_string = overlay_arrow_at_row (it, row),
          !NILP (overlay_arrow_string)))
     {
       /* Overlay arrow in window redisplay is a fringe bitmap.  */
@@ -15054,8 +16298,8 @@ display_line (it)
        }
       else
        {
-         it->w->overlay_arrow_bitmap = overlay_arrow_bitmap;
-         row->overlay_arrow_p = 1;
+         xassert (INTEGERP (overlay_arrow_string));
+         row->overlay_arrow_bitmap = XINT (overlay_arrow_string);
        }
       overlay_arrow_seen = 1;
     }
@@ -15066,6 +16310,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;
@@ -15336,6 +16585,7 @@ display_mode_line (w, face_id, format)
 {
   struct it it;
   struct face *face;
+  int count = SPECPDL_INDEX ();
 
   init_iterator (&it, w, -1, -1, NULL, face_id);
   prepare_desired_row (it.glyph_row);
@@ -15346,13 +16596,21 @@ display_mode_line (w, face_id, format)
     /* Force the mode-line to be displayed in the default face.  */
     it.base_face_id = it.face_id = DEFAULT_FACE_ID;
 
+  record_unwind_protect (unwind_format_mode_line,
+                        format_mode_line_unwind_data (NULL, 0));
+
+  mode_line_target = MODE_LINE_DISPLAY;
+
   /* Temporarily make frame's keyboard the current kboard so that
      kboard-local variables in the mode_line_format will get the right
      values.  */
   push_frame_kboard (it.f);
+  record_unwind_save_match_data ();
   display_mode_element (&it, 0, 0, 0, format, Qnil, 0);
   pop_frame_kboard ();
 
+  unbind_to (count, Qnil);
+
   /* Fill up with spaces.  */
   display_string (" ", Qnil, Qnil, 0, 0, &it, 10000, -1, -1, 0);
 
@@ -15375,17 +16633,43 @@ display_mode_line (w, face_id, format)
   return it.glyph_row->height;
 }
 
-/* Alist that caches the results of :propertize.
-   Each element is (PROPERTIZED-STRING . PROPERTY-LIST).  */
-Lisp_Object mode_line_proptrans_alist;
+/* Move element ELT in LIST to the front of LIST.
+   Return the updated list.  */
 
-/* List of strings making up the mode-line.  */
-Lisp_Object mode_line_string_list;
+static Lisp_Object
+move_elt_to_front (elt, list)
+     Lisp_Object elt, list;
+{
+  register Lisp_Object tail, prev;
+  register Lisp_Object tem;
 
-/* Base face property when building propertized mode line string.  */
-static Lisp_Object mode_line_string_face;
-static Lisp_Object mode_line_string_face_prop;
+  tail = list;
+  prev = Qnil;
+  while (CONSP (tail))
+    {
+      tem = XCAR (tail);
+
+      if (EQ (elt, tem))
+       {
+         /* Splice out the link TAIL.  */
+         if (NILP (prev))
+           list = XCDR (tail);
+         else
+           Fsetcdr (prev, XCDR (tail));
+
+         /* Now make it the first.  */
+         Fsetcdr (tail, list);
+         return tail;
+       }
+      else
+       prev = tail;
+      tail = XCDR (tail);
+      QUIT;
+    }
 
+  /* Not found--return unchanged LIST.  */
+  return list;
+}
 
 /* Contribute ELT to the mode line for window IT->w.  How it
    translates into text depends on its data type.
@@ -15407,8 +16691,9 @@ static Lisp_Object mode_line_string_face_prop;
    If RISKY is nonzero, remove (disregard) any properties in any string
    we encounter, and ignore :eval and :propertize.
 
-   If the global variable `frame_title_ptr' is non-NULL, then the output
-   is passed to `store_frame_title' instead of `display_string'.  */
+   The global variable `mode_line_target' determines whether the
+   output is passed to `store_mode_line_noprop',
+   `store_mode_line_string', or `display_string'.  */
 
 static int
 display_mode_element (it, depth, field_width, precision, elt, props, risky)
@@ -15433,9 +16718,10 @@ display_mode_element (it, depth, field_width, precision, elt, props, risky)
       {
        /* A string: output it and check for %-constructs within it.  */
        unsigned char c;
-       const unsigned char *this, *lisp_string;
+       int offset = 0;
 
-       if (!NILP (props) || risky)
+       if (SCHARS (elt) > 0
+           && (!NILP (props) || risky))
          {
            Lisp_Object oprops, aelt;
            oprops = Ftext_properties_at (make_number (0), elt);
@@ -15466,14 +16752,22 @@ display_mode_element (it, depth, field_width, precision, elt, props, risky)
                aelt = Fassoc (elt, mode_line_proptrans_alist);
                if (! NILP (aelt) && !NILP (Fequal (props, XCDR (aelt))))
                  {
-                   mode_line_proptrans_alist
-                     = Fcons (aelt, Fdelq (aelt, mode_line_proptrans_alist));
+                   /* AELT is what we want.  Move it to the front
+                      without consing.  */
                    elt = XCAR (aelt);
+                   mode_line_proptrans_alist
+                     = move_elt_to_front (aelt, mode_line_proptrans_alist);
                  }
                else
                  {
                    Lisp_Object tem;
 
+                   /* If AELT has the wrong props, it is useless.
+                      so get rid of it.  */
+                   if (! NILP (aelt))
+                     mode_line_proptrans_alist
+                       = Fdelq (aelt, mode_line_proptrans_alist);
+
                    elt = Fcopy_sequence (elt);
                    Fset_text_properties (make_number (0), Flength (elt),
                                          props, elt);
@@ -15491,80 +16785,97 @@ display_mode_element (it, depth, field_width, precision, elt, props, risky)
              }
          }
 
-       this = SDATA (elt);
-       lisp_string = this;
+       offset = 0;
 
        if (literal)
          {
            prec = precision - n;
-           if (frame_title_ptr)
-             n += store_frame_title (SDATA (elt), -1, prec);
-           else if (!NILP (mode_line_string_list))
-             n += store_mode_line_string (NULL, elt, 1, 0, prec, Qnil);
-           else
-             n += display_string (NULL, elt, Qnil, 0, 0, it,
-                                  0, prec, 0, STRING_MULTIBYTE (elt));
+           switch (mode_line_target)
+             {
+             case MODE_LINE_NOPROP:
+             case MODE_LINE_TITLE:
+               n += store_mode_line_noprop (SDATA (elt), -1, prec);
+               break;
+             case MODE_LINE_STRING:
+               n += store_mode_line_string (NULL, elt, 1, 0, prec, Qnil);
+               break;
+             case MODE_LINE_DISPLAY:
+               n += display_string (NULL, elt, Qnil, 0, 0, it,
+                                    0, prec, 0, STRING_MULTIBYTE (elt));
+               break;
+             }
 
            break;
          }
 
+       /* Handle the non-literal case.  */
+
        while ((precision <= 0 || n < precision)
-              && *this
-              && (frame_title_ptr
-                  || !NILP (mode_line_string_list)
+              && SREF (elt, offset) != 0
+              && (mode_line_target != MODE_LINE_DISPLAY
                   || it->current_x < it->last_visible_x))
          {
-           const unsigned char *last = this;
+           int last_offset = offset;
 
            /* Advance to end of string or next format specifier.  */
-           while ((c = *this++) != '\0' && c != '%')
+           while ((c = SREF (elt, offset++)) != '\0' && c != '%')
              ;
 
-           if (this - 1 != last)
+           if (offset - 1 != last_offset)
              {
                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;
+               offset--;
 
-               prec = c_string_width (last, this - last, precision - n,
+               prec = c_string_width (SDATA (elt) + last_offset,
+                                      offset - last_offset, precision - n,
                                       &nchars, &nbytes);
 
-               if (frame_title_ptr)
-                 n += store_frame_title (last, 0, prec);
-               else if (!NILP (mode_line_string_list))
+               switch (mode_line_target)
                  {
-                   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 (endpos)),
-                                                0, 0, 0, Qnil);
-                 }
-               else
-                 {
-                   int bytepos = last - lisp_string;
-                   int charpos = string_byte_to_char (elt, bytepos);
-                   n += display_string (NULL, elt, Qnil, 0, charpos,
-                                        it, 0, prec, 0,
-                                        STRING_MULTIBYTE (elt));
+                 case MODE_LINE_NOPROP:
+                 case MODE_LINE_TITLE:
+                   n += store_mode_line_noprop (SDATA (elt) + last_offset, 0, prec);
+                   break;
+                 case MODE_LINE_STRING:
+                   {
+                     int bytepos = last_offset;
+                     int charpos = string_byte_to_char (elt, bytepos);
+                     int endpos = (precision <= 0
+                                   ? string_byte_to_char (elt, offset)
+                                   : charpos + nchars);
+
+                     n += store_mode_line_string (NULL,
+                                                  Fsubstring (elt, make_number (charpos),
+                                                              make_number (endpos)),
+                                                  0, 0, 0, Qnil);
+                   }
+                   break;
+                 case MODE_LINE_DISPLAY:
+                   {
+                     int bytepos = last_offset;
+                     int charpos = string_byte_to_char (elt, bytepos);
+
+                     if (precision <= 0)
+                       nchars = string_byte_to_char (elt, offset) - charpos;
+                     n += display_string (NULL, elt, Qnil, 0, charpos,
+                                          it, 0, nchars, 0,
+                                          STRING_MULTIBYTE (elt));
+                   }
+                   break;
                  }
              }
            else /* c == '%' */
              {
-               const unsigned char *percent_position = this;
+               int percent_position = offset;
 
                /* Get the specified minimum width.  Zero means
                   don't pad.  */
                field = 0;
-               while ((c = *this++) >= '0' && c <= '9')
+               while ((c = SREF (elt, offset++)) >= '0' && c <= '9')
                  field = field * 10 + c - '0';
 
                /* Don't pad beyond the total padding allowed.  */
@@ -15584,7 +16895,7 @@ display_mode_element (it, depth, field_width, precision, elt, props, risky)
                    int bytepos, charpos;
                    unsigned char *spec;
 
-                   bytepos = percent_position - lisp_string;
+                   bytepos = percent_position;
                    charpos = (STRING_MULTIBYTE (elt)
                               ? string_byte_to_char (elt, bytepos)
                               : bytepos);
@@ -15592,44 +16903,51 @@ display_mode_element (it, depth, field_width, precision, elt, props, risky)
                    spec
                      = decode_mode_spec (it->w, c, field, prec, &multibyte);
 
-                   if (frame_title_ptr)
-                     n += store_frame_title (spec, field, prec);
-                   else if (!NILP (mode_line_string_list))
-                     {
-                       int len = strlen (spec);
-                       Lisp_Object tem = make_string (spec, len);
-                       props = Ftext_properties_at (make_number (charpos), elt);
-                       /* Should only keep face property in props */
-                       n += store_mode_line_string (NULL, tem, 0, field, prec, props);
-                     }
-                   else
+                   switch (mode_line_target)
                      {
-                       int nglyphs_before, nwritten;
-
-                       nglyphs_before = it->glyph_row->used[TEXT_AREA];
-                       nwritten = display_string (spec, Qnil, elt,
-                                                  charpos, 0, it,
-                                                  field, prec, 0,
-                                                  multibyte);
-
-                       /* Assign to the glyphs written above the
-                          string where the `%x' came from, position
-                          of the `%'.  */
-                       if (nwritten > 0)
-                         {
-                           struct glyph *glyph
-                             = (it->glyph_row->glyphs[TEXT_AREA]
-                                + nglyphs_before);
-                           int i;
-
-                           for (i = 0; i < nwritten; ++i)
-                             {
-                               glyph[i].object = elt;
-                               glyph[i].charpos = charpos;
-                             }
-
-                           n += nwritten;
-                         }
+                     case MODE_LINE_NOPROP:
+                     case MODE_LINE_TITLE:
+                       n += store_mode_line_noprop (spec, field, prec);
+                       break;
+                     case MODE_LINE_STRING:
+                       {
+                         int len = strlen (spec);
+                         Lisp_Object tem = make_string (spec, len);
+                         props = Ftext_properties_at (make_number (charpos), elt);
+                         /* Should only keep face property in props */
+                         n += store_mode_line_string (NULL, tem, 0, field, prec, props);
+                       }
+                       break;
+                     case MODE_LINE_DISPLAY:
+                       {
+                         int nglyphs_before, nwritten;
+
+                         nglyphs_before = it->glyph_row->used[TEXT_AREA];
+                         nwritten = display_string (spec, Qnil, elt,
+                                                    charpos, 0, it,
+                                                    field, prec, 0,
+                                                    multibyte);
+
+                         /* Assign to the glyphs written above the
+                            string where the `%x' came from, position
+                            of the `%'.  */
+                         if (nwritten > 0)
+                           {
+                             struct glyph *glyph
+                               = (it->glyph_row->glyphs[TEXT_AREA]
+                                  + nglyphs_before);
+                             int i;
+
+                             for (i = 0; i < nwritten; ++i)
+                               {
+                                 glyph[i].object = elt;
+                                 glyph[i].charpos = charpos;
+                               }
+
+                             n += nwritten;
+                           }
+                       }
+                       break;
                      }
                  }
                else /* c == 0 */
@@ -15777,7 +17095,12 @@ display_mode_element (it, depth, field_width, precision, elt, props, risky)
                   && --limit > 0
                   && (precision <= 0 || n < precision))
              {
-               n += display_mode_element (it, depth, field_width - n,
+               n += display_mode_element (it, depth,
+                                          /* Do padding only after the last
+                                             element in the list.  */
+                                          (! CONSP (XCDR (elt))
+                                           ? field_width - n
+                                           : 0),
                                           precision - n, XCAR (elt),
                                           props, risky);
                elt = XCDR (elt);
@@ -15795,13 +17118,20 @@ display_mode_element (it, depth, field_width, precision, elt, props, risky)
   /* Pad to FIELD_WIDTH.  */
   if (field_width > 0 && n < field_width)
     {
-      if (frame_title_ptr)
-       n += store_frame_title ("", field_width - n, 0);
-      else if (!NILP (mode_line_string_list))
-       n += store_mode_line_string ("", Qnil, 0, field_width - n, 0, Qnil);
-      else
-       n += display_string ("", Qnil, Qnil, 0, 0, it, field_width - n,
-                            0, 0, 0);
+      switch (mode_line_target)
+       {
+       case MODE_LINE_NOPROP:
+       case MODE_LINE_TITLE:
+         n += store_mode_line_noprop ("", field_width - n, 0);
+         break;
+       case MODE_LINE_STRING:
+         n += store_mode_line_string ("", Qnil, 0, field_width - n, 0, Qnil);
+         break;
+       case MODE_LINE_DISPLAY:
+         n += display_string ("", Qnil, Qnil, 0, 0, it, field_width - n,
+                              0, 0, 0);
+         break;
+       }
     }
 
   return n;
@@ -15848,7 +17178,7 @@ store_mode_line_string (string, lisp_string, copy_string, field_width, precision
        props = mode_line_string_face_prop;
       else if (!NILP (mode_line_string_face))
        {
-         Lisp_Object face = Fsafe_plist_get (props, Qface);
+         Lisp_Object face = Fplist_get (props, Qface);
          props = Fcopy_sequence (props);
          if (NILP (face))
            face = mode_line_string_face;
@@ -15873,7 +17203,7 @@ store_mode_line_string (string, lisp_string, copy_string, field_width, precision
          Lisp_Object face;
          if (NILP (props))
            props = Ftext_properties_at (make_number (0), lisp_string);
-         face = Fsafe_plist_get (props, Qface);
+         face = Fplist_get (props, Qface);
          if (NILP (face))
            face = mode_line_string_face;
          else
@@ -15909,22 +17239,33 @@ store_mode_line_string (string, lisp_string, copy_string, field_width, precision
 
 
 DEFUN ("format-mode-line", Fformat_mode_line, Sformat_mode_line,
-       0, 4, 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.
-Fourth optional arg BUFFER specifies which buffer to use.  */)
-  (format, window, no_props, buffer)
-     Lisp_Object format, window, no_props, buffer;
+       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);
+  int count = SPECPDL_INDEX ();
+  Lisp_Object str;
+  int string_start = 0;
 
   if (NILP (window))
     window = selected_window;
@@ -15933,83 +17274,72 @@ Fourth optional arg BUFFER specifies which buffer to use.  */)
 
   if (NILP (buffer))
     buffer = w->buffer;
-
   CHECK_BUFFER (buffer);
 
-  if (XBUFFER (buffer) != current_buffer)
-    {
-      old_buffer = current_buffer;
-      set_buffer_internal_1 (XBUFFER (buffer));
-    }
+  if (NILP (format))
+    return build_string ("");
+
+  if (no_props)
+    face = Qnil;
 
-  if (NILP (format) || EQ (format, Qt))
+  if (!NILP (face))
     {
-      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);
+      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);
     }
 
-  init_iterator (&it, w, -1, -1, NULL, face_id);
+  if (face_id < 0)
+    face_id = DEFAULT_FACE_ID;
 
-  if (NILP (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);
+  if (XBUFFER (buffer) != current_buffer)
+    old_buffer = current_buffer;
 
-      mode_line_string_face_prop
-       = (NILP (mode_line_string_face) ? Qnil
-          : Fcons (Qface, Fcons (mode_line_string_face, Qnil)));
+  /* Save things including mode_line_proptrans_alist,
+     and set that to nil so that we don't alter the outer value.  */
+  record_unwind_protect (unwind_format_mode_line,
+                        format_mode_line_unwind_data (old_buffer, 1));
+  mode_line_proptrans_alist = Qnil;
+
+  if (old_buffer)
+    set_buffer_internal_1 (XBUFFER (buffer));
+
+  init_iterator (&it, w, -1, -1, NULL, face_id);
 
-      /* 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);
-      frame_title_ptr = NULL;
+  if (no_props)
+    {
+      mode_line_target = MODE_LINE_NOPROP;
+      mode_line_string_face_prop = Qnil;
+      mode_line_string_list = Qnil;
+      string_start = MODE_LINE_NOPROP_LEN (0);
     }
   else
     {
-      mode_line_string_face_prop = Qnil;
+      mode_line_target = MODE_LINE_STRING;
       mode_line_string_list = Qnil;
-      frame_title_ptr = frame_title_buf;
+      mode_line_string_face = face;
+      mode_line_string_face_prop
+       = (NILP (face) ? Qnil : Fcons (Qface, Fcons (face, Qnil)));
     }
 
   push_frame_kboard (it.f);
   display_mode_element (&it, 0, 0, 0, format, Qnil, 0);
   pop_frame_kboard ();
 
-  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);
-      str = Fmapconcat (intern ("identity"), XCDR (mode_line_string_list),
-                       make_string ("", 0));
-      mode_line_string_face_prop = Qnil;
-      mode_line_string_list = Qnil;
-      return str;
+      len = MODE_LINE_NOPROP_LEN (string_start);
+      str = make_string (mode_line_noprop_buf + string_start, len);
     }
-
-  len = frame_title_ptr - frame_title_buf;
-  if (len > 0 && frame_title_ptr[-1] == '-')
+  else
     {
-      /* Mode lines typically ends with numerous dashes; reduce to two dashes.  */
-      while (frame_title_ptr > frame_title_buf && *--frame_title_ptr == '-')
-       ;
-      frame_title_ptr += 3;  /* restore last non-dash + two dashes */
-      if (len > frame_title_ptr - frame_title_buf)
-       len = frame_title_ptr - frame_title_buf;
+      mode_line_string_list = Fnreverse (mode_line_string_list);
+      str = Fmapconcat (intern ("identity"), mode_line_string_list,
+                       make_string ("", 0));
     }
 
-  frame_title_ptr = NULL;
-  return make_string (frame_title_buf, len);
+  unbind_to (count, Qnil);
+  return str;
 }
 
 /* Write a null-terminated, right justified decimal representation of
@@ -16327,7 +17657,8 @@ decode_mode_spec (w, c, field_width, precision, multibyte)
        register int i;
 
        /* Let lots_of_dashes be a string of infinite length.  */
-       if (!NILP (mode_line_string_list))
+       if (mode_line_target == MODE_LINE_NOPROP ||
+           mode_line_target == MODE_LINE_STRING)
          return "--";
        if (field_width <= 0
            || field_width > sizeof (lots_of_dashes))
@@ -16353,6 +17684,18 @@ decode_mode_spec (w, c, field_width, precision, multibyte)
        return decode_mode_spec_buf;
       }
 
+    case 'e':
+#ifndef SYSTEM_MALLOC
+      {
+       if (NILP (Vmemory_full))
+         return "";
+       else
+         return "!MEM FULL! ";
+      }
+#else
+      return "";
+#endif
+
     case 'F':
       /* %F displays the frame name.  */
       if (!NILP (f->title))
@@ -16768,7 +18111,7 @@ display_count_lines (start, start_byte, limit_byte, count, byte_pos_ptr)
    display them, and < 0 means obey the current buffer's value of
    enable_multibyte_characters.
 
-   Value is the number of glyphs produced.  */
+   Value is the number of columns displayed.  */
 
 static int
 display_string (string, lisp_string, face_string, face_string_pos,
@@ -17102,6 +18445,15 @@ calc_pixel_width_or_height (res, it, prop, font, width_p, align_to)
          if (pixels > 0)
            {
              double ppi;
+#ifdef HAVE_WINDOW_SYSTEM
+             if (FRAME_WINDOW_P (it->f)
+                 && (ppi = (width_p
+                            ? FRAME_X_DISPLAY_INFO (it->f)->resx
+                            : FRAME_X_DISPLAY_INFO (it->f)->resy),
+                     ppi > 0))
+               return OK_PIXELS (ppi / pixels);
+#endif
+
              if ((ppi = NUMVAL (Vdisplay_pixels_per_inch), ppi > 0)
                  || (CONSP (Vdisplay_pixels_per_inch)
                      && (ppi = (width_p
@@ -17409,8 +18761,7 @@ get_glyph_face_and_encoding (f, glyph, char2b, two_byte_p)
         sure to use a face suitable for unibyte.  */
       STORE_XCHAR2B (char2b, 0, glyph->u.ch);
     }
-  else if (glyph->u.ch < 128
-          && glyph->face_id < BASIC_FACE_ID_SENTINEL)
+  else if (glyph->u.ch < 128)
     {
       /* Case of ASCII in a face known to fit ASCII.  */
       STORE_XCHAR2B (char2b, 0, glyph->u.ch);
@@ -17449,22 +18800,23 @@ get_glyph_face_and_encoding (f, glyph, char2b, two_byte_p)
 
    FACES is an array of faces for all components of this composition.
    S->gidx is the index of the first component for S.
-   OVERLAPS_P non-zero means S should draw the foreground only, and
-   use its physical height for clipping.
+
+   OVERLAPS non-zero means S should draw the foreground only, and use
+   its physical height for clipping.  See also draw_glyphs.
 
    Value is the index of a component not in S.  */
 
 static int
-fill_composite_glyph_string (s, faces, overlaps_p)
+fill_composite_glyph_string (s, faces, overlaps)
      struct glyph_string *s;
      struct face **faces;
-     int overlaps_p;
+     int overlaps;
 {
   int i;
 
   xassert (s);
 
-  s->for_overlaps_p = overlaps_p;
+  s->for_overlaps = overlaps;
 
   s->face = faces[s->gidx];
   s->font = s->face->font;
@@ -17508,16 +18860,16 @@ fill_composite_glyph_string (s, faces, overlaps_p)
 
    FACE_ID is the face id of the string.  START is the index of the
    first glyph to consider, END is the index of the last + 1.
-   OVERLAPS_P non-zero means S should draw the foreground only, and
-   use its physical height for clipping.
+   OVERLAPS non-zero means S should draw the foreground only, and use
+   its physical height for clipping.  See also draw_glyphs.
 
    Value is the index of the first glyph not in S.  */
 
 static int
-fill_glyph_string (s, face_id, start, end, overlaps_p)
+fill_glyph_string (s, face_id, start, end, overlaps)
      struct glyph_string *s;
      int face_id;
-     int start, end, overlaps_p;
+     int start, end, overlaps;
 {
   struct glyph *glyph, *last;
   int voffset;
@@ -17527,7 +18879,7 @@ fill_glyph_string (s, face_id, start, end, overlaps_p)
   xassert (s->nchars == 0);
   xassert (start >= 0 && end > start);
 
-  s->for_overlaps_p = overlaps_p,
+  s->for_overlaps = overlaps,
   glyph = s->row->glyphs[s->area] + start;
   last = s->row->glyphs[s->area] + end;
   voffset = glyph->voffset;
@@ -17620,6 +18972,7 @@ fill_stretch_glyph_string (s, row, area, start, end)
   s->font = s->face->font;
   s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id);
   s->width = glyph->pixel_width;
+  s->nchars = 1;
   voffset = glyph->voffset;
 
   for (++glyph;
@@ -17810,7 +19163,7 @@ get_char_face_and_encoding (f, c, face_id, char2b, multibyte_p, display_p)
       face_id = FACE_FOR_CHAR (f, face, c);
       face = FACE_FROM_ID (f, face_id);
     }
-  else if (c < 128 && face_id < BASIC_FACE_ID_SENTINEL)
+  else if (c < 128)
     {
       /* Case of ASCII in a face known to fit ASCII.  */
       STORE_XCHAR2B (char2b, 0, c);
@@ -17862,19 +19215,15 @@ set_glyph_string_background_width (s, start, last_x)
 {
   /* If the face of this glyph string has to be drawn to the end of
      the drawing area, set S->extends_to_end_of_line_p.  */
-  struct face *default_face = FACE_FROM_ID (s->f, DEFAULT_FACE_ID);
 
   if (start == s->row->used[s->area]
       && s->area == TEXT_AREA
-      && ((s->hl == DRAW_NORMAL_TEXT
-          && (s->row->fill_line_p
-              || s->face->background != default_face->background
-              || s->face->stipple != default_face->stipple
-              || s->row->mouse_face_p))
-         || s->hl == DRAW_MOUSE_FACE
-         || ((s->hl == DRAW_IMAGE_RAISED || s->hl == DRAW_IMAGE_SUNKEN)
-             && s->row->fill_line_p)))
-      s->extends_to_end_of_line_p = 1;
+      && ((s->row->fill_line_p
+          && (s->hl == DRAW_NORMAL_TEXT
+              || s->hl == DRAW_IMAGE_RAISED
+              || s->hl == DRAW_IMAGE_SUNKEN))
+         || s->hl == DRAW_MOUSE_FACE))
+    s->extends_to_end_of_line_p = 1;
 
   /* If S extends its face to the end of the line, set its
      background_width to the distance to the right edge of the drawing
@@ -18004,7 +19353,7 @@ compute_overhangs_and_x (s, x, backward_p)
         INIT_GLYPH_STRING (s, char2b, w, row, area, START, HL);           \
         append_glyph_string (&HEAD, &TAIL, s);                            \
         s->x = (X);                                                       \
-        START = fill_glyph_string (s, face_id, START, END, overlaps_p);   \
+        START = fill_glyph_string (s, face_id, START, END, overlaps);   \
        }                                                                  \
      while (0)
 
@@ -18057,7 +19406,7 @@ compute_overhangs_and_x (s, x, backward_p)
        if (n == 0)                                                       \
          first_s = s;                                                    \
                                                                          \
-       n = fill_composite_glyph_string (s, faces, overlaps_p);           \
+       n = fill_composite_glyph_string (s, faces, overlaps);             \
       }                                                                          \
                                                                          \
     ++START;                                                             \
@@ -18126,23 +19475,30 @@ compute_overhangs_and_x (s, x, backward_p)
    DRAW_IMAGE_SUNKEN   draw an image with a sunken relief around it
    DRAW_IMAGE_RAISED   draw an image with a raised relief around it
 
-   If OVERLAPS_P is non-zero, draw only the foreground of characters
-   and clip to the physical height of ROW.
+   If OVERLAPS is non-zero, draw only the foreground of characters and
+   clip to the physical height of ROW.  Non-zero value also defines
+   the overlapping part to be drawn:
+
+   OVERLAPS_PRED               overlap with preceding rows
+   OVERLAPS_SUCC               overlap with succeeding rows
+   OVERLAPS_BOTH               overlap with both preceding/succeeding rows
+   OVERLAPS_ERASED_CURSOR      overlap with erased cursor area
 
    Value is the x-position reached, relative to AREA of W.  */
 
 static int
-draw_glyphs (w, x, row, area, start, end, hl, overlaps_p)
+draw_glyphs (w, x, row, area, start, end, hl, overlaps)
      struct window *w;
      int x;
      struct glyph_row *row;
      enum glyph_row_area area;
      int start, end;
      enum draw_glyphs_face hl;
-     int overlaps_p;
+     int overlaps;
 {
   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;
@@ -18187,7 +19543,7 @@ draw_glyphs (w, x, row, area, start, end, hl, overlaps_p)
   /* If there are any glyphs with lbearing < 0 or rbearing > width in
      the row, redraw some glyphs in front or following the glyph
      strings built above.  */
-  if (head && !overlaps_p && row->contains_overlapping_glyphs_p)
+  if (head && !overlaps && row->contains_overlapping_glyphs_p)
     {
       int dummy_x = 0;
       struct glyph_string *h, *t;
@@ -18211,6 +19567,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
@@ -18223,6 +19580,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)
@@ -18242,6 +19600,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
@@ -18252,6 +19611,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)
@@ -18259,6 +19619,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.  */
@@ -18270,10 +19636,11 @@ draw_glyphs (w, x, row, area, start, end, hl, overlaps_p)
       /* When drawing overlapping rows, only the glyph strings'
         foreground is drawn, which doesn't erase a cursor
         completely. */
-      && !overlaps_p)
+      && !overlaps)
     {
-      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;
@@ -18420,7 +19787,7 @@ produce_image_glyph (it)
 {
   struct image *img;
   struct face *face;
-  int glyph_ascent;
+  int glyph_ascent, crop;
   struct glyph_slice slice;
 
   xassert (it->what == IT_IMAGE);
@@ -18528,6 +19895,15 @@ produce_image_glyph (it)
 
   take_vertical_position_into_account (it);
 
+  /* Automatically crop wide image glyphs at right edge so we can
+     draw the cursor on same display row.  */
+  if ((crop = it->pixel_width - (it->last_visible_x - it->current_x), crop > 0)
+      && (it->hpos == 0 || it->pixel_width > it->last_visible_x / 4))
+    {
+      it->pixel_width -= crop;
+      slice.width -= crop;
+    }
+
   if (it->glyph_row)
     {
       struct glyph *glyph;
@@ -18656,14 +20032,14 @@ produce_stretch_glyph (it)
   plist = XCDR (it->object);
 
   /* Compute the width of the stretch.  */
-  if ((prop = Fsafe_plist_get (plist, QCwidth), !NILP (prop))
+  if ((prop = Fplist_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 = Fsafe_plist_get (plist, QCrelative_width),
+  else if (prop = Fplist_get (plist, QCrelative_width),
           NUMVAL (prop) > 0)
     {
       /* Relative width `:relative-width FACTOR' specified and valid.
@@ -18687,7 +20063,7 @@ produce_stretch_glyph (it)
       x_produce_glyphs (&it2);
       width = NUMVAL (prop) * it2.pixel_width;
     }
-  else if ((prop = Fsafe_plist_get (plist, QCalign_to), !NILP (prop))
+  else if ((prop = Fplist_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)
@@ -18707,13 +20083,13 @@ produce_stretch_glyph (it)
     width = 1;
 
   /* Compute height.  */
-  if ((prop = Fsafe_plist_get (plist, QCheight), !NILP (prop))
+  if ((prop = Fplist_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 = Fsafe_plist_get (plist, QCrelative_height),
+  else if (prop = Fplist_get (plist, QCrelative_height),
           NUMVAL (prop) > 0)
     height = FONT_HEIGHT (font) * NUMVAL (prop);
   else
@@ -18725,7 +20101,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 = Fsafe_plist_get (plist, QCascent),
+  if (prop = Fplist_get (plist, QCascent),
       NUMVAL (prop) > 0 && NUMVAL (prop) <= 100)
     ascent = height * NUMVAL (prop) / 100.0;
   else if (!NILP (prop)
@@ -18734,6 +20110,10 @@ produce_stretch_glyph (it)
   else
     ascent = (height * FONT_BASE (font)) / FONT_HEIGHT (font);
 
+  if (width > 0 && !it->truncate_lines_p
+      && it->current_x + width > it->last_visible_x)
+    width = it->last_visible_x - it->current_x - 1;
+
   if (width > 0 && height > 0 && it->glyph_row)
     {
       Lisp_Object object = it->stack[it->sp - 1].string;
@@ -18747,41 +20127,19 @@ produce_stretch_glyph (it)
   it->descent = it->phys_descent = height - it->ascent;
   it->nglyphs = width > 0 && height > 0 ? 1 : 0;
 
-  if (width > 0 && height > 0 && face->box != FACE_NO_BOX)
-    {
-      if (face->box_line_width > 0)
-       {
-         it->ascent += face->box_line_width;
-         it->descent += face->box_line_width;
-       }
-
-      if (it->start_of_box_run_p)
-       it->pixel_width += abs (face->box_line_width);
-      if (it->end_of_box_run_p)
-       it->pixel_width += abs (face->box_line_width);
-    }
-
   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;
+  Lisp_Object position;
 
   if (STRINGP (it->object))
     position = make_number (IT_STRING_CHARPOS (*it));
@@ -18790,33 +20148,44 @@ calc_line_height_property (it, prop, font, boff, total)
   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.  */
 
-  if (INTEGERP (val))
+
+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 (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);
@@ -18858,6 +20227,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))
@@ -18869,8 +20240,8 @@ calc_line_height_property (it, prop, font, boff, total)
 
 /* RIF:
    Produce glyphs/get display metrics for the display element IT is
-   loaded with.  See the description of struct display_iterator in
-   dispextern.h for an overview of struct display_iterator.  */
+   loaded with.  See the description of struct it in dispextern.h
+   for an overview of struct it.  */
 
 void
 x_produce_glyphs (it)
@@ -19029,7 +20400,7 @@ x_produce_glyphs (it)
          /* If face has an overline, add the height of the overline
             (1 pixel) and a 1 pixel margin to the character height.  */
          if (face->overline_p)
-           it->ascent += 2;
+           it->ascent += overline_margin;
 
          if (it->constrain_row_ascent_descent_p)
            {
@@ -19070,12 +20441,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)
            {
@@ -19089,7 +20470,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)
                {
@@ -19109,7 +20490,6 @@ x_produce_glyphs (it)
          else
            {
              Lisp_Object spacing;
-             int total = 0;
 
              it->phys_ascent = it->ascent;
              it->phys_descent = it->descent;
@@ -19125,25 +20505,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;
@@ -19216,7 +20602,7 @@ x_produce_glyphs (it)
          /* If face has an overline, add the height of the overline
             (1 pixel) and a 1 pixel margin to the character height.  */
          if (face->overline_p)
-           it->ascent += 2;
+           it->ascent += overline_margin;
 
          take_vertical_position_into_account (it);
 
@@ -19491,7 +20877,7 @@ x_produce_glyphs (it)
       /* If face has an overline, add the height of the overline
         (1 pixel) and a 1 pixel margin to the character height.  */
       if (face->overline_p)
-       it->ascent += 2;
+       it->ascent += overline_margin;
 
       take_vertical_position_into_account (it);
 
@@ -19815,8 +21201,13 @@ get_window_cursor_type (w, glyph, width, active_cursor)
     {
       if (w == XWINDOW (echo_area_window))
        {
-         *width = FRAME_CURSOR_WIDTH (f);
-         return FRAME_DESIRED_CURSOR (f);
+         if (EQ (b->cursor_type, Qt) || NILP (b->cursor_type))
+           {
+             *width = FRAME_CURSOR_WIDTH (f);
+             return FRAME_DESIRED_CURSOR (f);
+           }
+         else
+           return get_specified_cursor_type (b->cursor_type, width);
        }
 
       *active_cursor = 0;
@@ -19845,7 +21236,7 @@ get_window_cursor_type (w, glyph, width, active_cursor)
   /* Use cursor-in-non-selected-windows for non-selected window or frame.  */
   if (non_selected)
     {
-      alt_cursor = Fbuffer_local_value (Qcursor_in_non_selected_windows, w->buffer);
+      alt_cursor = b->cursor_in_non_selected_windows;
       return get_specified_cursor_type (alt_cursor, width);
     }
 
@@ -19861,10 +21252,35 @@ get_window_cursor_type (w, glyph, width, active_cursor)
   /* Use normal cursor if not blinked off.  */
   if (!w->cursor_off_p)
     {
-      if (glyph != NULL && glyph->type == IMAGE_GLYPH) {
-       if (cursor_type == FILLED_BOX_CURSOR)
-         cursor_type = HOLLOW_BOX_CURSOR;
+#ifdef HAVE_WINDOW_SYSTEM
+      if (glyph != NULL && glyph->type == IMAGE_GLYPH)
+       {
+         if (cursor_type == FILLED_BOX_CURSOR)
+           {
+             /* Using a block cursor on large images can be very annoying.
+                So use a hollow cursor for "large" images.
+                If image is not transparent (no mask), also use hollow cursor.  */
+             struct image *img = IMAGE_FROM_ID (f, glyph->u.img_id);
+             if (img != NULL && IMAGEP (img->spec))
+               {
+                 /* Arbitrarily, interpret "Large" as >32x32 and >NxN
+                    where N = size of default frame font size.
+                    This should cover most of the "tiny" icons people may use.  */
+                 if (!img->mask
+                     || img->width > max (32, WINDOW_FRAME_COLUMN_WIDTH (w))
+                     || img->height > max (32, WINDOW_FRAME_LINE_HEIGHT (w)))
+                   cursor_type = HOLLOW_BOX_CURSOR;
+               }
+           }
+         else if (cursor_type != NO_CURSOR)
+           {
+             /* Display current only supports BOX and HOLLOW cursors for images.
+                So for now, unconditionally use a HOLLOW cursor when cursor is
+                not a solid box cursor.  */
+             cursor_type = HOLLOW_BOX_CURSOR;
+           }
       }
+#endif
       return cursor_type;
     }
 
@@ -19929,8 +21345,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)
@@ -19980,13 +21398,15 @@ notice_overwritten_cursor (w, area, x0, x1, y0, y1)
 #ifdef HAVE_WINDOW_SYSTEM
 
 /* EXPORT for RIF:
-   Fix the display of area AREA of overlapping row ROW in window W.  */
+   Fix the display of area AREA of overlapping row ROW in window W
+   with respect to the overlapping part OVERLAPS.  */
 
 void
-x_fix_overlapping_area (w, row, area)
+x_fix_overlapping_area (w, row, area, overlaps)
      struct window *w;
      struct glyph_row *row;
      enum glyph_row_area area;
+     int overlaps;
 {
   int i, x;
 
@@ -20009,7 +21429,7 @@ x_fix_overlapping_area (w, row, area)
 
          draw_glyphs (w, start_x, row, area,
                       start, i,
-                      DRAW_NORMAL_TEXT, 1);
+                      DRAW_NORMAL_TEXT, overlaps);
        }
       else
        {
@@ -20051,13 +21471,17 @@ draw_phys_cursor_glyph (w, row, hl)
         are redrawn.  */
       else if (hl == DRAW_NORMAL_TEXT && row->overlapped_p)
        {
+         w->phys_cursor_width = x1 - w->phys_cursor.x;
+
          if (row > w->current_matrix->rows
              && MATRIX_ROW_OVERLAPS_SUCC_P (row - 1))
-           x_fix_overlapping_area (w, row - 1, TEXT_AREA);
+           x_fix_overlapping_area (w, row - 1, TEXT_AREA,
+                                   OVERLAPS_ERASED_CURSOR);
 
          if (MATRIX_ROW_BOTTOM_Y (row) < window_text_bottom_y (w)
              && MATRIX_ROW_OVERLAPS_PRED_P (row + 1))
-           x_fix_overlapping_area (w, row + 1, TEXT_AREA);
+           x_fix_overlapping_area (w, row + 1, TEXT_AREA,
+                                   OVERLAPS_ERASED_CURSOR);
        }
     }
 }
@@ -20142,7 +21566,7 @@ erase_phys_cursor (w)
   /* Maybe clear the display under the cursor.  */
   if (w->phys_cursor_type == HOLLOW_BOX_CURSOR)
     {
-      int x, y;
+      int x, y, left_x;
       int header_line_height = WINDOW_HEADER_LINE_HEIGHT (w);
       int width;
 
@@ -20150,11 +21574,16 @@ erase_phys_cursor (w)
       if (cursor_glyph == NULL)
        goto mark_cursor_off;
 
-      x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
+      width = cursor_glyph->pixel_width;
+      left_x = window_box_left_offset (w, TEXT_AREA);
+      x = w->phys_cursor.x;
+      if (x < left_x)
+       width -= left_x - x;
+      width = min (width, window_box_width (w, TEXT_AREA) - 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);
+      x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, max (x, left_x));
 
+      if (width > 0)
       rif->clear_frame_area (f, x, y, width, cursor_row->visible_height);
     }
 
@@ -20372,7 +21801,11 @@ show_mouse_face (dpyinfo, draw)
          if (row == last)
            end_hpos = dpyinfo->mouse_face_end_col;
          else
-           end_hpos = row->used[TEXT_AREA];
+           {
+             end_hpos = row->used[TEXT_AREA];
+             if (draw == DRAW_NORMAL_TEXT)
+               row->fill_line_p = 1; /* Clear to end of line */
+           }
 
          if (end_hpos > start_hpos)
            {
@@ -20504,6 +21937,30 @@ fast_find_position (w, charpos, hpos, vpos, x, y, stop)
       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)
+       {
+         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;
+       }
+    }
+
   *x = row->x;
   *y = row->y;
   *vpos = MATRIX_ROW_VPOS (row, w->current_matrix);
@@ -20908,11 +22365,12 @@ define_frame_cursor1 (f, cursor, pointer)
    position relative to the start of the mode line.  */
 
 static void
-note_mode_line_or_margin_highlight (w, x, y, area)
-     struct window *w;
+note_mode_line_or_margin_highlight (window, x, y, area)
+     Lisp_Object window;
      int x, y;
      enum window_part area;
 {
+  struct window *w = XWINDOW (window);
   struct frame *f = XFRAME (w->frame);
   Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
   Cursor cursor = FRAME_X_OUTPUT (f)->nontext_cursor;
@@ -20921,9 +22379,38 @@ note_mode_line_or_margin_highlight (w, x, y, area)
   Lisp_Object string, object = Qnil;
   Lisp_Object pos, help;
 
+  Lisp_Object mouse_face;
+  int original_x_pixel = x;
+  struct glyph * glyph = NULL;
+  struct glyph_row *row;
+
   if (area == ON_MODE_LINE || area == ON_HEADER_LINE)
-    string = mode_line_string (w, area, &x, &y, &charpos,
-                              &object, &dx, &dy, &width, &height);
+    {
+      int x0;
+      struct glyph *end;
+
+      string = mode_line_string (w, area, &x, &y, &charpos,
+                                &object, &dx, &dy, &width, &height);
+
+      row = (area == ON_MODE_LINE
+            ? MATRIX_MODE_LINE_ROW (w->current_matrix)
+            : MATRIX_HEADER_LINE_ROW (w->current_matrix));
+
+      /* Find glyph */
+      if (row->mode_line_p && row->enabled_p)
+       {
+         glyph = row->glyphs[TEXT_AREA];
+         end = glyph + row->used[TEXT_AREA];
+
+         for (x0 = original_x_pixel;
+              glyph < end && x0 >= glyph->pixel_width;
+              ++glyph)
+           x0 -= glyph->pixel_width;
+
+         if (glyph >= end)
+           glyph = NULL;
+       }
+    }
   else
     {
       x -= WINDOW_LEFT_SCROLL_BAR_AREA_WIDTH (w);
@@ -20936,7 +22423,7 @@ note_mode_line_or_margin_highlight (w, x, y, area)
   if (IMAGEP (object))
     {
       Lisp_Object image_map, hotspot;
-      if ((image_map = Fsafe_plist_get (XCDR (object), QCmap),
+      if ((image_map = Fplist_get (XCDR (object), QCmap),
           !NILP (image_map))
          && (hotspot = find_hot_spot (image_map, dx, dy),
              CONSP (hotspot))
@@ -20952,10 +22439,10 @@ note_mode_line_or_margin_highlight (w, x, y, area)
          if (CONSP (hotspot)
              && (plist = XCAR (hotspot), CONSP (plist)))
            {
-             pointer = Fsafe_plist_get (plist, Qpointer);
+             pointer = Fplist_get (plist, Qpointer);
              if (NILP (pointer))
                pointer = Qhand;
-             help = Fsafe_plist_get (plist, Qhelp_echo);
+             help = Fplist_get (plist, Qhelp_echo);
              if (!NILP (help))
                {
                  help_echo_string = help;
@@ -20965,9 +22452,9 @@ note_mode_line_or_margin_highlight (w, x, y, area)
                  help_echo_pos = charpos;
                }
            }
-         if (NILP (pointer))
-           pointer = Fsafe_plist_get (XCDR (object), QCpointer);
        }
+      if (NILP (pointer))
+       pointer = Fplist_get (XCDR (object), QCpointer);
     }
 
   if (STRINGP (string))
@@ -21001,8 +22488,110 @@ note_mode_line_or_margin_highlight (w, x, y, area)
          if (!KEYMAPP (map))
            cursor = dpyinfo->vertical_scroll_bar_cursor;
        }
-    }
 
+     /* Change the mouse face according to what is under X/Y.  */
+      mouse_face = Fget_text_property (pos, Qmouse_face, string);
+      if (!NILP (mouse_face)
+         && ((area == ON_MODE_LINE) || (area == ON_HEADER_LINE))
+         && glyph)
+       {
+         Lisp_Object b, e;
+
+         struct glyph * tmp_glyph;
+
+         int gpos;
+         int gseq_length;
+         int total_pixel_width;
+         int ignore;
+
+         int vpos, hpos;
+
+         b = Fprevious_single_property_change (make_number (charpos + 1),
+                                               Qmouse_face, string, Qnil);
+         if (NILP (b))
+           b = make_number (0);
+
+         e = Fnext_single_property_change (pos, Qmouse_face, string, Qnil);
+         if (NILP (e))
+           e = make_number (SCHARS (string));
+
+         /* Calculate the position(glyph position: GPOS) of GLYPH in
+            displayed string. GPOS is different from CHARPOS.
+
+            CHARPOS is the position of glyph in internal string
+            object. A mode line string format has structures which
+            is converted to a flatten by emacs lisp interpreter.
+            The internal string is an element of the structures.
+            The displayed string is the flatten string. */
+         for (tmp_glyph = glyph - 1, gpos = 0;
+              tmp_glyph->charpos >= XINT (b);
+              tmp_glyph--, gpos++)
+           {
+             if (!EQ (tmp_glyph->object, glyph->object))
+               break;
+           }
+
+         /* Calculate the lenght(glyph sequence length: GSEQ_LENGTH) of
+            displayed string holding GLYPH.
+
+            GSEQ_LENGTH is different from SCHARS (STRING).
+            SCHARS (STRING) returns the length of the internal string. */
+         for (tmp_glyph = glyph, gseq_length = gpos;
+              tmp_glyph->charpos < XINT (e);
+              tmp_glyph++, gseq_length++)
+             {
+               if (!EQ (tmp_glyph->object, glyph->object))
+                 break;
+             }
+
+         total_pixel_width = 0;
+         for (tmp_glyph = glyph - gpos; tmp_glyph != glyph; tmp_glyph++)
+           total_pixel_width += tmp_glyph->pixel_width;
+
+         /* Pre calculation of re-rendering position */
+         vpos = (x - gpos);
+         hpos = (area == ON_MODE_LINE
+                 ? (w->current_matrix)->nrows - 1
+                 : 0);
+
+         /* If the re-rendering position is included in the last
+            re-rendering area, we should do nothing. */
+         if ( EQ (window, dpyinfo->mouse_face_window)
+              && dpyinfo->mouse_face_beg_col <= vpos
+              && vpos < dpyinfo->mouse_face_end_col
+              && dpyinfo->mouse_face_beg_row == hpos )
+           return;
+
+         if (clear_mouse_face (dpyinfo))
+           cursor = No_Cursor;
+
+         dpyinfo->mouse_face_beg_col = vpos;
+         dpyinfo->mouse_face_beg_row = hpos;
+
+         dpyinfo->mouse_face_beg_x   = original_x_pixel - (total_pixel_width + dx);
+         dpyinfo->mouse_face_beg_y   = 0;
+
+         dpyinfo->mouse_face_end_col = vpos + gseq_length;
+         dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_beg_row;
+
+         dpyinfo->mouse_face_end_x   = 0;
+         dpyinfo->mouse_face_end_y   = 0;
+
+         dpyinfo->mouse_face_past_end = 0;
+         dpyinfo->mouse_face_window  = window;
+
+         dpyinfo->mouse_face_face_id = face_at_string_position (w, string,
+                                                                charpos,
+                                                                0, 0, 0, &ignore,
+                                                                glyph->face_id, 1);
+         show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
+
+         if (NILP (pointer))
+           pointer = Qhand;
+       }
+      else if ((area == ON_MODE_LINE) || (area == ON_HEADER_LINE))
+       clear_mouse_face (dpyinfo);
+    }
   define_frame_cursor1 (f, cursor, pointer);
 }
 
@@ -21055,7 +22644,8 @@ note_mouse_highlight (f, x, y)
   /* 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)))
+      || (part != ON_TEXT && part != ON_MODE_LINE && part != ON_HEADER_LINE
+         && !NILP (dpyinfo->mouse_face_window)))
     clear_mouse_face (dpyinfo);
 
   /* Not on a window -> return.  */
@@ -21081,12 +22671,15 @@ note_mouse_highlight (f, x, y)
   if (part == ON_MODE_LINE || part == ON_HEADER_LINE
       || part == ON_LEFT_MARGIN || part == ON_RIGHT_MARGIN)
     {
-      note_mode_line_or_margin_highlight (w, x, y, part);
+      note_mode_line_or_margin_highlight (window, x, y, part);
       return;
     }
 
   if (part == ON_VERTICAL_BORDER)
-    cursor = FRAME_X_OUTPUT (f)->horizontal_drag_cursor;
+    {
+      cursor = FRAME_X_OUTPUT (f)->horizontal_drag_cursor;
+      help_echo_string = build_string ("drag-mouse-1: resize");
+    }
   else if (part == ON_LEFT_FRINGE || part == ON_RIGHT_FRINGE
           || part == ON_SCROLL_BAR)
     cursor = FRAME_X_OUTPUT (f)->nontext_cursor;
@@ -21120,7 +22713,7 @@ note_mouse_highlight (f, x, y)
          if (img != NULL && IMAGEP (img->spec))
            {
              Lisp_Object image_map, hotspot;
-             if ((image_map = Fsafe_plist_get (XCDR (img->spec), QCmap),
+             if ((image_map = Fplist_get (XCDR (img->spec), QCmap),
                   !NILP (image_map))
                  && (hotspot = find_hot_spot (image_map,
                                               glyph->slice.x + dx,
@@ -21138,10 +22731,10 @@ note_mouse_highlight (f, x, y)
                  if (CONSP (hotspot)
                      && (plist = XCAR (hotspot), CONSP (plist)))
                    {
-                     pointer = Fsafe_plist_get (plist, Qpointer);
+                     pointer = Fplist_get (plist, Qpointer);
                      if (NILP (pointer))
                        pointer = Qhand;
-                     help_echo_string = Fsafe_plist_get (plist, Qhelp_echo);
+                     help_echo_string = Fplist_get (plist, Qhelp_echo);
                      if (!NILP (help_echo_string))
                        {
                          help_echo_window = window;
@@ -21151,7 +22744,7 @@ note_mouse_highlight (f, x, y)
                    }
                }
              if (NILP (pointer))
-               pointer = Fsafe_plist_get (XCDR (img->spec), QCpointer);
+               pointer = Fplist_get (XCDR (img->spec), QCpointer);
            }
        }
 
@@ -21341,6 +22934,7 @@ note_mouse_highlight (f, x, y)
                b = make_number (0);
              if (NILP (e))
                e = make_number (SCHARS (object) - 1);
+
              fast_find_string_pos (w, XINT (b), object,
                                    &dpyinfo->mouse_face_beg_col,
                                    &dpyinfo->mouse_face_beg_row,
@@ -21690,13 +23284,13 @@ expose_overlaps (w, first_overlapping_row, last_overlapping_row)
        xassert (row->enabled_p && !row->mode_line_p);
 
        if (row->used[LEFT_MARGIN_AREA])
-         x_fix_overlapping_area (w, row, LEFT_MARGIN_AREA);
+         x_fix_overlapping_area (w, row, LEFT_MARGIN_AREA, OVERLAPS_BOTH);
 
        if (row->used[TEXT_AREA])
-         x_fix_overlapping_area (w, row, TEXT_AREA);
+         x_fix_overlapping_area (w, row, TEXT_AREA, OVERLAPS_BOTH);
 
        if (row->used[RIGHT_MARGIN_AREA])
-         x_fix_overlapping_area (w, row, RIGHT_MARGIN_AREA);
+         x_fix_overlapping_area (w, row, RIGHT_MARGIN_AREA, OVERLAPS_BOTH);
       }
 }
 
@@ -21756,6 +23350,9 @@ x_draw_vertical_border (w)
       window_box_edges (w, -1, &x0, &y0, &x1, &y1);
       y1 -= 1;
 
+      if (WINDOW_LEFT_FRINGE_WIDTH (w) == 0)
+       x1 -= 1;
+
       rif->draw_vertical_window_border (w, x1, y0, y1);
     }
   else if (!WINDOW_LEFTMOST_P (w)
@@ -21766,6 +23363,9 @@ x_draw_vertical_border (w)
       window_box_edges (w, -1, &x0, &y0, &x1, &y1);
       y1 -= 1;
 
+      if (WINDOW_LEFT_FRINGE_WIDTH (w) == 0)
+       x0 -= 1;
+
       rif->draw_vertical_window_border (w, x0, y0, y1);
     }
 }
@@ -21845,7 +23445,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;
@@ -21885,20 +23487,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;
 }
 
@@ -21957,16 +23545,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.  */
@@ -22171,8 +23749,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");
@@ -22193,6 +23769,8 @@ syms_of_xdisp ()
   staticpro (&Qtrailing_whitespace);
   Qescape_glyph = intern ("escape-glyph");
   staticpro (&Qescape_glyph);
+  Qnobreak_space = intern ("nobreak-space");
+  staticpro (&Qnobreak_space);
   Qimage = intern ("image");
   staticpro (&Qimage);
   QCmap = intern (":map");
@@ -22207,8 +23785,6 @@ syms_of_xdisp ()
   staticpro (&Qpoly);
   Qmessage_truncate_lines = intern ("message-truncate-lines");
   staticpro (&Qmessage_truncate_lines);
-  Qcursor_in_non_selected_windows = intern ("cursor-in-non-selected-windows");
-  staticpro (&Qcursor_in_non_selected_windows);
   Qgrow_only = intern ("grow-only");
   staticpro (&Qgrow_only);
   Qinhibit_menubar_update = intern ("inhibit-menubar-update");
@@ -22268,9 +23844,14 @@ syms_of_xdisp ()
 
   mode_line_proptrans_alist = Qnil;
   staticpro (&mode_line_proptrans_alist);
-
   mode_line_string_list = Qnil;
   staticpro (&mode_line_string_list);
+  mode_line_string_face = Qnil;
+  staticpro (&mode_line_string_face);
+  mode_line_string_face_prop = Qnil;
+  staticpro (&mode_line_string_face_prop);
+  Vmode_line_unwind_vector = Qnil;
+  staticpro (&Vmode_line_unwind_vector);
 
   help_echo_string = Qnil;
   staticpro (&help_echo_string);
@@ -22295,10 +23876,19 @@ wide as that tab on the display.  */);
 The face used for trailing whitespace is `trailing-whitespace'.  */);
   Vshow_trailing_whitespace = Qnil;
 
+  DEFVAR_LISP ("nobreak-char-display", &Vnobreak_char_display,
+    doc: /* *Control highlighting of nobreak space and soft hyphen.
+A value of t means highlight the character itself (for nobreak space,
+use face `nobreak-space').
+A value of nil means no highlighting.
+Other values mean display the escape glyph followed by an ordinary
+space or ordinary hyphen.  */);
+  Vnobreak_char_display = 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',
-`hand', `vdrag', `hdrag', `modeline', and `hourglass'.  */);
+A value of nil means to show the text pointer.  Other options are `arrow',
+`text', `hand', `vdrag', `hdrag', `modeline', and `hourglass'.  */);
   Vvoid_text_area_pointer = Qarrow;
 
   DEFVAR_LISP ("inhibit-redisplay", &Vinhibit_redisplay,
@@ -22319,7 +23909,7 @@ See also `overlay-arrow-string'.  */);
   DEFVAR_LISP ("overlay-arrow-string", &Voverlay_arrow_string,
     doc: /* String to display as an arrow in non-window frames.
 See also `overlay-arrow-position'.  */);
-  Voverlay_arrow_string = Qnil;
+  Voverlay_arrow_string = build_string ("=>");
 
   DEFVAR_LISP ("overlay-arrow-variable-list", &Voverlay_arrow_variable_list,
     doc: /* List of variables (symbols) which hold markers for overlay arrows.
@@ -22348,7 +23938,7 @@ of the top or bottom of the window.  */);
   scroll_margin = 0;
 
   DEFVAR_LISP ("display-pixels-per-inch",  &Vdisplay_pixels_per_inch,
-    doc: /* Pixels per inch on current display.
+    doc: /* Pixels per inch value for non-window system displays.
 Value is a number or a cons (WIDTH-DPI . HEIGHT-DPI).  */);
   Vdisplay_pixels_per_inch = make_float (72.0);
 
@@ -22435,9 +24025,28 @@ and its new display-start position.  Note that the value of `window-end'
 is not valid when these functions are called.  */);
   Vwindow_scroll_functions = Qnil;
 
-  DEFVAR_BOOL ("mouse-autoselect-window", &mouse_autoselect_window,
-    doc: /* *Non-nil means autoselect window with mouse pointer.  */);
-  mouse_autoselect_window = 0;
+  DEFVAR_LISP ("redisplay-end-trigger-functions", &Vredisplay_end_trigger_functions,
+    doc: /* Functions called when redisplay of a window reaches the end trigger.
+Each function is called with two arguments, the window and the end trigger value.
+See `set-window-redisplay-end-trigger'.  */);
+  Vredisplay_end_trigger_functions = Qnil;
+
+  DEFVAR_LISP ("mouse-autoselect-window", &Vmouse_autoselect_window,
+     doc: /* *Non-nil means autoselect window with mouse pointer.
+If nil, do not autoselect windows.
+A positive number means delay autoselection by that many seconds: a
+window is autoselected only after the mouse has remained in that
+window for the duration of the delay.
+A negative number has a similar effect, but causes windows to be
+autoselected only after the mouse has stopped moving.  \(Because of
+the way Emacs compares mouse events, you will occasionally wait twice
+that time before the window gets selected.\)
+Any other value means to autoselect window instantaneously when the
+mouse pointer enters it.
+
+Autoselection selects the minibuffer only if it is active, and never
+unselects the minibuffer if it is active.  */);
+  Vmouse_autoselect_window = Qnil;
 
   DEFVAR_BOOL ("auto-resize-tool-bars", &auto_resize_tool_bars_p,
     doc: /* *Non-nil means automatically resize tool-bars.
@@ -22454,6 +24063,14 @@ otherwise.  */);
     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-border", &Vtool_bar_border,
+    doc: /* *Border below tool-bar in pixels.
+If an integer, use it as the height of the border.
+If it is one of `internal-border-width' or `border-width', use the
+value of the corresponding frame parameter.
+Otherwise, no border is added below the tool-bar.  */);
+  Vtool_bar_border = Qinternal_border_width;
+
   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.
@@ -22498,18 +24115,16 @@ only, until their display becomes empty, at which point the windows
 go back to their normal size.  */);
   Vresize_mini_windows = Qgrow_only;
 
-  DEFVAR_LISP ("cursor-in-non-selected-windows",
-              &Vcursor_in_non_selected_windows,
-    doc: /* *Cursor type to display in non-selected windows.
-t means to use hollow box cursor.  See `cursor-type' for other values.  */);
-  Vcursor_in_non_selected_windows = Qt;
-
   DEFVAR_LISP ("blink-cursor-alist", &Vblink_cursor_alist,
     doc: /* Alist specifying how to blink the cursor off.
 Each element has the form (ON-STATE . OFF-STATE).  Whenever the
 `cursor-type' frame-parameter or variable equals ON-STATE,
 comparing using `equal', Emacs uses OFF-STATE to specify
-how to blink it off.  */);
+how to blink it off.  ON-STATE and OFF-STATE are values for
+the `cursor-type' frame parameter.
+
+If a frame's ON-STATE has no entry in this list,
+the frame's other specifications determine how to blink the cursor off.  */);
   Vblink_cursor_alist = Qnil;
 
   DEFVAR_BOOL ("auto-hscroll-mode", &automatic_hscrolling_p,
@@ -22523,7 +24138,7 @@ before automatic hscrolling will horizontally scroll the window.  */);
 
   DEFVAR_LISP ("hscroll-step", &Vhscroll_step,
     doc: /* *How many columns to scroll the window when point gets too close to the edge.
-When point is less than `automatic-hscroll-margin' columns from the window
+When point is less than `hscroll-margin' columns from the window
 edge, automatic hscrolling will scroll the window by the amount of columns
 determined by this variable.  If its value is a positive integer, scroll that
 many columns.  If it's a positive floating-point number, it specifies the
@@ -22545,10 +24160,17 @@ 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_LISP ("menu-updating-frame", &Vmenu_updating_frame,
+              doc: /* Frame for which we are updating a menu.
+The enable predicate for a menu binding should check this variable.  */);
+  Vmenu_updating_frame = Qnil;
+
   DEFVAR_BOOL ("inhibit-menubar-update", &inhibit_menubar_update,
     doc: /* Non-nil means don't update menu bars.  Internal use only.  */);
   inhibit_menubar_update = 0;
@@ -22574,6 +24196,12 @@ Can be used to update submenus whose contents should vary.  */);
               doc: /* Inhibit try_cursor_movement display optimization.  */);
   inhibit_try_cursor_movement = 0;
 #endif /* GLYPH_DEBUG */
+
+  DEFVAR_INT ("overline-margin", &overline_margin,
+              doc: /* *Space between overline and text, in pixels.
+The default value is 2: the height of the overline (1 pixel) plus 1 pixel
+margin to the caracter height.  */);
+  overline_margin = 2;
 }
 
 
@@ -22620,9 +24248,10 @@ init_xdisp ()
     /* Allocate the buffer for frame titles.
        Also used for `format-mode-line'.  */
     int size = 100;
-    frame_title_buf = (char *) xmalloc (size);
-    frame_title_buf_end = frame_title_buf + size;
-    frame_title_ptr = NULL;
+    mode_line_noprop_buf = (char *) xmalloc (size);
+    mode_line_noprop_buf_end = mode_line_noprop_buf + size;
+    mode_line_noprop_ptr = mode_line_noprop_buf;
+    mode_line_target = MODE_LINE_DISPLAY;
   }
 
   help_echo_showing_p = 0;