]> code.delx.au - gnu-emacs/blobdiff - src/xdisp.c
(archive-l-e): New optional argument `float' means generate a float value.
[gnu-emacs] / src / xdisp.c
index 5ea68aff049106b54aa7c664fe81c9c7b53f103b..ecc097343f2720f986309f8b93fcf6725d2d85f3 100644 (file)
@@ -1,6 +1,7 @@
 /* Display generation from window structure and buffer text.
-   Copyright (C) 1985, 1986, 1987, 1988, 1993, 1994, 1995, 1997, 1998, 1999,
-     2000, 2001, 2002, 2003, 2004, 2005  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;
@@ -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;
@@ -320,7 +327,7 @@ Lisp_Object Vshow_trailing_whitespace;
 
 /* Non-nil means escape non-break space and hyphens.  */
 
-Lisp_Object Vshow_nonbreak_escape;
+Lisp_Object Vnobreak_char_display;
 
 #ifdef HAVE_WINDOW_SYSTEM
 extern Lisp_Object Voverflow_newline_into_fringe;
@@ -350,6 +357,10 @@ Lisp_Object Qtrailing_whitespace;
 
 Lisp_Object Qescape_glyph;
 
+/* 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.  */
 
@@ -621,12 +632,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;
 
@@ -849,11 +854,11 @@ 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 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));
@@ -964,7 +969,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));
@@ -1348,6 +1353,9 @@ pos_visible_p (w, charpos, x, y, rtop, rbot, 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);
+
   return visible_p;
 }
 
@@ -1766,15 +1774,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.  */
@@ -1817,10 +1830,27 @@ get_glyph_string_clip_rect (s, nr)
   /* 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
     {
@@ -1879,11 +1909,75 @@ get_glyph_string_clip_rect (s, nr)
        }
     }
 
+  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);
 }
 
 
@@ -1900,7 +1994,7 @@ get_phys_cursor_geometry (w, row, glyph, heightp)
      int *heightp;
 {
   struct frame *f = XFRAME (WINDOW_FRAME (w));
-  int x, y, wd, h, h0, y0;
+  int 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
@@ -1939,10 +2033,202 @@ get_phys_cursor_geometry (w, row, glyph, heightp)
        }
     }
 
-  *heightp = h - 1;
+  *heightp = h;
   return WINDOW_TO_FRAME_PIXEL_Y (w, y);
 }
 
+/*
+ * 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 */
 
@@ -2410,7 +2696,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;
@@ -2700,11 +2988,13 @@ 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)
@@ -2898,6 +3188,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
@@ -3331,6 +3624,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);
 
@@ -3351,7 +3649,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);
+            }
        }
     }
 
@@ -3424,7 +3741,7 @@ handle_display_prop (it)
     }
   else
     {
-      object = it->w->buffer;
+      XSETWINDOW (object, it->w);
       position = &it->current.pos;
     }
 
@@ -3445,6 +3762,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)
@@ -3477,7 +3797,10 @@ handle_display_prop (it)
     }
   else
     {
-      if (handle_single_display_spec (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;
     }
 
@@ -3521,7 +3844,8 @@ display_prop_end (it, object, start_pos)
    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_spec (it, spec, object, position,
@@ -3836,6 +4160,11 @@ handle_single_display_spec (it, spec, object, position,
 
       if (STRINGP (value))
        {
+         if (SCHARS (value) == 0)
+           {
+             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;
@@ -3853,7 +4182,7 @@ handle_single_display_spec (it, spec, object, position,
        {
          it->method = GET_FROM_STRETCH;
          it->object = value;
-         it->current.pos = it->position = start_pos;
+         *position = it->position = start_pos;
        }
 #ifdef HAVE_WINDOW_SYSTEM
       else
@@ -4791,7 +5120,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);
       }
 
@@ -5012,6 +5342,10 @@ static int (* get_next_element[NUM_IT_METHODS]) P_ ((struct it *it)) =
    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;
@@ -5090,9 +5424,11 @@ get_next_display_element (it)
                       ? ((it->c >= 127
                           && it->len == 1)
                          || !CHAR_PRINTABLE_P (it->c)
-                         || (!NILP (Vshow_nonbreak_escape)
-                             && (it->c == 0x8ad || it->c == 0x8a0
-                                 || it->c == 0xf2d || it->c == 0xf20)))
+                         || (!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)))))
@@ -5107,6 +5443,8 @@ get_next_display_element (it)
              int face_id, lface_id = 0 ;
              GLYPH escape_glyph;
 
+             /* Handle control characters with ^.  */
+
              if (it->c < 128 && it->ctl_arrow_p)
                {
                  g = '^';           /* default glyph for Control */
@@ -5124,11 +5462,19 @@ get_next_display_element (it)
                       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;
                    }
 
                  XSETINT (it->ctl_chars[0], g);
@@ -5138,7 +5484,28 @@ get_next_display_element (it)
                  goto display_control;
                }
 
-             escape_glyph = '\\';    /* default for Octal display */
+             /* 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;
+               }
+
+             /* 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))))
@@ -5148,22 +5515,50 @@ get_next_display_element (it)
                }
              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.  */
+
              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;
+                 g = it->c = ((it->c & 0xf) == 0 ? ' ' : '-');
                  XSETINT (it->ctl_chars[1], g);
                  ctl_len = 2;
                  goto display_control;
@@ -5332,6 +5727,8 @@ 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 = GET_FROM_C_STRING;
          else if (STRINGP (it->string))
@@ -5347,12 +5744,16 @@ set_iterator_to_next (it, reseat_p)
            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);
            }
 
-         /* Recheck faces after display vector */
-         it->stop_charpos = IT_CHARPOS (*it);
+         /* Maybe recheck faces after display vector */
+         if (recheck_faces)
+           it->stop_charpos = IT_CHARPOS (*it);
        }
       break;
 
@@ -5819,6 +6220,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.
 
@@ -5945,6 +6355,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)
            {
@@ -5976,8 +6388,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))
@@ -6327,8 +6753,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;
 
@@ -6435,6 +6865,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);
     }
@@ -6526,21 +6957,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
@@ -6636,7 +7091,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)
@@ -6847,10 +7305,7 @@ message_log_check_duplicate (prev_bol, prev_bol_byte, this_bol, this_bol_byte)
    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)
@@ -6928,7 +7383,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)
@@ -6940,18 +7397,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)
@@ -6999,6 +7468,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);
@@ -7527,14 +7999,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;
 }
@@ -7589,8 +8064,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)
@@ -7602,6 +8083,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,
@@ -7665,7 +8151,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;
        }
@@ -7876,7 +8362,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)
@@ -8150,52 +8640,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 frame title buffering code is also used by Fformat_mode_line.
-   So it is not conditioned by HAVE_WINDOW_SYSTEM.  */
+/* The buffer's end, and a current output position in it.  */
 
-/* A buffer for constructing frame titles in it; allocated from the
-   heap in init_xdisp and resized as needed in store_frame_title_char.  */
+static char *mode_line_noprop_buf_end;
+static char *mode_line_noprop_ptr;
 
-static char *frame_title_buf;
+#define MODE_LINE_NOPROP_LEN(start) \
+  ((mode_line_noprop_ptr - mode_line_noprop_buf) - start)
 
-/* The buffer's end, and a current output position in it.  */
+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);
 
-static char *frame_title_buf_end;
-static char *frame_title_ptr;
+  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;
+
+  if (obuf)
+    XSETBUFFER (AREF (vector, 6), obuf);
+  else
+    AREF (vector, 6) = Qnil;
+
+  return vector;
+}
 
+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;
+    }
+
+  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
@@ -8203,7 +8767,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;
 {
@@ -8214,19 +8778,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
@@ -8246,9 +8814,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))
        {
@@ -8267,18 +8837,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
@@ -8287,8 +8861,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);
     }
 }
 
@@ -8347,7 +8921,7 @@ prepare_menu_bars ()
       Lisp_Object tail, frame;
       int count = SPECPDL_INDEX ();
 
-      record_unwind_protect (Fset_match_data, Fmatch_data (Qnil, Qnil));
+      record_unwind_save_match_data ();
 
       FOR_EACH_FRAME (tail, frame)
        {
@@ -8380,6 +8954,9 @@ prepare_menu_bars ()
          update_menu_bar (f, 0);
 #ifdef HAVE_WINDOW_SYSTEM
          update_tool_bar (f, 0);
+#ifdef MAC_OS
+         mac_update_title_bar (f, 0);
+#endif
 #endif
          UNGCPRO;
        }
@@ -8392,6 +8969,9 @@ prepare_menu_bars ()
       update_menu_bar (sf, 1);
 #ifdef HAVE_WINDOW_SYSTEM
       update_tool_bar (sf, 1);
+#ifdef MAC_OS
+      mac_update_title_bar (sf, 1);
+#endif
 #endif
     }
 
@@ -8470,7 +9050,7 @@ 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);
@@ -8491,14 +9071,15 @@ update_menu_bar (f, save_match_data)
          /* 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.  */
@@ -8661,7 +9242,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))
@@ -8862,11 +9443,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;
@@ -8885,7 +9477,12 @@ display_tool_bar_line (it)
 
       /* 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;
@@ -8922,11 +9519,22 @@ 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)
+    {
+      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.  */
@@ -8950,28 +9558,36 @@ display_tool_bar_line (it)
 
 
 /* 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;
+  struct glyph_row *temp_row = w->desired_matrix->rows;
 
   /* 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);
 }
@@ -9001,7 +9617,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);
        }
     }
 
@@ -9027,28 +9643,87 @@ redisplay_tool_bar (f)
   return 0;
 #endif
 
-  /* If frame hasn't a tool-bar window or if it is zero-height, don't
-     do anything.  This means you must start with tool-bar-lines
-     non-zero to get the auto-sizing effect.  Or in other words, you
-     can turn off tool-bars by specifying tool-bar-lines zero.  */
-  if (!WINDOWP (f->tool_bar_window)
-      || (w = XWINDOW (f->tool_bar_window),
-          WINDOW_TOTAL_LINES (w) == 0))
-    return 0;
+  /* If frame hasn't a tool-bar window or if it is zero-height, don't
+     do anything.  This means you must start with tool-bar-lines
+     non-zero to get the auto-sizing effect.  Or in other words, you
+     can turn off tool-bars by specifying tool-bar-lines zero.  */
+  if (!WINDOWP (f->tool_bar_window)
+      || (w = XWINDOW (f->tool_bar_window),
+          WINDOW_TOTAL_LINES (w) == 0))
+    return 0;
+
+  /* Set up an iterator for the tool-bar window.  */
+  init_iterator (&it, w, -1, -1, w->desired_matrix->rows, TOOL_BAR_FACE_ID);
+  it.first_visible_x = 0;
+  it.last_visible_x = FRAME_TOTAL_COLS (f) * FRAME_COLUMN_WIDTH (f);
+  row = it.glyph_row;
+
+  /* Build a string that represents the contents of the tool-bar.  */
+  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);
+         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;
+             return 1;
+           }
+       }
+    }
+
+  /* Display as many lines as needed to display all tool-bar items.  */
+
+  if (f->n_tool_bar_rows > 0)
+    {
+      int border, rows, height, extra;
 
-  /* Set up an iterator for the tool-bar window.  */
-  init_iterator (&it, w, -1, -1, w->desired_matrix->rows, TOOL_BAR_FACE_ID);
-  it.first_visible_x = 0;
-  it.last_visible_x = FRAME_TOTAL_COLS (f) * FRAME_COLUMN_WIDTH (f);
-  row = it.glyph_row;
+      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;
 
-  /* Build a string that represents the contents of the tool-bar.  */
-  build_desired_tool_bar_string (f);
-  reseat_to_string (&it, NULL, f->desired_tool_bar_string, 0, 0, 0, -1);
+      rows = f->n_tool_bar_rows;
+      height = (it.last_visible_y - border) / rows;
+      extra = it.last_visible_y - border - height * rows;
 
-  /* 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);
+      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.  */
@@ -9081,7 +9756,7 @@ redisplay_tool_bar (f)
       /* 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, &f->n_tool_bar_rows),
              nlines != WINDOW_TOTAL_LINES (w)))
        {
          extern Lisp_Object Qtool_bar_lines;
@@ -9789,12 +10464,14 @@ overlay_arrow_at_row (it, row)
          if (FRAME_WINDOW_P (it->f)
              && WINDOW_LEFT_FRINGE_WIDTH (it->w) > 0)
            {
+#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);
@@ -9905,7 +10582,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))
@@ -9916,7 +10595,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);
 }
 
 
@@ -9990,9 +10669,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.  */
@@ -10049,7 +10740,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++;
@@ -10383,9 +11075,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);
+
+      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.  */
@@ -10424,8 +11116,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
@@ -10443,15 +11139,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;
                }
            }
        }
@@ -10461,12 +11149,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);
+               }
            }
        }
     }
@@ -10947,7 +11638,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;
@@ -10961,10 +11652,12 @@ set_cursor_from_row (w, row, matrix, delta, delta_bytes, dy, dvpos)
          /* 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 */
@@ -10975,14 +11668,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));
        }
     }
 
@@ -11128,6 +11822,7 @@ static int
 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;
@@ -11153,7 +11848,7 @@ cursor_row_fully_visible_p (w, force_p, current_matrix_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)
        return 1;
     }
   return 0;
@@ -11429,7 +12124,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)
     {
@@ -11683,7 +12378,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))
                {
@@ -12021,8 +12719,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,
@@ -12032,6 +12728,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;
@@ -12065,12 +12762,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)
        {
@@ -12113,7 +12814,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;
            }
        }
@@ -12187,6 +12888,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
@@ -12203,7 +12934,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)
@@ -12333,7 +13068,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
@@ -12353,13 +13088,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
        {
@@ -12500,10 +13235,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;
@@ -12542,14 +13276,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;
@@ -12574,6 +13312,31 @@ 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 < 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))
@@ -12809,7 +13572,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
@@ -14163,7 +14926,7 @@ dump_glyph_row (row, vpos, glyphs)
 {
   if (glyphs != 1)
     {
-      fprintf (stderr, "Row Start   End Used oEI><\\CTZFesm     X    Y    W    H    V    A    P\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\
@@ -14667,6 +15430,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)
@@ -14816,10 +15580,12 @@ 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).  */
+        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;
+       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,
@@ -15110,7 +15876,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)
                        {
@@ -15583,6 +16351,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);
@@ -15593,6 +16362,11 @@ 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.  */
@@ -15600,6 +16374,8 @@ display_mode_line (w, face_id, format)
   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);
 
@@ -15622,17 +16398,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.
@@ -15654,8 +16456,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)
@@ -15680,9 +16483,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);
@@ -15713,14 +16517,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);
@@ -15738,80 +16550,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))
-                 {
-                   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
+               switch (mode_line_target)
                  {
-                   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.  */
@@ -15831,7 +16660,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);
@@ -15839,44 +16668,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 */
@@ -16024,7 +16860,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);
@@ -16042,13 +16883,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;
@@ -16180,6 +17028,9 @@ are the selected window and the window's buffer).  */)
   struct buffer *old_buffer = NULL;
   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;
@@ -16207,64 +17058,53 @@ are the selected window and the window's buffer).  */)
     face_id = DEFAULT_FACE_ID;
 
   if (XBUFFER (buffer) != current_buffer)
-    {
-      old_buffer = current_buffer;
-      set_buffer_internal_1 (XBUFFER (buffer));
-    }
+    old_buffer = current_buffer;
+
+  /* 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);
 
-  if (!no_props)
+  if (no_props)
     {
-      mode_line_string_face = face;
-      mode_line_string_face_prop
-       = (NILP (face) ? Qnil : Fcons (Qface, Fcons (face, Qnil)));
-
-      /* We need a dummy last element in mode_line_string_list to
-        indicate we are building the propertized mode-line string.
-        Using mode_line_string_face_prop here GC protects it.  */
-      mode_line_string_list
-       = Fcons (mode_line_string_face_prop, Qnil);
-      frame_title_ptr = NULL;
+      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 (!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
@@ -16582,7 +17422,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))
@@ -16608,6 +17449,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))
@@ -17023,7 +17876,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,
@@ -17357,6 +18210,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
@@ -17664,8 +18526,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);
@@ -17704,22 +18565,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;
@@ -17763,16 +18625,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;
@@ -17782,7 +18644,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;
@@ -17875,6 +18737,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;
@@ -18065,7 +18928,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);
@@ -18117,19 +18980,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
@@ -18259,7 +19118,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)
 
@@ -18312,7 +19171,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;                                                             \
@@ -18381,20 +19240,26 @@ 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;
@@ -18443,7 +19308,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;
@@ -18536,7 +19401,7 @@ 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 = clip_head ? clip_head->x : (head ? head->x : x);
       int x1 = (clip_tail ? clip_tail->x + clip_tail->background_width
@@ -19001,6 +19866,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;
@@ -19014,20 +19883,6 @@ 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);
 }
 
@@ -19040,7 +19895,7 @@ get_line_height_property (it, prop)
      struct it *it;
      Lisp_Object prop;
 {
-  Lisp_Object position, val;
+  Lisp_Object position;
 
   if (STRINGP (it->object))
     position = make_number (IT_STRING_CHARPOS (*it));
@@ -19141,8 +19996,8 @@ calc_line_height_property (it, val, font, boff, override)
 
 /* 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)
@@ -19391,7 +20246,6 @@ x_produce_glyphs (it)
          else
            {
              Lisp_Object spacing;
-             int total = 0;
 
              it->phys_ascent = it->ascent;
              it->phys_descent = it->descent;
@@ -20103,8 +20957,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;
@@ -20133,7 +20992,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);
     }
 
@@ -20270,13 +21129,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;
 
@@ -20299,7 +21160,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
        {
@@ -20341,13 +21202,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);
        }
     }
 }
@@ -20662,7 +21527,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)
            {
@@ -21222,11 +22091,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;
@@ -21235,9 +22105,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);
@@ -21315,8 +22214,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);
 }
 
@@ -21369,7 +22370,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.  */
@@ -21395,12 +22397,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;
@@ -21655,6 +22660,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,
@@ -22004,13 +23010,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);
       }
 }
 
@@ -22070,6 +23076,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)
@@ -22080,6 +23089,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);
     }
 }
@@ -22483,6 +23495,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");
@@ -22497,8 +23511,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");
@@ -22558,9 +23570,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);
@@ -22585,14 +23602,19 @@ wide as that tab on the display.  */);
 The face used for trailing whitespace is `trailing-whitespace'.  */);
   Vshow_trailing_whitespace = Qnil;
 
-  DEFVAR_LISP ("show-nonbreak-escape", &Vshow_nonbreak_escape,
-    doc: /* *Non-nil means display escape character before non-break space and hyphen.  */);
-  Vshow_nonbreak_escape = Qt;
+  DEFVAR_LISP ("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,
@@ -22642,7 +23664,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);
 
@@ -22729,6 +23751,12 @@ 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_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_BOOL ("mouse-autoselect-window", &mouse_autoselect_window,
     doc: /* *Non-nil means autoselect window with mouse pointer.  */);
   mouse_autoselect_window = 0;
@@ -22748,6 +23776,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.
@@ -22792,18 +23828,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,
@@ -22817,7 +23851,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
@@ -22916,9 +23950,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;