(resize_mini_window): Don't resize while redisplaying.
[bpt/emacs.git] / src / xdisp.c
index ae35c98..6a56fe1 100644 (file)
@@ -1,5 +1,5 @@
 /* Display generation from window structure and buffer text.
-   Copyright (C) 1985, 86, 87, 88, 93, 94, 95, 97, 98, 99, 2000
+   Copyright (C) 1985, 86, 87, 88, 93, 94, 95, 97, 98, 99, 2000, 2001
    Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
@@ -226,6 +226,7 @@ Lisp_Object Qinhibit_point_motion_hooks;
 Lisp_Object QCeval, Qwhen, QCfile, QCdata;
 Lisp_Object Qfontified;
 Lisp_Object Qgrow_only;
+Lisp_Object Qinhibit_eval_during_redisplay;
 
 /* Functions called to fontify regions of text.  */
 
@@ -239,7 +240,7 @@ int auto_raise_tool_bar_buttons_p;
 
 /* Margin around tool bar buttons in pixels.  */
 
-int tool_bar_button_margin;
+Lisp_Object Vtool_bar_button_margin;
 
 /* Thickness of shadow to draw around tool bar buttons.  */
 
@@ -254,6 +255,10 @@ int auto_resize_tool_bars_p;
 
 Lisp_Object Vinhibit_redisplay, Qinhibit_redisplay;
 
+/* Non-zero means Lisp evaluation during redisplay is inhibited.  */
+
+int inhibit_eval_during_redisplay;
+
 /* Names of text properties relevant for redisplay.  */
 
 Lisp_Object Qdisplay, Qrelative_width, Qalign_to;
@@ -488,6 +493,11 @@ static int display_last_displayed_message_p;
 
 int message_buf_print;
 
+/* The symbol `inhibit-menubar-update' and its DEFVAR_BOOL variable.  */
+
+Lisp_Object Qinhibit_menubar_update;
+int inhibit_menubar_update;
+
 /* Maximum height for resizing mini-windows.  Either a float
    specifying a fraction of the available height, or an integer
    specifying a number of lines.  */
@@ -649,6 +659,10 @@ enum move_it_result
 \f
 /* Function prototypes.  */
 
+static void setup_for_ellipsis P_ ((struct it *));
+static void mark_window_display_accurate_1 P_ ((struct window *, int));
+static int single_display_prop_string_p P_ ((Lisp_Object, Lisp_Object));
+static int display_prop_string_p P_ ((Lisp_Object, Lisp_Object));
 static int cursor_row_p P_ ((struct window *, struct glyph_row *));
 static int redisplay_mode_lines P_ ((Lisp_Object, int));
 static char *decode_mode_spec_coding P_ ((Lisp_Object, char *, int));
@@ -719,7 +733,7 @@ static int display_string P_ ((unsigned char *, Lisp_Object, Lisp_Object,
                               int, int, struct it *, int, int, int, int));
 static void compute_line_metrics P_ ((struct it *));
 static void run_redisplay_end_trigger_hook P_ ((struct it *));
-static int get_overlay_strings P_ ((struct it *));
+static int get_overlay_strings P_ ((struct it *, int));
 static void next_overlay_string P_ ((struct it *));
 static void reseat P_ ((struct it *, struct text_pos, int));
 static void reseat_1 P_ ((struct it *, struct text_pos, int));
@@ -733,7 +747,7 @@ static int next_element_from_buffer P_ ((struct it *));
 static int next_element_from_composition P_ ((struct it *));
 static int next_element_from_image P_ ((struct it *));
 static int next_element_from_stretch P_ ((struct it *));
-static void load_overlay_strings P_ ((struct it *));
+static void load_overlay_strings P_ ((struct it *, int));
 static void init_from_display_pos P_ ((struct it *, struct window *,
                                       struct display_pos *));
 static void reseat_to_string P_ ((struct it *, unsigned char *,
@@ -758,8 +772,11 @@ static void compute_string_pos P_ ((struct text_pos *, struct text_pos,
 static int face_before_or_after_it_pos P_ ((struct it *, int));
 static int next_overlay_change P_ ((int));
 static int handle_single_display_prop P_ ((struct it *, Lisp_Object,
-                                          Lisp_Object, struct text_pos *));
+                                          Lisp_Object, struct text_pos *,
+                                          int));
 static int underlying_face_id P_ ((struct it *));
+static int in_ellipses_for_invisible_text_p P_ ((struct display_pos *,
+                                                struct window *));
 
 #define face_before_it_pos(IT) face_before_or_after_it_pos ((IT), 1)
 #define face_after_it_pos(IT)  face_before_or_after_it_pos ((IT), 0)
@@ -971,6 +988,46 @@ window_box_edges (w, area, top_left_x, top_left_y,
                              Utilities
  ***********************************************************************/
 
+/* Return the bottom y-position of the line the iterator IT is in.
+   This can modify IT's settings.  */
+
+int
+line_bottom_y (it)
+     struct it *it;
+{
+  int line_height = it->max_ascent + it->max_descent;
+  int line_top_y = it->current_y;
+  
+  if (line_height == 0)
+    {
+      if (last_height)
+       line_height = last_height;
+      else if (IT_CHARPOS (*it) < ZV)
+       {
+         move_it_by_lines (it, 1, 1);
+         line_height = (it->max_ascent || it->max_descent
+                        ? it->max_ascent + it->max_descent
+                        : last_height);
+       }
+      else
+       {
+         struct glyph_row *row = it->glyph_row;
+         
+         /* Use the default character height.  */
+         it->glyph_row = NULL;
+         it->what = IT_CHARACTER;
+         it->c = ' ';
+         it->len = 1;
+         PRODUCE_GLYPHS (it);
+         line_height = it->ascent + it->descent;
+         it->glyph_row = row;
+       }
+    }
+
+  return line_top_y + line_height;
+}
+
+
 /* Return 1 if position CHARPOS is visible in window W.  Set *FULLY to
    1 if POS is visible and the line containing POS is fully visible.
    EXACT_MODE_LINE_HEIGHTS_P non-zero means compute exact mode-line
@@ -1012,43 +1069,20 @@ pos_visible_p (w, charpos, fully, exact_mode_line_heights_p)
   start_display (&it, w, top);
   move_it_to (&it, charpos, 0, it.last_visible_y, -1,
              MOVE_TO_POS | MOVE_TO_X | MOVE_TO_Y);
-  
-  if (IT_CHARPOS (it) == charpos)
+
+  /* Note that we may overshoot because of invisible text.  */
+  if (IT_CHARPOS (it) >= charpos)
     {
-      int line_height, line_bottom_y;
-      int line_top_y = it.current_y;
+      int top_y = it.current_y;
+      int bottom_y = line_bottom_y (&it);
       int window_top_y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
       
-      line_height = it.max_ascent + it.max_descent;
-      if (line_height == 0)
-       {
-         if (last_height)
-           line_height = last_height;
-         else if (charpos < ZV)
-           {
-             move_it_by_lines (&it, 1, 1);
-             line_height = (it.max_ascent || it.max_descent
-                            ? it.max_ascent + it.max_descent
-                            : last_height);
-           }
-         else
-           {
-             /* Use the default character height.  */
-             it.what = IT_CHARACTER;
-             it.c = ' ';
-             it.len = 1;
-             PRODUCE_GLYPHS (&it);
-             line_height = it.ascent + it.descent;
-           }
-       }
-      line_bottom_y = line_top_y + line_height;
-
-      if (line_top_y < window_top_y)
-       visible_p = line_bottom_y > window_top_y;
-      else if (line_top_y < it.last_visible_y)
+      if (top_y < window_top_y)
+       visible_p = bottom_y > window_top_y;
+      else if (top_y < it.last_visible_y)
        {
          visible_p = 1;
-         *fully = line_bottom_y <= it.last_visible_y;
+         *fully = bottom_y <= it.last_visible_y;
        }
     }
   else if (it.current_y + it.max_ascent + it.max_descent > it.last_visible_y)
@@ -1250,15 +1284,24 @@ Lisp_Object
 safe_eval (sexpr)
      Lisp_Object sexpr;
 {
-  int count = BINDING_STACK_SIZE ();
-  struct gcpro gcpro1;
   Lisp_Object val;
+  
+  if (inhibit_eval_during_redisplay)
+    val = Qnil;
+  else
+    {
+      int count = BINDING_STACK_SIZE ();
+      struct gcpro gcpro1;
 
-  GCPRO1 (sexpr);
-  specbind (Qinhibit_redisplay, Qt);
-  val = internal_condition_case_1 (Feval, sexpr, Qerror, safe_eval_handler);
-  UNGCPRO;
-  return unbind_to (count, val);
+      GCPRO1 (sexpr);
+      specbind (Qinhibit_redisplay, Qt);
+      val = internal_condition_case_1 (Feval, sexpr, Qerror,
+                                      safe_eval_handler);
+      UNGCPRO;
+      val = unbind_to (count, val);
+    }
+  
+  return val;
 }
 
 
@@ -1270,17 +1313,25 @@ safe_call (nargs, args)
      int nargs;
      Lisp_Object *args;
 {
-  int count = BINDING_STACK_SIZE ();
   Lisp_Object val;
-  struct gcpro gcpro1;
+  
+  if (inhibit_eval_during_redisplay)
+    val = Qnil;
+  else
+    {
+      int count = BINDING_STACK_SIZE ();
+      struct gcpro gcpro1;
 
-  GCPRO1 (args[0]);
-  gcpro1.nvars = nargs;
-  specbind (Qinhibit_redisplay, Qt);
-  val = internal_condition_case_2 (Ffuncall, nargs, args, Qerror,
-                                  safe_eval_handler);
-  UNGCPRO;
-  return unbind_to (count, val);
+      GCPRO1 (args[0]);
+      gcpro1.nvars = nargs;
+      specbind (Qinhibit_redisplay, Qt);
+      val = internal_condition_case_2 (Ffuncall, nargs, args, Qerror,
+                                      safe_eval_handler);
+      UNGCPRO;
+      val = unbind_to (count, val);
+    }
+
+  return val;
 }
 
 
@@ -1449,7 +1500,11 @@ init_iterator (it, w, charpos, bytepos, row, base_face_id)
      attribute changes of named faces, recompute them.  When running
      in batch mode, the face cache of Vterminal_frame is null.  If
      we happen to get called, make a dummy face cache.  */
-  if (noninteractive && FRAME_FACE_CACHE (it->f) == NULL)
+  if (
+#ifndef WINDOWSNT
+      noninteractive &&
+#endif
+      FRAME_FACE_CACHE (it->f) == NULL)
     init_frame_faces (it->f);
   if (FRAME_FACE_CACHE (it->f)->used == 0)
     recompute_basic_faces (it->f);
@@ -1495,6 +1550,7 @@ init_iterator (it, w, charpos, bytepos, row, base_face_id)
          /* Or show the region if we are in the mini-buffer and W is
             the window the mini-buffer refers to.  */
          || (MINI_WINDOW_P (XWINDOW (selected_window))
+             && WINDOWP (Vminibuf_scroll_window)
              && w == XWINDOW (Vminibuf_scroll_window))))
     {
       int charpos = marker_position (current_buffer->mark);
@@ -1709,6 +1765,42 @@ start_display (it, w, pos)
 }
 
 
+/* Return 1 if POS is a position in ellipses displayed for invisible
+   text.  W is the window we display, for text property lookup.  */
+
+static int
+in_ellipses_for_invisible_text_p (pos, w)
+     struct display_pos *pos;
+     struct window *w;
+{
+  Lisp_Object prop, window;
+  int ellipses_p = 0;
+  int charpos = CHARPOS (pos->pos);
+  
+  /* If POS specifies a position in a display vector, this might
+     be for an ellipsis displayed for invisible text.  We won't
+     get the iterator set up for delivering that ellipsis unless
+     we make sure that it gets aware of the invisible text.  */
+  if (pos->dpvec_index >= 0
+      && pos->overlay_string_index < 0
+      && CHARPOS (pos->string_pos) < 0
+      && charpos > BEGV
+      && (XSETWINDOW (window, w),
+         prop = Fget_char_property (make_number (charpos),
+                                    Qinvisible, window),
+         !TEXT_PROP_MEANS_INVISIBLE (prop)))
+    {
+      prop = Fget_char_property (make_number (charpos - 1), Qinvisible,
+                                window);
+      if (TEXT_PROP_MEANS_INVISIBLE (prop)
+         && TEXT_PROP_MEANS_INVISIBLE_WITH_ELLIPSIS (prop))
+       ellipses_p = 1;
+    }
+
+  return ellipses_p;
+}
+
+
 /* Initialize IT for stepping through current_buffer in window W,
    starting at position POS that includes overlay string and display
    vector/ control character translation position information.  */
@@ -1719,6 +1811,18 @@ init_from_display_pos (it, w, pos)
      struct window *w;
      struct display_pos *pos;
 {
+  int charpos = CHARPOS (pos->pos), bytepos = BYTEPOS (pos->pos);
+  
+  /* If POS specifies a position in a display vector, this might
+     be for an ellipsis displayed for invisible text.  We won't
+     get the iterator set up for delivering that ellipsis unless
+     we make sure that it gets aware of the invisible text.  */
+  if (in_ellipses_for_invisible_text_p (pos, w))
+    {
+      --charpos;
+      bytepos = 0;
+    }
+    
   /* Keep in mind: the call to reseat in init_iterator skips invisible
      text, so we might end up at a position different from POS.  This
      is only a problem when POS is a row start after a newline and an
@@ -1728,8 +1832,7 @@ init_from_display_pos (it, w, pos)
      newline before the row start, such a POS will not be in a string,
      but the call to init_iterator below will move us to the
      after-string.  */
-  init_iterator (it, w, CHARPOS (pos->pos), BYTEPOS (pos->pos),
-                NULL, DEFAULT_FACE_ID);
+  init_iterator (it, w, charpos, bytepos, NULL, DEFAULT_FACE_ID);
 
   /* If position is within an overlay string, set up IT to
      the right overlay string.  */
@@ -1746,7 +1849,7 @@ init_from_display_pos (it, w, pos)
          it->current.overlay_string_index = 0;
          while (n--)
            {
-             load_overlay_strings (it);
+             load_overlay_strings (it, 0);
              it->current.overlay_string_index += OVERLAY_STRING_CHUNK_SIZE;
            }
        }
@@ -1782,12 +1885,12 @@ init_from_display_pos (it, w, pos)
       xassert (STRINGP (it->string));
     }
 
-  /* Restore position in display vector translations or control
-     character translations.  */
+  /* Restore position in display vector translations, control
+     character translations or ellipses.  */
   if (pos->dpvec_index >= 0)
     {
-      /* This fills IT->dpvec.  */
-      get_next_display_element (it);
+      if (it->dpvec == NULL)
+       get_next_display_element (it);
       xassert (it->dpvec && it->current.dpvec_index == 0);
       it->current.dpvec_index = pos->dpvec_index;
     }
@@ -1906,7 +2009,7 @@ compute_stop_pos (it)
         properties.  */
       object = it->string;
       limit = Qnil;
-      XSETFASTINT (position, IT_STRING_CHARPOS (*it));
+      position = make_number (IT_STRING_CHARPOS (*it));
     }
   else
     {
@@ -1933,8 +2036,8 @@ compute_stop_pos (it)
       /* Set up variables for computing the stop position from text
          property changes.  */
       XSETBUFFER (object, current_buffer);
-      XSETFASTINT (limit, IT_CHARPOS (*it) + TEXT_PROP_DISTANCE_LIMIT);
-      XSETFASTINT (position, IT_CHARPOS (*it));
+      limit = make_number (IT_CHARPOS (*it) + TEXT_PROP_DISTANCE_LIMIT);
+      position = make_number (IT_CHARPOS (*it));
 
     }
 
@@ -2189,7 +2292,7 @@ handle_face_prop (it)
                                             it->region_beg_charpos,
                                             it->region_end_charpos,
                                             &next_stop,
-                                            base_face_id);
+                                            base_face_id, 0);
       
 #if 0 /* This shouldn't be neccessary.  Let's check it.  */
       /* If IT is used to display a mode line we would really like to
@@ -2297,7 +2400,7 @@ face_before_or_after_it_pos (it, before_p)
                                         it->region_beg_charpos,
                                         it->region_end_charpos,
                                         &next_check_charpos,
-                                        base_face_id);
+                                        base_face_id, 0);
 
       /* Correct the face for charsets different from ASCII.  Do it
         for the multibyte case only.  The face returned above is
@@ -2379,7 +2482,7 @@ handle_invisible_prop (it)
       /* Get the value of the invisible text property at the
         current position.  Value will be nil if there is no such
         property.  */
