]> 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 fb5b8fbe6f2f42acdffaf955102b46e425c92e8a..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;
@@ -352,7 +359,7 @@ Lisp_Object Qescape_glyph;
 
 /* Name and number of the face used to highlight non-breaking spaces.  */
 
-Lisp_Object Qno_break_space;
+Lisp_Object Qnobreak_space;
 
 /* The symbol `image' which is the car of the lists used to represent
    images in Lisp.  */
@@ -851,7 +858,7 @@ 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));
@@ -962,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));
@@ -1346,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;
 }
 
@@ -1764,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.  */
@@ -1815,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
     {
@@ -1877,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, *rects);
+#else
+      *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
-  CONVERT_FROM_XRECT (r, *nr);
+      XRectangle rs[2];
 #else
-  *nr = r;
+      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);
 }
 
 
@@ -1898,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
@@ -1937,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 */
 
@@ -2408,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;
@@ -2698,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)
@@ -2896,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
@@ -3329,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);
 
@@ -3349,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);
+            }
        }
     }
 
@@ -3422,7 +3741,7 @@ handle_display_prop (it)
     }
   else
     {
-      object = it->w->buffer;
+      XSETWINDOW (object, it->w);
       position = &it->current.pos;
     }
 
@@ -3443,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)
@@ -3860,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
@@ -4798,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);
       }
 
@@ -5019,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;
@@ -5097,7 +5424,7 @@ get_next_display_element (it)
                       ? ((it->c >= 127
                           && it->len == 1)
                          || !CHAR_PRINTABLE_P (it->c)
-                         || (!NILP (Vshow_nonbreak_escape)
+                         || (!NILP (Vnobreak_char_display)
                              && (it->c == 0x8a0 || it->c == 0x8ad
                                  || it->c == 0x920 || it->c == 0x92d
                                  || it->c == 0xe20 || it->c == 0xe2d
@@ -5135,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);
@@ -5152,12 +5487,12 @@ get_next_display_element (it)
              /* Handle non-break space in the mode where it only gets
                 highlighting.  */
 
-             if (! EQ (Vshow_nonbreak_escape, Qt)
+             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, Qno_break_space, 0,
+                 face_id = merge_faces (it->f, Qnobreak_space, 0,
                                         it->face_id);
 
                  g = it->c = ' ';
@@ -5186,17 +5521,25 @@ 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;
                }
 
              /* Handle soft hyphens in the mode where they only get
                 highlighting.  */
 
-             if (! EQ (Vshow_nonbreak_escape, Qt)
+             if (EQ (Vnobreak_char_display, Qt)
                  && (it->c == 0x8ad || it->c == 0x92d
                      || it->c == 0xe2d || it->c == 0xf2d))
                {
@@ -5384,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))
@@ -5399,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;
 
@@ -5871,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.
 
@@ -5997,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)
            {
@@ -6028,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))
@@ -6379,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;
 
@@ -6487,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);
     }
@@ -6578,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
@@ -6688,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)
@@ -6899,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)
@@ -6999,7 +7402,15 @@ message3 (m, nbytes, multibyte)
   /* 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;
@@ -7057,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);
@@ -7585,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;
 }
@@ -7647,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)
@@ -7660,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,
@@ -7723,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;
        }
@@ -7934,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)
@@ -8249,10 +8681,9 @@ static Lisp_Object mode_line_string_face_prop;
 static Lisp_Object Vmode_line_unwind_vector;
 
 static Lisp_Object
-format_mode_line_unwind_data (obuf)
+format_mode_line_unwind_data (obuf, save_proptrans)
      struct buffer *obuf;
 {
-  int i = 0;
   Lisp_Object vector;
 
   /* Reduce consing by keeping one vector in
@@ -8266,7 +8697,7 @@ format_mode_line_unwind_data (obuf)
   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) = mode_line_proptrans_alist;
+  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;
 
@@ -8285,7 +8716,8 @@ unwind_format_mode_line (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);
-  mode_line_proptrans_alist = AREF (vector, 3);
+  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);
 
@@ -8408,7 +8840,7 @@ x_consider_frame_title (frame)
         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));
+                            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;
@@ -8489,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)
        {
@@ -8522,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;
        }
@@ -8534,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
     }
 
@@ -8612,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);
@@ -8633,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.  */
@@ -8803,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))
@@ -9004,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;
@@ -9027,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;
@@ -9064,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.  */
@@ -9092,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);
 }
@@ -9143,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);
        }
     }
 
@@ -9188,9 +9662,68 @@ redisplay_tool_bar (f)
   build_desired_tool_bar_string (f);
   reseat_to_string (&it, NULL, f->desired_tool_bar_string, 0, 0, 0, -1);
 