-      XSETFASTINT (charpos, IT_STRING_CHARPOS (*it));
+      charpos = make_number (IT_STRING_CHARPOS (*it));
       prop = Fget_text_property (charpos, Qinvisible, it->string);
 
       if (!NILP (prop)
@@ -2429,12 +2532,14 @@ handle_invisible_prop (it)
     }
   else
     {
-      int visible_p, newpos, next_stop;
-      Lisp_Object pos, prop;
+      int visible_p, newpos, next_stop, start_charpos;
+      Lisp_Object pos, prop, overlay;
 
       /* First of all, is there invisible text at this position?  */
-      XSETFASTINT (pos, IT_CHARPOS (*it));
-      prop = Fget_char_property (pos, Qinvisible, it->window);
+      start_charpos = IT_CHARPOS (*it);
+      pos = make_number (IT_CHARPOS (*it));
+      prop = get_char_property_and_overlay (pos, Qinvisible, it->window,
+                                           &overlay);
       
       /* If we are on invisible text, skip over it.  */
       if (TEXT_PROP_MEANS_INVISIBLE (prop)
@@ -2472,7 +2577,7 @@ handle_invisible_prop (it)
                     the char before the given position, i.e. if we
                     get visible_p = 1, this means that the char at
                     newpos is visible.  */
-                 XSETFASTINT (pos, newpos);
+                 pos = make_number (newpos);
                  prop = Fget_char_property (pos, Qinvisible, it->window);
                  visible_p = !TEXT_PROP_MEANS_INVISIBLE (prop);
                }
@@ -2483,36 +2588,25 @@ handle_invisible_prop (it)
                IT_CHARPOS (*it) = next_stop;
            }
          while (!visible_p);
-         
+
          /* The position newpos is now either ZV or on visible text.  */
          IT_CHARPOS (*it) = newpos;
          IT_BYTEPOS (*it) = CHAR_TO_BYTE (newpos);
          
-         /* Maybe return `...' next for the end of the invisible text.  */
-         if (display_ellipsis_p)
+         /* If there are before-strings at the start of invisible
+            text, and the text is invisible because of a text
+            property, arrange to show before-strings because 20.x did
+            it that way.  (If the text is invisible because of an
+            overlay property instead of a text property, this is
+            already handled in the overlay code.)  */
+         if (NILP (overlay)
+             && get_overlay_strings (it, start_charpos))
            {
-             if (it->dp 
-                 && VECTORP (DISP_INVIS_VECTOR (it->dp)))
-               {
-                 struct Lisp_Vector *v = XVECTOR (DISP_INVIS_VECTOR (it->dp));
-                 it->dpvec = v->contents;
-                 it->dpend = v->contents + v->size;
-               }
-             else 
-               {
-                 /* Default `...'.  */
-                 it->dpvec = default_invis_vector;
-                 it->dpend = default_invis_vector + 3;
-               }
-
-             /* The ellipsis display does not replace the display of
-                the character at the new position.  Indicate this by
-                setting IT->dpvec_char_len to zero.  */
-             it->dpvec_char_len = 0;
-             
-             it->current.dpvec_index = 0;
-             it->method = next_element_from_display_vector;
+             handled = HANDLED_RECOMPUTE_PROPS;
+             it->stack[it->sp - 1].display_ellipsis_p = display_ellipsis_p;
            }
+         else if (display_ellipsis_p)
+           setup_for_ellipsis (it);
        }
     }
 
@@ -2520,6 +2614,36 @@ handle_invisible_prop (it)
 }
 
 
+/* Make iterator IT return `...' next.  */
+
+static void
+setup_for_ellipsis (it)
+     struct it *it;
+{
+  if (it->dp 
+      && VECTORP (DISP_INVIS_VECTOR (it->dp)))
+    {
+      struct Lisp_Vector *v = XVECTOR (DISP_INVIS_VECTOR (it->dp));
+      it->dpvec = v->contents;
+      it->dpend = v->contents + v->size;
+    }
+  else 
+    {
+      /* Default `...'.  */
+      it->dpvec = default_invis_vector;
+      it->dpend = default_invis_vector + 3;
+    }
+  
+  /* The ellipsis display does not replace the display of the
+     character at the new position.  Indicate this by setting
+     IT->dpvec_char_len to zero.  */
+  it->dpvec_char_len = 0;
+  
+  it->current.dpvec_index = 0;
+  it->method = next_element_from_display_vector;
+}
+
+
 \f
 /***********************************************************************
                            'display' property
@@ -2534,7 +2658,7 @@ handle_display_prop (it)
 {
   Lisp_Object prop, object;
   struct text_pos *position;
-  int space_or_image_found_p;
+  int display_replaced_p = 0;
 
   if (STRINGP (it->string))
     {
@@ -2543,7 +2667,7 @@ handle_display_prop (it)
     }
   else
     {
-      object = Qnil;
+      object = it->w->buffer;
       position = &it->current.pos;
     }
 
@@ -2563,34 +2687,40 @@ handle_display_prop (it)
   if (NILP (prop))
     return HANDLED_NORMALLY;
 
-  space_or_image_found_p = 0;
   if (CONSP (prop)
-      && CONSP (XCAR (prop))
-      && !EQ (Qmargin, XCAR (XCAR (prop))))
+      /* Simple properties.  */
+      && !EQ (XCAR (prop), Qimage)
+      && !EQ (XCAR (prop), Qspace)
+      && !EQ (XCAR (prop), Qwhen)
+      && !EQ (XCAR (prop), Qspace_width)
+      && !EQ (XCAR (prop), Qheight)
+      && !EQ (XCAR (prop), Qraise)
+      /* Marginal area specifications.  */
+      && !(CONSP (XCAR (prop)) && EQ (XCAR (XCAR (prop)), Qmargin))
+      && !NILP (XCAR (prop)))
     {
-      /* A list of sub-properties.  */
-      while (CONSP (prop))
+      for (; CONSP (prop); prop = XCDR (prop))
        {
-         if (handle_single_display_prop (it, XCAR (prop), object, position))
-           space_or_image_found_p = 1;
-         prop = XCDR (prop);
+         if (handle_single_display_prop (it, XCAR (prop), object,
+                                         position, display_replaced_p))
+           display_replaced_p = 1;
        }
     }
   else if (VECTORP (prop))
     {
       int i;
-      for (i = 0; i < XVECTOR (prop)->size; ++i)
-       if (handle_single_display_prop (it, XVECTOR (prop)->contents[i],
-                                       object, position))
-         space_or_image_found_p = 1;
+      for (i = 0; i < ASIZE (prop); ++i)
+       if (handle_single_display_prop (it, AREF (prop, i), object,
+                                       position, display_replaced_p))
+         display_replaced_p = 1;
     }
   else
     {
-      if (handle_single_display_prop (it, prop, object, position))
-       space_or_image_found_p = 1;
+      if (handle_single_display_prop (it, prop, object, position, 0))
+       display_replaced_p = 1;
     }
 
-  return space_or_image_found_p ? HANDLED_RETURN : HANDLED_NORMALLY;
+  return display_replaced_p ? HANDLED_RETURN : HANDLED_NORMALLY;
 }
 
 
@@ -2620,22 +2750,28 @@ display_prop_end (it, object, start_pos)
 
 /* Set up IT from a single `display' sub-property value PROP.  OBJECT
    is the object in which the `display' property was found.  *POSITION
-   is the position at which it was found.
+   is the position at which it was found.  DISPLAY_REPLACED_P non-zero
+   means that we previously saw a display sub-property which already
+   replaced text display with something else, for example an image;
+   ignore such properties after the first one has been processed.
 
    If PROP is a `space' or `image' sub-property, set *POSITION to the
    end position of the `display' property.
 
-   Value is non-zero if a `space' or `image' property value was found.  */
+   Value is non-zero something was found which replaces the display
+   of buffer or string text.  */
 
 static int
-handle_single_display_prop (it, prop, object, position)
+handle_single_display_prop (it, prop, object, position,
+                           display_replaced_before_p)
      struct it *it;
      Lisp_Object prop;
      Lisp_Object object;
      struct text_pos *position;
+     int display_replaced_before_p;
 {
   Lisp_Object value;
-  int space_or_image_found_p = 0;
+  int replaces_text_display_p = 0;
   Lisp_Object form;
 
   /* If PROP is a list of the form `(when FORM . VALUE)', FORM is
@@ -2828,9 +2964,10 @@ handle_single_display_prop (it, prop, object, position)
       if ((EQ (location, Qleft_margin)
           || EQ (location, Qright_margin)
           || NILP (location))
-         && valid_p)
+         && valid_p
+         && !display_replaced_before_p)
        {
-         space_or_image_found_p = 1;
+         replaces_text_display_p = 1;
          
          /* Save current settings of IT so that we can restore them
             when we are finished with the glyph property value.  */
@@ -2854,6 +2991,10 @@ handle_single_display_prop (it, prop, object, position)
              it->method = next_element_from_string;
              it->stop_charpos = 0;
              it->string_from_display_prop_p = 1;
+             /* Say that we haven't consumed the characters with
+                `display' property yet.  The call to pop_it in
+                set_iterator_to_next will clean this up.  */
+             *position = start_pos;
            }
          else if (CONSP (value) && EQ (XCAR (value), Qspace))
            {
@@ -2883,7 +3024,7 @@ handle_single_display_prop (it, prop, object, position)
        *position = start_pos;
     }
 
-  return space_or_image_found_p;
+  return replaces_text_display_p;
 }
 
 
@@ -2948,8 +3089,8 @@ display_prop_intangible_p (prop)
     {
       /* A vector of sub-properties.  */
       int i;
-      for (i = 0; i < XVECTOR (prop)->size; ++i)
-       if (single_display_prop_intangible_p (XVECTOR (prop)->contents[i]))
+      for (i = 0; i < ASIZE (prop); ++i)
+       if (single_display_prop_intangible_p (AREF (prop, i)))
          return 1;
     }
   else
@@ -2958,6 +3099,132 @@ display_prop_intangible_p (prop)
   return 0;
 }
 
+
+/* Return 1 if PROP is a display sub-property value containing STRING.  */
+
+static int
+single_display_prop_string_p (prop, string)
+     Lisp_Object prop, string;
+{
+  extern Lisp_Object Qwhen, Qmargin;
+
+  if (EQ (string, prop))
+    return 1;
+  
+  /* Skip over `when FORM'.  */
+  if (CONSP (prop) && EQ (XCAR (prop), Qwhen))
+    {
+      prop = XCDR (prop);
+      if (!CONSP (prop))
+       return 0;
+      prop = XCDR (prop);
+    }
+
+  if (CONSP (prop))
+    /* Skip over `margin LOCATION'.  */
+    if (EQ (XCAR (prop), Qmargin))
+      {
+       prop = XCDR (prop);
+       if (!CONSP (prop))
+         return 0;
+
+       prop = XCDR (prop);
+       if (!CONSP (prop))
+         return 0;
+      }
+  
+  return CONSP (prop) && EQ (XCAR (prop), string);
+}
+
+
+/* Return 1 if STRING appears in the `display' property PROP.  */
+
+static int
+display_prop_string_p (prop, string)
+     Lisp_Object prop, string;
+{
+  extern Lisp_Object Qwhen, Qmargin;
+  
+  if (CONSP (prop)
+      && CONSP (XCAR (prop))
+      && !EQ (Qmargin, XCAR (XCAR (prop))))
+    {
+      /* A list of sub-properties.  */
+      while (CONSP (prop))
+       {
+         if (single_display_prop_string_p (XCAR (prop), string))
+           return 1;
+         prop = XCDR (prop);
+       }
+    }
+  else if (VECTORP (prop))
+    {
+      /* A vector of sub-properties.  */
+      int i;
+      for (i = 0; i < ASIZE (prop); ++i)
+       if (single_display_prop_string_p (AREF (prop, i), string))
+         return 1;
+    }
+  else
+    return single_display_prop_string_p (prop, string);
+
+  return 0;
+}
+
+
+/* Determine from which buffer position in W's buffer STRING comes
+   from.  AROUND_CHARPOS is an approximate position where it could
+   be from.  Value is the buffer position or 0 if it couldn't be
+   determined.
+
+   W's buffer must be current.
+
+   This function is necessary because we don't record buffer positions
+   in glyphs generated from strings (to keep struct glyph small).
+   This function may only use code that doesn't eval because it is
+   called asynchronously from note_mouse_highlight.  */
+
+int
+string_buffer_position (w, string, around_charpos)
+     struct window *w;
+     Lisp_Object string;
+     int around_charpos;
+{
+  Lisp_Object around = make_number (around_charpos);
+  Lisp_Object limit, prop, pos;
+  const int MAX_DISTANCE = 1000;
+  int found = 0;
+
+  pos = make_number (around_charpos);
+  limit = make_number (min (XINT (pos) + MAX_DISTANCE, ZV));
+  while (!found && !EQ (pos, limit))
+    {
+      prop = Fget_char_property (pos, Qdisplay, Qnil);
+      if (!NILP (prop) && display_prop_string_p (prop, string))
+       found = 1;
+      else
+       pos = Fnext_single_property_change (pos, Qdisplay, Qnil, limit);
+    }
+
+  if (!found)
+    {
+      pos = make_number (around_charpos);
+      limit = make_number (max (XINT (pos) - MAX_DISTANCE, BEGV));
+      while (!found && !EQ (pos, limit))
+       {
+         prop = Fget_char_property (pos, Qdisplay, Qnil);
+         if (!NILP (prop) && display_prop_string_p (prop, string))
+           found = 1;
+         else
+           pos = Fprevious_single_property_change (pos, Qdisplay, Qnil,
+                                                   limit);
+       }
+    }
+
+  return found ? XINT (pos) : 0;
+}
+
+
 \f
 /***********************************************************************
                        `composition' property
@@ -3040,7 +3307,7 @@ static enum prop_handled
 handle_overlay_change (it)
      struct it *it;
 {
-  if (!STRINGP (it->string) && get_overlay_strings (it))
+  if (!STRINGP (it->string) && get_overlay_strings (it, 0))
     return HANDLED_RECOMPUTE_PROPS;
   else
     return HANDLED_NORMALLY;
@@ -3064,6 +3331,8 @@ next_overlay_string (it)
       /* No more overlay strings.  Restore IT's settings to what
         they were before overlay strings were processed, and
         continue to deliver from current_buffer.  */
+      int display_ellipsis_p = it->stack[it->sp - 1].display_ellipsis_p;
+      
       pop_it (it);
       xassert (it->stop_charpos >= BEGV
               && it->stop_charpos <= it->end_charpos);
@@ -3078,6 +3347,11 @@ next_overlay_string (it)
         next_element_from_buffer doesn't try it again.  */
       if (IT_CHARPOS (*it) >= it->end_charpos)
        it->overlay_strings_at_end_processed_p = 1;