+  if (f->n_tool_bar_rows == 0)
+    {
+      int nlines;
+
+      if ((nlines = tool_bar_lines_needed (f, &f->n_tool_bar_rows),
+          nlines != WINDOW_TOTAL_LINES (w)))
+       {
+         extern Lisp_Object Qtool_bar_lines;
+         Lisp_Object frame;
+         int old_height = WINDOW_TOTAL_LINES (w);
+
+         XSETFRAME (frame, f);
+         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.  */
-  while (it.current_y < it.last_visible_y)
-    display_tool_bar_line (&it);
+
+  if (f->n_tool_bar_rows > 0)
+    {
+      int border, rows, height, extra;
+
+      if (INTEGERP (Vtool_bar_border))
+       border = XINT (Vtool_bar_border);
+      else if (EQ (Vtool_bar_border, Qinternal_border_width))
+       border = FRAME_INTERNAL_BORDER_WIDTH (f);
+      else if (EQ (Vtool_bar_border, Qborder_width))
+       border = f->border_width;
+      else
+       border = 0;
+      if (border < 0)
+       border = 0;
+
+      rows = f->n_tool_bar_rows;
+      height = (it.last_visible_y - border) / rows;
+      extra = it.last_visible_y - border - height * rows;
+
+      while (it.current_y < it.last_visible_y)
+       {
+         int h = 0;
+         if (extra > 0 && rows-- > 0)
+           {
+             h = (extra + rows - 1) / rows;
+             extra -= h;
+           }
+         display_tool_bar_line (&it, height + h);
+       }
+    }
+  else
+    {
+      while (it.current_y < it.last_visible_y)
+       display_tool_bar_line (&it, 0);
+    }
 
   /* It doesn't make much sense to try scrolling in the tool-bar
      window, so don't do it.  */
@@ -9223,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;
@@ -9931,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);
@@ -10047,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))
@@ -10058,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);
 }
 
 
@@ -10132,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.  */
@@ -10191,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++;
@@ -10525,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.  */
@@ -10566,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
@@ -10585,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;
                }
            }
        }
@@ -10603,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);
+               }
            }
        }
     }
@@ -11089,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;
@@ -11103,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 */
@@ -11117,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));
        }
     }
 
@@ -11270,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;
@@ -11295,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;
@@ -11571,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)
     {
@@ -11825,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))
                {
@@ -12163,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,
@@ -12174,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;
@@ -12207,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)
        {
@@ -12255,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;
            }
        }
@@ -12329,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
@@ -12345,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)
@@ -12475,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
@@ -12495,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
        {
@@ -12642,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;
@@ -12684,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;
@@ -12716,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))
@@ -12951,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
@@ -14305,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\
@@ -14809,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)
@@ -14958,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,
@@ -15252,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)
                        {
@@ -15737,7 +16363,7 @@ display_mode_line (w, face_id, format)
     it.base_face_id = it.face_id = DEFAULT_FACE_ID;
 
   record_unwind_protect (unwind_format_mode_line,
-                        format_mode_line_unwind_data (NULL));
+                        format_mode_line_unwind_data (NULL, 0));
 
   mode_line_target = MODE_LINE_DISPLAY;
 
@@ -15772,6 +16398,44 @@ display_mode_line (w, face_id, format)
   return it.glyph_row->height;
 }
 
+/* Move element ELT in LIST to the front of LIST.
+   Return the updated list.  */
+
+static Lisp_Object
+move_elt_to_front (elt, list)
+     Lisp_Object elt, list;
+{
+  register Lisp_Object tail, prev;
+  register Lisp_Object tem;
+
+  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.
 
@@ -15819,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);
@@ -15852,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);
@@ -15877,8 +16550,7 @@ display_mode_element (it, depth, field_width, precision, elt, props, risky)
              }
          }
 
-       this = SDATA (elt);
-       lisp_string = this;
+       offset = 0;
 
        if (literal)
          {
@@ -15901,42 +16573,44 @@ display_mode_element (it, depth, field_width, precision, elt, props, risky)
            break;
          }
 