+
+      /* If we have to display `...' for invisible text, set
+        the iterator up for that.  */
+      if (display_ellipsis_p)
+       setup_for_ellipsis (it);
     }
   else
     {
@@ -3088,7 +3362,7 @@ next_overlay_string (it)
       int i = it->current.overlay_string_index % OVERLAY_STRING_CHUNK_SIZE;
   
       if (it->current.overlay_string_index && i == 0)
-       load_overlay_strings (it);
+       load_overlay_strings (it, 0);
 
       /* Initialize IT to deliver display elements from the overlay
          string.  */
@@ -3148,8 +3422,8 @@ compare_overlay_entries (e1, e2)
 
 
 /* Load the vector IT->overlay_strings with overlay strings from IT's
-   current buffer position.  Set IT->n_overlays to the total number of
-   overlay strings found.  
+   current buffer position, or from CHARPOS if that is > 0.  Set
+   IT->n_overlays to the total number of overlay strings found.
 
    Overlay strings are processed OVERLAY_STRING_CHUNK_SIZE strings at
    a time.  On entry into load_overlay_strings,
@@ -3172,8 +3446,9 @@ compare_overlay_entries (e1, e2)
    compare_overlay_entries.  */
    
 static void
-load_overlay_strings (it)
+load_overlay_strings (it, charpos)
      struct it *it;
+     int charpos;
 {
   extern Lisp_Object Qafter_string, Qbefore_string, Qwindow, Qpriority;
   Lisp_Object ov, overlay, window, str, invisible;
@@ -3182,7 +3457,9 @@ load_overlay_strings (it)
   int n = 0, i, j, invis_p;
   struct overlay_entry *entries
     = (struct overlay_entry *) alloca (size * sizeof *entries);
-  int charpos = IT_CHARPOS (*it);
+
+  if (charpos <= 0)
+    charpos = IT_CHARPOS (*it);
 
   /* Append the overlay string STRING of overlay OVERLAY to vector
      `entries' which has size `size' and currently contains `n'
@@ -3314,12 +3591,13 @@ load_overlay_strings (it)
 
 
 /* Get the first chunk of overlay strings at IT's current buffer
-   position.  Value is non-zero if at least one overlay string was
-   found.   */
+   position, or at CHARPOS if that is > 0.  Value is non-zero if at
+   least one overlay string was found.  */
 
 static int
-get_overlay_strings (it)
+get_overlay_strings (it, charpos)
      struct it *it;
+     int charpos;
 {
   /* Get the first OVERLAY_STRING_CHUNK_SIZE overlay strings to
      process.  This fills IT->overlay_strings with strings, and sets
@@ -3329,7 +3607,7 @@ get_overlay_strings (it)
      when no overlay strings are found because a zero value would
      indicate a position in the first overlay string.  */
   it->current.overlay_string_index = 0;
-  load_overlay_strings (it);
+  load_overlay_strings (it, charpos);
 
   /* If we found overlay strings, set up IT to deliver display
      elements from the first one.  Otherwise set up IT to deliver
@@ -3350,8 +3628,9 @@ get_overlay_strings (it)
       /* Set up IT to deliver display elements from the first overlay
         string.  */
       IT_STRING_CHARPOS (*it) = IT_STRING_BYTEPOS (*it) = 0;
-      it->stop_charpos = 0;
       it->string = it->overlay_strings[0];
+      it->stop_charpos = 0;
+      it->end_charpos = XSTRING (it->string)->size;
       it->multibyte_p = STRING_MULTIBYTE (it->string);
       xassert (STRINGP (it->string));
       it->method = next_element_from_string;
@@ -3402,6 +3681,7 @@ push_it (it)
   p->font_height = it->font_height;
   p->voffset = it->voffset;
   p->string_from_display_prop_p = it->string_from_display_prop_p;
+  p->display_ellipsis_p = 0;
   ++it->sp;
 }
 
@@ -3480,9 +3760,12 @@ forward_to_next_line_start (it, skipped_p)
 
   /* If already on a newline, just consume it to avoid unintended
      skipping over invisible text below.  */
-  if (it->what == IT_CHARACTER && it->c == '\n')
+  if (it->what == IT_CHARACTER
+      && it->c == '\n'
+      && CHARPOS (it->position) == IT_CHARPOS (*it))
     {
       set_iterator_to_next (it, 0);
+      it->c = 0;
       return 1;
     }
 
@@ -3495,20 +3778,19 @@ forward_to_next_line_start (it, skipped_p)
 
   /* Scan for a newline within MAX_NEWLINE_DISTANCE display elements
      from buffer text.  */
-  n = newline_found_p = 0;
-  while (n < MAX_NEWLINE_DISTANCE
-        && get_next_display_element (it)
-        && !newline_found_p)
+  for (n = newline_found_p = 0;
+       !newline_found_p && n < MAX_NEWLINE_DISTANCE;
+       n += STRINGP (it->string) ? 0 : 1)
     {
+      if (!get_next_display_element (it))
+       break;
       newline_found_p = it->what == IT_CHARACTER && it->c == '\n';
       set_iterator_to_next (it, 0);
-      if (!STRINGP (it->string))
-       ++n;
     }
 
   /* If we didn't find a newline near enough, see if we can use a
      short-cut.  */
-  if (!newline_found_p && n == MAX_NEWLINE_DISTANCE)
+  if (n == MAX_NEWLINE_DISTANCE)
     {
       int start = IT_CHARPOS (*it);
       int limit = find_next_newline_no_quit (start, 1);
@@ -3631,9 +3913,12 @@ reseat_at_next_visible_line_start (it, on_newline_p)
      more than the value of IT->selective.  */
   if (it->selective > 0)
     while (IT_CHARPOS (*it) < ZV
-           && indented_beyond_p (IT_CHARPOS (*it), IT_BYTEPOS (*it),
+          && indented_beyond_p (IT_CHARPOS (*it), IT_BYTEPOS (*it),
                                 it->selective))
-      newline_found_p = forward_to_next_line_start (it, &skipped_p);
+      {
+       xassert (FETCH_BYTE (IT_BYTEPOS (*it) - 1) == '\n');
+       newline_found_p = forward_to_next_line_start (it, &skipped_p);
+      }
 
   /* Position on the newline if that's what's requested.  */
   if (on_newline_p && newline_found_p)
@@ -3708,6 +3993,7 @@ reseat_1 (it, pos, set_stop_p)
 
   it->current.pos = it->position = pos;
   XSETBUFFER (it->object, current_buffer);
+  it->end_charpos = ZV;
   it->dpvec = NULL;
   it->current.dpvec_index = -1;
   it->current.overlay_string_index = -1;
@@ -3761,7 +4047,8 @@ reseat_to_string (it, s, string, charpos, precision, field_width, multibyte)
   it->current.dpvec_index = -1;
   xassert (charpos >= 0);
   
-  /* Use the setting of MULTIBYTE if specified.  */
+  /* If STRING is specified, use its multibyteness, otherwise use the
+     setting of MULTIBYTE, if specified.  */
   if (multibyte >= 0)
     it->multibyte_p = multibyte > 0;
   
@@ -3869,9 +4156,13 @@ get_next_display_element (it)
                  it->dpend = v->contents + v->size;
                  it->current.dpvec_index = 0;
                  it->method = next_element_from_display_vector;
+                 success_p = get_next_display_element (it);
+               }
+             else
+               {
+                 set_iterator_to_next (it, 0);
+                 success_p = get_next_display_element (it);
                }
-
-             success_p = get_next_display_element (it);
            }
 
          /* Translate control characters into `\003' or `^C' form.
@@ -3936,7 +4227,22 @@ get_next_display_element (it)
                  if (SINGLE_BYTE_CHAR_P (it->c))
                    str[0] = it->c, len = 1;
                  else
-                   len = CHAR_STRING (it->c, str);
+                   {
+                     len = CHAR_STRING_NO_SIGNAL (it->c, str);
+                     if (len < 0)
+                       {
+                         /* It's an invalid character, which
+                            shouldn't happen actually, but due to
+                            bugs it may happen.  Let's print the char
+                            as is, there's not much meaningful we can
+                            do with it.  */
+                         str[0] = it->c;
+                         str[1] = it->c >> 8;
+                         str[2] = it->c >> 16;
+                         str[3] = it->c >> 24;
+                         len = 4;
+                       }
+                   }
 
                  for (i = 0; i < len; i++)
                    {
@@ -4119,6 +4425,8 @@ set_iterator_to_next (it, reseat_p)
              pop_it (it);
              if (!STRINGP (it->string))
                it->method = next_element_from_buffer;
+             else
+               goto consider_string_end;
            }
        }
     }
@@ -4443,7 +4751,7 @@ next_element_from_buffer (it)
          else
            {
              it->overlay_strings_at_end_processed_p = 1;
-             overlay_strings_follow_p = get_overlay_strings (it);
+             overlay_strings_follow_p = get_overlay_strings (it, 0);
            }
 
          if (overlay_strings_follow_p)
@@ -5071,6 +5379,20 @@ move_it_vertically (it, dy)
 }
 
 
+/* Move iterator IT past the end of the text line it is in.  */
+
+void
+move_it_past_eol (it)
+     struct it *it;
+{
+  enum move_it_result rc;
+  
+  rc = move_it_in_display_line_to (it, Z, 0, MOVE_TO_POS);
+  if (rc == MOVE_NEWLINE_OR_CR)
+    set_iterator_to_next (it, 0);
+}
+
+
 #if 0 /* Currently not used.  */
 
 /* Return non-zero if some text between buffer positions START_CHARPOS
@@ -5192,6 +5514,12 @@ add_to_log (format, arg1, arg2)
   int len;
   struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
 
+  /* Do nothing if called asynchronously.  Inserting text into
+     a buffer may call after-change-functions and alike and
+     that would means running Lisp asynchronously.  */
+  if (handling_signal)
+    return;
+
   fmt = msg = Qnil;
   GCPRO4 (fmt, msg, arg1, arg2);
   
@@ -5219,16 +5547,16 @@ message_log_maybe_newline ()
 }
 
 
-/* Add a string M of length LEN to the message log, optionally
+/* Add a string M of length NBYTES to the message log, optionally
    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.  */
 
 void
-message_dolog (m, len, nlflag, multibyte)
+message_dolog (m, nbytes, nlflag, multibyte)
      char *m;
-     int len, nlflag, multibyte;
+     int nbytes, nlflag, multibyte;
 {
   if (!NILP (Vmessage_log_max))
     {
@@ -5266,14 +5594,14 @@ message_dolog (m, len, nlflag, multibyte)
       if (multibyte
          && NILP (current_buffer->enable_multibyte_characters))
        {
-         int i, c, nbytes;
+         int i, c, char_bytes;
          unsigned char work[1];
          
          /* Convert a multibyte string to single-byte
             for the *Message* buffer.  */
-         for (i = 0; i < len; i += nbytes)
+         for (i = 0; i < nbytes; i += nbytes)
            {
-             c = string_char_and_length (m + i, len - i, &nbytes);
+             c = string_char_and_length (m + i, nbytes - i, &char_bytes);
              work[0] = (SINGLE_BYTE_CHAR_P (c)
                         ? c
                         : multibyte_char_to_unibyte (c, Qnil));
@@ -5283,20 +5611,20 @@ message_dolog (m, len, nlflag, multibyte)
       else if (! multibyte
               && ! NILP (current_buffer->enable_multibyte_characters))
        {
-         int i, c, nbytes;
+         int i, c, char_bytes;
          unsigned char *msg = (unsigned char *) m;
          unsigned char str[MAX_MULTIBYTE_LENGTH];
          /* Convert a single-byte string to multibyte
             for the *Message* buffer.  */
-         for (i = 0; i < len; i++)
+         for (i = 0; i < nbytes; i++)
            {
              c = unibyte_char_to_multibyte (msg[i]);
-             nbytes = CHAR_STRING (c, str);
-             insert_1_both (str, 1, nbytes, 1, 0, 0);
+             char_bytes = CHAR_STRING (c, str);
+             insert_1_both (str, 1, char_bytes, 1, 0, 0);
            }
        }
-      else if (len)
-       insert_1 (m, len, 1, 0, 0);
+      else if (nbytes)
+       insert_1 (m, nbytes, 1, 0, 0);
 
       if (nlflag)
        {
@@ -5417,9 +5745,10 @@ message_log_check_duplicate (prev_bol, prev_bol_byte, this_bol, this_bol_byte)
 }
 
 
-/* Display an echo area message M with a specified length of LEN
-   chars.  The string may include null characters.  If M is 0, clear
-   out any existing message, and let the mini-buffer text show through.
+/* Display an echo area message M with a specified length of NBYTES
+   bytes.  The string may include null characters.  If M is 0, clear
+   out any existing message, and let the mini-buffer text show
+   through.
 
    The buffer M must continue to exist until after the echo area gets
    cleared or some other message gets displayed there.  This means do
@@ -5427,25 +5756,25 @@ message_log_check_duplicate (prev_bol, prev_bol_byte, this_bol, this_bol_byte)
    a buffer that was alloca'd.  */
 
 void
-message2 (m, len, multibyte)
+message2 (m, nbytes, multibyte)
      char *m;
-     int len;
+     int nbytes;
      int multibyte;
 {
   /* First flush out any partial line written with print.  */
   message_log_maybe_newline ();
   if (m)
-    message_dolog (m, len, 1, multibyte);
-  message2_nolog (m, len, multibyte);
+    message_dolog (m, nbytes, 1, multibyte);
+  message2_nolog (m, nbytes, multibyte);
 }
 
 
 /* The non-logging counterpart of message2.  */
 
 void
-message2_nolog (m, len, multibyte)
+message2_nolog (m, nbytes, multibyte)
      char *m;
-     int len;
+     int nbytes;
 {
   struct frame *sf = SELECTED_FRAME ();
   message_enable_multibyte = multibyte;
@@ -5456,7 +5785,7 @@ message2_nolog (m, len, multibyte)
        putc ('\n', stderr);
       noninteractive_need_newline = 0;
       if (m)
-       fwrite (m, len, 1, stderr);
+       fwrite (m, nbytes, 1, stderr);
       if (cursor_in_echo_area == 0)
        fprintf (stderr, "\n");
       fflush (stderr);
@@ -5483,7 +5812,7 @@ message2_nolog (m, len, multibyte)
 
       if (m)
        {
-         set_message (m, Qnil, len, multibyte);
+         set_message (m, Qnil, nbytes, multibyte);
          if (minibuffer_auto_raise)
            Fraise_frame  (WINDOW_FRAME (XWINDOW (mini_window)));
        }
@@ -5866,6 +6195,11 @@ with_echo_area_buffer (w, which, fn, a1, a2, a3, a4)
 
   buffer = echo_area_buffer[this_one];
 
+  /* Don't get confused by reusing the buffer used for echoing
+     for a different purpose.  */
+  if (!echoing && EQ (buffer, echo_message_buffer))
+    cancel_echoing ();
+
   record_unwind_protect (unwind_with_echo_area_buffer,
                         with_echo_area_buffer_unwind_data (w));
 
@@ -5921,27 +6255,25 @@ with_echo_area_buffer_unwind_data (w)
   if (NILP (vector))
     vector = Fmake_vector (make_number (7), Qnil);
   
-  XSETBUFFER (XVECTOR (vector)->contents[i], current_buffer); ++i;
-  XVECTOR (vector)->contents[i++] = Vdeactivate_mark;
-  XVECTOR (vector)->contents[i++] = make_number (windows_or_buffers_changed);
+  XSETBUFFER (AREF (vector, i), current_buffer); ++i;
+  AREF (vector, i) = Vdeactivate_mark, ++i;
+  AREF (vector, i) = make_number (windows_or_buffers_changed), ++i;
   
   if (w)
     {
-      XSETWINDOW (XVECTOR (vector)->contents[i], w); ++i;
-      XVECTOR (vector)->contents[i++] = w->buffer;
-      XVECTOR (vector)->contents[i++]
-       = make_number (XMARKER (w->pointm)->charpos);
-      XVECTOR (vector)->contents[i++]
-       = make_number (XMARKER (w->pointm)->bytepos);
+      XSETWINDOW (AREF (vector, i), w); ++i;
+      AREF (vector, i) = w->buffer; ++i;
+      AREF (vector, i) = make_number (XMARKER (w->pointm)->charpos); ++i;
+      AREF (vector, i) = make_number (XMARKER (w->pointm)->bytepos); ++i;
     }
   else
     {
       int end = i + 4;
-      while (i < end)
-       XVECTOR (vector)->contents[i++] = Qnil;
+      for (; i < end; ++i)
+       AREF (vector, i) = Qnil;
     }
 
-  xassert (i == XVECTOR (vector)->size);
+  xassert (i == ASIZE (vector));
   return vector;
 }
 
@@ -5997,6 +6329,7 @@ setup_echo_area_for_printing (multibyte_p)
 
       /* Switch to that buffer and clear it.  */
       set_buffer_internal (XBUFFER (echo_area_buffer[0]));
+      current_buffer->truncate_lines = Qnil;
       
       if (Z > BEG)
        {
@@ -6035,8 +6368,11 @@ setup_echo_area_for_printing (multibyte_p)
        }
       
       if (current_buffer != XBUFFER (echo_area_buffer[0]))
-       /* Someone switched buffers between print requests.  */
-       set_buffer_internal (XBUFFER (echo_area_buffer[0]));
+       {
+         /* Someone switched buffers between print requests.  */
+         set_buffer_internal (XBUFFER (echo_area_buffer[0]));
+         current_buffer->truncate_lines = Qnil;
+       }
     }
 }
 
@@ -6164,6 +6500,12 @@ resize_mini_window (w, exact_p)
 
   xassert (MINI_WINDOW_P (w));
 
+  /* Don't resize windows while redisplaying; it would confuse
+     redisplay functions when the size of the window they are
+     displaying changes from under them.  */
+  if (redisplaying_p)
+    return 0;
+  
   /* Nil means don't try to resize.  */
   if (NILP (Vresize_mini_windows)
       || (FRAME_X_P (f) && f->output_data.x == NULL))
@@ -6333,6 +6675,17 @@ push_message ()
 }
 
 
+/* Handler for record_unwind_protect calling pop_message.  */
+
+Lisp_Object
+push_message_unwind (dummy)
+     Lisp_Object dummy;
+{
+  pop_message ();
+  return Qnil;
+}
+
+
 /* Restore message display from the top of Vmessage_stack.  */
 
 void
@@ -6632,7 +6985,10 @@ echo_area_display (update_frame_p)
          if (!display_completed)
            n = redisplay_mode_lines (FRAME_ROOT_WINDOW (f), 0);
            
-         if (window_height_changed_p)
+         if (window_height_changed_p
+             /* Don't do this if Emacs is shutting down.  Redisplay
+                needs to run hooks.  */
+             && !NILP (Vrun_hooks))
            {
              /* Must update other windows.  Likewise as in other
                 cases, don't let this update be interrupted by
@@ -6719,12 +7075,12 @@ store_frame_title_char (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 more
-   than PRECISION number of bytes from STR; 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 pad.
-   Called from display_mode_element when it is used to build a frame
-   title.  */
+   frame_title_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
+   pad.  Called from display_mode_element when it is used to build a
+   frame title.  */
 
 static int
 store_frame_title (str, field_width, precision)
@@ -6732,14 +7088,13 @@ store_frame_title (str, field_width, precision)
      int field_width, precision;
 {
   int n = 0;
+  int dummy, nbytes, width;
 
   /* Copy at most PRECISION chars from STR.  */
-  while ((precision <= 0 || n < precision)
-        && *str)
-    {
-      store_frame_title_char (*str++);
-      ++n;
-    }
+  nbytes = strlen (str);
+  n+= c_string_width (str, nbytes, precision, &dummy, &nbytes);
+  while (nbytes--)
+    store_frame_title_char (*str++);
 
   /* Fill up with spaces until FIELD_WIDTH reached.  */
   while (field_width > 0
@@ -6797,7 +7152,8 @@ x_consider_frame_title (frame)
       frame_title_ptr = frame_title_buf;
       init_iterator (&it, XWINDOW (f->selected_window), -1, -1,
                     NULL, DEFAULT_FACE_ID);
-      len = display_mode_element (&it, 0, -1, -1, fmt);
+      display_mode_element (&it, 0, -1, -1, fmt);
+      len = frame_title_ptr - frame_title_buf;
       frame_title_ptr = NULL;
       set_buffer_internal (obuf);
 
@@ -6943,6 +7299,12 @@ update_menu_bar (f, save_match_data)
   Lisp_Object window;
   register struct window *w;
 
+  /* If called recursively during a menu update, do nothing.  This can
+     happen when, for instance, an activate-menubar-hook causes a
+     redisplay.  */
+  if (inhibit_menubar_update)
+    return;
+
   window = FRAME_SELECTED_WINDOW (f);
   w = XWINDOW (window);
   
@@ -6977,6 +7339,8 @@ update_menu_bar (f, save_match_data)
          struct buffer *prev = current_buffer;
          int count = BINDING_STACK_SIZE ();
 
+         specbind (Qinhibit_menubar_update, Qt);
+
          set_buffer_internal_1 (XBUFFER (w->buffer));
          if (save_match_data)
            record_unwind_protect (Fset_match_data, Fmatch_data (Qnil, Qnil));
@@ -6987,7 +7351,7 @@ update_menu_bar (f, save_match_data)
            }
 
          /* Run the Lucid hook.  */
-         call1 (Vrun_hooks, Qactivate_menubar_hook);
+         safe_run_hooks (Qactivate_menubar_hook);
          
          /* If it has changed current-menubar from previous value,
             really recompute the menu-bar from the value.  */
@@ -7107,7 +7471,7 @@ static void
 build_desired_tool_bar_string (f)
      struct frame *f;
 {
-  int i, size, size_needed, string_idx;
+  int i, size, size_needed;
   struct gcpro gcpro1, gcpro2, gcpro3;
   Lisp_Object image, plist, props;
 
@@ -7122,12 +7486,11 @@ build_desired_tool_bar_string (f)
          ? XSTRING (f->desired_tool_bar_string)->size
          : 0);
 
-  /* Each image in the string we build is preceded by a space,
-     and there is a space at the end.  */
-  size_needed = f->n_tool_bar_items + 1;
-
+  /* We need one space in the string for each image.  */
+  size_needed = f->n_tool_bar_items;
+  
   /* Reuse f->desired_tool_bar_string, if possible.  */
-  if (size < size_needed)
+  if (size < size_needed || NILP (f->desired_tool_bar_string))
     f->desired_tool_bar_string = Fmake_string (make_number (size_needed),
                                               make_number (' '));
   else
@@ -7140,16 +7503,14 @@ build_desired_tool_bar_string (f)
   /* Put a `display' property on the string for the images to display,
      put a `menu_item' property on tool-bar items with a value that
      is the index of the item in F's tool-bar item vector.  */
-  for (i = 0, string_idx = 0;
-       i < f->n_tool_bar_items;
-       ++i, string_idx += 1)
+  for (i = 0; i < f->n_tool_bar_items; ++i)
     {
 #define PROP(IDX) AREF (f->tool_bar_items, i * TOOL_BAR_ITEM_NSLOTS + (IDX))
 
       int enabled_p = !NILP (PROP (TOOL_BAR_ITEM_ENABLED_P));
       int selected_p = !NILP (PROP (TOOL_BAR_ITEM_SELECTED_P));
-      int margin, relief, idx;
-      extern Lisp_Object QCrelief, QCmargin, QCalgorithm, Qimage;
+      int hmargin, vmargin, relief, idx, end;
+      extern Lisp_Object QCrelief, QCmargin, QCconversion, Qimage;
       extern Lisp_Object Qlaplace;
 
       /* If image is a vector, choose the image according to the
@@ -7180,8 +7541,27 @@ build_desired_tool_bar_string (f)
       plist = Fcopy_sequence (XCDR (image));
 
       /* Compute margin and relief to draw.  */
-      relief = tool_bar_button_relief > 0 ? tool_bar_button_relief : 3;
-      margin = relief + max (0, tool_bar_button_margin);
+      relief = (tool_bar_button_relief > 0
+               ? tool_bar_button_relief
+               : DEFAULT_TOOL_BAR_BUTTON_RELIEF);
+      hmargin = vmargin = relief;
+
+      if (INTEGERP (Vtool_bar_button_margin)
+         && XINT (Vtool_bar_button_margin) > 0)
+       {
+         hmargin += XFASTINT (Vtool_bar_button_margin);
+         vmargin += XFASTINT (Vtool_bar_button_margin);
+       }
+      else if (CONSP (Vtool_bar_button_margin))
+       {
+         if (INTEGERP (XCAR (Vtool_bar_button_margin))
+             && XINT (XCAR (Vtool_bar_button_margin)) > 0)
+           hmargin += XFASTINT (XCAR (Vtool_bar_button_margin));
+         
+         if (INTEGERP (XCDR (Vtool_bar_button_margin))
+             && XINT (XCDR (Vtool_bar_button_margin)) > 0)
+           vmargin += XFASTINT (XCDR (Vtool_bar_button_margin));
+       }
       
       if (auto_raise_tool_bar_buttons_p)
        {
@@ -7190,7 +7570,8 @@ build_desired_tool_bar_string (f)
          if (selected_p)
            {
              plist = Fplist_put (plist, QCrelief, make_number (-relief));
-             margin -= relief;
+             hmargin -= relief;
+             vmargin -= relief;
            }
        }
       else
@@ -7202,18 +7583,26 @@ build_desired_tool_bar_string (f)
                              (selected_p
                               ? make_number (-relief)
                               : make_number (relief)));
-         margin -= relief;
+         hmargin -= relief;
+         vmargin -= relief;
        }
 
       /* Put a margin around the image.  */
-      if (margin)
-       plist = Fplist_put (plist, QCmargin, make_number (margin));
+      if (hmargin || vmargin)
+       {
+         if (hmargin == vmargin)
+           plist = Fplist_put (plist, QCmargin, make_number (hmargin));
+         else
+           plist = Fplist_put (plist, QCmargin,
+                               Fcons (make_number (hmargin),
+                                      make_number (vmargin)));
+       }
          
       /* If button is not enabled, and we don't have special images
         for the disabled state, make the image appear disabled by
         applying an appropriate algorithm to it.  */
       if (!enabled_p && idx < 0)
-       plist = Fplist_put (plist, QCalgorithm, Qdisabled);
+       plist = Fplist_put (plist, QCconversion, Qdisabled);
       
       /* Put a `display' text property on the string for the image to
         display.  Put a `menu-item' property on the string that gives
@@ -7221,9 +7610,16 @@ build_desired_tool_bar_string (f)
         vector.  */
       image = Fcons (Qimage, plist);
       props = list4 (Qdisplay, image,
-                    Qmenu_item, make_number (i * TOOL_BAR_ITEM_NSLOTS)),
-      Fadd_text_properties (make_number (string_idx),
-                           make_number (string_idx + 1),
+                    Qmenu_item, make_number (i * TOOL_BAR_ITEM_NSLOTS));
+
+      /* Let the last image hide all remaining spaces in the tool bar
+         string.  The string can be longer than needed when we reuse a
+         previous string.  */
+      if (i + 1 == f->n_tool_bar_items)
+       end = XSTRING (f->desired_tool_bar_string)->size;
+      else
+       end = i + 1;
+      Fadd_text_properties (make_number (i), make_number (end),
                            props, f->desired_tool_bar_string);
 #undef PROP
     }
@@ -7346,6 +7742,38 @@ tool_bar_lines_needed (f)
 }
 
 
+DEFUN ("tool-bar-lines-needed", Ftool_bar_lines_needed, Stool_bar_lines_needed,
+       0, 1, 0,
+  "Return the number of lines occupied by the tool bar of FRAME.")
+  (frame)
+     Lisp_Object frame;
+{
+  struct frame *f;
+  struct window *w;
+  int nlines = 0;
+
+  if (NILP (frame))
+    frame = selected_frame;
+  else
+    CHECK_FRAME (frame, 0);
+  f = XFRAME (frame);
+  
+  if (WINDOWP (f->tool_bar_window)
+      || (w = XWINDOW (f->tool_bar_window),
+         XFASTINT (w->height) > 0))
+    {
+      update_tool_bar (f, 1);
+      if (f->n_tool_bar_items)
+       {
+         build_desired_tool_bar_string (f);
+         nlines = tool_bar_lines_needed (f);
+       }
+    }
+
+  return make_number (nlines);
+}
+
+
 /* Display the tool-bar of frame F.  Value is non-zero if tool-bar's
    height should be changed.  */
 
@@ -7389,6 +7817,11 @@ redisplay_tool_bar (f)
   if (auto_resize_tool_bars_p)
     {
       int nlines;
+
+      /* If we couldn't display everything, change the tool-bar's
+        height.  */
+      if (IT_STRING_CHARPOS (it) < it.end_charpos)
+       change_height_p = 1;
       
       /* If there are blank lines at the end, except for a partially
         visible blank line at the end that is smaller than
@@ -7877,6 +8310,12 @@ redisplay_internal (preserve_echo_area)
       fonts_changed_p = 0;
     }
 
+  /* If face_change_count is non-zero, init_iterator will free all
+     realized faces, which includes the faces referenced from current
+     matrices.  So, we can't reuse current matrices in this case.  */
+  if (face_change_count)
+    ++windows_or_buffers_changed;
+
   if (! FRAME_WINDOW_P (sf)
       && previous_terminal_frame != sf)
     {
@@ -8203,6 +8642,10 @@ redisplay_internal (preserve_echo_area)
              xassert (this_line_vpos == it.vpos);
              xassert (this_line_y == it.current_y);
              set_cursor_from_row (w, row, w->current_matrix, 0, 0, 0, 0);
+#if GLYPH_DEBUG
+             *w->desired_matrix->method = 0;
+             debug_method_add (w, "optimization 3");
+#endif
              goto update;
            }
          else
@@ -8226,6 +8669,9 @@ redisplay_internal (preserve_echo_area)
   if (consider_all_windows_p)
     {
       Lisp_Object tail, frame;
+      int i, n = 0, size = 50;
+      struct frame **updated
+       = (struct frame **) alloca (size * sizeof *updated);
 
       /* Clear the face cache eventually.  */
       if (clear_face_cache_count > CLEAR_FACE_CACHE_COUNT)
@@ -8281,12 +8727,29 @@ redisplay_internal (preserve_echo_area)
                  if (pause)
                    break;
 
-                 mark_window_display_accurate (f->root_window, 1);
-                 if (frame_up_to_date_hook)
-                   frame_up_to_date_hook (f);
+                 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;
                }
            }
        }