+       /* Handle the non-literal case.  */
+
        while ((precision <= 0 || n < precision)
-              && *this
+              && 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);
 
                switch (mode_line_target)
                  {
                  case MODE_LINE_NOPROP:
                  case MODE_LINE_TITLE:
-                   n += store_mode_line_noprop (last, 0, prec);
+                   n += store_mode_line_noprop (SDATA (elt) + last_offset, 0, prec);
                    break;
                  case MODE_LINE_STRING:
                    {
-                     int bytepos = last - lisp_string;
+                     int bytepos = last_offset;
                      int charpos = string_byte_to_char (elt, bytepos);
                      int endpos = (precision <= 0
-                                   ? string_byte_to_char (elt,
-                                                          this - lisp_string)
+                                   ? string_byte_to_char (elt, offset)
                                    : charpos + nchars);
 
                      n += store_mode_line_string (NULL,
@@ -15947,10 +16621,13 @@ display_mode_element (it, depth, field_width, precision, elt, props, risky)
                    break;
                  case MODE_LINE_DISPLAY:
                    {
-                     int bytepos = last - lisp_string;
+                     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, prec, 0,
+                                          it, 0, nchars, 0,
                                           STRING_MULTIBYTE (elt));
                    }
                    break;
@@ -15958,12 +16635,12 @@ display_mode_element (it, depth, field_width, precision, elt, props, risky)
              }
            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.  */
@@ -15983,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);
@@ -16383,8 +17060,11 @@ are the selected window and the window's buffer).  */)
   if (XBUFFER (buffer) != current_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));
+                        format_mode_line_unwind_data (old_buffer, 1));
+  mode_line_proptrans_alist = Qnil;
 
   if (old_buffer)
     set_buffer_internal_1 (XBUFFER (buffer));
@@ -16769,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))
@@ -17184,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,
@@ -17518,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
@@ -17825,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);
@@ -17865,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;
@@ -17924,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;
@@ -17943,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;
@@ -18036,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;
@@ -18226,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);
@@ -18278,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
@@ -18420,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)
 
@@ -18473,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;                                                             \
@@ -18542,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;
@@ -18604,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;
@@ -18697,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
@@ -19162,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;
@@ -19175,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);
 }
 
@@ -19201,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));
@@ -19302,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)
@@ -19552,7 +20246,6 @@ x_produce_glyphs (it)
          else
            {
              Lisp_Object spacing;
-             int total = 0;
 
              it->phys_ascent = it->ascent;
              it->phys_descent = it->descent;
@@ -20264,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;
@@ -20294,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 = XBUFFER (w->buffer)->cursor_in_non_selected_windows;
+      alt_cursor = b->cursor_in_non_selected_windows;
       return get_specified_cursor_type (alt_cursor, width);
     }
 
@@ -20431,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;
 
@@ -20460,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
        {
@@ -20502,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);
        }
     }
 }
@@ -20823,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)
            {
@@ -21523,7 +22231,7 @@ note_mode_line_or_margin_highlight (window, x, y, area)
          int ignore;
 
          int vpos, hpos;
-         
+
          b = Fprevious_single_property_change (make_number (charpos + 1),
                                                Qmouse_face, string, Qnil);
          if (NILP (b))
@@ -21571,18 +22279,18 @@ note_mode_line_or_margin_highlight (window, x, y, area)
          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 ( window == dpyinfo->mouse_face_window
+         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;
 
@@ -21607,8 +22315,9 @@ note_mode_line_or_margin_highlight (window, x, y, area)
          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);
 }
 
@@ -21661,7 +22370,7 @@ 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 && part != ON_MODE_LINE && part != ON_HEADER_LINE 
+      || (part != ON_TEXT && part != ON_MODE_LINE && part != ON_HEADER_LINE
          && !NILP (dpyinfo->mouse_face_window)))
     clear_mouse_face (dpyinfo);
 
@@ -21693,7 +22402,10 @@ note_mouse_highlight (f, x, y)
     }
 
   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;
@@ -22298,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);
       }
 }
 
@@ -22364,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)
@@ -22374,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);
     }
 }
@@ -22777,8 +23495,8 @@ syms_of_xdisp ()
   staticpro (&Qtrailing_whitespace);
   Qescape_glyph = intern ("escape-glyph");
   staticpro (&Qescape_glyph);
-  Qno_break_space = intern ("no-break-space");
-  staticpro (&Qno_break_space);
+  Qnobreak_space = intern ("nobreak-space");
+  staticpro (&Qnobreak_space);
   Qimage = intern ("image");
   staticpro (&Qimage);
   QCmap = intern (":map");
@@ -22884,18 +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: /* *Control highlighting of non-break space and soft hyphen.
-t means highlight the character itself (for non-break space,
-use face `non-break-space'.
-nil means no highlighting.
-other values mean display the escape glyph before the character.  */);
-  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,
@@ -22945,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);
 
@@ -23032,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;
@@ -23051,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.
@@ -23100,7 +23833,11 @@ go back to their normal size.  */);
 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,
@@ -23114,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