+
+      /* 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)
+       {
+         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);
+       }
     }
   else if (FRAME_VISIBLE_P (sf) && !FRAME_OBSCURED_P (sf))
     {
@@ -8357,54 +8820,19 @@ redisplay_internal (preserve_echo_area)
          && !FRAME_WINDOW_P (XFRAME (w->frame)))
        update_mode_lines = 1;
     }
-
-  /* Now text on frame agrees with windows, so put info into the
-     windows for partial redisplay to follow.  */
-  if (!pause)
+  else
     {
-      register struct buffer *b = XBUFFER (w->buffer);
-
-      BUF_UNCHANGED_MODIFIED (b) = BUF_MODIFF (b);
-      BUF_OVERLAY_UNCHANGED_MODIFIED (b) = BUF_OVERLAY_MODIFF (b);
-      BUF_BEG_UNCHANGED (b) = BUF_GPT (b) - BUF_BEG (b);
-      BUF_END_UNCHANGED (b) = BUF_Z (b) - BUF_GPT (b);
-
-      if (consider_all_windows_p)
-       mark_window_display_accurate (FRAME_ROOT_WINDOW (sf), 1);
-      else
+      if (!consider_all_windows_p)
        {
-         XSETFASTINT (w->last_point, BUF_PT (b));
-         w->last_cursor = w->cursor;
-         w->last_cursor_off_p = w->cursor_off_p;
-
-         b->clip_changed = 0;
-         b->prevent_redisplay_optimizations_p = 0;
-         w->update_mode_line = Qnil;
-         XSETFASTINT (w->last_modified, BUF_MODIFF (b));
-         XSETFASTINT (w->last_overlay_modified, BUF_OVERLAY_MODIFF (b));
-         w->last_had_star
-           = (BUF_MODIFF (XBUFFER (w->buffer)) > BUF_SAVE_MODIFF (XBUFFER (w->buffer))
-              ? Qt : Qnil);
-
-         /* Record if we are showing a region, so can make sure to
-            update it fully at next redisplay.  */
-         w->region_showing = (!NILP (Vtransient_mark_mode)
-                              && (EQ (selected_window,
-                                      current_buffer->last_selected_window)
-                                  || highlight_nonselected_windows)
-                              && !NILP (XBUFFER (w->buffer)->mark_active)
-                              ? Fmarker_position (XBUFFER (w->buffer)->mark)
-                              : Qnil);
-
-         w->window_end_valid = w->buffer;
+         /* This has already been done above if
+            consider_all_windows_p is set.  */
+         mark_window_display_accurate_1 (w, 1);
+         
          last_arrow_position = COERCE_MARKER (Voverlay_arrow_position);
          last_arrow_string = Voverlay_arrow_string;
+         
          if (frame_up_to_date_hook != 0)
-           (*frame_up_to_date_hook) (sf);
-
-         w->current_matrix->buffer = b;
-         w->current_matrix->begv = BUF_BEGV (b);
-         w->current_matrix->zv = BUF_ZV (b);
+           frame_up_to_date_hook (sf);
        }
 
       update_mode_lines = 0;
@@ -8468,11 +8896,17 @@ redisplay_internal (preserve_echo_area)
    This is useful in situations where you need to redisplay but no
    user action has occurred, making it inappropriate for the message
    area to be cleared.  See tracking_off and
-   wait_reading_process_input for examples of these situations.  */
+   wait_reading_process_input for examples of these situations.
+
+   FROM_WHERE is an integer saying from where this function was
+   called.  This is useful for debugging.  */
 
 void
-redisplay_preserve_echo_area ()
+redisplay_preserve_echo_area (from_where)
+     int from_where;
 {
+  TRACE ((stderr, "redisplay_preserve_echo_area (%d)\n", from_where));
+
   if (!NILP (echo_area_buffer[1]))
     {
       /* We have a previously displayed message, but no current
@@ -8499,64 +8933,75 @@ unwind_redisplay (old_redisplaying_p)
 }
 
 
-/* Mark the display of windows in the window tree rooted at WINDOW as
-   accurate or inaccurate.  If FLAG is non-zero mark display of WINDOW
-   as accurate.  If FLAG is zero arrange for WINDOW to be redisplayed
-   the next time redisplay_internal is called.  */
+/* Mark the display of window W as accurate or inaccurate.  If
+   ACCURATE_P is non-zero mark display of W as accurate.  If
+   ACCURATE_P is zero, arrange for W to be redisplayed the next time
+   redisplay_internal is called.  */
 
-void
-mark_window_display_accurate (window, accurate_p)
-     Lisp_Object window;
+static void
+mark_window_display_accurate_1 (w, accurate_p)
+     struct window *w;
      int accurate_p;
 {
-  struct window *w;
-  
-  for (; !NILP (window); window = w->next)
+  if (BUFFERP (w->buffer))
     {
-      w = XWINDOW (window);
+      struct buffer *b = XBUFFER (w->buffer);
+         
+      w->last_modified
+       = make_number (accurate_p ? BUF_MODIFF (b) : 0);
+      w->last_overlay_modified
+       = make_number (accurate_p ? BUF_OVERLAY_MODIFF (b) : 0);
+      w->last_had_star
+       = BUF_MODIFF (b) > BUF_SAVE_MODIFF (b) ? Qt : Qnil;
 
-      if (BUFFERP (w->buffer))
+      if (accurate_p)
        {
-         struct buffer *b = XBUFFER (w->buffer);
+         b->clip_changed = 0;
+         b->prevent_redisplay_optimizations_p = 0;
+
+         BUF_UNCHANGED_MODIFIED (b) = BUF_MODIFF (b);
+         BUF_OVERLAY_UNCHANGED_MODIFIED (b) = BUF_OVERLAY_MODIFF (b);
+         BUF_BEG_UNCHANGED (b) = BUF_GPT (b) - BUF_BEG (b);
+         BUF_END_UNCHANGED (b) = BUF_Z (b) - BUF_GPT (b);
          
-         XSETFASTINT (w->last_modified,
-                      accurate_p ? BUF_MODIFF (b) : 0);
-         XSETFASTINT (w->last_overlay_modified,
-                      accurate_p ? BUF_OVERLAY_MODIFF (b) : 0);
-         w->last_had_star = (BUF_MODIFF (b) > BUF_SAVE_MODIFF (b)
-                             ? Qt : Qnil);
-
-#if 0 /* I don't think this is necessary because display_line does it.
-        Let's check it.  */
-         /* Record if we are showing a region, so can make sure to
-            update it fully at next redisplay.  */
-         w->region_showing
-           = (!NILP (Vtransient_mark_mode)
-              && (w == XWINDOW (current_buffer->last_selected_window)
-                  || highlight_nonselected_windows)
-              && (!NILP (b->mark_active)
-                  ? Fmarker_position (b->mark)
-                  : Qnil));
-#endif
+         w->current_matrix->buffer = b;
+         w->current_matrix->begv = BUF_BEGV (b);
+         w->current_matrix->zv = BUF_ZV (b);
          
-         if (accurate_p)
-           {
-             b->clip_changed = 0;
-             b->prevent_redisplay_optimizations_p = 0;
-             w->current_matrix->buffer = b;
-             w->current_matrix->begv = BUF_BEGV (b);
-             w->current_matrix->zv = BUF_ZV (b);
-             w->last_cursor = w->cursor;
-             w->last_cursor_off_p = w->cursor_off_p;
-             if (w == XWINDOW (selected_window))
-               w->last_point = make_number (BUF_PT (b));
-             else
-               w->last_point = make_number (XMARKER (w->pointm)->charpos);
-           }
+         w->last_cursor = w->cursor;
+         w->last_cursor_off_p = w->cursor_off_p;
+         
+         if (w == XWINDOW (selected_window))
+           w->last_point = make_number (BUF_PT (b));
+         else
+           w->last_point = make_number (XMARKER (w->pointm)->charpos);
        }
+    }
 
+  if (accurate_p)
+    {
       w->window_end_valid = w->buffer;
       w->update_mode_line = Qnil;
+    }
+}
+
+
+/* Mark the display of windows in the window tree rooted at WINDOW as
+   accurate or inaccurate.  If ACCURATE_P is non-zero mark display of
+   windows as accurate.  If ACCURATE_P is zero, arrange for windows to
+   be redisplayed the next time redisplay_internal is called.  */
+
+void
+mark_window_display_accurate (window, accurate_p)
+     Lisp_Object window;
+     int accurate_p;
+{
+  struct window *w;
+  
+  for (; !NILP (window); window = w->next)
+    {
+      w = XWINDOW (window);
+      mark_window_display_accurate_1 (w, accurate_p);
 
       if (!NILP (w->vchild))
        mark_window_display_accurate (w->vchild, accurate_p);
@@ -8759,7 +9204,7 @@ make_cursor_line_fully_visible (w)
 {
   struct glyph_matrix *matrix;
   struct glyph_row *row;
-  int window_height, header_line_height;
+  int window_height;
   
   /* It's not always possible to find the cursor, e.g, when a window
      is full of overlay strings.  Don't do anything in that case.  */
@@ -8889,9 +9334,6 @@ try_scrolling (window, just_this_one_p, scroll_conservatively,
   if (PT >= CHARPOS (scroll_margin_pos))
     {
       int y0;
-#if 0
-      int line_height;
-#endif
       
       /* Point is in the scroll margin at the bottom of the window, or
         below.  Compute a new window start that makes point visible.  */
@@ -8902,19 +9344,13 @@ try_scrolling (window, just_this_one_p, scroll_conservatively,
       y0 = it.current_y;
       move_it_to (&it, PT, 0, it.last_visible_y, -1,
                  MOVE_TO_POS | MOVE_TO_X | MOVE_TO_Y);
-#if 0 /* Taking the line's height into account here looks wrong.  */
-      line_height = (it.max_ascent + it.max_descent
-                    ? it.max_ascent + it.max_descent
-                    : last_height);
-      dy = it.current_y + line_height - y0;
-#else
+      
       /* With a scroll_margin of 0, scroll_margin_pos is at the window
         end, which is one line below the window.  The iterator's
         current_y will be same as y0 in that case, but we have to
         scroll a line to make PT visible.  That's the reason why 1 is
         added below.  */
       dy = 1 + it.current_y - y0;
-#endif
       
       if (dy > scroll_max)
        return 0;
@@ -8925,8 +9361,9 @@ try_scrolling (window, just_this_one_p, scroll_conservatively,
       start_display (&it, w, startp);
 
       if (scroll_conservatively)
-       amount_to_scroll =
-         max (dy, CANON_Y_UNIT (f) * max (scroll_step, temp_scroll_step));
+       amount_to_scroll
+         = max (max (dy, CANON_Y_UNIT (f)),
+                CANON_Y_UNIT (f) * max (scroll_step, temp_scroll_step));
       else if (scroll_step || temp_scroll_step)
        amount_to_scroll = scroll_max;
       else
@@ -9163,7 +9600,7 @@ try_cursor_movement (window, startp, scroll_step)
          || current_buffer != XMARKER (Voverlay_arrow_position)->buffer))
     {
       int this_scroll_margin;
-      struct glyph_row *row;
+      struct glyph_row *row = NULL;
 
 #if GLYPH_DEBUG
       debug_method_add (w, "cursor movement");
@@ -9378,6 +9815,8 @@ redisplay_window (window, just_this_one_p)
            blank_row (w, row, y);
          goto finish_scroll_bars;
        }
+
+      clear_glyph_matrix (w->desired_matrix);
     }
 
   /* Otherwise set up data on this window; select its buffer and point
@@ -9528,8 +9967,8 @@ redisplay_window (window, just_this_one_p)
          startp = run_window_scroll_functions (window, startp);
        }
       
-      XSETFASTINT (w->last_modified, 0);
-      XSETFASTINT (w->last_overlay_modified, 0);
+      w->last_modified = make_number (0);
+      w->last_overlay_modified = make_number (0);
       if (CHARPOS (startp) < BEGV)
        SET_TEXT_POS (startp, BEGV, BEGV_BYTE);
       else if (CHARPOS (startp) > ZV)
@@ -9608,36 +10047,10 @@ redisplay_window (window, just_this_one_p)
       goto recenter;
     }
   
-  /* Try scrolling with try_window_id.  */
-  else if (/* Windows and buffers haven't changed.  */
-          !windows_or_buffers_changed
-          /* Window must be either use window-based redisplay or
-             be full width.  */
-          && (FRAME_WINDOW_P (f)
-              || (line_ins_del_ok && WINDOW_FULL_WIDTH_P (w)))
-          && !MINI_WINDOW_P (w)
-          /* Point is not known NOT to appear in window.  */
-          && PT >= CHARPOS (startp)
-          && XFASTINT (w->last_modified)
-          /* Window is not hscrolled.  */
-          && XFASTINT (w->hscroll) == 0
-          /* Selective display has not changed.  */
-          && !current_buffer->clip_changed
-          /* Current matrix is up to date.  */
-          && !NILP (w->window_end_valid)
-          /* Can't use this case if highlighting a region because
-             a cursor movement will do more than just set the cursor.  */
-          && !(!NILP (Vtransient_mark_mode)
-               && !NILP (current_buffer->mark_active))
-          && NILP (w->region_showing)
-          && NILP (Vshow_trailing_whitespace)
-          /* Overlay arrow position and string not changed.  */
-          && EQ (last_arrow_position, COERCE_MARKER (Voverlay_arrow_position))
-          && EQ (last_arrow_string, Voverlay_arrow_string)
-          /* Value is > 0 if update has been done, it is -1 if we
-             know that the same window start will not work.  It is 0
-             if unsuccessful for some other reason.  */
-          && (tem = try_window_id (w)) != 0)
+  /* Try scrolling with try_window_id.  Value is > 0 if update has
+     been done, it is -1 if we know that the same window start will
+     not work.  It is 0 if unsuccessful for some other reason.  */
+  else if ((tem = try_window_id (w)) != 0)
     {
 #if GLYPH_DEBUG
       debug_method_add (w, "try_window_id %d", tem);
@@ -9698,8 +10111,8 @@ redisplay_window (window, just_this_one_p)
 
  try_to_scroll:
 
-  XSETFASTINT (w->last_modified, 0);
-  XSETFASTINT (w->last_overlay_modified, 0);
+  w->last_modified = make_number (0);
+  w->last_overlay_modified = make_number (0);
 
   /* Redisplay the mode line.  Select the buffer properly for that.  */
   if (!update_mode_line)
@@ -9748,7 +10161,7 @@ redisplay_window (window, just_this_one_p)
   /* Move backward half the height of the window.  */
   init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID);
   it.current_y = it.last_visible_y;
-  move_it_vertically_backward (&it, it.last_visible_y / 2);
+  move_it_vertically_backward (&it, window_box_height (w) / 2);
   xassert (IT_CHARPOS (it) >= BEGV);
 
   /* The function move_it_vertically_backward may move over more
@@ -10018,18 +10431,17 @@ try_window (window, pos)
       xassert (MATRIX_ROW_DISPLAYS_TEXT_P (last_text_row));
       w->window_end_bytepos
        = Z_BYTE - MATRIX_ROW_END_BYTEPOS (last_text_row);
-      XSETFASTINT (w->window_end_pos,
-                  Z - MATRIX_ROW_END_CHARPOS (last_text_row));
-      XSETFASTINT (w->window_end_vpos,
-                  MATRIX_ROW_VPOS (last_text_row, w->desired_matrix));
+      w->window_end_pos
+       = make_number (Z - MATRIX_ROW_END_CHARPOS (last_text_row));
+      w->window_end_vpos
+       = make_number (MATRIX_ROW_VPOS (last_text_row, w->desired_matrix));
       xassert (MATRIX_ROW (w->desired_matrix, XFASTINT (w->window_end_vpos))
               ->displays_text_p);
     }
   else
     {
       w->window_end_bytepos = 0;
-      XSETFASTINT (w->window_end_pos, 0);
-      XSETFASTINT (w->window_end_vpos, 0);
+      w->window_end_pos = w->window_end_vpos = make_number (0);
     }
   
   /* But that is not valid info until redisplay finishes.  */
@@ -10101,6 +10513,13 @@ try_window_reusing_current_matrix (w)
     {
       int first_row_y;
       
+      /* Don't use this method if the display starts with an ellipsis
+        displayed for invisible text.  It's not easy to handle that case
+        below, and it's certainly not worth the effort since this is
+        not a frequent case.  */
+      if (in_ellipses_for_invisible_text_p (&start_row->start, w))
+       return 0;
+
       IF_DEBUG (debug_method_add (w, "twu1"));
       
       /* Display up to a row that can be reused.  The variable
@@ -10185,10 +10604,10 @@ try_window_reusing_current_matrix (w)
                         MATRIX_ROW_VPOS (bottom_row, w->current_matrix),
                         nrows_scrolled);
          
-         /* Disable lines not reused.  */
+         /* Disable lines that must be updated.  */
          for (i = 0; i < it.vpos; ++i)
            (start_row + i)->enabled_p = 0;
-         
+
          /* Re-compute Y positions.  */
          min_y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
          max_y = it.last_visible_y;
@@ -10213,6 +10632,11 @@ try_window_reusing_current_matrix (w)
              if (MATRIX_ROW_BOTTOM_Y (row) >= it.last_visible_y)
                break;
            }
+         
+         /* Disable lines in the current matrix which are now
+            below the window.  */
+         for (++row; row < bottom_row; ++row)
+           row->enabled_p = 0;
        }
 
       /* Update window_end_pos etc.; last_reused_text_row is the last
@@ -10223,27 +10647,26 @@ try_window_reusing_current_matrix (w)
        {
          w->window_end_bytepos
            = Z_BYTE - MATRIX_ROW_END_BYTEPOS (last_reused_text_row);
-         XSETFASTINT (w->window_end_pos,
-                      Z - MATRIX_ROW_END_CHARPOS (last_reused_text_row));
-         XSETFASTINT (w->window_end_vpos,
-                      MATRIX_ROW_VPOS (last_reused_text_row,
-                                       w->current_matrix));
+         w->window_end_pos
+           = make_number (Z - MATRIX_ROW_END_CHARPOS (last_reused_text_row));
+         w->window_end_vpos
+           = make_number (MATRIX_ROW_VPOS (last_reused_text_row,
+                                           w->current_matrix));
        }
       else if (last_text_row)
        {
          w->window_end_bytepos
            = Z_BYTE - MATRIX_ROW_END_BYTEPOS (last_text_row);
-         XSETFASTINT (w->window_end_pos,
-                      Z - MATRIX_ROW_END_CHARPOS (last_text_row));
-         XSETFASTINT (w->window_end_vpos,
-                      MATRIX_ROW_VPOS (last_text_row, w->desired_matrix));
+         w->window_end_pos
+           = make_number (Z - MATRIX_ROW_END_CHARPOS (last_text_row));
+         w->window_end_vpos
+           = make_number (MATRIX_ROW_VPOS (last_text_row, w->desired_matrix));
        }
       else
        {
          /* This window must be completely empty.  */
          w->window_end_bytepos = 0;
-         XSETFASTINT (w->window_end_pos, 0);
-         XSETFASTINT (w->window_end_vpos, 0);
+         w->window_end_pos = w->window_end_vpos = make_number (0);
        }
       w->window_end_valid = Qnil;
 
@@ -10263,8 +10686,6 @@ try_window_reusing_current_matrix (w)
       int dy;
       int yb = window_text_bottom_y (w);
 
-      IF_DEBUG (debug_method_add (w, "twu2"));
-      
       /* Find the row starting at new_start, if there is one.  Don't
         reuse a partially visible line at the end.  */
       first_reusable_row = start_row;
@@ -10285,20 +10706,20 @@ try_window_reusing_current_matrix (w)
          first_reusable_row to the end of the window.  Set
          first_row_to_display to the first row that cannot be reused.
          Set pt_row to the row containing point, if there is any.  */
-      first_row_to_display = first_reusable_row;
       pt_row = NULL;
-      while (MATRIX_ROW_BOTTOM_Y (first_row_to_display) < yb)
+      for (first_row_to_display = first_reusable_row;
+          MATRIX_ROW_BOTTOM_Y (first_row_to_display) < yb;
+          ++first_row_to_display)
        {
          if (PT >= MATRIX_ROW_START_CHARPOS (first_row_to_display)
              && PT < MATRIX_ROW_END_CHARPOS (first_row_to_display))
            pt_row = first_row_to_display;
-
-         ++first_row_to_display;
        }
 
       /* Start displaying at the start of first_row_to_display.  */
       xassert (first_row_to_display->y < yb);
       init_to_row_start (&it, w, first_row_to_display);
+
       nrows_scrolled = (MATRIX_ROW_VPOS (first_reusable_row, w->current_matrix)
                        - start_vpos);
       it.vpos = (MATRIX_ROW_VPOS (first_row_to_display, w->current_matrix)
@@ -10366,13 +10787,6 @@ try_window_reusing_current_matrix (w)
            row->visible_height = row->height;
        }
 
-      /* Disable rows not reused.  */
-      while (row < bottom_row)
-       {
-         row->enabled_p = 0;
-         ++row;
-       }
-
       /* Scroll the current matrix.  */
       xassert (nrows_scrolled > 0);
       rotate_matrix (w->current_matrix,
@@ -10380,6 +10794,10 @@ try_window_reusing_current_matrix (w)
                     MATRIX_ROW_VPOS (bottom_row, w->current_matrix),
                     -nrows_scrolled);
 
+      /* Disable rows not reused.  */
+      for (row -= nrows_scrolled; row < bottom_row; ++row)
+       row->enabled_p = 0;
+
       /* Adjust window end.  A null value of last_text_row means that
         the window end is in reused rows which in turn means that
         only its vpos can have changed.  */
@@ -10387,15 +10805,15 @@ try_window_reusing_current_matrix (w)
        {
          w->window_end_bytepos
            = Z_BYTE - MATRIX_ROW_END_BYTEPOS (last_text_row);
-         XSETFASTINT (w->window_end_pos,
-                      Z - MATRIX_ROW_END_CHARPOS (last_text_row));
-         XSETFASTINT (w->window_end_vpos,
-                      MATRIX_ROW_VPOS (last_text_row, w->desired_matrix));
+         w->window_end_pos
+           = make_number (Z - MATRIX_ROW_END_CHARPOS (last_text_row));
+         w->window_end_vpos
+           = make_number (MATRIX_ROW_VPOS (last_text_row, w->desired_matrix));
        }
       else
        {
-         XSETFASTINT (w->window_end_vpos,
-                      XFASTINT (w->window_end_vpos) - nrows_scrolled);
+         w->window_end_vpos
+           = make_number (XFASTINT (w->window_end_vpos) - nrows_scrolled);
        }
       
       w->window_end_valid = Qnil;
@@ -10456,15 +10874,14 @@ find_last_row_displaying_text (matrix, it, start)
 
 
 /* Return the last row in the current matrix of W that is not affected
-   by changes at the start of current_buffer that occurred since the
-   last time W was redisplayed.  Value is null if no such row exists.
+   by changes at the start of current_buffer that occurred since W's
+   current matrix was built.  Value is null if no such row exists.
 
-   The global variable beg_unchanged has to contain the number of
-   bytes unchanged at the start of current_buffer.  BEG +
-   beg_unchanged is the buffer position of the first changed byte in
-   current_buffer.  Characters at positions < BEG + beg_unchanged are
-   at the same buffer positions as they were when the current matrix
-   was built.  */
+   BEG_UNCHANGED us the number of characters unchanged at the start of
+   current_buffer.  BEG + BEG_UNCHANGED is the buffer position of the
+   first changed character in current_buffer.  Characters at positions <
+   BEG + BEG_UNCHANGED are at the same buffer positions as they were
+   when the current matrix was built.  */
 
 static struct glyph_row *
 find_last_unchanged_at_beg_row (w)
@@ -10505,12 +10922,16 @@ find_last_unchanged_at_beg_row (w)
 
 
 /* Find the first glyph row in the current matrix of W that is not
-   affected by changes at the end of current_buffer since the last
-   time the window was redisplayed.  Return in *DELTA the number of
-   chars by which buffer positions in unchanged text at the end of
-   current_buffer must be adjusted.  Return in *DELTA_BYTES the
-   corresponding number of bytes.  Value is null if no such row
-   exists, i.e. all rows are affected by changes.  */
+   affected by changes at the end of current_buffer since the 
+   time W's current matrix was built.
+
+   Return in *DELTA the number of chars by which buffer positions in
+   unchanged text at the end of current_buffer must be adjusted.
+   
+   Return in *DELTA_BYTES the corresponding number of bytes.
+
+   Value is null if no such row exists, i.e. all rows are affected by
+   changes.  */
    
 static struct glyph_row *
 find_first_unchanged_at_end_row (w, delta, delta_bytes)
@@ -10555,8 +10976,8 @@ find_first_unchanged_at_end_row (w, delta, delta_bytes)
 
       /* Set last_unchanged_pos to the buffer position of the last
         character in the buffer that has not been changed.  Z is the
-        index + 1 of the last byte in current_buffer, i.e. by
-        subtracting end_unchanged we get the index of the last
+        index + 1 of the last character in current_buffer, i.e. by
+        subtracting END_UNCHANGED we get the index of the last
         unchanged character, and we have to add BEG to get its buffer
         position.  */
       last_unchanged_pos = Z - END_UNCHANGED + BEG;
@@ -10703,8 +11124,6 @@ row_containing_pos (w, charpos, start, end)
 
    7. Update W's window end information.  */
 
-  /* Check that window end is what we expect it to be.  */
-
 static int
 try_window_id (w)
      struct window *w;
@@ -10724,15 +11143,78 @@ try_window_id (w)
   int first_unchanged_at_end_vpos = 0;
   struct glyph_row *last_text_row, *last_text_row_at_end;
   struct text_pos start;
+  int first_changed_charpos, last_changed_charpos;
 
+  /* This is handy for debugging.  */
+#if 0
+#define GIVE_UP(X)                                             \
+  do {                                                         \
+    fprintf (stderr, "try_window_id give up %d\n", (X));       \
+    return 0;                                                  \
+  } while (0)
+#else
+#define GIVE_UP(X) return 0
+#endif
+  
   SET_TEXT_POS_FROM_MARKER (start, w->start);
 
-  /* Check pre-conditions.  Window end must be valid, otherwise
-     the current matrix would not be up to date.  */
-  xassert (!NILP (w->window_end_valid));
-  xassert (FRAME_WINDOW_P (XFRAME (w->frame))
-          || (line_ins_del_ok && WINDOW_FULL_WIDTH_P (w)));
+  /* Don't use this for mini-windows because these can show
+     messages and mini-buffers, and we don't handle that here.  */
+  if (MINI_WINDOW_P (w))
+    GIVE_UP (1);
+  
+  /* This flag is used to prevent redisplay optimizations.  */
+  if (windows_or_buffers_changed)
+    GIVE_UP (2);
+  
+  /* Verify that narrowing has not changed.  This flag is also set to prevent
+     redisplay optimizations.  It would be nice to further
+     reduce the number of cases where this prevents try_window_id.  */
+  if (current_buffer->clip_changed)
+    GIVE_UP (3);
+
+  /* Window must either use window-based redisplay or be full width.  */
+  if (!FRAME_WINDOW_P (f)
+      && (!line_ins_del_ok
+         || !WINDOW_FULL_WIDTH_P (w)))
+    GIVE_UP (4);
+
+  /* Give up if point is not known NOT to appear in W.  */
+  if (PT < CHARPOS (start))
+    GIVE_UP (5);
+
+  /* Another way to prevent redisplay optimizations.  */
+  if (XFASTINT (w->last_modified) == 0)
+    GIVE_UP (6);
+  
+  /* Verify that window is not hscrolled.  */
+  if (XFASTINT (w->hscroll) != 0)
+    GIVE_UP (7);
+  
+  /* Verify that display wasn't paused.  */
+  if (NILP (w->window_end_valid))
+    GIVE_UP (8);
+  
+  /* Can't use this if highlighting a region because a cursor movement
+     will do more than just set the cursor.  */
+  if (!NILP (Vtransient_mark_mode)
+      && !NILP (current_buffer->mark_active))
+    GIVE_UP (9);
+
+  /* Likewise if highlighting trailing whitespace.  */
+  if (!NILP (Vshow_trailing_whitespace))
+    GIVE_UP (11);
+  
+  /* Likewise if showing a region.  */
+  if (!NILP (w->region_showing))
+    GIVE_UP (10);
+  
+  /* Can use this if overlay arrow position and or string have changed.  */
+  if (!EQ (last_arrow_position, COERCE_MARKER (Voverlay_arrow_position))
+      || !EQ (last_arrow_string, Voverlay_arrow_string))
+    GIVE_UP (12);
 
+  
   /* Make sure beg_unchanged and end_unchanged are up to date.  Do it
      only if buffer has really changed.  The reason is that the gap is
      initially at Z for freshly visited files.  The code below would
@@ -10747,73 +11229,119 @@ try_window_id (w)
        END_UNCHANGED = Z - GPT;
     }
 
+  /* The position of the first and last character that has been changed.  */
+  first_changed_charpos = BEG + BEG_UNCHANGED;
+  last_changed_charpos  = Z - END_UNCHANGED;
+
   /* If window starts after a line end, and the last change is in
      front of that newline, then changes don't affect the display.
      This case happens with stealth-fontification.  Note that although
      the display is unchanged, glyph positions in the matrix have to
      be adjusted, of course.  */
   row = MATRIX_ROW (w->current_matrix, XFASTINT (w->window_end_vpos));
-  if (CHARPOS (start) > BEGV
-      && Z - END_UNCHANGED < CHARPOS (start) - 1
-      && FETCH_BYTE (BYTEPOS (start) - 1) == '\n'
-      && PT < MATRIX_ROW_END_CHARPOS (row))
+  if (MATRIX_ROW_DISPLAYS_TEXT_P (row)
+      && ((last_changed_charpos < CHARPOS (start)
+          && CHARPOS (start) == BEGV)
+         || (last_changed_charpos < CHARPOS (start) - 1
+             && FETCH_BYTE (BYTEPOS (start) - 1) == '\n')))
+    {
+      int Z_old, delta, Z_BYTE_old, delta_bytes;
+      struct glyph_row *r0;
+
+      /* Compute how many chars/bytes have been added to or removed
+        from the buffer.  */
+      Z_old = MATRIX_ROW_END_CHARPOS (row) + XFASTINT (w->window_end_pos);
+      Z_BYTE_old = MATRIX_ROW_END_BYTEPOS (row) + w->window_end_bytepos;
+      delta = Z - Z_old;
+      delta_bytes = Z_BYTE - Z_BYTE_old;
+         
+      /* Give up if PT is not in the window.  Note that it already has
+        been checked at the start of try_window_id that PT is not in
+        front of the window start.  */
+      if (PT >= MATRIX_ROW_END_CHARPOS (row) + delta)
+       GIVE_UP (13);
+
+      /* If window start is unchanged, we can reuse the whole matrix
+        as is, after adjusting glyph positions.  No need to compute
+        the window end again, since its offset from Z hasn't changed.  */
+      r0 = MATRIX_FIRST_TEXT_ROW (current_matrix);
+      if (CHARPOS (start) == MATRIX_ROW_START_CHARPOS (r0) + delta
+         && BYTEPOS (start) == MATRIX_ROW_START_BYTEPOS (r0) + delta_bytes)
+       {
+         /* Adjust positions in the glyph matrix.  */
+         if (delta || delta_bytes)
+           {
+             struct glyph_row *r1
+               = MATRIX_BOTTOM_TEXT_ROW (current_matrix, w);
+             increment_matrix_positions (w->current_matrix,
+                                         MATRIX_ROW_VPOS (r0, current_matrix),
+                                         MATRIX_ROW_VPOS (r1, current_matrix),
+                                         delta, delta_bytes);
+           }
+      
+         /* Set the cursor.  */
+         row = row_containing_pos (w, PT, r0, NULL);
+         set_cursor_from_row (w, row, current_matrix, 0, 0, 0, 0);
+         return 1;
+       }
+    }
+
+  /* Handle the case that changes are all below what is displayed in
+     the window, and that PT is in the window.  This shortcut cannot
+     be taken if ZV is visible in the window, and text has been added
+     there that is visible in the window.  */
+  if (first_changed_charpos >= MATRIX_ROW_END_CHARPOS (row)
+      /* ZV is not visible in the window, or there are no
+        changes at ZV, actually.  */
+      && (current_matrix->zv > MATRIX_ROW_END_CHARPOS (row)
+         || first_changed_charpos == last_changed_charpos))
     {
-      struct glyph_row *r0 = MATRIX_FIRST_TEXT_ROW (current_matrix);
-      int delta = CHARPOS (start) - MATRIX_ROW_START_CHARPOS (r0);
+      struct glyph_row *r0;
+
+      /* Give up if PT is not in the window.  Note that it already has
+        been checked at the start of try_window_id that PT is not in
+        front of the window start.  */
+      if (PT >= MATRIX_ROW_END_CHARPOS (row))
+       GIVE_UP (14);
 
-      if (delta)
+      /* If window start is unchanged, we can reuse the whole matrix
+        as is, without changing glyph positions since no text has
+        been added/removed in front of the window end.  */
+      r0 = MATRIX_FIRST_TEXT_ROW (current_matrix);
+      if (TEXT_POS_EQUAL_P (start, r0->start.pos))
        {
-         struct glyph_row *r1 = MATRIX_BOTTOM_TEXT_ROW (current_matrix, w);
-         int delta_bytes = BYTEPOS (start) - MATRIX_ROW_START_BYTEPOS (r0);
+         /* We have to compute the window end anew since text
+            can have been added/removed after it.  */
+         w->window_end_pos
+           = make_number (Z - MATRIX_ROW_END_CHARPOS (row));
+         w->window_end_bytepos
+           = Z_BYTE - MATRIX_ROW_END_BYTEPOS (row);
 
-         increment_matrix_positions (w->current_matrix,
-                                     MATRIX_ROW_VPOS (r0, current_matrix),
-                                     MATRIX_ROW_VPOS (r1, current_matrix),
-                                     delta, delta_bytes);
+         /* Set the cursor.  */
+         row = row_containing_pos (w, PT, r0, NULL);
+         set_cursor_from_row (w, row, current_matrix, 0, 0, 0, 0);
+         return 2;
        }
-      
-#if 0  /* If changes are all in front of the window start, the
-         distance of the last displayed glyph from Z hasn't
-         changed.  */
-      w->window_end_pos
-       = make_number (Z - MATRIX_ROW_END_CHARPOS (row));
-      w->window_end_bytepos
-       = Z_BYTE - MATRIX_ROW_END_BYTEPOS (row);
-#endif
-
-      row = row_containing_pos (w, PT, r0, NULL);
-      if (row == NULL)
-       return 0;
-      
-      set_cursor_from_row (w, row, w->current_matrix, 0, 0, 0, 0);
-      return 1;
     }
 
-  /* Return quickly if changes are all below what is displayed in the
-     window, and if PT is in the window.  */
-  if (BEG_UNCHANGED > MATRIX_ROW_END_CHARPOS (row)
-      && PT < MATRIX_ROW_END_CHARPOS (row))
-    {
-      /* We have to update window end positions because the buffer's
-        size has changed.  */
-      w->window_end_pos
-       = make_number (Z - MATRIX_ROW_END_CHARPOS (row));
-      w->window_end_bytepos
-       = Z_BYTE - MATRIX_ROW_END_BYTEPOS (row);
+  /* Give up if window start is in the changed area.
+     
+     The condition used to read
 
-      row = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
-      row = row_containing_pos (w, PT, row, NULL);
-      set_cursor_from_row (w, row, w->current_matrix, 0, 0, 0, 0);
-      return 2;
-    }
+     (BEG_UNCHANGED + END_UNCHANGED != Z - BEG && ...)
 
+     but why that was tested escapes me at the moment.  */
+  if (CHARPOS (start) >= first_changed_charpos
+      && CHARPOS (start) <= last_changed_charpos)
+    GIVE_UP (15);
+  
   /* Check that window start agrees with the start of the first glyph
      row in its current matrix.  Check this after we know the window
      start is not in changed text, otherwise positions would not be
      comparable.  */
-  row = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
+  row = MATRIX_FIRST_TEXT_ROW (current_matrix);
   if (!TEXT_POS_EQUAL_P (start, row->start.pos))
-    return 0;
+    GIVE_UP (16);
 
   /* Compute the position at which we have to start displaying new
      lines.  Some of the lines at the top of the window might be
@@ -10833,7 +11361,7 @@ try_window_id (w)
        --last_unchanged_at_beg_row;
 
       if (MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (last_unchanged_at_beg_row))
-       return 0;
+       GIVE_UP (17);
       
       init_to_row_end (&it, w, last_unchanged_at_beg_row);
       start_pos = it.current.pos;
@@ -10902,7 +11430,7 @@ try_window_id (w)
        }
     }
   else if (last_unchanged_at_beg_row == NULL)
-    return 0;
+    GIVE_UP (18);
 
 
 #if GLYPH_DEBUG
@@ -10921,7 +11449,7 @@ try_window_id (w)
   
 #endif /* GLYPH_DEBUG != 0 */
 
-
+  
   /* Display new lines.  Set last_text_row to the last new line
      displayed which has text on it, i.e. might end up as being the
      line where the window_end_vpos is.  */
@@ -11047,7 +11575,9 @@ try_window_id (w)
          int first_unchanged_at_end_vpos
            = MATRIX_ROW_VPOS (first_unchanged_at_end_row, w->current_matrix);
          int from = XFASTINT (w->top) + first_unchanged_at_end_vpos;
-         int end = XFASTINT (w->top) + window_internal_height (w);
+         int end = (XFASTINT (w->top)
+                    + (WINDOW_WANTS_HEADER_LINE_P (w) ? 1 : 0)
+                    + window_internal_height (w));
          
          /* Perform the operation on the screen.  */
          if (dvpos > 0)
@@ -11194,31 +11724,36 @@ try_window_id (w)
                                           first_unchanged_at_end_row);
       xassert (row && MATRIX_ROW_DISPLAYS_TEXT_P (row));
       
-      XSETFASTINT (w->window_end_pos, Z - MATRIX_ROW_END_CHARPOS (row));
+      w->window_end_pos = make_number (Z - MATRIX_ROW_END_CHARPOS (row));
       w->window_end_bytepos = Z_BYTE - MATRIX_ROW_END_BYTEPOS (row);
-      XSETFASTINT (w->window_end_vpos,
-                  MATRIX_ROW_VPOS (row, w->current_matrix));
+      w->window_end_vpos
+       = make_number (MATRIX_ROW_VPOS (row, w->current_matrix));
+      xassert (w->window_end_bytepos >= 0);
+      IF_DEBUG (debug_method_add (w, "A"));
     }
   else if (last_text_row_at_end)
     {
-      XSETFASTINT (w->window_end_pos,
-                  Z - MATRIX_ROW_END_CHARPOS (last_text_row_at_end));
+      w->window_end_pos
+       = make_number (Z - MATRIX_ROW_END_CHARPOS (last_text_row_at_end));
       w->window_end_bytepos
        = Z_BYTE - MATRIX_ROW_END_BYTEPOS (last_text_row_at_end);
-      XSETFASTINT (w->window_end_vpos,
-                  MATRIX_ROW_VPOS (last_text_row_at_end, desired_matrix));
+      w->window_end_vpos
+       = make_number (MATRIX_ROW_VPOS (last_text_row_at_end, desired_matrix));
+      xassert (w->window_end_bytepos >= 0);
+      IF_DEBUG (debug_method_add (w, "B"));
     }
   else if (last_text_row)
     {
       /* We have displayed either to the end of the window or at the
         end of the window, i.e. the last row with text is to be found
         in the desired matrix.  */
-      XSETFASTINT (w->window_end_pos,
-                  Z - MATRIX_ROW_END_CHARPOS (last_text_row));
+      w->window_end_pos
+       = make_number (Z - MATRIX_ROW_END_CHARPOS (last_text_row));
       w->window_end_bytepos
        = Z_BYTE - MATRIX_ROW_END_BYTEPOS (last_text_row);
-      XSETFASTINT (w->window_end_vpos,
-                  MATRIX_ROW_VPOS (last_text_row, desired_matrix));
+      w->window_end_vpos
+       = make_number (MATRIX_ROW_VPOS (last_text_row, desired_matrix));
+      xassert (w->window_end_bytepos >= 0);
     }
   else if (first_unchanged_at_end_row == NULL
           && last_text_row == NULL
@@ -11226,20 +11761,42 @@ try_window_id (w)
     {
       /* Displayed to end of window, but no line containing text was
         displayed.  Lines were deleted at the end of the window.  */
-      int vpos;
-      int header_line_p = WINDOW_WANTS_HEADER_LINE_P (w) ? 1 : 0;
-
-      for (vpos = XFASTINT (w->window_end_vpos); vpos > 0; --vpos)
-       if ((w->desired_matrix->rows[vpos + header_line_p].enabled_p
-            && w->desired_matrix->rows[vpos + header_line_p].displays_text_p)
-           || (!w->desired_matrix->rows[vpos + header_line_p].enabled_p
-               && w->current_matrix->rows[vpos + header_line_p].displays_text_p))
-         break;
+      int first_vpos = WINDOW_WANTS_HEADER_LINE_P (w) ? 1 : 0;
+      int vpos = XFASTINT (w->window_end_vpos);
+      struct glyph_row *current_row = current_matrix->rows + vpos;
+      struct glyph_row *desired_row = desired_matrix->rows + vpos;
+
+      for (row = NULL;
+          row == NULL && vpos >= first_vpos;
+          --vpos, --current_row, --desired_row)
+       {
+         if (desired_row->enabled_p)
+           {
+             if (desired_row->displays_text_p)
+               row = desired_row;
+           }
+         else if (current_row->displays_text_p)
+           row  = current_row;
+       }
 
-      w->window_end_vpos = make_number (vpos);
+      xassert (row != NULL);
+      w->window_end_vpos = make_number (vpos + 1);
+      w->window_end_pos = make_number (Z - MATRIX_ROW_END_CHARPOS (row));
+      w->window_end_bytepos = Z_BYTE - MATRIX_ROW_END_BYTEPOS (row);
+      xassert (w->window_end_bytepos >= 0);
+      IF_DEBUG (debug_method_add (w, "C"));
     }
   else
     abort ();
+
+#if 0 /* This leads to problems, for instance when the cursor is
+        at ZV, and the cursor line displays no text.  */
+  /* Disable rows below what's displayed in the window.  This makes
+     debugging easier.  */
+  enable_glyph_matrix_rows (current_matrix,
+                           XFASTINT (w->window_end_vpos) + 1,
+                           bottom_vpos, 0);
+#endif
   
   IF_DEBUG (debug_end_pos = XFASTINT (w->window_end_pos);
            debug_end_vpos = XFASTINT (w->window_end_vpos));
@@ -11248,6 +11805,8 @@ try_window_id (w)
   w->window_end_valid = Qnil;
   w->desired_matrix->no_scrolling_p = 1;
   return 3;
+
+#undef GIVE_UP
 }
 
 
@@ -11260,6 +11819,7 @@ try_window_id (w)
 
 void dump_glyph_row P_ ((struct glyph_matrix *, int, int));
 void dump_glyph_matrix P_ ((struct glyph_matrix *, int));
+void dump_glyph P_ ((struct glyph_row *, struct glyph *, int));
 
 
 /* Dump the contents of glyph matrix MATRIX on stderr.
@@ -11279,6 +11839,77 @@ dump_glyph_matrix (matrix, glyphs)
 }
 
 
+/* Dump contents of glyph GLYPH to stderr.  ROW and AREA are
+   the glyph row and area where the glyph comes from.  */
+
+void
+dump_glyph (row, glyph, area)
+     struct glyph_row *row;
+     struct glyph *glyph;
+     int area;
+{
+  if (glyph->type == CHAR_GLYPH)
+    {
+      fprintf (stderr,
+              "  %5d %4c %6d %c %3d 0x%05x %c %4d %1.1d%1.1d\n",
+              glyph - row->glyphs[TEXT_AREA],
+              'C',
+              glyph->charpos,
+              (BUFFERP (glyph->object)
+               ? 'B'
+               : (STRINGP (glyph->object)
+                  ? 'S'
+                  : '-')),
+              glyph->pixel_width,
+              glyph->u.ch,
+              (glyph->u.ch < 0x80 && glyph->u.ch >= ' '
+               ? glyph->u.ch
+               : '.'),
+              glyph->face_id,
+              glyph->left_box_line_p,
+              glyph->right_box_line_p);
+    }
+  else if (glyph->type == STRETCH_GLYPH)
+    {
+      fprintf (stderr,
+              "  %5d %4c %6d %c %3d 0x%05x %c %4d %1.1d%1.1d\n",
+              glyph - row->glyphs[TEXT_AREA],
+              'S',
+              glyph->charpos,
+              (BUFFERP (glyph->object)
+               ? 'B'
+               : (STRINGP (glyph->object)
+                  ? 'S'
+                  : '-')),
+              glyph->pixel_width,
+              0,
+              '.',
+              glyph->face_id,
+              glyph->left_box_line_p,
+              glyph->right_box_line_p);
+    }
+  else if (glyph->type == IMAGE_GLYPH)
+    {
+      fprintf (stderr,
+              "  %5d %4c %6d %c %3d 0x%05x %c %4d %1.1d%1.1d\n",
+              glyph - row->glyphs[TEXT_AREA],
+              'I',
+              glyph->charpos,
+              (BUFFERP (glyph->object)
+               ? 'B'
+               : (STRINGP (glyph->object)
+                  ? 'S'
+                  : '-')),
+              glyph->pixel_width,
+              glyph->u.img_id,
+              '.',
+              glyph->face_id,
+              glyph->left_box_line_p,
+              glyph->right_box_line_p);
+    }
+}
+
+
 /* Dump the contents of glyph row at VPOS in MATRIX to stderr.
    GLYPHS 0 means don't show glyph contents.
    GLYPHS 1 means show glyphs in short form
@@ -11298,11 +11929,11 @@ dump_glyph_row (matrix, vpos, glyphs)
 
   if (glyphs != 1)
     {
-      fprintf (stderr, "Row Start   End Used oEI><O\\CTZFes     X    Y    W    H    V    A    P\n");
+      fprintf (stderr, "Row Start   End Used oEI><O\\CTZFesm     X    Y    W    H    V    A    P\n");
       fprintf (stderr, "=======================================================================\n");
   
       fprintf (stderr, "%3d %5d %5d %4d %1.1d%1.1d%1.1d%1.1d%1.1d%1.1d\
-%1.1d%1.1d%1.1d%1.1d%1.1d%1.1d%1.1d %4d %4d %4d %4d %4d %4d %4d\n",
+%1.1d%1.1d%1.1d%1.1d%1.1d%1.1d%1.1d%1.1d  %4d %4d %4d %4d %4d %4d %4d\n",
               row - matrix->rows,
               MATRIX_ROW_START_CHARPOS (row),
               MATRIX_ROW_END_CHARPOS (row),
@@ -11320,6 +11951,7 @@ dump_glyph_row (matrix, vpos, glyphs)
               row->fill_line_p,
               row->ends_in_middle_of_char_p,
               row->starts_in_middle_of_char_p,
+              row->mouse_face_p,
               row->x,
               row->y,
               row->pixel_width,
@@ -11327,8 +11959,9 @@ dump_glyph_row (matrix, vpos, glyphs)
               row->visible_height,
               row->ascent,
               row->phys_ascent);
-      fprintf (stderr, "%9d %5d\n", row->start.overlay_string_index,
-              row->end.overlay_string_index);
+      fprintf (stderr, "%9d %5d\t%5d\n", row->start.overlay_string_index,
+              row->end.overlay_string_index,
+              row->continuation_lines_width);
       fprintf (stderr, "%9d %5d\n",
               CHARPOS (row->start.string_pos),
               CHARPOS (row->end.string_pos));
@@ -11338,106 +11971,47 @@ dump_glyph_row (matrix, vpos, glyphs)
   
   if (glyphs > 1)
     {
-      struct glyph *glyph, *glyph_end;
-      int prev_had_glyphs_p;
-      
-      glyph = row->glyphs[TEXT_AREA];
-      glyph_end = glyph + row->used[TEXT_AREA];
+      int area;
+
+      for (area = LEFT_MARGIN_AREA; area < LAST_AREA; ++area)
+       {
+         struct glyph *glyph = row->glyphs[area];
+         struct glyph *glyph_end = glyph + row->used[area];
       
-      /* Glyph for a line end in text.  */
-      if (glyph == glyph_end && glyph->charpos > 0)
-       ++glyph_end;
+         /* Glyph for a line end in text.  */
+         if (area == TEXT_AREA && glyph == glyph_end && glyph->charpos > 0)
+           ++glyph_end;
       
-      if (glyph < glyph_end)
-       {
-         fprintf (stderr, "  Glyph    Type Pos   O W    Code C Face LR\n");
-         prev_had_glyphs_p = 1;
-       }
-      else
-       prev_had_glyphs_p = 0;
+         if (glyph < glyph_end)
+           fprintf (stderr, "  Glyph    Type Pos   O W    Code C Face LR\n");
       
-      while (glyph < glyph_end)
-       {
-         if (glyph->type == CHAR_GLYPH)
-           {
-             fprintf (stderr,
-                      "  %5d %4c %6d %c %3d 0x%05x %c %4d %1.1d%1.1d\n",
-                      glyph - row->glyphs[TEXT_AREA],
-                      'C',
-                      glyph->charpos,
-                      (BUFFERP (glyph->object)
-                       ? 'B'
-                       : (STRINGP (glyph->object)
-                          ? 'S'
-                          : '-')),
-                      glyph->pixel_width,
-                      glyph->u.ch,
-                      (glyph->u.ch < 0x80 && glyph->u.ch >= ' '
-                       ? glyph->u.ch
-                       : '.'),
-                      glyph->face_id,
-                      glyph->left_box_line_p,
-                      glyph->right_box_line_p);
-           }
-         else if (glyph->type == STRETCH_GLYPH)
-           {
-             fprintf (stderr,
-                      "  %5d %4c %6d %c %3d 0x%05x %c %4d %1.1d%1.1d\n",
-                      glyph - row->glyphs[TEXT_AREA],
-                      'S',
-                      glyph->charpos,
-                      (BUFFERP (glyph->object)
-                       ? 'B'
-                       : (STRINGP (glyph->object)
-                          ? 'S'
-                          : '-')),
-                      glyph->pixel_width,
-                      0,
-                      '.',
-                      glyph->face_id,
-                      glyph->left_box_line_p,
-                      glyph->right_box_line_p);
-           }
-         else if (glyph->type == IMAGE_GLYPH)
-           {
-             fprintf (stderr,
-                      "  %5d %4c %6d %c %3d 0x%05x %c %4d %1.1d%1.1d\n",
-                      glyph - row->glyphs[TEXT_AREA],
-                      'I',
-                      glyph->charpos,
-                      (BUFFERP (glyph->object)
-                       ? 'B'
-                       : (STRINGP (glyph->object)
-                          ? 'S'
-                          : '-')),
-                      glyph->pixel_width,
-                      glyph->u.img_id,
-                      '.',
-                      glyph->face_id,
-                      glyph->left_box_line_p,
-                      glyph->right_box_line_p);
-           }
-         ++glyph;
+         for (; glyph < glyph_end; ++glyph)
+           dump_glyph (row, glyph, area);
        }
     }
   else if (glyphs == 1)
     {
-      char *s = (char *) alloca (row->used[TEXT_AREA] + 1);
-      int i;
+      int area;
 
-      for (i = 0; i < row->used[TEXT_AREA]; ++i)
+      for (area = LEFT_MARGIN_AREA; area < LAST_AREA; ++area)
        {
-         struct glyph *glyph = row->glyphs[TEXT_AREA] + i;
-         if (glyph->type == CHAR_GLYPH
-             && glyph->u.ch < 0x80
-             && glyph->u.ch >= ' ')
-           s[i] = glyph->u.ch;
-         else
-           s[i] = '.';
-       }
+         char *s = (char *) alloca (row->used[area] + 1);
+         int i;
+
+         for (i = 0; i < row->used[area]; ++i)
+           {
+             struct glyph *glyph = row->glyphs[area] + i;
+             if (glyph->type == CHAR_GLYPH
+                 && glyph->u.ch < 0x80
+                 && glyph->u.ch >= ' ')
+               s[i] = glyph->u.ch;
+             else
+               s[i] = '.';
+           }
       
-      s[i] = '\0';
-      fprintf (stderr, "%3d: (%d) '%s'\n", vpos, row->enabled_p, s);
+         s[i] = '\0';
+         fprintf (stderr, "%3d: (%d) '%s'\n", vpos, row->enabled_p, s);
+       }
     }
 }
 
@@ -11481,24 +12055,35 @@ GLYPH > 1 or omitted means dump glyphs in long form.")
 }
 
 
-DEFUN ("dump-tool-bar-row", Fdump_tool_bar_row, Sdump_tool_bar_row,
-       0, 0, "", "")
-  ()
+DEFUN ("dump-tool-bar-row", Fdump_tool_bar_row, Sdump_tool_bar_row, 1, 2, "",
+  "Dump glyph row ROW of the tool-bar of the current frame to stderr.\n\
+GLYPH 0 means don't dump glyphs.\n\
+GLYPH 1 means dump glyphs in short form.\n\
+GLYPH > 1 or omitted means dump glyphs in long form.")
+  (row, glyphs)
+     Lisp_Object row, glyphs;
 {
   struct frame *sf = SELECTED_FRAME ();
-  struct glyph_matrix *m = (XWINDOW (sf->tool_bar_window)
-                           ->current_matrix);
-  dump_glyph_row (m, 0, 1);
+  struct glyph_matrix *m = (XWINDOW (sf->tool_bar_window)->current_matrix);
+  dump_glyph_row (m, XINT (row), INTEGERP (glyphs) ? XINT (glyphs) : 2);
   return Qnil;
 }
 
 
-DEFUN ("trace-redisplay-toggle", Ftrace_redisplay_toggle,
-       Strace_redisplay_toggle, 0, 0, "",
-  "Toggle tracing of redisplay.")
-     ()
+DEFUN ("trace-redisplay", Ftrace_redisplay, Strace_redisplay, 0, 1, "P",
+  "Toggle tracing of redisplay.\n\
+With ARG, turn tracing on if and only if ARG is positive.")
+  (arg)
+     Lisp_Object arg;
 {
-  trace_redisplay_p = !trace_redisplay_p;
+  if (NILP (arg))
+    trace_redisplay_p = !trace_redisplay_p;
+  else
+    {
+      arg = Fprefix_numeric_value (arg);
+      trace_redisplay_p = XINT (arg) > 0;
+    }
+  
   return Qnil;
 }
 
@@ -11558,7 +12143,7 @@ get_overlay_arrow_glyph_row (w)
       p += it.len;
       
       /* Get its face.  */
-      XSETFASTINT (ilisp, p - arrow_string);
+      ilisp = make_number (p - arrow_string);
       face = Fget_text_property (ilisp, Qface, Voverlay_arrow_string);
       it.face_id = compute_char_face (f, it.c, face);
 
@@ -11615,14 +12200,16 @@ insert_left_trunc_glyphs (it)
   while (from < end)
     *to++ = *from++;
 
-  /* There may be padding glyphs left over.  Remove them.  */
-  from = to;
-  while (from < toend && CHAR_GLYPH_PADDING_P (*from))
-    ++from;
-  while (from < toend)
-    *to++ = *from++;
+  /* There may be padding glyphs left over.  Overwrite them too.  */
+  while (to < toend && CHAR_GLYPH_PADDING_P (*to))
+    {
+      from = truncate_it.glyph_row->glyphs[TEXT_AREA];
+      while (from < end)
+       *to++ = *from++;
+    }
 
-  it->glyph_row->used[TEXT_AREA] = to - it->glyph_row->glyphs[TEXT_AREA];
+  if (to > toend)
+    it->glyph_row->used[TEXT_AREA] = to - it->glyph_row->glyphs[TEXT_AREA];
 }
 
 
@@ -11704,6 +12291,10 @@ compute_line_metrics (it)
   else
     {
       row->pixel_width = row->used[TEXT_AREA];
+      if (row->continued_p)
+       row->pixel_width -= it->continuation_pixel_width;
+      else if (row->truncated_on_right_p)
+       row->pixel_width -= it->truncation_pixel_width;
       row->ascent = row->phys_ascent = 0;
       row->height = row->phys_height = row->visible_height = 1;
     }
@@ -11752,7 +12343,7 @@ append_space (it, default_face_p)
             Must save IT->c and IT->len because otherwise
             ITERATOR_AT_END_P wouldn't work anymore after
             append_space has been called.  */
-         int saved_what = it->what;
+         enum display_element_type saved_what = it->what;
          int saved_c = it->c, saved_len = it->len;
          int saved_x = it->current_x;
          int saved_face_id = it->face_id;
@@ -11853,7 +12444,7 @@ extend_face_to_end_of_line (it)
       int saved_x = it->current_x;
       struct text_pos saved_pos;
       Lisp_Object saved_object;
-      int saved_what = it->what;
+      enum display_element_type saved_what = it->what;
       int saved_face_id = it->face_id;
 
       saved_object = it->object;
@@ -11920,11 +12511,13 @@ highlight_trailing_whitespace (f, row)
       struct glyph *start = row->glyphs[TEXT_AREA];
       struct glyph *glyph = start + used - 1;
 
-      /* Skip over the space glyph inserted to display the
-        cursor at the end of a line.  */
-      if (glyph->type == CHAR_GLYPH
-         && glyph->u.ch == ' '
-         && INTEGERP (glyph->object))
+      /* Skip over glyphs inserted to display the cursor at the
+        end of a line, for extending the face of the last glyph
+        to the end of the line on terminals, and for truncation
+        and continuation glyphs.  */
+      while (glyph >= start
+            && glyph->type == CHAR_GLYPH
+            && INTEGERP (glyph->object))
        --glyph;
 
       /* If last glyph is a space or stretch, and it's trailing
@@ -12107,11 +12700,13 @@ display_line (it)
       nglyphs = row->used[TEXT_AREA] - n_glyphs_before;
       hpos_before = it->hpos;
       x_before = x;
-         
-      if (nglyphs == 1
+
+      if (/* Not a newline. */
+         nglyphs > 0
+         /* Glyphs produced fit entirely in the line.  */
          && it->current_x < it->last_visible_x)
        {
-         ++it->hpos;
+         it->hpos += nglyphs;
          row->ascent = max (row->ascent, it->max_ascent);
          row->height = max (row->height, it->max_ascent + it->max_descent);
          row->phys_ascent = max (row->phys_ascent, it->max_phys_ascent);
@@ -12281,8 +12876,17 @@ display_line (it)
          /* Maybe add truncation glyphs.  */
          if (!FRAME_WINDOW_P (it->f))
            {
-             --it->glyph_row->used[TEXT_AREA];
-             produce_special_glyphs (it, IT_TRUNCATION);
+             int i, n;
+             
+             for (i = row->used[TEXT_AREA] - 1; i > 0; --i)
+               if (!CHAR_GLYPH_PADDING_P (row->glyphs[TEXT_AREA][i]))
+                 break;
+
+             for (n = row->used[TEXT_AREA]; i < n; ++i)
+               {
+                 row->used[TEXT_AREA] = i;
+                 produce_special_glyphs (it, IT_TRUNCATION);
+               }
            }
          
          row->truncated_on_right_p = 1;
@@ -12462,12 +13066,12 @@ display_menu_bar (w)
       Lisp_Object string;
 
       /* Stop at nil string.  */
-      string = XVECTOR (items)->contents[i + 1];
+      string = AREF (items, i + 1);
       if (NILP (string))
        break;
 
       /* Remember where item was displayed.  */
-      XSETFASTINT (XVECTOR (items)->contents[i + 3], it.hpos);
+      AREF (items, i + 3) = make_number (it.hpos);
 
       /* Display the item, pad with one space.  */
       if (it.current_x < it.last_visible_x)
@@ -12700,12 +13304,13 @@ display_mode_element (it, depth, field_width, precision, elt)
                /* Output to end of string or up to '%'.  Field width
                   is length of string.  Don't output more than
                   PRECISION allows us.  */
-               prec = --this - last;
+               --this;
+               prec = strwidth (last, this - last);
                if (precision > 0 && prec > precision - n)
                  prec = precision - n;
                
                if (frame_title_ptr)
-                 n += store_frame_title (last, prec, prec);
+                 n += store_frame_title (last, 0, prec);
                else
                  n += display_string (NULL, elt, Qnil, 0, last - lisp_string,
                                       it, 0, prec, 0, -1);
@@ -12787,9 +13392,7 @@ display_mode_element (it, depth, field_width, precision, elt)
               don't check for % within it.  */
            if (STRINGP (tem))
              {
-               prec = XSTRING (tem)->size;
-               if (precision > 0 && prec > precision - n)
-                 prec = precision - n;
+               prec = precision - n;
                if (frame_title_ptr)
                  n += store_frame_title (XSTRING (tem)->data, -1, prec);
                else
@@ -12996,7 +13599,7 @@ decode_mode_spec_coding (coding_system, buf, eol_flag)
       eolvalue = Fget (coding_system, Qeol_type);
 
       if (multibyte)
-       *buf++ = XFASTINT (XVECTOR (val)->contents[1]);
+       *buf++ = XFASTINT (AREF (val, 1));
 
       if (eol_flag)
        {
@@ -13138,7 +13741,7 @@ decode_mode_spec (w, c, field_width, precision)
     case 'c':
       {
        int col = current_column ();
-       XSETFASTINT (w->column_number_displayed, col);
+       w->column_number_displayed = make_number (col);
        pint2str (decode_mode_spec_buf, field_width, col);
        return decode_mode_spec_buf;
       }
@@ -13208,8 +13811,8 @@ decode_mode_spec (w, c, field_width, precision)
           go back past it.  */
        if (startpos == BUF_BEGV (b))
          {
-           XSETFASTINT (w->base_line_number, topline);
-           XSETFASTINT (w->base_line_pos, BUF_BEGV (b));
+           w->base_line_number = make_number (topline);
+           w->base_line_pos = make_number (BUF_BEGV (b));
          }
        else if (nlines < height + 25 || nlines > height * 3 + 50
                 || linepos == BUF_BEGV (b))
@@ -13239,8 +13842,8 @@ decode_mode_spec (w, c, field_width, precision)
                goto no_value;
              }
 
-           XSETFASTINT (w->base_line_number, topline - nlines);
-           XSETFASTINT (w->base_line_pos, BYTE_TO_CHAR (position));
+           w->base_line_number = make_number (topline - nlines);
+           w->base_line_pos = make_number (BYTE_TO_CHAR (position));
          }
 
        /* Now count lines from the start pos to point.  */
@@ -13560,9 +14163,7 @@ display_string (string, lisp_string, face_string, face_string_pos,
   struct glyph_row *row = it->glyph_row;
 
   /* Initialize the iterator IT for iteration over STRING beginning
-     with index START.  We assume that IT may be modified here (which
-     means that display_line has to do something when displaying a
-     mini-buffer prompt, which it does).  */
+     with index START.  */
   reseat_to_string (it, string, lisp_string, start,
                    precision, field_width, multibyte);
 
@@ -13577,7 +14178,7 @@ display_string (string, lisp_string, face_string, face_string_pos,
        = face_at_string_position (it->w, face_string, face_string_pos,
                                   0, it->region_beg_charpos,
                                   it->region_end_charpos,
-                                  &endptr, it->base_face_id);
+                                  &endptr, it->base_face_id, 0);
       face = FACE_FROM_ID (it->f, it->face_id);
       it->face_box_p = face->box != FACE_NO_BOX;
     }
@@ -13626,8 +14227,17 @@ display_string (string, lisp_string, face_string, face_string_pos,
              && x + glyph->pixel_width > max_x)
            {
              /* End of continued line or max_x reached.  */
-             it->glyph_row->used[TEXT_AREA] = n_glyphs_before + i;
-             it->current_x = x;
+             if (CHAR_GLYPH_PADDING_P (*glyph))
+               {
+                 /* A wide character is unbreakable.  */
+                 it->glyph_row->used[TEXT_AREA] = n_glyphs_before;
+                 it->current_x = x_before;
+               }
+             else
+               {
+                 it->glyph_row->used[TEXT_AREA] = n_glyphs_before + i;
+                 it->current_x = x;
+               }
              break;
            }
          else if (x + glyph->pixel_width > it->first_visible_x)
@@ -13675,7 +14285,22 @@ display_string (string, lisp_string, face_string, face_string_pos,
          if (IT_CHARPOS (*it) < it->string_nchars)
            {
              if (!FRAME_WINDOW_P (it->f))
-               produce_special_glyphs (it, IT_TRUNCATION);
+               {
+                 int i, n;
+
+                 if (it->current_x > it->last_visible_x)
+                   {
+                     for (i = row->used[TEXT_AREA] - 1; i > 0; --i)
+                       if (!CHAR_GLYPH_PADDING_P (row->glyphs[TEXT_AREA][i]))
+                         break;
+                     for (n = row->used[TEXT_AREA]; i < n; ++i)
+                       {
+                         row->used[TEXT_AREA] = i;
+                         produce_special_glyphs (it, IT_TRUNCATION);
+                       }
+                   }
+                 produce_special_glyphs (it, IT_TRUNCATION);
+               }
              it->glyph_row->truncated_on_right_p = 1;
            }
          break;
@@ -13804,9 +14429,12 @@ syms_of_xdisp ()
   defsubr (&Sdump_glyph_matrix);
   defsubr (&Sdump_glyph_row);
   defsubr (&Sdump_tool_bar_row);
-  defsubr (&Strace_redisplay_toggle);
+  defsubr (&Strace_redisplay);
   defsubr (&Strace_to_stderr);
 #endif
+#ifdef HAVE_WINDOW_SYSTEM
+  defsubr (&Stool_bar_lines_needed);
+#endif
 
   staticpro (&Qmenu_bar_update_hook);
   Qmenu_bar_update_hook = intern ("menu-bar-update-hook");
@@ -13870,6 +14498,10 @@ syms_of_xdisp ()
   staticpro (&Qmessage_truncate_lines);
   Qgrow_only = intern ("grow-only");
   staticpro (&Qgrow_only);
+  Qinhibit_menubar_update = intern ("inhibit-menubar-update");
+  staticpro (&Qinhibit_menubar_update);
+  Qinhibit_eval_during_redisplay = intern ("inhibit-eval-during-redisplay");
+  staticpro (&Qinhibit_eval_during_redisplay);
 
   last_arrow_position = Qnil;
   last_arrow_string = Qnil;
@@ -13997,7 +14629,7 @@ and is used only on frames for which no explicit name has been set\n\
     "Maximum number of lines to keep in the message log buffer.\n\
 If nil, disable message logging.  If t, log messages but don't truncate\n\
 the buffer when it becomes large.");
-  XSETFASTINT (Vmessage_log_max, 50);
+  Vmessage_log_max = make_number (50);
 
   DEFVAR_LISP ("window-size-change-functions", &Vwindow_size_change_functions,
     "Functions called before redisplay, if window sizes have changed.\n\
@@ -14025,13 +14657,17 @@ otherwise.");
     "*Non-nil means raise tool-bar buttons when the mouse moves over them.");
   auto_raise_tool_bar_buttons_p = 1;
 
-  DEFVAR_INT ("tool-bar-button-margin", &tool_bar_button_margin,
-    "*Margin around tool-bar buttons in pixels.");
-  tool_bar_button_margin = 1;
+  DEFVAR_LISP ("tool-bar-button-margin", &Vtool_bar_button_margin,
+    "*Margin around tool-bar buttons in pixels.\n\
+If an integer, use that for both horizontal and vertical margins.\n\
+Otherwise, value should be a pair of integers `(HORZ : VERT)' with\n\
+HORZ specifying the horizontal margin, and VERT specifying the\n\
+vertical margin.");
+  Vtool_bar_button_margin = make_number (DEFAULT_TOOL_BAR_BUTTON_MARGIN);
 
   DEFVAR_INT ("tool-bar-button-relief", &tool_bar_button_relief,
     "Relief thickness of tool-bar buttons.");
-  tool_bar_button_relief = 3;
+  tool_bar_button_relief = DEFAULT_TOOL_BAR_BUTTON_RELIEF;
 
   DEFVAR_LISP ("fontification-functions", &Vfontification_functions,
     "List of functions to call to fontify regions of text.\n\
@@ -14090,6 +14726,14 @@ Bind this around calls to `message' to let it take effect.");
     "Normal hook run for clicks on menu bar, before displaying a submenu.\n\
 Can be used to update submenus whose contents should vary.");
   Vmenu_bar_update_hook = Qnil;
+  
+  DEFVAR_BOOL ("inhibit-menubar-update", &inhibit_menubar_update,
+    "Non-nil means don't update menu bars.  Internal use only.");
+  inhibit_menubar_update = 0;
+
+  DEFVAR_BOOL ("inhibit-eval-during-redisplay", &inhibit_eval_during_redisplay,
+    "Non-nil means don't eval Lisp during redisplay.");
+  inhibit_eval_during_redisplay = 0;
 }
 
 
@@ -14113,15 +14757,15 @@ init_xdisp ()
       struct frame *f = XFRAME (WINDOW_FRAME (XWINDOW (root_window)));
       int i;
 
-      XSETFASTINT (XWINDOW (root_window)->top, FRAME_TOP_MARGIN (f));
+      XWINDOW (root_window)->top = make_number (FRAME_TOP_MARGIN (f));
       set_window_height (root_window,
                         FRAME_HEIGHT (f) - 1 - FRAME_TOP_MARGIN (f),
                         0);
-      XSETFASTINT (mini_w->top, FRAME_HEIGHT (f) - 1);
+      mini_w->top = make_number (FRAME_HEIGHT (f) - 1);
       set_window_height (minibuf_window, 1, 0);
 
-      XSETFASTINT (XWINDOW (root_window)->width, FRAME_WIDTH (f));
-      XSETFASTINT (mini_w->width, FRAME_WIDTH (f));
+      XWINDOW (root_window)->width = make_number (FRAME_WIDTH (f));
+      mini_w->width = make_number (FRAME_WIDTH (f));
 
       scratch_glyph_row.glyphs[TEXT_AREA] = scratch_glyphs;
       scratch_glyph_row.glyphs[TEXT_AREA + 1]
@@ -14129,7 +14773,7 @@ init_xdisp ()
 
       /* The default ellipsis glyphs `...'.  */ 
       for (i = 0; i < 3; ++i)
-       XSETFASTINT (default_invis_vector[i], '.');
+       default_invis_vector[i] = make_number ('.');
     }
 
 #ifdef HAVE_WINDOW_SYSTEM