]> code.delx.au - gnu-emacs/blobdiff - src/xdisp.c
Include fontset.h dependent on HAVE_WINDOW_SYSTEM, not HAVE_X_WINDOWS.
[gnu-emacs] / src / xdisp.c
index ed5b22c879737da0ffffca4a078505cb23fbcfee..7b6eb35fcdcd872f147dc618ecb63a3669419433 100644 (file)
@@ -169,9 +169,6 @@ Boston, MA 02111-1307, USA.  */
 
 #include <config.h>
 #include <stdio.h>
-#ifdef STDC_HEADERS
-#include <stdlib.h>
-#endif
 #include "lisp.h"
 #include "frame.h"
 #include "window.h"
@@ -189,10 +186,14 @@ Boston, MA 02111-1307, USA.  */
 #include "coding.h"
 #include "process.h"
 #include "region-cache.h"
+#include "fontset.h"
 
 #ifdef HAVE_X_WINDOWS
 #include "xterm.h"
 #endif
+#ifdef WINDOWSNT
+#include "w32term.h"
+#endif
 
 #define min(a, b) ((a) < (b) ? (a) : (b))
 #define max(a, b) ((a) > (b) ? (a) : (b))
@@ -219,7 +220,7 @@ Lisp_Object Qoverriding_local_map, Qoverriding_terminal_local_map;
 Lisp_Object Qwindow_scroll_functions, Vwindow_scroll_functions;
 Lisp_Object Qredisplay_end_trigger_functions;
 Lisp_Object Qinhibit_point_motion_hooks;
-Lisp_Object QCeval, QCwhen;
+Lisp_Object QCeval, Qwhen, QCfile, QCdata;
 Lisp_Object Qfontified;
 
 /* Functions called to fontify regions of text.  */
@@ -227,23 +228,23 @@ Lisp_Object Qfontified;
 Lisp_Object Vfontification_functions;
 Lisp_Object Qfontification_functions;
 
-/* Non-zero means draw toolbar buttons raised when the mouse moves
+/* Non-zero means draw tool bar buttons raised when the mouse moves
    over them.  */
 
-int auto_raise_toolbar_buttons_p;
+int auto_raise_tool_bar_buttons_p;
 
-/* Margin around toolbar buttons in pixels.  */
+/* Margin around tool bar buttons in pixels.  */
 
-int toolbar_button_margin;
+int tool_bar_button_margin;
 
-/* Thickness of shadow to draw around toolbar buttons.  */
+/* Thickness of shadow to draw around tool bar buttons.  */
 
-int toolbar_button_relief;
+int tool_bar_button_relief;
 
-/* Non-zero means automatically resize toolbars so that all toolbar
+/* Non-zero means automatically resize tool-bars so that all tool-bar
    items are visible, and no blank lines remain.  */
 
-int auto_resize_toolbars_p;
+int auto_resize_tool_bars_p;
 
 /* Non-nil means don't actually do any redisplay.  */
 
@@ -251,19 +252,19 @@ Lisp_Object Vinhibit_redisplay, Qinhibit_redisplay;
 
 /* Names of text properties relevant for redisplay.  */
 
-Lisp_Object Qdisplay, Qrelative_width, Qwidth, Qalign_to;
-extern Lisp_Object Qface, Qinvisible, Qimage;
+Lisp_Object Qdisplay, Qrelative_width, Qalign_to;
+extern Lisp_Object Qface, Qinvisible, Qimage, Qwidth;
 
 /* Symbols used in text property values.  */
 
 Lisp_Object Qspace, QCalign_to, QCrelative_width, QCrelative_height;
-Lisp_Object Qleft_margin, Qright_margin, Qspace_width, Qheight, Qraise;
+Lisp_Object Qleft_margin, Qright_margin, Qspace_width, Qraise;
+Lisp_Object Qmargin;
+extern Lisp_Object Qheight;
 
-/* Name of the variable controlling the highlighting of trailing
-   whitespace.  The implementation uses find_symbol_value to get its
-   value.  */
+/* Non-nil means highlight trailing whitespace.  */
 
-Lisp_Object Qshow_trailing_whitespace;
+Lisp_Object Vshow_trailing_whitespace;
 
 /* Name of the face used to highlight trailing whitespace.  */
 
@@ -383,11 +384,6 @@ static int scroll_conservatively;
 
 int scroll_margin;
 
-/* Number of characters of overlap to show, when scrolling a one-line
-   window such as a minibuffer.  */
-
-static int minibuffer_scroll_overlap;
-
 /* Number of windows showing the buffer of the selected window (or
    another buffer with the same base buffer).  keyboard.c refers to
    this.  */
@@ -412,37 +408,19 @@ Lisp_Object minibuf_prompt;
 int minibuf_prompt_width;
 int minibuf_prompt_pixel_width;
 
-/* Message to display instead of mini-buffer contents.  This is what
-   the functions error and message make, and command echoing uses it
-   as well.  It overrides the minibuf_prompt as well as the buffer.  */
-
-char *echo_area_glyphs;
-
-/* A Lisp string to display instead of mini-buffer contents, analogous
-   to echo_area_glyphs.  If this is a string, display that string.
-   Otherwise, if echo_area_glyphs is non-null, display that.  */
-
-Lisp_Object echo_area_message;
-
-/* This is the length of the message in echo_area_glyphs or
-   echo_area_message.  */
-
-int echo_area_glyphs_length;
-
-/* Value of echo_area_glyphs when it was last acted on.  If this is
-   nonzero, there is a message on the frame in the mini-buffer and it
-   should be erased as soon as it is no longer requested to appear.  */
-
-char *previous_echo_glyphs;
-Lisp_Object previous_echo_area_message;
-static int previous_echo_glyphs_length;
-
 /* This is the window where the echo area message was displayed.  It
    is always a mini-buffer window, but it may not be the same window
    currently active as a mini-buffer.  */
 
 Lisp_Object echo_area_window;
 
+/* List of pairs (MESSAGE . MULTIBYTE).  The function save_message
+   pushes the current message and the value of
+   message_enable_multibyte on the stack, the function restore_message
+   pops the stack and displays MESSAGE again.  */
+
+Lisp_Object Vmessage_stack;
+
 /* Nonzero means multibyte characters were enabled when the echo area
    message was specified.  */
 
@@ -452,28 +430,6 @@ int message_enable_multibyte;
 
 int update_mode_lines;
 
-/* Smallest number of characters before the gap at any time since last
-   redisplay that finished.  Valid for current buffer when
-   try_window_id can be called.  */
-
-int beg_unchanged;
-
-/* Smallest number of characters after the gap at any time since last
-   redisplay that finished.  Valid for current buffer when
-   try_window_id can be called.  */
-
-int end_unchanged;
-
-/* MODIFF as of last redisplay that finished; if it matches MODIFF,
-   and overlay_unchanged_modified matches OVERLAY_MODIFF, that means
-   beg_unchanged and end_unchanged contain no useful information.  */
-
-int unchanged_modified;
-
-/* OVERLAY_MODIFF as of last redisplay that finished.  */
-
-int overlay_unchanged_modified;
-
 /* Nonzero if window sizes or contents have changed since last
    redisplay that finished */
 
@@ -486,13 +442,57 @@ int line_number_displayed;
 
 /* Maximum buffer size for which to display line numbers.  */
 
-static int line_number_display_limit;
+Lisp_Object Vline_number_display_limit;
+
+/* line width to consider when repostioning for line number display */
+
+static int line_number_display_limit_width;
 
 /* Number of lines to keep in the message log buffer.  t means
    infinite.  nil means don't log at all.  */
 
 Lisp_Object Vmessage_log_max;
 
+/* Current, index 0, and last displayed echo area message.  Either
+   buffers from echo_buffers, or nil to indicate no message.  */
+
+Lisp_Object echo_area_buffer[2];
+
+/* The buffers referenced from echo_area_buffer.  */
+
+static Lisp_Object echo_buffer[2];
+
+/* A vector saved used in with_area_buffer to reduce consing.  */
+
+static Lisp_Object Vwith_echo_area_save_vector;
+
+/* Non-zero means display_echo_area should display the last echo area
+   message again.  Set by redisplay_preserve_echo_area.  */
+
+static int display_last_displayed_message_p;
+
+/* Nonzero if echo area is being used by print; zero if being used by
+   message.  */
+
+int message_buf_print;
+
+/* Maximum height for resizing mini-windows.  Either a float
+   specifying a fraction of the available height, or an integer
+   specifying a number of lines.  */
+
+Lisp_Object Vmax_mini_window_height;
+
+/* Non-zero means messages should be displayed with truncated
+   lines instead of being continued.  */
+
+int message_truncate_lines;
+Lisp_Object Qmessage_truncate_lines;
+
+/* Non-zero means we want a hollow cursor in windows that are not
+   selected.  Zero means there's no cursor in such windows.  */
+
+int cursor_in_non_selected_windows;
+
 /* A scratch glyph row with contents used for generating truncation
    glyphs.  Also used in direct_output_for_insert.  */
 
@@ -519,6 +519,15 @@ static int last_max_ascent, last_height;
 int trace_redisplay_p;
 #endif
 
+/* Non-zero means automatically scroll windows horizontally to make
+   point visible.  */
+
+int automatic_hscrolling_p;
+
+/* A list of symbols, one for each supported image type.  */
+
+Lisp_Object Vimage_types;
+
 /* Value returned from text property handlers (see below).  */
 
 enum prop_handled
@@ -548,6 +557,7 @@ struct props
 static enum prop_handled handle_face_prop P_ ((struct it *));
 static enum prop_handled handle_invisible_prop P_ ((struct it *));
 static enum prop_handled handle_display_prop P_ ((struct it *));
+static enum prop_handled handle_composition_prop P_ ((struct it *));
 static enum prop_handled handle_overlay_change P_ ((struct it *));
 static enum prop_handled handle_fontified_prop P_ ((struct it *));
 
@@ -561,6 +571,7 @@ static struct props it_props[] =
   {&Qface,             FACE_PROP_IDX,          handle_face_prop},
   {&Qdisplay,          DISPLAY_PROP_IDX,       handle_display_prop},
   {&Qinvisible,                INVISIBLE_PROP_IDX,     handle_invisible_prop},
+  {&Qcomposition,      COMPOSITION_PROP_IDX,   handle_composition_prop},
   {NULL,               0,                      NULL}
 };
 
@@ -598,6 +609,20 @@ enum move_it_result
 \f
 /* Function prototypes.  */
 
+static int single_display_prop_intangible_p P_ ((Lisp_Object));
+static void ensure_echo_area_buffers P_ ((void));
+static struct glyph_row *row_containing_pos P_ ((struct window *, int,
+                                                struct glyph_row *,
+                                                struct glyph_row *));
+static Lisp_Object unwind_with_echo_area_buffer P_ ((Lisp_Object));
+static Lisp_Object with_echo_area_buffer_unwind_data P_ ((struct window *));
+static void clear_garbaged_frames P_ ((void));
+static int current_message_1 P_ ((Lisp_Object *));
+static int truncate_message_1 P_ ((int));
+static int set_message_1 P_ ((char *s, Lisp_Object, int, int));
+static int display_echo_area P_ ((struct window *));
+static int display_echo_area_1 P_ ((struct window *));
+static Lisp_Object unwind_redisplay P_ ((Lisp_Object));
 static int string_char_and_length P_ ((unsigned char *, int, int *));
 static struct text_pos display_prop_end P_ ((struct it *, Lisp_Object,
                                             struct text_pos));
@@ -607,7 +632,7 @@ static Lisp_Object eval_form P_ ((Lisp_Object));
 static void insert_left_trunc_glyphs P_ ((struct it *));
 static struct glyph_row *get_overlay_arrow_glyph_row P_ ((struct window *));
 static void extend_face_to_end_of_line P_ ((struct it *));
-static void append_space P_ ((struct it *, int));
+static int append_space P_ ((struct it *, int));
 static void make_cursor_line_fully_visible P_ ((struct window *));
 static int try_scrolling P_ ((Lisp_Object, int, int, int, int));
 static int trailing_whitespace_p P_ ((int));
@@ -618,7 +643,7 @@ static void push_it P_ ((struct it *));
 static void pop_it P_ ((struct it *));
 static void sync_frame_with_window_matrix_rows P_ ((struct window *));
 static void redisplay_internal P_ ((int));
-static void echo_area_display P_ ((int));
+static int echo_area_display P_ ((int));
 static void redisplay_windows P_ ((Lisp_Object));
 static void redisplay_window P_ ((Lisp_Object, int));
 static void update_menu_bar P_ ((struct frame *, int));
@@ -629,7 +654,7 @@ static void display_mode_lines P_ ((struct window *));
 static void display_mode_line P_ ((struct window *, enum face_id,
                                   Lisp_Object));
 static int display_mode_element P_ ((struct it *, int, int, int, Lisp_Object));
-static char *decode_mode_spec P_ ((struct window *, char, int, int));
+static char *decode_mode_spec P_ ((struct window *, int, int, int));
 static void display_menu_bar P_ ((struct window *));
 static int display_count_lines P_ ((int, int, int, int, int *));
 static int display_string P_ ((unsigned char *, Lisp_Object, Lisp_Object,
@@ -648,6 +673,7 @@ static int next_element_from_display_vector P_ ((struct it *));
 static int next_element_from_string P_ ((struct it *));
 static int next_element_from_c_string P_ ((struct it *));
 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 *));
@@ -655,7 +681,6 @@ static void init_from_display_pos P_ ((struct it *, struct window *,
                                       struct display_pos *));
 static void reseat_to_string P_ ((struct it *, unsigned char *,
                                  Lisp_Object, int, int, int, int));
-static int charset_at_position P_ ((struct text_pos));
 static enum move_it_result move_it_in_display_line_to P_ ((struct it *,
                                                           int, int, int));
 void move_it_vertically_backward P_ ((struct it *, int));
@@ -683,10 +708,10 @@ static int handle_single_display_prop P_ ((struct it *, Lisp_Object,
 
 #ifdef HAVE_WINDOW_SYSTEM
 
-static void update_toolbar P_ ((struct frame *, int));
-static void build_desired_toolbar_string P_ ((struct frame *f));
-static int redisplay_toolbar P_ ((struct frame *));
-static void display_toolbar_line P_ ((struct it *));
+static void update_tool_bar P_ ((struct frame *, int));
+static void build_desired_tool_bar_string P_ ((struct frame *f));
+static int redisplay_tool_bar P_ ((struct frame *));
+static void display_tool_bar_line P_ ((struct it *));
 
 #endif /* HAVE_WINDOW_SYSTEM */
 
@@ -726,7 +751,7 @@ window_box_width (w, area)
   
   if (!w->pseudo_window_p)
     {
-      width -= FRAME_SCROLL_BAR_WIDTH (f) + 2 * FRAME_FLAGS_AREA_COLS (f);
+      width -= FRAME_SCROLL_BAR_WIDTH (f) + FRAME_FLAGS_AREA_COLS (f);
       
       if (area == TEXT_AREA)
        {
@@ -760,8 +785,8 @@ window_box_height (w)
   if (WINDOW_WANTS_MODELINE_P (w))
     height -= CURRENT_MODE_LINE_HEIGHT (w);
 
-  if (WINDOW_WANTS_TOP_LINE_P (w))
-    height -= CURRENT_TOP_LINE_HEIGHT (w);
+  if (WINDOW_WANTS_HEADER_LINE_P (w))
+    height -= CURRENT_HEADER_LINE_HEIGHT (w);
 
   return height;
 }
@@ -783,7 +808,7 @@ window_box_left (w, area)
   if (!w->pseudo_window_p)
     {
       x += (WINDOW_LEFT_MARGIN (w) * CANON_X_UNIT (f)
-           + FRAME_FLAGS_AREA_WIDTH (f));
+           + FRAME_LEFT_FLAGS_AREA_WIDTH (f));
       
       if (area == TEXT_AREA)
        x += window_box_width (w, LEFT_MARGIN_AREA);
@@ -830,8 +855,8 @@ window_box (w, area, box_x, box_y, box_width, box_height)
   *box_x = window_box_left (w, area);
   *box_y = (FRAME_INTERNAL_BORDER_WIDTH_SAFE (f)
            + XFASTINT (w->top) * CANON_Y_UNIT (f));
-  if (WINDOW_WANTS_TOP_LINE_P (w))
-    *box_y += CURRENT_TOP_LINE_HEIGHT (w);
+  if (WINDOW_WANTS_HEADER_LINE_P (w))
+    *box_y += CURRENT_HEADER_LINE_HEIGHT (w);
 }
 
 
@@ -865,7 +890,7 @@ window_box_edges (w, area, top_left_x, top_left_y,
 /* Return the next character from STR which is MAXLEN bytes long.
    Return in *LEN the length of the character.  This is like
    STRING_CHAR_AND_LENGTH but never returns an invalid character.  If
-   we find one, we return a `?', but with the length of the illegal
+   we find one, we return a `?', but with the length of the invalid
    character.  */
 
 static INLINE int
@@ -878,7 +903,7 @@ string_char_and_length (str, maxlen, len)
   c = STRING_CHAR_AND_LENGTH (str, maxlen, *len);
   if (!CHAR_VALID_P (c, 1))
     /* We may not change the length here because other places in Emacs
-       don't use this function, i.e. they silently accept illegal
+       don't use this function, i.e. they silently accept invalid
        characters.  */
     c = '?';
 
@@ -1013,38 +1038,13 @@ compute_string_pos (newpos, pos, string)
   xassert (CHARPOS (*newpos) >= CHARPOS (pos));
   
   if (STRING_MULTIBYTE (string))
-    *newpos = string_pos_nchars_ahead (pos, CHARPOS (*newpos) - CHARPOS (pos),
-                                      string);
+    *newpos = string_pos_nchars_ahead (pos, string,
+                                      CHARPOS (*newpos) - CHARPOS (pos));
   else
     BYTEPOS (*newpos) = CHARPOS (*newpos);
 }
 
 
-/* Return the charset of the character at position POS in
-   current_buffer.  */
-
-static int
-charset_at_position (pos)
-     struct text_pos pos;
-{
-  int c, multibyte_p;
-  unsigned char *p = BYTE_POS_ADDR (BYTEPOS (pos));
-
-  multibyte_p = !NILP (current_buffer->enable_multibyte_characters);
-  if (multibyte_p)
-    {
-      int maxlen = ((BYTEPOS (pos) >= GPT_BYTE ? ZV_BYTE : GPT_BYTE)
-                   - BYTEPOS (pos));
-      int len;
-      c = string_char_and_length (p, maxlen, &len);
-    }
-  else
-    c = *p;
-
-  return CHAR_CHARSET (c);
-}
-
-
 \f
 /***********************************************************************
                        Lisp form evaluation
@@ -1161,11 +1161,11 @@ check_window_end (w)
 
    BASE_FACE_ID is the id of a base face to use.  It must be one of
    DEFAULT_FACE_ID for normal text, MODE_LINE_FACE_ID or
-   TOP_LINE_FACE_ID for displaying mode lines, or TOOLBAR_FACE_ID for
-   displaying the toolbar.
+   HEADER_LINE_FACE_ID for displaying mode lines, or TOOL_BAR_FACE_ID for
+   displaying the tool-bar.
    
    If ROW is null and BASE_FACE_ID is equal to MODE_LINE_FACE_ID or
-   TOP_LINE_FACE_ID, the iterator will be initialized to use the
+   HEADER_LINE_FACE_ID, the iterator will be initialized to use the
    corresponding mode line glyph row of the desired matrix of W.  */
 
 void
@@ -1177,11 +1177,9 @@ init_iterator (it, w, charpos, bytepos, row, base_face_id)
      enum face_id base_face_id;
 {
   int highlight_region_p;
-  Lisp_Object value;
 
   /* Some precondition checks.  */
   xassert (w != NULL && it != NULL);
-  xassert (charpos < 0 || current_buffer == XBUFFER (w->buffer));
   xassert (charpos < 0 || (charpos > 0 && charpos <= ZV));
 
   /* If face attributes have been changed since the last redisplay,
@@ -1199,15 +1197,14 @@ init_iterator (it, w, charpos, bytepos, row, base_face_id)
     {
       if (base_face_id == MODE_LINE_FACE_ID)
        row = MATRIX_MODE_LINE_ROW (w->desired_matrix);
-      else if (base_face_id == TOP_LINE_FACE_ID)
-       row = MATRIX_TOP_LINE_ROW (w->desired_matrix);
+      else if (base_face_id == HEADER_LINE_FACE_ID)
+       row = MATRIX_HEADER_LINE_ROW (w->desired_matrix);
     }
   
   /* Clear IT.  */
   bzero (it, sizeof *it);
   it->current.overlay_string_index = -1;
   it->current.dpvec_index = -1;
-  it->charset = CHARSET_ASCII;
   it->base_face_id = base_face_id;
 
   /* The window in which we iterate over current_buffer:  */
@@ -1215,16 +1212,21 @@ init_iterator (it, w, charpos, bytepos, row, base_face_id)
   it->w = w;
   it->f = XFRAME (w->frame);
 
+  /* Extra space between lines (on window systems only).  */
+  if (base_face_id == DEFAULT_FACE_ID
+      && FRAME_WINDOW_P (it->f))
+    {
+      if (NATNUMP (current_buffer->extra_line_spacing))
+       it->extra_line_spacing = XFASTINT (current_buffer->extra_line_spacing);
+      else if (it->f->extra_line_spacing > 0)
+       it->extra_line_spacing = it->f->extra_line_spacing;
+    }
+
   /* If realized faces have been removed, e.g. because of face
      attribute changes of named faces, recompute them.  */
   if (FRAME_FACE_CACHE (it->f)->used == 0)
     recompute_basic_faces (it->f);
 
-  /* Should we highlight trailing whitespace?  */
-  value = find_symbol_value (Qshow_trailing_whitespace);
-  it->show_trailing_whitespace_p 
-    = EQ (value, Qunbound) ? 0 : !NILP (value);
-
   /* Current value of the `space-width', and 'height' properties.  */
   it->space_width = Qnil;
   it->font_height = Qnil;
@@ -1358,8 +1360,8 @@ init_iterator (it, w, charpos, bytepos, row, base_face_id)
            it->last_visible_x -= it->continuation_pixel_width;
        }
 
-      it->top_line_p = WINDOW_WANTS_TOP_LINE_P (w);
-      it->current_y = WINDOW_DISPLAY_TOP_LINE_HEIGHT (w) + w->vscroll;
+      it->header_line_p = WINDOW_WANTS_HEADER_LINE_P (w);
+      it->current_y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w) + w->vscroll;
     }
 
   /* Leave room for a border glyph.  */
@@ -1416,7 +1418,7 @@ start_display (it, w, pos)
 {
   int start_at_line_beg_p;
   struct glyph_row *row;
-  int first_vpos = WINDOW_WANTS_TOP_LINE_P (w) ? 1 : 0;
+  int first_vpos = WINDOW_WANTS_HEADER_LINE_P (w) ? 1 : 0;
   int first_y;
 
   row = w->desired_matrix->rows + first_vpos;
@@ -1431,16 +1433,6 @@ start_display (it, w, pos)
   if (!start_at_line_beg_p)
     reseat_at_previous_visible_line_start (it);
 
-#if NO_PROMPT_IN_BUFFER
-  /* Take the mini-buffer prompt width into account for tab
-     calculations.  */
-  if (MINI_WINDOW_P (w) && IT_CHARPOS (*it) == BEGV)
-    {
-      /* Why is mini-buffer_prompt_width guaranteed to be set here?  */
-      it->prompt_width = minibuf_prompt_pixel_width;
-    }
-#endif /* NO_PROMPT_IN_BUFFER */
-
   /* If window start is not at a line start, skip forward to POS to
      get the correct continuation_lines_width and current_x.  */
   if (!start_at_line_beg_p)
@@ -1605,6 +1597,7 @@ handle_stop (it)
 
   it->dpvec = NULL;
   it->current.dpvec_index = -1;
+  it->add_overlay_start = 0;
 
   do
     {
@@ -1614,7 +1607,7 @@ handle_stop (it)
       for (p = it_props; p->handler; ++p)
        {
          handled = p->handler (it);
-         
+
          if (handled == HANDLED_RECOMPUTE_PROPS)
            break;
          else if (handled == HANDLED_RETURN)
@@ -1819,7 +1812,7 @@ handle_fontified_prop (it)
       /* Run the hook functions.  */
       args[0] = Qfontification_functions;
       args[1] = pos;
-      Frun_hook_with_args (make_number (2), args);
+      Frun_hook_with_args (2, args);
 
       /* Return HANDLED_RECOMPUTE_PROPS only if function fontified
         something.  This avoids an endless loop if they failed to
@@ -1926,7 +1919,6 @@ handle_face_prop (it)
     }
   
   it->face_id = new_face_id;
-  it->charset = CHARSET_ASCII;
   return HANDLED_NORMALLY;
 }
 
@@ -1959,7 +1951,11 @@ face_before_or_after_it_pos (it, before_p)
       if (before_p)
        pos = string_pos (IT_STRING_CHARPOS (*it) - 1, it->string);
       else
-       pos = string_pos (IT_STRING_CHARPOS (*it) + 1, it->string);
+       /* For composition, we must check the character after the
+           composition.  */
+       pos = (it->what == IT_COMPOSITION
+              ? string_pos (IT_STRING_CHARPOS (*it) + it->cmp_len, it->string)
+              : string_pos (IT_STRING_CHARPOS (*it) + 1, it->string));
 
       /* Get the face for ASCII, or unibyte.  */
       face_id
@@ -1981,12 +1977,11 @@ face_before_or_after_it_pos (it, before_p)
        {
          unsigned char *p = XSTRING (it->string)->data + BYTEPOS (pos);
          int rest = STRING_BYTES (XSTRING (it->string)) - BYTEPOS (pos);
-         int c, len, charset;
+         int c, len;
+         struct face *face = FACE_FROM_ID (it->f, face_id);
       
          c = string_char_and_length (p, rest, &len);
-         charset = CHAR_CHARSET (c);
-         if (charset != CHARSET_ASCII)
-           face_id = FACE_FOR_CHARSET (it->f, face_id, charset);
+         face_id = FACE_FOR_CHAR (it->f, face, c);
        }
     }
   else
@@ -1999,10 +1994,16 @@ face_before_or_after_it_pos (it, before_p)
       pos = it->current.pos;
       
       if (before_p)
-       DEC_TEXT_POS (pos);
+       DEC_TEXT_POS (pos, it->multibyte_p);
       else
-       INC_TEXT_POS (pos);
-
+       {
+         if (it->what == IT_COMPOSITION)
+           /* For composition, we must check the position after the
+              composition.  */
+           pos.charpos += it->cmp_len, pos.bytepos += it->len;
+         else
+           INC_TEXT_POS (pos, it->multibyte_p);
+       }
       /* Determine face for CHARSET_ASCII, or unibyte.  */
       face_id = face_at_buffer_position (it->w,
                                         CHARPOS (pos),
@@ -2016,9 +2017,9 @@ face_before_or_after_it_pos (it, before_p)
         suitable for unibyte text if current_buffer is unibyte.  */
       if (it->multibyte_p)
        {
-         int charset = charset_at_position (pos);
-         if (charset != CHARSET_ASCII)
-           face_id = FACE_FOR_CHARSET (it->f, face_id, charset);
+         int c = FETCH_MULTIBYTE_CHAR (CHARPOS (pos));
+         struct face *face = FACE_FROM_ID (it->f, face_id);
+         face_id = FACE_FOR_CHAR (it->f, face, c);
        }
     }
   
@@ -2051,7 +2052,8 @@ handle_invisible_prop (it)
       XSETFASTINT (charpos, IT_STRING_CHARPOS (*it));
       prop = Fget_text_property (charpos, Qinvisible, it->string);
 
-      if (!NILP (prop))
+      if (!NILP (prop)
+         && IT_STRING_CHARPOS (*it) < it->end_charpos)
        {
          handled = HANDLED_RECOMPUTE_PROPS;
          
@@ -2105,7 +2107,8 @@ handle_invisible_prop (it)
       prop = Fget_char_property (pos, Qinvisible, it->window);
       
       /* If we are on invisible text, skip over it.  */
-      if (TEXT_PROP_MEANS_INVISIBLE (prop))
+      if (TEXT_PROP_MEANS_INVISIBLE (prop)
+         && IT_CHARPOS (*it) < it->end_charpos)
        {
          /* Record whether we have to display an ellipsis for the
             invisible text.  */
@@ -2113,6 +2116,7 @@ handle_invisible_prop (it)
            = TEXT_PROP_MEANS_INVISIBLE_WITH_ELLIPSIS (prop);
 
          handled = HANDLED_RECOMPUTE_PROPS;
+         it->add_overlay_start = IT_CHARPOS (*it);
          
          /* Loop skipping over invisible text.  The loop is left at
             ZV or with IT on the first char being visible again.  */
@@ -2231,8 +2235,11 @@ handle_display_prop (it)
     return HANDLED_NORMALLY;
 
   space_or_image_found_p = 0;
-  if (CONSP (prop) && CONSP (XCAR (prop)))
+  if (CONSP (prop)
+      && CONSP (XCAR (prop))
+      && !EQ (Qmargin, XCAR (XCAR (prop))))
     {
+      /* A list of sub-properties.  */
       while (CONSP (prop))
        {
          if (handle_single_display_prop (it, XCAR (prop), object, position))
@@ -2258,7 +2265,7 @@ handle_display_prop (it)
 }
 
 
-/* Value is the position of the end of the `display' property stating
+/* Value is the position of the end of the `display' property starting
    at START_POS in OBJECT.  */
 
 static struct text_pos
@@ -2269,27 +2276,14 @@ display_prop_end (it, object, start_pos)
 {
   Lisp_Object end;
   struct text_pos end_pos;
-  
-  /* Characters having this form of property are not displayed, so
-     we have to find the end of the property.  */
-  end = Fnext_single_property_change (make_number (start_pos.charpos),
-                                     Qdisplay, object, Qnil);
-  if (NILP (end))
-    {
-      /* A nil value of `end' means there are no changes of the
-        property to the end of the buffer or string.  */
-      if (it->current.overlay_string_index >= 0)
-       end_pos.charpos = XSTRING (it->string)->size;
-      else
-       end_pos.charpos = it->end_charpos;
-    }
-  else
-    end_pos.charpos = XFASTINT (end);
 
-  if (STRINGP (it->string))
+  end = next_single_char_property_change (make_number (CHARPOS (start_pos)),
+                                         Qdisplay, object, Qnil);
+  CHARPOS (end_pos) = XFASTINT (end);
+  if (STRINGP (object))
     compute_string_pos (&end_pos, start_pos, it->string);
   else
-    end_pos.bytepos = CHAR_TO_BYTE (end_pos.charpos);
+    BYTEPOS (end_pos) = CHAR_TO_BYTE (XFASTINT (end));
 
   return end_pos;
 }
@@ -2313,22 +2307,18 @@ handle_single_display_prop (it, prop, object, position)
 {
   Lisp_Object value;
   int space_or_image_found_p = 0;
-
   Lisp_Object form;
 
-  /* If PROP is a list of the form `(:when FORM VALUE)', FORM is
-     evaluated.  If the result is nil, VALUE is ignored.  */
+  /* If PROP is a list of the form `(when FORM . VALUE)', FORM is
+     evaluated.  If the result is nil, VALUE is ignored. */
   form = Qt;
-  if (CONSP (prop) && EQ (XCAR (prop), QCwhen))
+  if (CONSP (prop) && EQ (XCAR (prop), Qwhen))
     {
       prop = XCDR (prop);
       if (!CONSP (prop))
        return 0;
       form = XCAR (prop);
       prop = XCDR (prop);
-      if (!CONSP (prop))
-       return 0;
-      prop = XCAR (prop);
     }
 
   if (!NILP (form) && !EQ (form, Qt))
@@ -2336,16 +2326,22 @@ handle_single_display_prop (it, prop, object, position)
       struct gcpro gcpro1;
       struct text_pos end_pos, pt;
       
-      end_pos = display_prop_end (it, object, *position);
       GCPRO1 (form);
+      end_pos = display_prop_end (it, object, *position);
 
       /* Temporarily set point to the end position, and then evaluate
         the form.  This makes `(eolp)' work as FORM.  */
-      CHARPOS (pt) = PT;
-      BYTEPOS (pt) = PT_BYTE;
-      TEMP_SET_PT_BOTH (CHARPOS (end_pos), BYTEPOS (end_pos));
+      if (BUFFERP (object))
+       {
+         CHARPOS (pt) = PT;
+         BYTEPOS (pt) = PT_BYTE;
+         TEMP_SET_PT_BOTH (CHARPOS (end_pos), BYTEPOS (end_pos));
+       }
+      
       form = eval_form (form);
-      TEMP_SET_PT_BOTH (CHARPOS (pt), BYTEPOS (pt));
+      
+      if (BUFFERP (object))
+       TEMP_SET_PT_BOTH (CHARPOS (pt), BYTEPOS (pt));
       UNGCPRO;  
     }
   
@@ -2437,53 +2433,65 @@ handle_single_display_prop (it, prop, object, position)
           && EQ (XCAR (prop), Qraise)
           && CONSP (XCDR (prop)))
     {
-#ifdef HAVE_WINDOW_SYSTEM
       /* `(raise FACTOR)'.  */
       if (FRAME_TERMCAP_P (it->f) || FRAME_MSDOS_P (it->f))
        return 0;
       
+#ifdef HAVE_WINDOW_SYSTEM
       value = XCAR (XCDR (prop));
       if (NUMBERP (value))
        {
          struct face *face = FACE_FROM_ID (it->f, it->face_id);
          it->voffset = - (XFLOATINT (value)
-                          * (face->font->ascent + face->font->descent));
+                          * (FONT_HEIGHT (face->font)));
        }
 #endif /* HAVE_WINDOW_SYSTEM */
     }
   else if (!it->string_from_display_prop_p)
     {
-      /* `(left-margin VALUE)' or `(right-margin VALUE)
-        or `(nil VALUE)' or VALUE.  */
+      /* `((margin left-margin) VALUE)' or `((margin right-margin)
+        VALUE) or `((margin nil) VALUE)' or VALUE. */
       Lisp_Object location, value;
       struct text_pos start_pos;
       int valid_p;
 
       /* Characters having this form of property are not displayed, so
          we have to find the end of the property.  */
-      space_or_image_found_p = 1;
       start_pos = *position;
       *position = display_prop_end (it, object, start_pos);
+      value = Qnil;
 
       /* Let's stop at the new position and assume that all
         text properties change there.  */
       it->stop_charpos = position->charpos;
 
-      if (CONSP (prop)
-         && !EQ (XCAR (prop), Qspace)
-         && !EQ (XCAR (prop), Qimage))
+      location = Qunbound;
+      if (CONSP (prop) && CONSP (XCAR (prop)))
        {
-         location = XCAR (prop);
+         Lisp_Object tem;
+         
          value = XCDR (prop);
+         if (CONSP (value))
+           value = XCAR (value);
+
+         tem = XCAR (prop);
+         if (EQ (XCAR (tem), Qmargin)
+             && (tem = XCDR (tem),
+                 tem = CONSP (tem) ? XCAR (tem) : Qnil,
+                 (NILP (tem)
+                  || EQ (tem, Qleft_margin)
+                  || EQ (tem, Qright_margin))))
+           location = tem;
        }
-      else
+
+      if (EQ (location, Qunbound))
        {
          location = Qnil;
          value = prop;
        }
 
 #ifdef HAVE_WINDOW_SYSTEM
-      if (FRAME_TERMCAP_P (it->f) || FRAME_MSDOS_P (it->f))
+      if (FRAME_TERMCAP_P (it->f))
        valid_p = STRINGP (value);
       else
        valid_p = (STRINGP (value)
@@ -2498,6 +2506,8 @@ handle_single_display_prop (it, prop, object, position)
           || NILP (location))
          && valid_p)
        {
+         space_or_image_found_p = 1;
+         
          /* Save current settings of IT so that we can restore them
             when we are finished with the glyph property value.  */
          push_it (it);
@@ -2536,19 +2546,152 @@ handle_single_display_prop (it, prop, object, position)
              it->object = NILP (object) ? it->w->buffer : object;
              it->method = next_element_from_image;
              
-             /* Say that we don't have consumed the characters with
+             /* Say that we haven't consumed the characters with
                 `display' property yet.  The call to pop_it in
                 set_iterator_to_next will clean this up.  */
              *position = start_pos;
            }
 #endif /* HAVE_WINDOW_SYSTEM */
        }
+      else
+       /* Invalid property or property not supported.  Restore
+          the position to what it was before.  */
+       *position = start_pos;
     }
 
   return space_or_image_found_p;
 }
 
 
+/* Check if PROP is a display sub-property value whose text should be
+   treated as intangible.  */
+
+static int
+single_display_prop_intangible_p (prop)
+     Lisp_Object prop;
+{
+  /* 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))
+    return 0;
+
+  /* Skip over `margin LOCATION'.  If LOCATION is in the margins,
+     we don't need to treat text as intangible.  */
+  if (EQ (XCAR (prop), Qmargin))
+    {
+      prop = XCDR (prop);
+      if (!CONSP (prop))
+       return 0;
+
+      prop = XCDR (prop);
+      if (!CONSP (prop)
+         || EQ (XCAR (prop), Qleft_margin)
+         || EQ (XCAR (prop), Qright_margin))
+       return 0;
+    }
+  
+  return CONSP (prop) && EQ (XCAR (prop), Qimage);
+}
+
+
+/* Check if PROP is a display property value whose text should be
+   treated as intangible.  */
+
+int
+display_prop_intangible_p (prop)
+     Lisp_Object prop;
+{
+  if (CONSP (prop)
+      && CONSP (XCAR (prop))
+      && !EQ (Qmargin, XCAR (XCAR (prop))))
+    {
+      /* A list of sub-properties.  */
+      while (CONSP (prop))
+       {
+         if (single_display_prop_intangible_p (XCAR (prop)))
+           return 1;
+         prop = XCDR (prop);
+       }
+    }
+  else if (VECTORP (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]))
+         return 1;
+    }
+  else
+    return single_display_prop_intangible_p (prop);
+
+  return 0;
+}
+
+\f
+/***********************************************************************
+                       `composition' property
+ ***********************************************************************/
+
+/* Set up iterator IT from `composition' property at its current
+   position.  Called from handle_stop.  */
+
+static enum prop_handled
+handle_composition_prop (it)
+     struct it *it;
+{
+  Lisp_Object prop, string;
+  int pos, pos_byte, end;
+  enum prop_handled handled = HANDLED_NORMALLY;
+
+  if (STRINGP (it->string))
+    {
+      pos = IT_STRING_CHARPOS (*it);
+      pos_byte = IT_STRING_BYTEPOS (*it);
+      string = it->string;
+    }
+  else
+    {
+      pos = IT_CHARPOS (*it);
+      pos_byte = IT_BYTEPOS (*it);
+      string = Qnil;
+    }
+
+  /* If there's a valid composition and point is not inside of the
+     composition (in the case that the composition is from the current
+     buffer), draw a glyph composed from the composition components.  */
+  if (find_composition (pos, -1, &pos, &end, &prop, string)
+      && COMPOSITION_VALID_P (pos, end, prop)
+      && (STRINGP (it->string) || (PT <= pos || PT >= end)))
+    {
+      int id = get_composition_id (pos, pos_byte, end - pos, prop, string);
+
+      if (id >= 0)
+       {
+         it->method = next_element_from_composition;
+         it->cmp_id = id;
+         it->cmp_len = COMPOSITION_LENGTH (prop);
+         /* For a terminal, draw only the first character of the
+             components.  */
+         it->c = COMPOSITION_GLYPH (composition_table[id], 0);
+         it->len = (STRINGP (it->string)
+                    ? string_char_to_byte (it->string, end)
+                    : CHAR_TO_BYTE (end)) - pos_byte;
+         it->stop_charpos = end;
+         handled = HANDLED_RETURN;
+       }
+    }
+
+  return handled;
+}
+
+
 \f
 /***********************************************************************
                           Overlay strings
@@ -2559,6 +2702,7 @@ handle_single_display_prop (it, prop, object, position)
 
 struct overlay_entry
 {
+  Lisp_Object overlay;
   Lisp_Object string;
   int priority;
   int after_string_p;
@@ -2572,13 +2716,10 @@ static enum prop_handled
 handle_overlay_change (it)
      struct it *it;
 {
-  /* Overlays are handled in current_buffer only.  */
-  if (STRINGP (it->string))
-    return HANDLED_NORMALLY;
+  if (!STRINGP (it->string) && get_overlay_strings (it))
+    return HANDLED_RECOMPUTE_PROPS;
   else
-    return (get_overlay_strings (it)
-           ? HANDLED_RECOMPUTE_PROPS
-           : HANDLED_NORMALLY);
+    return HANDLED_NORMALLY;
 }
 
 
@@ -2607,6 +2748,12 @@ next_overlay_string (it)
       SET_TEXT_POS (it->current.string_pos, -1, -1);
       it->n_overlay_strings = 0;
       it->method = next_element_from_buffer;
+
+      /* If we're at the end of the buffer, record that we have
+        processed the overlay strings there already, so that
+        next_element_from_buffer doesn't try it again.  */
+      if (IT_CHARPOS (*it) >= it->end_charpos)
+       it->overlay_strings_at_end_processed_p = 1;
     }
   else
     {
@@ -2636,7 +2783,8 @@ next_overlay_string (it)
    comparison function for qsort in load_overlay_strings.  Overlay
    strings for the same position are sorted so that
 
-   1. All after-strings come in front of before-strings.
+   1. All after-strings come in front of before-strings, except
+   when they come from the same overlay.
    
    2. Within after-strings, strings are sorted so that overlay strings
    from overlays with higher priorities come first.
@@ -2656,8 +2804,14 @@ compare_overlay_entries (e1, e2)
   int result;
 
   if (entry1->after_string_p != entry2->after_string_p)
-    /* Let after-strings appear in front of before-strings.  */
-    result = entry1->after_string_p ? -1 : 1;
+    {
+      /* Let after-strings appear in front of before-strings if
+        they come from different overlays.  */
+      if (EQ (entry1->overlay, entry2->overlay))
+       result = entry1->after_string_p ? 1 : -1;
+      else
+       result = entry1->after_string_p ? -1 : 1;
+    }
   else if (entry1->after_string_p)
     /* After-strings sorted in order of decreasing priority.  */
     result = entry2->priority - entry1->priority;
@@ -2679,6 +2833,15 @@ compare_overlay_entries (e1, e2)
    strings that have already been loaded by previous calls to this
    function.
 
+   IT->add_overlay_start contains an additional overlay start
+   position to consider for taking overlay strings from, if non-zero.
+   This position comes into play when the overlay has an `invisible'
+   property, and both before and after-strings.  When we've skipped to
+   the end of the overlay, because of its `invisible' property, we
+   nevertheless want its before-string to appear.
+   IT->add_overlay_start will contain the overlay start position
+   in this case.
+
    Overlay strings are sorted so that after-string strings come in
    front of before-string strings.  Within before and after-strings,
    strings are sorted by overlay priority.  See also function
@@ -2717,20 +2880,18 @@ load_overlay_strings (it)
        }                                                               \
                                                                        \
       entries[n].string = (STRING);                                    \
+      entries[n].overlay = (OVERLAY);                                  \
       priority = Foverlay_get ((OVERLAY), Qpriority);                  \
-      entries[n].priority                                              \
-       = INTEGERP (priority) ? XFASTINT (priority) : 0;                \
+      entries[n].priority = INTEGERP (priority) ? XINT (priority) : 0;  \
       entries[n].after_string_p = (AFTER_P);                           \
       ++n;                                                             \
     }                                                                  \
   while (0)
 
   /* Process overlay before the overlay center.  */
-  for (ov = current_buffer->overlays_before;
-       CONSP (ov);
-       ov = XCONS (ov)->cdr)
+  for (ov = current_buffer->overlays_before; CONSP (ov); ov = XCDR (ov))
     {
-      overlay = XCONS (ov)->car;
+      overlay = XCAR (ov);
       xassert (OVERLAYP (overlay));
       start = OVERLAY_POSITION (OVERLAY_START (overlay));
       end = OVERLAY_POSITION (OVERLAY_END (overlay));
@@ -2740,7 +2901,9 @@ load_overlay_strings (it)
 
       /* Skip this overlay if it doesn't start or end at IT's current
         position.  */
-      if (end != IT_CHARPOS (*it) && start != IT_CHARPOS (*it))
+      if (end != IT_CHARPOS (*it)
+         && start != IT_CHARPOS (*it)
+         && it->add_overlay_start != IT_CHARPOS (*it))
        continue;
       
       /* Skip this overlay if it doesn't apply to IT->w.  */
@@ -2749,7 +2912,8 @@ load_overlay_strings (it)
        continue;
 
       /* If overlay has a non-empty before-string, record it.  */
-      if (start == IT_CHARPOS (*it)
+      if ((start == IT_CHARPOS (*it)
+          || start == it->add_overlay_start)
          && (str = Foverlay_get (overlay, Qbefore_string), STRINGP (str))
          && XSTRING (str)->size)
        RECORD_OVERLAY_STRING (overlay, str, 0);
@@ -2762,11 +2926,9 @@ load_overlay_strings (it)
     }
       
   /* Process overlays after the overlay center.  */
-  for (ov = current_buffer->overlays_after;
-       CONSP (ov);
-       ov = XCONS (ov)->cdr)
+  for (ov = current_buffer->overlays_after; CONSP (ov); ov = XCDR (ov))
     {
-      overlay = XCONS (ov)->car;
+      overlay = XCAR (ov);
       xassert (OVERLAYP (overlay));
       start = OVERLAY_POSITION (OVERLAY_START (overlay));
       end = OVERLAY_POSITION (OVERLAY_END (overlay));
@@ -2776,7 +2938,9 @@ load_overlay_strings (it)
       
       /* Skip this overlay if it doesn't start or end at IT's current
         position.  */
-      if (end != IT_CHARPOS (*it) && start != IT_CHARPOS (*it))
+      if (end != IT_CHARPOS (*it)
+         && start != IT_CHARPOS (*it)
+         && it->add_overlay_start != IT_CHARPOS (*it))
        continue;
 
       /* Skip this overlay if it doesn't apply to IT->w.  */
@@ -2785,7 +2949,8 @@ load_overlay_strings (it)
        continue;
       
       /* If overlay has a non-empty before-string, record it.  */
-      if (start == IT_CHARPOS (*it)
+      if ((start == IT_CHARPOS (*it)
+          || start == it->add_overlay_start)
          && (str = Foverlay_get (overlay, Qbefore_string), STRINGP (str))
          && XSTRING (str)->size)
        RECORD_OVERLAY_STRING (overlay, str, 0);
@@ -2800,7 +2965,8 @@ load_overlay_strings (it)
 #undef RECORD_OVERLAY_STRING
    
   /* Sort entries.  */
-  qsort (entries, n, sizeof *entries, compare_overlay_entries);
+  if (n)
+    qsort (entries, n, sizeof *entries, compare_overlay_entries);
 
   /* Record the total number of strings to process.  */
   it->n_overlay_strings = n;
@@ -2812,7 +2978,7 @@ load_overlay_strings (it)
   j = it->current.overlay_string_index;
   while (i < OVERLAY_STRING_CHUNK_SIZE && j < n)
     it->overlay_strings[i++] = entries[j++].string;
-  
+
   CHECK_IT (it);
 }
 
@@ -2995,16 +3161,15 @@ back_to_previous_visible_line_start (it)
          && indented_beyond_p (IT_CHARPOS (*it), IT_BYTEPOS (*it),
                                it->selective))
        visible_p = 0;
-#ifdef USE_TEXT_PROPERTIES
       else 
        {
          Lisp_Object prop;
 
-         prop = Fget_char_property (IT_CHARPOS (*it), Qinvisible, it->window);
+         prop = Fget_char_property (make_number (IT_CHARPOS (*it)),
+                                    Qinvisible, it->window);
          if (TEXT_PROP_MEANS_INVISIBLE (prop))
            visible_p = 0;
        }
-#endif /* USE_TEXT_PROPERTIES  */
 
       /* Back one more newline if the current one is invisible.  */
       if (!visible_p)
@@ -3080,7 +3245,9 @@ reseat_at_next_visible_line_start (it, on_newline_p)
          forward_to_next_line_start (it);
 
       /* Position on the newline if we should.  */
-      if (on_newline_p && IT_CHARPOS (*it) > BEGV)
+      if (on_newline_p
+         && IT_CHARPOS (*it) > BEGV
+         && FETCH_BYTE (IT_BYTEPOS (*it) - 1) == '\n')
        {
          --IT_CHARPOS (*it);
          IT_BYTEPOS (*it) = CHAR_TO_BYTE (IT_CHARPOS (*it));
@@ -3196,7 +3363,6 @@ reseat_to_string (it, s, string, charpos, precision, field_width, multibyte)
   bzero (&it->current, sizeof it->current);
   it->current.overlay_string_index = -1;
   it->current.dpvec_index = -1;
-  it->charset = CHARSET_ASCII;
   xassert (charpos >= 0);
   
   /* Use the setting of MULTIBYTE if specified.  */
@@ -3275,7 +3441,6 @@ get_next_display_element (it)
      function pointer `method' used here turns out to be faster than
      using a sequence of if-statements.  */
   int success_p = (*it->method) (it);
-  int charset;
 
   if (it->what == IT_CHARACTER)
     {
@@ -3317,14 +3482,16 @@ get_next_display_element (it)
             Control characters coming from a display table entry are
             currently not translated because we use IT->dpvec to hold
             the translation.  This could easily be changed but I
-            don't believe that it is worth doing.  */
+            don't believe that it is worth doing.
+
+            Non-printable multibyte characters are also translated
+            octal form.  */
          else if ((it->c < ' '
                    && (it->area != TEXT_AREA
-                       || (it->c != '\n'
-                           && it->c != '\t'
-                           && it->c != '\r')))
+                       || (it->c != '\n' && it->c != '\t')))
                   || (it->c >= 127
-                      && it->len == 1))
+                      && it->len == 1)
+                  || !CHAR_PRINTABLE_P (it->c))
            {
              /* IT->c is a control character which must be displayed
                 either as '\003' or as `^C' where the '\\' and '^'
@@ -3357,29 +3524,42 @@ get_next_display_element (it)
                }
              else
                {
+                 unsigned char str[MAX_MULTIBYTE_LENGTH];
+                 int len;
+                 int i;
+                 GLYPH escape_glyph;
+
                  /* Set IT->ctl_chars[0] to the glyph for `\\'.  */
                  if (it->dp
                      && INTEGERP (DISP_ESCAPE_GLYPH (it->dp))
                      && GLYPH_CHAR_VALID_P (XFASTINT (DISP_ESCAPE_GLYPH (it->dp))))
-                   g = XFASTINT (DISP_ESCAPE_GLYPH (it->dp));
+                   escape_glyph = XFASTINT (DISP_ESCAPE_GLYPH (it->dp));
                  else
-                   g = FAST_MAKE_GLYPH ('\\', 0);
-                 XSETINT (it->ctl_chars[0], g);
+                   escape_glyph = FAST_MAKE_GLYPH ('\\', 0);
 
-                 /* Insert three more glyphs into IT->ctl_chars for
-                    the octal display of the character.  */
-                 g = FAST_MAKE_GLYPH (((it->c >> 6) & 7) + '0', 0); 
-                 XSETINT (it->ctl_chars[1], g);
-                 g = FAST_MAKE_GLYPH (((it->c >> 3) & 7) + '0', 0); 
-                 XSETINT (it->ctl_chars[2], g);
-                 g = FAST_MAKE_GLYPH ((it->c & 7) + '0', 0); 
-                 XSETINT (it->ctl_chars[3], g);
+                 if (SINGLE_BYTE_CHAR_P (it->c))
+                   str[0] = it->c, len = 1;
+                 else
+                   len = CHAR_STRING (it->c, str);
+
+                 for (i = 0; i < len; i++)
+                   {
+                     XSETINT (it->ctl_chars[i * 4], escape_glyph);
+                     /* Insert three more glyphs into IT->ctl_chars for
+                        the octal display of the character.  */
+                     g = FAST_MAKE_GLYPH (((str[i] >> 6) & 7) + '0', 0); 
+                     XSETINT (it->ctl_chars[i * 4 + 1], g);
+                     g = FAST_MAKE_GLYPH (((str[i] >> 3) & 7) + '0', 0); 
+                     XSETINT (it->ctl_chars[i * 4 + 2], g);
+                     g = FAST_MAKE_GLYPH ((str[i] & 7) + '0', 0); 
+                     XSETINT (it->ctl_chars[i * 4 + 3], g);
+                   }
 
                  /* Set up IT->dpvec and return the first character
                      from it.  */
                  it->dpvec_char_len = it->len;
                  it->dpvec = it->ctl_chars;
-                 it->dpend = it->dpvec + 4;
+                 it->dpend = it->dpvec + len * 4;
                  it->current.dpvec_index = 0;
                  it->method = next_element_from_display_vector;
                  get_next_display_element (it);
@@ -3387,16 +3567,14 @@ get_next_display_element (it)
            }
        }
 
-      /* Adjust face id if charset changes.  There are no charset
-         changes in unibyte text because Emacs' charsets are not
-        applicable there.  */
+      /* Adjust face id for a multibyte character.  There are no
+         multibyte character in unibyte text.  */
       if (it->multibyte_p
          && success_p
-         && (charset = CHAR_CHARSET (it->c),
-             charset != it->charset))
+         && FRAME_WINDOW_P (it->f))
        {
-         it->charset = charset;
-         it->face_id = FACE_FOR_CHARSET (it->f, it->face_id, charset);
+         struct face *face = FACE_FROM_ID (it->f, it->face_id);
+         it->face_id = FACE_FOR_CHAR (it->f, face, it->c);
        }
     }
 
@@ -3451,6 +3629,23 @@ set_iterator_to_next (it)
          xassert (IT_BYTEPOS (*it) == CHAR_TO_BYTE (IT_CHARPOS (*it)));
        }
     }
+  else if (it->method == next_element_from_composition)
+    {
+      xassert (it->cmp_id >= 0 && it ->cmp_id < n_compositions);
+      if (STRINGP (it->string))
+       {
+         IT_STRING_BYTEPOS (*it) += it->len;
+         IT_STRING_CHARPOS (*it) += it->cmp_len;
+         it->method = next_element_from_string;
+         goto consider_string_end;
+       }
+      else
+       {
+         IT_BYTEPOS (*it) += it->len;
+         IT_CHARPOS (*it) += it->cmp_len;
+         it->method = next_element_from_buffer;
+       }
+    }
   else if (it->method == next_element_from_c_string)
     {
       /* Current display element of IT is from a C string.  */
@@ -3463,15 +3658,11 @@ set_iterator_to_next (it)
         Advance in the display table definition.  Reset it to null if
         end reached, and continue with characters from buffers/
         strings.  */
-      struct face *face;
-      
       ++it->current.dpvec_index;
 
-      /* Restore face and charset of the iterator to what they were
-        before the display vector entry (these entries may contain
-        faces, and of course characters of different charsets).  */
+      /* Restore face of the iterator to what they were before the
+         display vector entry (these entries may contain faces).  */
       it->face_id = it->saved_face_id;
-      it->charset = FACE_FROM_ID (it->f, it->face_id)->charset;
       
       if (it->dpvec + it->current.dpvec_index == it->dpend)
        {
@@ -3580,7 +3771,7 @@ next_element_from_display_vector (it)
 
       g = XFASTINT (it->dpvec[it->current.dpvec_index]);
       it->c = FAST_GLYPH_CHAR (g);
-      it->len = CHAR_LEN (it->c);
+      it->len = CHAR_BYTES (it->c);
 
       /* The entry may contain a face id to use.  Such a face id is
         the id of a Lisp face, not a realized face.  A face id of
@@ -3592,7 +3783,6 @@ next_element_from_display_vector (it)
          if (face_id >= 0)
            {
              it->face_id = face_id;
-             it->charset = CHARSET_ASCII;
            }
        }
     }
@@ -3754,32 +3944,37 @@ next_element_from_c_string (it)
    entry.  This function Fills IT with the first glyph from the
    ellipsis if an ellipsis is to be displayed.  */
 
-static void
+static int
 next_element_from_ellipsis (it)
      struct it *it;
 {
-  if (it->dp && VECTORP (DISP_INVIS_VECTOR (it->dp)))
-    {
-      /* Use the display table definition for `...'.  Invalid glyphs
-        will be handled by the method returning elements from dpvec.  */
-      struct Lisp_Vector *v = XVECTOR (DISP_INVIS_VECTOR (it->dp));
-      it->dpvec_char_len = it->len;
-      it->dpvec = v->contents;
-      it->dpend = v->contents + v->size;
-      it->current.dpvec_index = 0;
-      it->method = next_element_from_display_vector;
-      get_next_display_element (it);
-    }
-  else if (it->selective_display_ellipsis_p)
+  if (it->selective_display_ellipsis_p)
     {
-      /* Use default `...' which is stored in default_invis_vector.  */
-      it->dpvec_char_len = it->len;
-      it->dpvec = default_invis_vector;
-      it->dpend = default_invis_vector + 3;
-      it->current.dpvec_index = 0;
-      it->method = next_element_from_display_vector;
-      get_next_display_element (it);
+      if (it->dp && VECTORP (DISP_INVIS_VECTOR (it->dp)))
+       {
+         /* Use the display table definition for `...'.  Invalid glyphs
+            will be handled by the method returning elements from dpvec.  */
+         struct Lisp_Vector *v = XVECTOR (DISP_INVIS_VECTOR (it->dp));
+         it->dpvec_char_len = it->len;
+         it->dpvec = v->contents;
+         it->dpend = v->contents + v->size;
+         it->current.dpvec_index = 0;
+         it->method = next_element_from_display_vector;
+       }
+      else
+       {
+         /* Use default `...' which is stored in default_invis_vector.  */
+         it->dpvec_char_len = it->len;
+         it->dpvec = default_invis_vector;
+         it->dpend = default_invis_vector + 3;
+         it->current.dpvec_index = 0;
+         it->method = next_element_from_display_vector;
+       }
     }
+  else
+    reseat_at_next_visible_line_start (it, 1);
+  
+  return get_next_display_element (it);
 }
 
 
@@ -3839,8 +4034,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);
            }
 
          if (overlay_strings_follow_p)
@@ -3873,7 +4067,7 @@ next_element_from_buffer (it)
 
       /* Get the next character, maybe multibyte.  */
       p = BYTE_POS_ADDR (IT_BYTEPOS (*it));
-      if (it->multibyte_p)
+      if (it->multibyte_p && !ASCII_BYTE_P (*p))
        {
          int maxlen = ((IT_BYTEPOS (*it) >= GPT_BYTE ? ZV_BYTE : GPT_BYTE)
                        - IT_BYTEPOS (*it));
@@ -3901,7 +4095,7 @@ next_element_from_buffer (it)
                                        IT_BYTEPOS (*it) + 1,
                                        it->selective))
                {
-                 next_element_from_ellipsis (it);
+                 success_p = next_element_from_ellipsis (it);
                  it->dpvec_char_len = -1;
                }
            }
@@ -3910,14 +4104,14 @@ next_element_from_buffer (it)
              /* A value of selective == -1 means that everything from the
                 CR to the end of the line is invisible, with maybe an
                 ellipsis displayed for it.  */
-             next_element_from_ellipsis (it);
+             success_p = next_element_from_ellipsis (it);
              it->dpvec_char_len = -1;
            }
        }
     }
 
   /* Value is zero if end of buffer reached.  */
-  xassert (!success_p || it->len > 0);
+  xassert (!success_p || it->what != IT_CHARACTER || it->len > 0);
   return success_p;
 }
 
@@ -3950,6 +4144,22 @@ run_redisplay_end_trigger_hook (it)
 }
 
 
+/* Deliver a composition display element.  The iterator IT is already
+   filled with composition information (done in
+   handle_composition_prop).  Value is always 1.  */
+
+static int
+next_element_from_composition (it)
+     struct it *it;
+{
+  it->what = IT_COMPOSITION;
+  it->position = (STRINGP (it->string)
+                 ? it->current.string_pos
+                 : it->current.pos);
+  return 1;
+}
+
+
 \f
 /***********************************************************************
             Moving an iterator without producing glyphs
@@ -3988,7 +4198,7 @@ run_redisplay_end_trigger_hook (it)
      - when we stopped at a line end, i.e. a newline or a CR and selective
      display is on.  */
 
-enum move_it_result
+static enum move_it_result
 move_it_in_display_line_to (it, to_charpos, to_x, op)
      struct it *it;
      int to_charpos, to_x, op;
@@ -4000,16 +4210,6 @@ move_it_in_display_line_to (it, to_charpos, to_x, op)
   saved_glyph_row = it->glyph_row;
   it->glyph_row = NULL;
 
-#if NO_PROMPT_IN_BUFFER
-  /* Take a mini-buffer prompt into account.  */
-  if (MINI_WINDOW_P (it->w)
-      && IT_CHARPOS (*it) == BEGV)
-    {
-      it->current_x = minibuf_prompt_pixel_width;
-      it->hpos = minibuf_prompt_width;
-    }
-#endif
-
   while (1)
     {
       int x, i;
@@ -4171,8 +4371,6 @@ move_it_to (it, to_charpos, to_x, to_y, to_vpos, op)
   enum move_it_result skip, skip2 = MOVE_X_REACHED;
   int line_height;
 
-  xassert (XBUFFER (it->w->buffer) == current_buffer);
-
   while (1)
     {
       if (op & MOVE_TO_VPOS)
@@ -4427,7 +4625,6 @@ invisible_text_between_p (it, start_charpos, end_charpos)
      struct it *it;
      int start_charpos, end_charpos;
 {
-#ifdef USE_TEXT_PROPERTIES
   Lisp_Object prop, limit;
   int invisible_found_p;
   
@@ -4440,18 +4637,13 @@ invisible_text_between_p (it, start_charpos, end_charpos)
     invisible_found_p = 1;
   else
     {
-      limit = Fnext_single_property_change (make_number (start_charpos),
-                                           Qinvisible,
-                                           Fcurrent_buffer (),
-                                           make_number (end_charpos));
+      limit = next_single_char_property_change (make_number (start_charpos),
+                                               Qinvisible, Qnil,
+                                               make_number (end_charpos));
       invisible_found_p = XFASTINT (limit) < end_charpos;
     }
 
   return invisible_found_p;
-  
-#else /* not USE_TEXT_PROPERTIES */
-  return 0;
-#endif /* not USE_TEXT_PROPERTIES */
 }
 
 
@@ -4595,6 +4787,37 @@ move_it_by_lines (it, dvpos, need_y_p)
  ***********************************************************************/
 
 
+/* Add a message with format string FORMAT and arguments ARG1 and ARG2
+   to *Messages*.  */
+
+void
+add_to_log (format, arg1, arg2)
+     char *format;
+     Lisp_Object arg1, arg2;
+{
+  Lisp_Object args[3];
+  Lisp_Object msg, fmt;
+  char *buffer;
+  int len;
+  struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
+
+  fmt = msg = Qnil;
+  GCPRO4 (fmt, msg, arg1, arg2);
+  
+  args[0] = fmt = build_string (format);
+  args[1] = arg1;
+  args[2] = arg2;
+  msg = Fformat (3, args);
+
+  len = STRING_BYTES (XSTRING (msg)) + 1;
+  buffer = (char *) alloca (len);
+  strcpy (buffer, XSTRING (msg)->data);
+  
+  message_dolog (buffer, len - 1, 1, 0);
+  UNGCPRO;
+}
+
+
 /* Output a newline in the *Messages* buffer if "needs" one.  */
 
 void
@@ -4671,14 +4894,14 @@ message_dolog (m, len, nlflag, multibyte)
        {
          int i, c, nbytes;
          unsigned char *msg = (unsigned char *) m;
-         unsigned char *str, work[4];
+         unsigned char str[MAX_MULTIBYTE_LENGTH];
          /* Convert a single-byte string to multibyte
             for the *Message* buffer.  */
          for (i = 0; i < len; i++)
            {
              c = unibyte_char_to_multibyte (msg[i]);
-             nbytes = CHAR_STRING (c, work, str);
-             insert_1_both (work, 1, nbytes, 1, 0, 0);
+             nbytes = CHAR_STRING (c, str);
+             insert_1_both (str, 1, nbytes, 1, 0, 0);
            }
        }
       else if (len)
@@ -4834,6 +5057,7 @@ message2_nolog (m, len, multibyte)
      char *m;
      int len;
 {
+  struct frame *sf = SELECTED_FRAME ();
   message_enable_multibyte = multibyte;
 
   if (noninteractive)
@@ -4851,55 +5075,49 @@ message2_nolog (m, len, multibyte)
      initialized yet.  Error messages get reported properly by
      cmd_error, so this must be just an informative message; toss it.  */
   else if (INTERACTIVE 
-          && selected_frame->glyphs_initialized_p
-          && FRAME_MESSAGE_BUF (selected_frame))
+          && sf->glyphs_initialized_p
+          && FRAME_MESSAGE_BUF (sf))
     {
       Lisp_Object mini_window;
       struct frame *f;
 
       /* Get the frame containing the mini-buffer
         that the selected frame is using.  */
-      mini_window = FRAME_MINIBUF_WINDOW (selected_frame);
+      mini_window = FRAME_MINIBUF_WINDOW (sf);
       f = XFRAME (WINDOW_FRAME (XWINDOW (mini_window)));
 
       FRAME_SAMPLE_VISIBILITY (f);
-      if (FRAME_VISIBLE_P (selected_frame)
+      if (FRAME_VISIBLE_P (sf)
          && ! FRAME_VISIBLE_P (f))
        Fmake_frame_visible (WINDOW_FRAME (XWINDOW (mini_window)));
 
       if (m)
        {
-         echo_area_glyphs = m;
-         echo_area_glyphs_length = len;
-         echo_area_message = Qnil;
-
+         set_message (m, Qnil, len, multibyte);
          if (minibuffer_auto_raise)
            Fraise_frame  (WINDOW_FRAME (XWINDOW (mini_window)));
        }
       else
-       {
-         echo_area_glyphs = previous_echo_glyphs = NULL;
-         echo_area_message = previous_echo_area_message = Qnil;
-       }
+       clear_message (1, 1);
 
-      do_pending_window_change ();
+      do_pending_window_change (0);
       echo_area_display (1);
-      do_pending_window_change ();
+      do_pending_window_change (0);
       if (frame_up_to_date_hook != 0 && ! gc_in_progress)
        (*frame_up_to_date_hook) (f);
     }
 }
 
 
-/* Display an echo area message M with a specified length of LEN
-   chars.  The string may include null characters.  If M is not a
+/* Display an echo area message M with a specified length of NBYTES
+   bytes.  The string may include null characters.  If M is not a
    string, clear out any existing message, and let the mini-buffer
    text show through.  */
 
 void
-message3 (m, len, multibyte)
+message3 (m, nbytes, multibyte)
      Lisp_Object m;
-     int len;
+     int nbytes;
      int multibyte;
 {
   struct gcpro gcpro1;
@@ -4909,8 +5127,8 @@ message3 (m, len, multibyte)
   /* First flush out any partial line written with print.  */
   message_log_maybe_newline ();
   if (STRINGP (m))
-    message_dolog (XSTRING (m)->data, len, 1, multibyte);
-  message3_nolog (m, len, multibyte);
+    message_dolog (XSTRING (m)->data, nbytes, 1, multibyte);
+  message3_nolog (m, nbytes, multibyte);
 
   UNGCPRO;
 }
@@ -4919,10 +5137,11 @@ message3 (m, len, multibyte)
 /* The non-logging version of message3.  */
 
 void
-message3_nolog (m, len, multibyte)
+message3_nolog (m, nbytes, multibyte)
      Lisp_Object m;
-     int len, multibyte;
+     int nbytes, multibyte;
 {
+  struct frame *sf = SELECTED_FRAME ();
   message_enable_multibyte = multibyte;
 
   if (noninteractive)
@@ -4931,7 +5150,7 @@ message3_nolog (m, len, multibyte)
        putc ('\n', stderr);
       noninteractive_need_newline = 0;
       if (STRINGP (m))
-       fwrite (XSTRING (m)->data, len, 1, stderr);
+       fwrite (XSTRING (m)->data, nbytes, 1, stderr);
       if (cursor_in_echo_area == 0)
        fprintf (stderr, "\n");
       fflush (stderr);
@@ -4940,40 +5159,36 @@ message3_nolog (m, len, multibyte)
      initialized yet.  Error messages get reported properly by
      cmd_error, so this must be just an informative message; toss it.  */
   else if (INTERACTIVE 
-          && selected_frame->glyphs_initialized_p
-          && FRAME_MESSAGE_BUF (selected_frame))
+          && sf->glyphs_initialized_p
+          && FRAME_MESSAGE_BUF (sf))
     {
       Lisp_Object mini_window;
+      Lisp_Object frame;
       struct frame *f;
 
       /* Get the frame containing the mini-buffer
         that the selected frame is using.  */
-      mini_window = FRAME_MINIBUF_WINDOW (selected_frame);
-      f = XFRAME (WINDOW_FRAME (XWINDOW (mini_window)));
+      mini_window = FRAME_MINIBUF_WINDOW (sf);
+      frame = XWINDOW (mini_window)->frame;
+      f = XFRAME (frame);
 
       FRAME_SAMPLE_VISIBILITY (f);
-      if (FRAME_VISIBLE_P (selected_frame)
-         && ! FRAME_VISIBLE_P (f))
-       Fmake_frame_visible (WINDOW_FRAME (XWINDOW (mini_window)));
+      if (FRAME_VISIBLE_P (sf)
+         && !FRAME_VISIBLE_P (f))
+       Fmake_frame_visible (frame);
 
-      if (STRINGP (m))
+      if (STRINGP (m) && XSTRING (m)->size)
        {
-         echo_area_glyphs = NULL;
-         echo_area_message = m;
-         echo_area_glyphs_length = len;
-
+         set_message (NULL, m, nbytes, multibyte);
          if (minibuffer_auto_raise)
-           Fraise_frame  (WINDOW_FRAME (XWINDOW (mini_window)));
+           Fraise_frame (frame);
        }
       else
-       {
-         echo_area_glyphs = previous_echo_glyphs = NULL;
-         echo_area_message = previous_echo_area_message = Qnil;
-       }
+       clear_message (1, 1);
 
-      do_pending_window_change ();
+      do_pending_window_change (0);
       echo_area_display (1);
-      do_pending_window_change ();
+      do_pending_window_change (0);
       if (frame_up_to_date_hook != 0 && ! gc_in_progress)
        (*frame_up_to_date_hook) (f);
     }
@@ -5033,11 +5248,11 @@ message_with_string (m, string, log)
         It may be larger than the selected frame, so we need
         to use its buffer, not the selected frame's buffer.  */
       Lisp_Object mini_window;
-      FRAME_PTR f;
+      struct frame *f, *sf = SELECTED_FRAME ();
 
       /* Get the frame containing the minibuffer
         that the selected frame is using.  */
-      mini_window = FRAME_MINIBUF_WINDOW (selected_frame);
+      mini_window = FRAME_MINIBUF_WINDOW (sf);
       f = XFRAME (WINDOW_FRAME (XWINDOW (mini_window)));
 
       /* A null message buffer means that the frame hasn't really been
@@ -5067,27 +5282,6 @@ message_with_string (m, string, log)
 }
 
 
-/* Truncate what will be displayed in the echo area
-   the next time we display it--but don't redisplay it now.  */
-
-void
-truncate_echo_area (len)
-     int len;
-{
-  /* A null message buffer means that the frame hasn't really been
-     initialized yet.  Error messages get reported properly by
-     cmd_error, so this must be just an informative message; toss it.  */
-  if (!noninteractive && INTERACTIVE && FRAME_MESSAGE_BUF (selected_frame))
-    echo_area_glyphs_length = len;
-}
-
-
-/* Nonzero if FRAME_MESSAGE_BUF (selected_frame) is being used by
-   print; zero if being used by message.  */
-
-int message_buf_print;
-
-
 /* Dump an informative message to the minibuf.  If M is 0, clear out
    any existing message, and let the mini-buffer text show through.  */
 
@@ -5116,11 +5310,11 @@ message (m, a1, a2, a3)
         on.  It may be larger than the selected frame, so we need to
         use its buffer, not the selected frame's buffer.  */
       Lisp_Object mini_window;
-      struct frame *f;
+      struct frame *f, *sf = SELECTED_FRAME ();
 
       /* Get the frame containing the mini-buffer
         that the selected frame is using.  */
-      mini_window = FRAME_MINIBUF_WINDOW (selected_frame);
+      mini_window = FRAME_MINIBUF_WINDOW (sf);
       f = XFRAME (WINDOW_FRAME (XWINDOW (mini_window)));
 
       /* A null message buffer means that the frame hasn't really been
@@ -5174,59 +5368,716 @@ message_nolog (m, a1, a2, a3)
 }
 
 
-/* Display echo_area_message or echo_area_glyphs in the current
-   mini-buffer.  */
+/* Display the current message in the current mini-buffer.  This is
+   only called from error handlers in process.c, and is not time
+   critical.  */
 
 void
 update_echo_area ()
 {
-  if (STRINGP (echo_area_message))
-    message3 (echo_area_message, echo_area_glyphs_length,
-             !NILP (current_buffer->enable_multibyte_characters));
-  else
-    message2 (echo_area_glyphs, echo_area_glyphs_length,
-             !NILP (current_buffer->enable_multibyte_characters));
+  if (!NILP (echo_area_buffer[0]))
+    {
+      Lisp_Object string;
+      string = Fcurrent_message ();
+      message3 (string, XSTRING (string)->size, 
+               !NILP (current_buffer->enable_multibyte_characters));
+    }
 }
 
 
-/* Redisplay the echo area of selected_frame.  If UPDATE_FRAME_P is
-   non-zero update selected_frame.  */
+/* Make sure echo area buffers in echo_buffers[] are life.  If they
+   aren't, make new ones.  */
 
 static void
-echo_area_display (update_frame_p)
-     int update_frame_p;
+ensure_echo_area_buffers ()
 {
-  Lisp_Object mini_window;
-  struct window *w;
-  struct frame *f;
+  int i;
 
-  mini_window = FRAME_MINIBUF_WINDOW (selected_frame);
-  w = XWINDOW (mini_window);
-  f = XFRAME (WINDOW_FRAME (w));
+  for (i = 0; i < 2; ++i)
+    if (!BUFFERP (echo_buffer[i])
+       || NILP (XBUFFER (echo_buffer[i])->name))
+      {
+       char name[30];
+       sprintf (name, " *Echo Area %d*", i);
+       echo_buffer[i] = Fget_buffer_create (build_string (name));
+       XBUFFER (echo_buffer[i])->truncate_lines = Qnil;
+      }
+}
 
-  /* Don't display if frame is invisible or not yet initialized.  */
-  if (!FRAME_VISIBLE_P (f) 
-      || !f->glyphs_initialized_p)
-    return;
 
-  /* When Emacs starts, selected_frame may be a visible terminal
-     frame, even if we run under a window system.  If we let this
-     through, a message would be displayed on the terminal.  */
-#ifdef HAVE_WINDOW_SYSTEM
-  if (!inhibit_window_system && !FRAME_WINDOW_P (selected_frame))
-    return;
-#endif /* HAVE_WINDOW_SYSTEM */
+/* Call FN with args A1..A5 with either the current or last displayed
+   echo_area_buffer as current buffer.
 
-  /* Redraw garbaged frames.  */
+   WHICH zero means use the current message buffer
+   echo_area_buffer[0].  If that is nil, choose a suitable buffer
+   from echo_buffer[] and clear it.
+
+   WHICH > 0 means use echo_area_buffer[1].  If that is nil, choose a
+   suitable buffer from echo_buffer[] and clear it.
+
+   If WHICH < 0, set echo_area_buffer[1] to echo_area_buffer[0], so
+   that the current message becomes the last displayed one, make
+   choose a suitable buffer for echo_area_buffer[0], and clear it.
+
+   Value is what FN returns. */
+
+static int
+with_echo_area_buffer (w, which, fn, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10)
+     struct window *w;
+     int which;
+     int (*fn) ();
+     int a1, a2, a3, a4, a5, a6, a7, a8, a9, a10;
+{
+  Lisp_Object buffer;
+  int this_one, the_other, clear_buffer_p, rc;
+  int count = specpdl_ptr - specpdl;
+
+  /* If buffers aren't life, make new ones.  */
+  ensure_echo_area_buffers ();
+
+  clear_buffer_p = 0;
+  
+  if (which == 0)
+    this_one = 0, the_other = 1;
+  else if (which > 0)
+    this_one = 1, the_other = 0;
+  else
+    {
+      this_one = 0, the_other = 1;
+      clear_buffer_p = 1;
+      
+      /* We need a fresh one in case the current echo buffer equals
+        the one containing the last displayed echo area message.  */
+      if (!NILP (echo_area_buffer[this_one])
+         && EQ (echo_area_buffer[this_one], echo_area_buffer[the_other]))
+       echo_area_buffer[this_one] = Qnil;
+    }
+
+  /* Choose a suitable buffer from echo_buffer[] is we don't
+     have one.  */
+  if (NILP (echo_area_buffer[this_one]))
+    {
+      echo_area_buffer[this_one]
+       = (EQ (echo_area_buffer[the_other], echo_buffer[this_one])
+          ? echo_buffer[the_other]
+          : echo_buffer[this_one]);
+      clear_buffer_p = 1;
+    }
+
+  buffer = echo_area_buffer[this_one];
+
+  record_unwind_protect (unwind_with_echo_area_buffer,
+                        with_echo_area_buffer_unwind_data (w));
+
+  /* Make the echo area buffer current.  Note that for display
+     purposes, it is not necessary that the displayed window's buffer
+     == current_buffer, except for text property lookup.  So, let's
+     only set that buffer temporarily here without doing a full
+     Fset_window_buffer.  We must also change w->pointm, though,
+     because otherwise an assertions in unshow_buffer fails, and Emacs
+     aborts.  */
+  set_buffer_internal_1 (XBUFFER (buffer));
+  if (w)
+    {
+      w->buffer = buffer;
+      set_marker_both (w->pointm, buffer, BEG, BEG_BYTE);
+    }
+
+  current_buffer->undo_list = Qt;
+  current_buffer->read_only = Qnil;
+
+  if (clear_buffer_p && Z > BEG)
+    del_range (BEG, Z);
+
+  xassert (BEGV >= BEG);
+  xassert (ZV <= Z && ZV >= BEGV);
+
+  rc = fn (a1, a2, a3, a4, a5);
+
+  xassert (BEGV >= BEG);
+  xassert (ZV <= Z && ZV >= BEGV);
+
+  unbind_to (count, Qnil);
+  return rc;
+}
+
+
+/* Save state that should be preserved around the call to the function
+   FN called in with_echo_area_buffer.  */
+
+static Lisp_Object
+with_echo_area_buffer_unwind_data (w)
+     struct window *w;
+{
+  int i = 0;
+  Lisp_Object vector;
+
+  /* Reduce consing by keeping one vector in
+     Vwith_echo_area_save_vector.  */
+  vector = Vwith_echo_area_save_vector;
+  Vwith_echo_area_save_vector = Qnil;
+  
+  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);
+  
+  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);
+    }
+  else
+    {
+      int end = i + 4;
+      while (i < end)
+       XVECTOR (vector)->contents[i++] = Qnil;
+    }
+
+  xassert (i == XVECTOR (vector)->size);
+  return vector;
+}
+
+
+/* Restore global state from VECTOR which was created by
+   with_echo_area_buffer_unwind_data.  */
+
+static Lisp_Object
+unwind_with_echo_area_buffer (vector)
+     Lisp_Object vector;
+{
+  int i = 0;
+  
+  set_buffer_internal_1 (XBUFFER (XVECTOR (vector)->contents[i])); ++i;
+  Vdeactivate_mark = XVECTOR (vector)->contents[i]; ++i;
+  windows_or_buffers_changed = XFASTINT (XVECTOR (vector)->contents[i]); ++i;
+
+  if (WINDOWP (XVECTOR (vector)->contents[i]))
+    {
+      struct window *w;
+      Lisp_Object buffer, charpos, bytepos;
+      
+      w = XWINDOW (XVECTOR (vector)->contents[i]); ++i;
+      buffer = XVECTOR (vector)->contents[i]; ++i;
+      charpos = XVECTOR (vector)->contents[i]; ++i;
+      bytepos = XVECTOR (vector)->contents[i]; ++i;
+      
+      w->buffer = buffer;
+      set_marker_both (w->pointm, buffer,
+                      XFASTINT (charpos), XFASTINT (bytepos));
+    }
+
+  Vwith_echo_area_save_vector = vector;
+  return Qnil;
+}
+
+
+/* Set up the echo area for use by print functions.  MULTIBYTE_P
+   non-zero means we will print multibyte.  */
+
+void
+setup_echo_area_for_printing (multibyte_p)
+     int multibyte_p;
+{
+  ensure_echo_area_buffers ();
+
+  if (!message_buf_print)
+    {
+      /* A message has been output since the last time we printed.
+        Choose a fresh echo area buffer.  */
+      if (EQ (echo_area_buffer[1], echo_buffer[0]))
+       echo_area_buffer[0] = echo_buffer[1]; 
+      else
+       echo_area_buffer[0] = echo_buffer[0];
+
+      /* Switch to that buffer and clear it.  */
+      set_buffer_internal (XBUFFER (echo_area_buffer[0]));
+      if (Z > BEG)
+       del_range (BEG, Z);
+      TEMP_SET_PT_BOTH (BEG, BEG_BYTE);
+
+      /* Set up the buffer for the multibyteness we need.  */
+      if (multibyte_p
+         != !NILP (current_buffer->enable_multibyte_characters))
+       Fset_buffer_multibyte (multibyte_p ? Qt : Qnil);
+
+      /* Raise the frame containing the echo area.  */
+      if (minibuffer_auto_raise)
+       {
+         struct frame *sf = SELECTED_FRAME ();
+         Lisp_Object mini_window;
+         mini_window = FRAME_MINIBUF_WINDOW (sf);
+         Fraise_frame  (WINDOW_FRAME (XWINDOW (mini_window)));
+       }
+
+      message_log_maybe_newline ();
+      message_buf_print = 1;
+    }
+  else
+    {
+      if (NILP (echo_area_buffer[0]))
+       {
+         if (EQ (echo_area_buffer[1], echo_buffer[0]))
+           echo_area_buffer[0] = echo_buffer[1]; 
+         else
+           echo_area_buffer[0] = echo_buffer[0];
+       }
+      
+      if (current_buffer != XBUFFER (echo_area_buffer[0]))
+       /* Someone switched buffers between print requests.  */
+       set_buffer_internal (XBUFFER (echo_area_buffer[0]));
+    }
+}
+
+
+/* Display an echo area message in window W.  Value is non-zero if W's
+   height is changed.  If display_last_displayed_message_p is
+   non-zero, display the message that was last displayed, otherwise
+   display the current message.  */
+
+static int
+display_echo_area (w)
+     struct window *w;
+{
+  int i, no_message_p, window_height_changed_p, count;
+
+  /* Temporarily disable garbage collections while displaying the echo
+     area.  This is done because a GC can print a message itself.
+     That message would modify the echo area buffer's contents while a
+     redisplay of the buffer is going on, and seriously confuse
+     redisplay.  */
+  count = inhibit_garbage_collection ();
+
+  /* If there is no message, we must call display_echo_area_1
+     nevertheless because it resizes the window.  But we will have to
+     reset the echo_area_buffer in question to nil at the end because
+     with_echo_area_buffer will sets it to an empty buffer.  */
+  i = display_last_displayed_message_p ? 1 : 0;
+  no_message_p = NILP (echo_area_buffer[i]);
+  
+  window_height_changed_p
+    = with_echo_area_buffer (w, display_last_displayed_message_p,
+                            (int (*) ()) display_echo_area_1, w);
+
+  if (no_message_p)
+    echo_area_buffer[i] = Qnil;
+
+  unbind_to (count, Qnil);
+  return window_height_changed_p;
+}
+
+
+/* Helper for display_echo_area.  Display the current buffer which
+   contains the current echo area message in window W, a mini-window.
+   Change the height of W so that all of the message is displayed.
+   Value is non-zero if height of W was changed.  */
+
+static int
+display_echo_area_1 (w)
+     struct window *w;
+{
+  Lisp_Object window;
+  struct text_pos start;
+  int window_height_changed_p = 0;
+
+  /* Do this before displaying, so that we have a large enough glyph
+     matrix for the display.  */
+  window_height_changed_p = resize_mini_window (w, 0);
+
+  /* Display.  */
+  clear_glyph_matrix (w->desired_matrix);
+  XSETWINDOW (window, w);
+  SET_TEXT_POS (start, BEG, BEG_BYTE);
+  try_window (window, start);
+
+  return window_height_changed_p;
+}
+
+
+/* Resize the echo area window to exactly the size needed for the
+   currently displayed message, if there is one.  */
+
+void
+resize_echo_area_axactly ()
+{
+  if (BUFFERP (echo_area_buffer[0])
+      && WINDOWP (echo_area_window))
+    {
+      struct window *w = XWINDOW (echo_area_window);
+      int resized_p;
+      
+      resized_p = with_echo_area_buffer (w, 0,
+                                        (int (*) ()) resize_mini_window,
+                                        w, 1);
+      if (resized_p)
+       {
+         ++windows_or_buffers_changed;
+         ++update_mode_lines;
+         redisplay_internal (0);
+       }
+    }
+}
+
+
+/* Resize mini-window W to fit the size of its contents.  EXACT:P
+   means size the window exactly to the size needed.  Otherwise, it's
+   only enlarged until W's buffer is empty.  Value is non-zero if
+   the window height has been changed. */
+
+int
+resize_mini_window (w, exact_p)
+     struct window *w;
+     int exact_p;
+{
+  struct frame *f = XFRAME (w->frame);
+  int window_height_changed_p = 0;
+
+  xassert (MINI_WINDOW_P (w));
+
+  /* Nil means don't try to resize.  */
+  if (NILP (Vmax_mini_window_height)
+      || (FRAME_X_P (f) && f->output_data.x == NULL))
+    return 0;
+  
+  if (!FRAME_MINIBUF_ONLY_P (f))
+    {
+      struct it it;
+      struct window *root = XWINDOW (FRAME_ROOT_WINDOW (f));
+      int total_height = XFASTINT (root->height) + XFASTINT (w->height);
+      int height, max_height;
+      int unit = CANON_Y_UNIT (f);
+      struct text_pos start;
+
+      init_iterator (&it, w, BEGV, BEGV_BYTE, NULL, DEFAULT_FACE_ID);
+
+      /* Compute the max. number of lines specified by the user.  */
+      if (FLOATP (Vmax_mini_window_height))
+       max_height = XFLOATINT (Vmax_mini_window_height) * total_height;
+      else if (INTEGERP (Vmax_mini_window_height))
+       max_height = XINT (Vmax_mini_window_height);
+      else
+       max_height = total_height / 4;
+      
+      /* Correct that max. height if it's bogus. */
+      max_height = max (1, max_height);
+      max_height = min (total_height, max_height);
+      
+      /* Find out the height of the text in the window.  */
+      if (it.truncate_lines_p)
+       height = 1;
+      else
+       {
+         last_height = 0;
+         move_it_to (&it, ZV, -1, -1, -1, MOVE_TO_POS);
+         if (it.max_ascent == 0 && it.max_descent == 0)
+           height = it.current_y + last_height;
+         else
+           height = it.current_y + it.max_ascent + it.max_descent;
+         height = (height + unit - 1) / unit;
+       }
+      
+      /* Compute a suitable window start.  */
+      if (height > max_height)
+       {
+         height = max_height;
+         init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID);
+         move_it_vertically_backward (&it, (height - 1) * unit);
+         start = it.current.pos;
+       }
+      else
+       SET_TEXT_POS (start, BEGV, BEGV_BYTE);
+      SET_MARKER_FROM_TEXT_POS (w->start, start);
+
+      /* Let it grow only, until we display an empty message, in which
+        case the window shrinks again.  */
+      if (height > XFASTINT (w->height))
+       {
+         int old_height = XFASTINT (w->height);
+         freeze_window_starts (f, 1);
+         grow_mini_window (w, height - XFASTINT (w->height));
+         window_height_changed_p = XFASTINT (w->height) != old_height;
+       }
+      else if (height < XFASTINT (w->height)
+              && (exact_p || BEGV == ZV))
+       {
+         int old_height = XFASTINT (w->height);
+         freeze_window_starts (f, 0);
+         shrink_mini_window (w);
+         window_height_changed_p = XFASTINT (w->height) != old_height;
+       }
+    }
+
+  return window_height_changed_p;
+}
+
+
+/* Value is the current message, a string, or nil if there is no
+   current message.  */
+
+Lisp_Object
+current_message ()
+{
+  Lisp_Object msg;
+
+  if (NILP (echo_area_buffer[0]))
+    msg = Qnil;
+  else
+    {
+      with_echo_area_buffer (0, 0, (int (*) ()) current_message_1, &msg);
+      if (NILP (msg))
+       echo_area_buffer[0] = Qnil;
+    }
+  
+  return msg;
+}
+
+
+static int
+current_message_1 (msg)
+     Lisp_Object *msg;
+{
+  if (Z > BEG)
+    *msg = make_buffer_string (BEG, Z, 1);
+  else
+    *msg = Qnil;
+  return 0;
+}
+
+
+/* Push the current message on Vmessage_stack for later restauration
+   by restore_message.  Value is non-zero if the current message isn't
+   empty.  This is a relatively infrequent operation, so it's not
+   worth optimizing.  */
+
+int
+push_message ()
+{
+  Lisp_Object msg;
+  msg = current_message ();
+  Vmessage_stack = Fcons (msg, Vmessage_stack);
+  return STRINGP (msg);
+}
+
+
+/* Restore message display from the top of Vmessage_stack.  */
+
+void
+restore_message ()
+{
+  Lisp_Object msg;
+  
+  xassert (CONSP (Vmessage_stack));
+  msg = XCAR (Vmessage_stack);
+  if (STRINGP (msg))
+    message3_nolog (msg, STRING_BYTES (XSTRING (msg)), STRING_MULTIBYTE (msg));
+  else
+    message3_nolog (msg, 0, 0);
+}
+
+
+/* Pop the top-most entry off Vmessage_stack.  */
+
+void
+pop_message ()
+{
+  xassert (CONSP (Vmessage_stack));
+  Vmessage_stack = XCDR (Vmessage_stack);
+}
+
+
+/* Check that Vmessage_stack is nil.  Called from emacs.c when Emacs
+   exits.  If the stack is not empty, we have a missing pop_message
+   somewhere.  */
+
+void
+check_message_stack ()
+{
+  if (!NILP (Vmessage_stack))
+    abort ();
+}
+
+
+/* Truncate to NCHARS what will be displayed in the echo area the next
+   time we display it---but don't redisplay it now.  */
+
+void
+truncate_echo_area (nchars)
+     int nchars;
+{
+  if (nchars == 0)
+    echo_area_buffer[0] = Qnil;
+  /* A null message buffer means that the frame hasn't really been
+     initialized yet.  Error messages get reported properly by
+     cmd_error, so this must be just an informative message; toss it.  */
+  else if (!noninteractive
+          && INTERACTIVE
+          && !NILP (echo_area_buffer[0]))
+    {
+      struct frame *sf = SELECTED_FRAME ();
+      if (FRAME_MESSAGE_BUF (sf))
+       with_echo_area_buffer (0, 0, (int (*) ()) truncate_message_1, nchars);
+    }
+}
+
+
+/* Helper function for truncate_echo_area.  Truncate the current
+   message to at most NCHARS characters.  */
+
+static int
+truncate_message_1 (nchars)
+     int nchars;
+{
+  if (BEG + nchars < Z)
+    del_range (BEG + nchars, Z);
+  if (Z == BEG)
+    echo_area_buffer[0] = Qnil;
+  return 0;
+}
+
+
+/* Set the current message to a substring of S or STRING.
+
+   If STRING is a Lisp string, set the message to the first NBYTES
+   bytes from STRING.  NBYTES zero means use the whole string.  If
+   STRING is multibyte, the message will be displayed multibyte.
+
+   If S is not null, set the message to the first LEN bytes of S.  LEN
+   zero means use the whole string.  MULTIBYTE_P non-zero means S is
+   multibyte.  Display the message multibyte in that case.  */
+
+void
+set_message (s, string, nbytes, multibyte_p)
+     char *s;
+     Lisp_Object string;
+     int nbytes;
+{
+  message_enable_multibyte
+    = ((s && multibyte_p)
+       || (STRINGP (string) && STRING_MULTIBYTE (string)));
+  
+  with_echo_area_buffer (0, -1, (int (*) ()) set_message_1,
+                        s, string, nbytes, multibyte_p);
+  message_buf_print = 0;
+}
+
+
+/* Helper function for set_message.  Arguments have the same meaning
+   as there.  This function is called with the echo area buffer being
+   current.  */
+
+static int
+set_message_1 (s, string, nbytes, multibyte_p)
+     char *s;
+     Lisp_Object string;
+     int nbytes, multibyte_p;
+{
+  xassert (BEG == Z);
+  
+  /* Change multibyteness of the echo buffer appropriately.  */
+  if (message_enable_multibyte
+      != !NILP (current_buffer->enable_multibyte_characters))
+    Fset_buffer_multibyte (message_enable_multibyte ? Qt : Qnil);
+
+  current_buffer->truncate_lines = message_truncate_lines ? Qt : Qnil;
+  
+  /* Insert new message at BEG.  */
+  TEMP_SET_PT_BOTH (BEG, BEG_BYTE);
+
+  if (STRINGP (string))
+    {
+      int nchars;
+      
+      if (nbytes == 0)
+       nbytes = XSTRING (string)->size_byte;
+      nchars = string_byte_to_char (string, nbytes);
+      
+      /* This function takes care of single/multibyte conversion.  We
+         just have to ensure that the echo area buffer has the right
+         setting of enable_multibyte_characters.  */
+      insert_from_string (string, 0, 0, nchars, nbytes, 1);
+    }
+  else if (s)
+    {
+      if (nbytes == 0)
+       nbytes = strlen (s);
+      
+      if (multibyte_p && NILP (current_buffer->enable_multibyte_characters))
+       {
+         /* Convert from multi-byte to single-byte.  */
+         int i, c, n;
+         unsigned char work[1];
+         
+         /* Convert a multibyte string to single-byte.  */
+         for (i = 0; i < nbytes; i += n)
+           {
+             c = string_char_and_length (s + i, nbytes - i, &n);
+             work[0] = (SINGLE_BYTE_CHAR_P (c)
+                        ? c
+                        : multibyte_char_to_unibyte (c, Qnil));
+             insert_1_both (work, 1, 1, 1, 0, 0);
+           }
+       }
+      else if (!multibyte_p
+              && !NILP (current_buffer->enable_multibyte_characters))
+       {
+         /* Convert from single-byte to multi-byte.  */
+         int i, c, n;
+         unsigned char *msg = (unsigned char *) s;
+         unsigned char str[MAX_MULTIBYTE_LENGTH];
+      
+         /* Convert a single-byte string to multibyte.  */
+         for (i = 0; i < nbytes; i++)
+           {
+             c = unibyte_char_to_multibyte (msg[i]);
+             n = CHAR_STRING (c, str);
+             insert_1_both (str, 1, n, 1, 0, 0);
+           }
+       }
+      else
+       insert_1 (s, nbytes, 1, 0, 0);
+    }
+
+  return 0;
+}
+
+
+/* Clear messages.  CURRENT_P non-zero means clear the current
+   message.  LAST_DISPLAYED_P non-zero means clear the message
+   last displayed.  */
+
+void
+clear_message (current_p, last_displayed_p)
+     int current_p, last_displayed_p;
+{
+  if (current_p)
+    echo_area_buffer[0] = Qnil;
+  
+  if (last_displayed_p)
+    echo_area_buffer[1] = Qnil;
+  
+  message_buf_print = 0;
+}
+
+/* Clear garbaged frames.
+
+   This function is used where the old redisplay called
+   redraw_garbaged_frames which in turn called redraw_frame which in
+   turn called clear_frame.  The call to clear_frame was a source of
+   flickering.  I believe a clear_frame is not necessary.  It should
+   suffice in the new redisplay to invalidate all current matrices,
+   and ensure a complete redisplay of all windows.  */
+
+static void
+clear_garbaged_frames ()
+{
   if (frame_garbaged)
     {
-      /* Old redisplay called redraw_garbaged_frames here which in
-        turn called redraw_frame which in turn called clear_frame.
-        The call to clear_frame is a source of flickering.  After
-        checking the places where SET_FRAME_GARBAGED is called, I
-        believe a clear_frame is not necessary.  It should suffice in
-        the new redisplay to invalidate all current matrices, and
-        ensure a complete redisplay of all windows.  */
       Lisp_Object tail, frame;
       
       FOR_EACH_FRAME (tail, frame)
@@ -5243,57 +6094,63 @@ echo_area_display (update_frame_p)
       frame_garbaged = 0;
       ++windows_or_buffers_changed;
     }
+}
 
-  if (echo_area_glyphs
-      || STRINGP (echo_area_message)
-      || minibuf_level == 0)
-    {
-      struct it it;
 
-      echo_area_window = mini_window;
-      clear_glyph_matrix (w->desired_matrix);
-      init_iterator (&it, w, -1, -1, w->desired_matrix->rows, DEFAULT_FACE_ID);
-      
-      if (STRINGP (echo_area_message)
-         && echo_area_glyphs_length)
-       {
-         prepare_desired_row (it.glyph_row);
-         display_string (NULL, echo_area_message, Qnil, 0, 0,
-                         &it, -1, echo_area_glyphs_length, 0,
-                         message_enable_multibyte);
-         it.glyph_row->truncated_on_right_p = 0;
-         compute_line_metrics (&it);
-       }
-      else if (echo_area_glyphs
-              && echo_area_glyphs_length)
-       {
-         prepare_desired_row (it.glyph_row);
-         display_string (echo_area_glyphs, Qnil, Qnil, 0, 0, &it,
-                         -1, echo_area_glyphs_length, 0,
-                         message_enable_multibyte);
-         it.glyph_row->truncated_on_right_p = 0;
-         compute_line_metrics (&it);
-       }
-      else
-       blank_row (w, it.glyph_row, 0);
-      
-      it.glyph_row->y = it.current_y;
-      it.current_y += it.glyph_row->height;
+/* Redisplay the echo area of the selected frame.  If UPDATE_FRAME_P
+   is non-zero update selected_frame.  Value is non-zero if the
+   mini-windows height has been changed.  */
 
-      /* Clear the rest of the lines.  */
-      while (it.current_y < it.last_visible_y)
-       {
-         ++it.glyph_row;
-         blank_row (w, it.glyph_row, it.current_y);
-         it.current_y += it.glyph_row->height;
-       }
+static int
+echo_area_display (update_frame_p)
+     int update_frame_p;
+{
+  Lisp_Object mini_window;
+  struct window *w;
+  struct frame *f;
+  int window_height_changed_p = 0;
+  struct frame *sf = SELECTED_FRAME ();
+
+  mini_window = FRAME_MINIBUF_WINDOW (sf);
+  w = XWINDOW (mini_window);
+  f = XFRAME (WINDOW_FRAME (w));
+
+  /* Don't display if frame is invisible or not yet initialized.  */
+  if (!FRAME_VISIBLE_P (f) || !f->glyphs_initialized_p)
+    return 0;
 
+#ifdef HAVE_WINDOW_SYSTEM
+  /* When Emacs starts, selected_frame may be a visible terminal
+     frame, even if we run under a window system.  If we let this
+     through, a message would be displayed on the terminal.  */
+  if (EQ (selected_frame, Vterminal_frame) 
+      && !NILP (Vwindow_system))
+    return 0;
+#endif /* HAVE_WINDOW_SYSTEM */
+
+  /* Redraw garbaged frames.  */
+  if (frame_garbaged)
+    clear_garbaged_frames ();
+
+  if (!NILP (echo_area_buffer[0]) || minibuf_level == 0)
+    {
+      echo_area_window = mini_window;
+      window_height_changed_p = display_echo_area (w);
       w->must_be_updated_p = 1;
+
       if (update_frame_p)
        {
-         /* Calling update_single_window is faster when we can use
-            window-based redisplay.  */
-         if (FRAME_WINDOW_P (f))
+         /* Not called from redisplay_internal.  If we changed
+            window configuration, we must redisplay thoroughly.
+            Otherwise, we can do with updating what we displayed
+            above.  */
+         if (window_height_changed_p)
+           {
+             ++windows_or_buffers_changed;
+             ++update_mode_lines;
+             redisplay_internal (0);
+           }
+         else if (FRAME_WINDOW_P (f))
            {
              update_single_window (w, 1);
              rif->flush_display (f);
@@ -5305,15 +6162,16 @@ echo_area_display (update_frame_p)
   else if (!EQ (mini_window, selected_window))
     windows_or_buffers_changed++;
 
+  /* Last displayed message is now the current message.  */
+  echo_area_buffer[1] = echo_area_buffer[0];
+      
   /* Prevent redisplay optimization in redisplay_internal by resetting
      this_line_start_pos.  This is done because the mini-buffer now
      displays the message instead of its buffer text.  */
   if (EQ (mini_window, selected_window))
     CHARPOS (this_line_start_pos) = 0;
-  
-  previous_echo_glyphs = echo_area_glyphs;
-  previous_echo_area_message = echo_area_message;
-  previous_echo_glyphs_length = echo_area_glyphs_length;
+
+  return window_height_changed_p;
 }
 
 
@@ -5414,9 +6272,9 @@ x_consider_frame_title (frame)
       int len;
       struct it it;
 
-      for (tail = Vframe_list; CONSP (tail); tail = XCONS (tail)->cdr)
+      for (tail = Vframe_list; CONSP (tail); tail = XCDR (tail))
        {
-         struct frame *tf = XFRAME (XCONS (tail)->car);
+         struct frame *tf = XFRAME (XCAR (tail));
 
          if (tf != f 
              && FRAME_KBOARD (tf) == FRAME_KBOARD (f)
@@ -5545,7 +6403,7 @@ prepare_menu_bars ()
          GCPRO1 (tail);
          update_menu_bar (f, 0);
 #ifdef HAVE_WINDOW_SYSTEM
-         update_toolbar (f, 0);
+         update_tool_bar (f, 0);
 #endif
          UNGCPRO;
        }
@@ -5554,9 +6412,10 @@ prepare_menu_bars ()
     }
   else
     {
-      update_menu_bar (selected_frame, 1);
+      struct frame *sf = SELECTED_FRAME ();
+      update_menu_bar (sf, 1);
 #ifdef HAVE_WINDOW_SYSTEM
-      update_toolbar (selected_frame, 1);
+      update_tool_bar (sf, 1);
 #endif
     }
 
@@ -5659,23 +6518,23 @@ update_menu_bar (f, save_match_data)
 
 \f
 /***********************************************************************
-                              Toolbars
+                              Tool-bars
  ***********************************************************************/
 
 #ifdef HAVE_WINDOW_SYSTEM
 
-/* Update the toolbar item list for frame F.  This has to be done
+/* Update the tool-bar item list for frame F.  This has to be done
    before we start to fill in any display lines.  Called from
    prepare_menu_bars.  If SAVE_MATCH_DATA is non-zero, we must save
    and restore it here.  */
 
 static void
-update_toolbar (f, save_match_data)
+update_tool_bar (f, save_match_data)
      struct frame *f;
      int save_match_data;
 {
-  if (WINDOWP (f->toolbar_window)
-      && XFASTINT (XWINDOW (f->toolbar_window)->height) > 0)
+  if (WINDOWP (f->tool_bar_window)
+      && XFASTINT (XWINDOW (f->tool_bar_window)->height) > 0)
     {
       Lisp_Object window;
       struct window *w;
@@ -5718,12 +6577,12 @@ update_toolbar (f, save_match_data)
              specbind (Qoverriding_local_map, Qnil);
            }
 
-         /* Build desired toolbar items from keymaps.  */
-         f->desired_toolbar_items
-           = toolbar_items (f->desired_toolbar_items,
-                            &f->n_desired_toolbar_items);
+         /* Build desired tool-bar items from keymaps.  */
+         f->desired_tool_bar_items
+           = tool_bar_items (f->desired_tool_bar_items,
+                             &f->n_desired_tool_bar_items);
          
-         /* Redisplay the toolbar in case we changed it.  */
+         /* Redisplay the tool-bar in case we changed it.  */
          w->update_mode_line = Qt;
 
          unbind_to (count, Qnil);
@@ -5733,12 +6592,12 @@ update_toolbar (f, save_match_data)
 }
 
 
-/* Set F->desired_toolbar_string to a Lisp string representing frame
-   F's desired toolbar contents.  F->desired_toolbar_items must have
+/* Set F->desired_tool_bar_string to a Lisp string representing frame
+   F's desired tool-bar contents.  F->desired_tool_bar_items must have
    been set up previously by calling prepare_menu_bars.  */
 
 static void
-build_desired_toolbar_string (f)
+build_desired_tool_bar_string (f)
      struct frame *f;
 {
   int i, size, size_needed, string_idx;
@@ -5748,60 +6607,61 @@ build_desired_toolbar_string (f)
   image = plist = props = Qnil;
   GCPRO3 (image, plist, props);
 
-  /* Prepare F->desired_toolbar_string.  If we can reuse it, do so.
+  /* Prepare F->desired_tool_bar_string.  If we can reuse it, do so.
      Otherwise, make a new string.  */
   
   /* The size of the string we might be able to reuse.  */
-  size = (STRINGP (f->desired_toolbar_string)
-         ? XSTRING (f->desired_toolbar_string)->size
+  size = (STRINGP (f->desired_tool_bar_string)
+         ? 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_desired_toolbar_items + 1;
+  size_needed = f->n_desired_tool_bar_items + 1;
 
-  /* Reuse f->desired_toolbar_string, if possible.  */
+  /* Reuse f->desired_tool_bar_string, if possible.  */
   if (size < size_needed)
-    f->desired_toolbar_string = Fmake_string (make_number (size_needed), ' ');
+    f->desired_tool_bar_string = Fmake_string (make_number (size_needed),
+                                              make_number (' '));
   else
     {
       props = list4 (Qdisplay, Qnil, Qmenu_item, Qnil);
       Fremove_text_properties (make_number (0), make_number (size),
-                              props, f->desired_toolbar_string);
+                              props, f->desired_tool_bar_string);
     }
 
   /* Put a `display' property on the string for the images to display,
-     put a `menu_item' property on toolbar items with a value that
-     is the index of the item in F's toolbar item vector.  */
+     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_desired_toolbar_items;
+       i < f->n_desired_tool_bar_items;
        ++i, string_idx += 1)
     {
 #define PROP(IDX)                                      \
-      (XVECTOR (f->desired_toolbar_items)              \
-       ->contents[i * TOOLBAR_ITEM_NSLOTS + (IDX)])
+      (XVECTOR (f->desired_tool_bar_items)             \
+       ->contents[i * TOOL_BAR_ITEM_NSLOTS + (IDX)])
 
-      int enabled_p = !NILP (PROP (TOOLBAR_ITEM_ENABLED_P));
-      int selected_p = !NILP (PROP (TOOLBAR_ITEM_SELECTED_P));
+      int enabled_p = !NILP (PROP (TOOL_BAR_ITEM_ENABLED_P));
+      int selected_p = !NILP (PROP (TOOL_BAR_ITEM_SELECTED_P));
       int margin, relief;
       extern Lisp_Object QCrelief, QCmargin, QCalgorithm, Qimage;
       extern Lisp_Object Qlaplace;
 
       /* If image is a vector, choose the image according to the
         button state.  */
-      image = PROP (TOOLBAR_ITEM_IMAGES);
+      image = PROP (TOOL_BAR_ITEM_IMAGES);
       if (VECTORP (image))
        {
-         enum toolbar_item_image idx;
+         enum tool_bar_item_image idx;
          
          if (enabled_p)
            idx = (selected_p
-                  ? TOOLBAR_IMAGE_ENABLED_SELECTED
-                  : TOOLBAR_IMAGE_ENABLED_DESELECTED);
+                  ? TOOL_BAR_IMAGE_ENABLED_SELECTED
+                  : TOOL_BAR_IMAGE_ENABLED_DESELECTED);
          else
            idx = (selected_p
-                  ? TOOLBAR_IMAGE_DISABLED_SELECTED
-                  : TOOLBAR_IMAGE_DISABLED_DESELECTED);
+                  ? TOOL_BAR_IMAGE_DISABLED_SELECTED
+                  : TOOL_BAR_IMAGE_DISABLED_DESELECTED);
          
          xassert (XVECTOR (image)->size >= idx);
          image = XVECTOR (image)->contents[idx];
@@ -5811,14 +6671,14 @@ build_desired_toolbar_string (f)
       if (!valid_image_p (image))
        continue;
 
-      /* Display the toolbar button pressed, or depressed.  */
+      /* Display the tool-bar button pressed, or depressed.  */
       plist = Fcopy_sequence (XCDR (image));
 
       /* Compute margin and relief to draw.  */
-      relief = toolbar_button_relief > 0 ? toolbar_button_relief : 3;
-      margin = relief + max (0, toolbar_button_margin);
+      relief = tool_bar_button_relief > 0 ? tool_bar_button_relief : 3;
+      margin = relief + max (0, tool_bar_button_margin);
       
-      if (auto_raise_toolbar_buttons_p)
+      if (auto_raise_tool_bar_buttons_p)
        {
          /* Add a `:relief' property to the image spec if the item is
             selected.  */
@@ -5851,14 +6711,14 @@ build_desired_toolbar_string (f)
       
       /* Put a `display' text property on the string for the image to
         display.  Put a `menu-item' property on the string that gives
-        the start of this item's properties in the toolbar items
+        the start of this item's properties in the tool-bar items
         vector.  */
       image = Fcons (Qimage, plist);
       props = list4 (Qdisplay, image,
-                    Qmenu_item, make_number (i * TOOLBAR_ITEM_NSLOTS)),
+                    Qmenu_item, make_number (i * TOOL_BAR_ITEM_NSLOTS)),
       Fadd_text_properties (make_number (string_idx),
                            make_number (string_idx + 1),
-                           props, f->desired_toolbar_string);
+                           props, f->desired_tool_bar_string);
 #undef PROP
     }
 
@@ -5866,10 +6726,10 @@ build_desired_toolbar_string (f)
 }
 
 
-/* Display one line of the toolbar of frame IT->f.  */
+/* Display one line of the tool-bar of frame IT->f.  */
 
 static void
-display_toolbar_line (it)
+display_tool_bar_line (it)
      struct it *it;
 {
   struct glyph_row *row = it->glyph_row;
@@ -5927,7 +6787,7 @@ display_toolbar_line (it)
   last->right_box_line_p = 1;
   compute_line_metrics (it);
   
-  /* If line is empty, make it occupy the rest of the toolbar.  */
+  /* If line is empty, make it occupy the rest of the tool-bar.  */
   if (!row->displays_text_p)
     {
       row->height = row->phys_height = it->last_visible_y - row->y;
@@ -5946,39 +6806,39 @@ display_toolbar_line (it)
 }
 
 
-/* Value is the number of screen lines needed to make all toolbar
+/* Value is the number of screen lines needed to make all tool-bar
    items of frame F visible.  */
 
 static int
-toolbar_lines_needed (f)
+tool_bar_lines_needed (f)
      struct frame *f;
 {
-  struct window *w = XWINDOW (f->toolbar_window);
+  struct window *w = XWINDOW (f->tool_bar_window);
   struct it it;
   
-  /* Initialize an iterator for iteration over F->desired_toolbar_string
-     in the toolbar window of frame F.  */
-  init_iterator (&it, w, -1, -1, w->desired_matrix->rows, TOOLBAR_FACE_ID);
+  /* Initialize an iterator for iteration over
+     F->desired_tool_bar_string in the tool-bar window of frame F.  */
+  init_iterator (&it, w, -1, -1, w->desired_matrix->rows, TOOL_BAR_FACE_ID);
   it.first_visible_x = 0;
   it.last_visible_x = FRAME_WINDOW_WIDTH (f) * CANON_X_UNIT (f);
-  reseat_to_string (&it, NULL, f->desired_toolbar_string, 0, 0, 0, -1);
+  reseat_to_string (&it, NULL, f->desired_tool_bar_string, 0, 0, 0, -1);
 
   while (!ITERATOR_AT_END_P (&it))
     {
       it.glyph_row = w->desired_matrix->rows;
       clear_glyph_row (it.glyph_row);
-      display_toolbar_line (&it);
+      display_tool_bar_line (&it);
     }
 
   return (it.current_y + CANON_Y_UNIT (f) - 1) / CANON_Y_UNIT (f);
 }
 
 
-/* Display the toolbar of frame F.  Value is non-zero if toolbar's
+/* Display the tool-bar of frame F.  Value is non-zero if tool-bar's
    height should be changed.  */
 
 static int
-redisplay_toolbar (f)
+redisplay_tool_bar (f)
      struct frame *f;
 {
   struct window *w;
@@ -5986,65 +6846,65 @@ redisplay_toolbar (f)
   struct glyph_row *row;
   int change_height_p = 0;
   
-  /* If frame hasn't a toolbar window or if it is zero-height, don't
-     do anything.  This means you must start with toolbar-lines
+  /* If frame hasn't a tool-bar window or if it is zero-height, don't
+     do anything.  This means you must start with tool-bar-lines
      non-zero to get the auto-sizing effect.  Or in other words, you
-     can turn off toolbars by specifying toolbar-lines zero.  */
-  if (!WINDOWP (f->toolbar_window)
-      || (w = XWINDOW (f->toolbar_window),
+     can turn off tool-bars by specifying tool-bar-lines zero.  */
+  if (!WINDOWP (f->tool_bar_window)
+      || (w = XWINDOW (f->tool_bar_window),
          XFASTINT (w->height) == 0))
     return 0;
 
-  /* Set up an iterator for the toolbar window.  */
-  init_iterator (&it, w, -1, -1, w->desired_matrix->rows, TOOLBAR_FACE_ID);
+  /* Set up an iterator for the tool-bar window.  */
+  init_iterator (&it, w, -1, -1, w->desired_matrix->rows, TOOL_BAR_FACE_ID);
   it.first_visible_x = 0;
   it.last_visible_x = FRAME_WINDOW_WIDTH (f) * CANON_X_UNIT (f);
   row = it.glyph_row;
 
-  /* Build a string that represents the contents of the toolbar.  */
-  build_desired_toolbar_string (f);
-  reseat_to_string (&it, NULL, f->desired_toolbar_string, 0, 0, 0, -1);
+  /* Build a string that represents the contents of the tool-bar.  */
+  build_desired_tool_bar_string (f);
+  reseat_to_string (&it, NULL, f->desired_tool_bar_string, 0, 0, 0, -1);
 
-  /* Display as many lines as needed to display all toolbar items.  */
+  /* Display as many lines as needed to display all tool-bar items.  */
   while (it.current_y < it.last_visible_y)
-    display_toolbar_line (&it);
+    display_tool_bar_line (&it);
 
-  /* It doesn't make much sense to try scrolling in the toolbar
+  /* It doesn't make much sense to try scrolling in the tool-bar
      window, so don't do it.  */
   w->desired_matrix->no_scrolling_p = 1;
   w->must_be_updated_p = 1;
 
-  if (auto_resize_toolbars_p)
+  if (auto_resize_tool_bars_p)
     {
       int nlines;
       
       /* If there are blank lines at the end, except for a partially
         visible blank line at the end that is smaller than
-        CANON_Y_UNIT, change the toolbar's height.  */
+        CANON_Y_UNIT, change the tool-bar's height.  */
       row = it.glyph_row - 1;
       if (!row->displays_text_p
          && row->height >= CANON_Y_UNIT (f))
        change_height_p = 1;
 
-      /* If row displays toolbar items, but is partially visible,
-        change the toolbar's height.  */
+      /* If row displays tool-bar items, but is partially visible,
+        change the tool-bar's height.  */
       if (row->displays_text_p
          && MATRIX_ROW_BOTTOM_Y (row) > it.last_visible_y)
        change_height_p = 1;
 
-      /* Resize windows as needed by changing the `toolbar-lines'
+      /* Resize windows as needed by changing the `tool-bar-lines'
         frame parameter.  */
       if (change_height_p
-         && (nlines = toolbar_lines_needed (f),
+         && (nlines = tool_bar_lines_needed (f),
              nlines != XFASTINT (w->height)))
        {
-         extern Lisp_Object Qtoolbar_lines;
+         extern Lisp_Object Qtool_bar_lines;
          Lisp_Object frame;
          
          XSETFRAME (frame, f);
          clear_glyph_matrix (w->desired_matrix);
          Fmodify_frame_parameters (frame,
-                                   Fcons (Fcons (Qtoolbar_lines,
+                                   Fcons (Fcons (Qtool_bar_lines,
                                                  make_number (nlines)),
                                           Qnil));
          fonts_changed_p = 1;
@@ -6055,13 +6915,13 @@ redisplay_toolbar (f)
 }
 
 
-/* Get information about the toolbar item which is displayed in GLYPH
-   on frame F.  Return in *PROP_IDX the index where toolbar item
-   properties start in F->current_toolbar_items.  Value is zero if
-   GLYPH doesn't display a toolbar item.  */
+/* Get information about the tool-bar item which is displayed in GLYPH
+   on frame F.  Return in *PROP_IDX the index where tool-bar item
+   properties start in F->current_tool_bar_items.  Value is zero if
+   GLYPH doesn't display a tool-bar item.  */
 
 int
-toolbar_item_info (f, glyph, prop_idx)
+tool_bar_item_info (f, glyph, prop_idx)
      struct frame *f;
      struct glyph *glyph;
      int *prop_idx;
@@ -6071,9 +6931,9 @@ toolbar_item_info (f, glyph, prop_idx)
   
   /* Get the text property `menu-item' at pos. The value of that
      property is the start index of this item's properties in
-     F->current_toolbar_items.  */
+     F->current_tool_bar_items.  */
   prop = Fget_text_property (make_number (glyph->charpos),
-                            Qmenu_item, f->current_toolbar_string);
+                            Qmenu_item, f->current_tool_bar_string);
   if (INTEGERP (prop))
     {
       *prop_idx = XINT (prop);
@@ -6120,8 +6980,14 @@ hscroll_window_tree (window)
        {
          int hscroll_margin, text_area_x, text_area_y;
          int text_area_width, text_area_height;
-         struct glyph_row *cursor_row = MATRIX_ROW (w->current_matrix,
-                                                    w->cursor.vpos);
+         struct glyph_row *current_cursor_row
+           = MATRIX_ROW (w->current_matrix, w->cursor.vpos);
+         struct glyph_row *desired_cursor_row
+           = MATRIX_ROW (w->desired_matrix, w->cursor.vpos);
+         struct glyph_row *cursor_row
+           = (desired_cursor_row->enabled_p
+              ? desired_cursor_row
+              : current_cursor_row);
 
          window_box (w, TEXT_AREA, &text_area_x, &text_area_y,
                      &text_area_width, &text_area_height);
@@ -6131,7 +6997,8 @@ hscroll_window_tree (window)
          
          if ((XFASTINT (w->hscroll)
               && w->cursor.x < hscroll_margin)
-             || (cursor_row->truncated_on_right_p
+             || (cursor_row->enabled_p
+                 && cursor_row->truncated_on_right_p
                  && (w->cursor.x > text_area_width - hscroll_margin)))
            {
              struct it it;
@@ -6192,9 +7059,16 @@ static int
 hscroll_windows (window)
      Lisp_Object window;
 {
-  int hscrolled_p = hscroll_window_tree (window);
-  if (hscrolled_p)
-    clear_desired_matrices (XFRAME (WINDOW_FRAME (XWINDOW (window))));
+  int hscrolled_p;
+  
+  if (automatic_hscrolling_p)
+    {
+      hscrolled_p = hscroll_window_tree (window);
+      if (hscrolled_p)
+       clear_desired_matrices (XFRAME (WINDOW_FRAME (XWINDOW (window))));
+    }
+  else
+    hscrolled_p = 0;
   return hscrolled_p;
 }
 
@@ -6210,11 +7084,6 @@ hscroll_windows (window)
 
 #if GLYPH_DEBUG
 
-/* Values of beg_unchanged and end_unchanged as of last call to
-   try_window_id.  */
-
-int debug_beg_unchanged, debug_end_unchanged;
-
 /* First and last unchanged row for try_window_id.  */
 
 int debug_first_unchanged_at_end_vpos;
@@ -6311,8 +7180,8 @@ text_outside_line_unchanged_p (w, start, end)
 
       /* Changes start in front of the line, or end after it?  */
       if (unchanged_p
-         && (beg_unchanged < start - 1
-             || end_unchanged < end))
+         && (BEG_UNCHANGED < start - 1
+             || END_UNCHANGED < end))
        unchanged_p = 0;
       
       /* If selective display, can't optimize if changes start at the
@@ -6320,7 +7189,7 @@ text_outside_line_unchanged_p (w, start, end)
       if (unchanged_p
          && INTEGERP (current_buffer->selective_display)
          && XINT (current_buffer->selective_display) > 0
-         && (beg_unchanged < start || GPT <= start))
+         && (BEG_UNCHANGED < start || GPT <= start))
        unchanged_p = 0;
     }
 
@@ -6341,6 +7210,85 @@ redisplay ()
   redisplay_internal (0);
 }
 
+/* Return 1 if point moved out of or into a composition.  Otherwise
+   return 0.  PREV_BUF and PREV_PT are the last point buffer and
+   position.  BUF and PT are the current point buffer and position.  */
+
+int
+check_point_in_composition (prev_buf, prev_pt, buf, pt)
+     struct buffer *prev_buf, *buf;
+     int prev_pt, pt;
+{
+  int start, end;
+  Lisp_Object prop;
+  Lisp_Object buffer;
+
+  XSETBUFFER (buffer, buf);
+  /* Check a composition at the last point if point moved within the
+     same buffer.  */
+  if (prev_buf == buf)
+    {
+      if (prev_pt == pt)
+       /* Point didn't move.  */
+       return 0;
+    
+      if (prev_pt > BUF_BEGV (buf) && prev_pt < BUF_ZV (buf)
+         && find_composition (prev_pt, -1, &start, &end, &prop, buffer)
+         && COMPOSITION_VALID_P (start, end, prop)
+         && start < prev_pt && end > prev_pt)
+       /* The last point was within the composition.  Return 1 iff
+            point moved out of the composition.  */
+       return (pt <= start || pt >= end);
+    }
+
+  /* Check a composition at the current point.  */
+  return (pt > BUF_BEGV (buf) && pt < BUF_ZV (buf)
+         && find_composition (pt, -1, &start, &end, &prop, buffer)
+         && COMPOSITION_VALID_P (start, end, prop)
+         && start < pt && end > pt);
+}
+
+/* Reconsider the setting of B->clip_changed which is displayed
+   in window W.  */
+
+static INLINE void
+reconsider_clip_changes (w, b)
+     struct window *w;
+     struct buffer *b;
+{
+  if (b->prevent_redisplay_optimizations_p)
+    b->clip_changed = 1;
+  else if (b->clip_changed
+          && !NILP (w->window_end_valid)
+          && w->current_matrix->buffer == b
+          && w->current_matrix->zv == BUF_ZV (b)
+          && w->current_matrix->begv == BUF_BEGV (b))
+    b->clip_changed = 0;
+
+  /* If display wasn't paused, and W is not a tool bar window, see if
+     point has been moved into or out of a composition.  In that case,
+     we set b->clip_changed to 1 to force updating the screen.  If
+     b->clip_changed has already been set to 1, we can skip this
+     check.  */
+  if (!b->clip_changed
+      && BUFFERP (w->buffer) && !NILP (w->window_end_valid))
+    {
+      int pt;
+
+      if (w == XWINDOW (selected_window))
+       pt = BUF_PT (current_buffer);
+      else
+       pt = marker_position (w->pointm);
+
+      if ((w->current_matrix->buffer != XBUFFER (w->buffer)
+          || pt != XINT (w->last_point))
+         && check_point_in_composition (w->current_matrix->buffer,
+                                        XINT (w->last_point),
+                                        XBUFFER (w->buffer), pt))
+       b->clip_changed = 1;
+    }
+}
+
 
 /* If PRESERVE_ECHO_AREA is nonzero, it means this redisplay is not in
    response to any user action; therefore, we should preserve the echo
@@ -6358,6 +7306,8 @@ redisplay_internal (preserve_echo_area)
   int must_finish = 0;
   struct text_pos tlbufpos, tlendpos;
   int number_of_visible_frames;
+  int count;
+  struct frame *sf = SELECTED_FRAME ();
 
   /* Non-zero means redisplay has to consider all windows on all
      frames.  Zero means, only selected_window is considered.  */
@@ -6388,12 +7338,20 @@ redisplay_internal (preserve_echo_area)
     return;
 #endif
 
+  /* I don't think this happens but let's be paranoid.  */
   if (redisplaying_p)
     return;
-  ++redisplaying_p;
 
+  /* Record a function that resets redisplaying_p to its old value
+     when we leave this function.  */
+  count = specpdl_ptr - specpdl;
+  record_unwind_protect (unwind_redisplay, make_number (redisplaying_p));
+  ++redisplaying_p;
+  
  retry:
 
+  reconsider_clip_changes (w, current_buffer);
+
   /* If new fonts have been loaded that make a glyph matrix adjustment
      necessary, do it.  */
   if (fonts_changed_p)
@@ -6403,17 +7361,17 @@ redisplay_internal (preserve_echo_area)
       fonts_changed_p = 0;
     }
 
-  if (! FRAME_WINDOW_P (selected_frame)
-      && previous_terminal_frame != selected_frame)
+  if (! FRAME_WINDOW_P (sf)
+      && previous_terminal_frame != sf)
     {
       /* Since frames on an ASCII terminal share the same display
         area, displaying a different frame means redisplay the whole
         thing.  */
       windows_or_buffers_changed++;
-      SET_FRAME_GARBAGED (selected_frame);
-      XSETFRAME (Vterminal_frame, selected_frame);
+      SET_FRAME_GARBAGED (sf);
+      XSETFRAME (Vterminal_frame, sf);
     }
-  previous_terminal_frame = selected_frame;
+  previous_terminal_frame = sf;
 
   /* Set the visible flags for all frames.  Do this before checking
      for resized or garbaged frames; they want to know if their frames
@@ -6436,36 +7394,13 @@ redisplay_internal (preserve_echo_area)
   }
 
   /* Notice any pending interrupt request to change frame size.  */
-  do_pending_window_change ();
+  do_pending_window_change (1);
 
   /* Clear frames marked as garbaged.  */
   if (frame_garbaged)
-    {
-      /* Old redisplay called redraw_garbaged_frames here which in
-        turn called redraw_frame which in turn called clear_frame.
-        The call to clear_frame is a source of flickering.  After
-        checking the places where SET_FRAME_GARBAGED is called, I
-        believe a clear_frame is not necessary.  It should suffice in
-        the new redisplay to invalidate all current matrices, and
-        ensure a complete redisplay of all windows.  */
-      Lisp_Object tail, frame;
-      
-      FOR_EACH_FRAME (tail, frame)
-       {
-         struct frame *f = XFRAME (frame);
-         
-         if (FRAME_VISIBLE_P (f) && FRAME_GARBAGED_P (f))
-           {
-             clear_current_matrices (f);
-             f->garbaged = 0;
-           }
-       }
-
-      frame_garbaged = 0;
-      ++windows_or_buffers_changed;
-    }
+    clear_garbaged_frames ();
 
-  /* Build menubar and toolbar items.  */
+  /* Build menubar and tool-bar items.  */
   prepare_menu_bars ();
 
   if (windows_or_buffers_changed)
@@ -6505,15 +7440,48 @@ redisplay_internal (preserve_echo_area)
   /* Normally the message* functions will have already displayed and
      updated the echo area, but the frame may have been trashed, or
      the update may have been preempted, so display the echo area
-     again here.  */
-  if (echo_area_glyphs
-      || STRINGP (echo_area_message)
-      || previous_echo_glyphs
-      || STRINGP (previous_echo_area_message))
+     again here.  Checking both message buffers captures the case that
+     the echo area should be cleared.  */
+  if (!NILP (echo_area_buffer[0]) || !NILP (echo_area_buffer[1]))
+    {
+      int window_height_changed_p = echo_area_display (0);
+      must_finish = 1;
+      
+      if (fonts_changed_p)
+       goto retry;
+      else if (window_height_changed_p)
+       {
+         consider_all_windows_p = 1;
+         ++update_mode_lines;
+         ++windows_or_buffers_changed;
+         
+         /* If window configuration was changed, frames may have been
+            marked garbaged.  Clear them or we will experience
+            surprises wrt scrolling.  */
+         if (frame_garbaged)
+           clear_garbaged_frames ();
+       }
+    }
+  else if (w == XWINDOW (minibuf_window)
+          && (current_buffer->clip_changed
+              || XFASTINT (w->last_modified) < MODIFF
+              || XFASTINT (w->last_overlay_modified) < OVERLAY_MODIFF)
+          && resize_mini_window (w, 0))
     {
-      echo_area_display (0);
+      /* Resized active mini-window to fit the size of what it is
+         showing if its contents might have changed.  */
       must_finish = 1;
+      consider_all_windows_p = 1;
+      ++windows_or_buffers_changed;
+      ++update_mode_lines;
+      
+      /* If window configuration was changed, frames may have been
+        marked garbaged.  Clear them or we will experience
+        surprises wrt scrolling.  */
+      if (frame_garbaged)
+       clear_garbaged_frames ();
     }
+  
 
   /* If showing the region, and mark has changed, we must redisplay
      the whole window.  The assignment to this_line_start_pos prevents
@@ -6637,10 +7605,10 @@ redisplay_internal (preserve_echo_area)
                                     - MATRIX_ROW_START_BYTEPOS (row));
                    }
   
-                 increment_glyph_matrix_buffer_positions (w->current_matrix,
-                                                          this_line_vpos + 1,
-                                                          w->current_matrix->nrows,
-                                                          delta, delta_bytes);
+                 increment_matrix_positions (w->current_matrix,
+                                             this_line_vpos + 1,
+                                             w->current_matrix->nrows,
+                                             delta, delta_bytes);
                }
 
              /* If this row displays text now but previously didn't,
@@ -6677,7 +7645,7 @@ redisplay_internal (preserve_echo_area)
        {
          if (!must_finish)
            {
-             do_pending_window_change ();
+             do_pending_window_change (1);
 
              /* We used to always goto end_of_redisplay here, but this 
                 isn't enough if we have a blinking cursor.  */
@@ -6693,6 +7661,7 @@ redisplay_internal (preserve_echo_area)
               && (w == XWINDOW (current_buffer->last_selected_window)
                   || highlight_nonselected_windows)
               && NILP (w->region_showing)
+              && NILP (Vshow_trailing_whitespace)
               && !cursor_in_echo_area)
        {
          struct it it;
@@ -6756,7 +7725,7 @@ redisplay_internal (preserve_echo_area)
       FOR_EACH_FRAME (tail, frame)
        {
          struct frame *f = XFRAME (frame);
-         if (FRAME_WINDOW_P (f) || f == selected_frame)
+         if (FRAME_WINDOW_P (f) || f == sf)
            {
              /* Mark all the scroll bars to be removed; we'll redeem
                 the ones we want when we redisplay their windows.  */
@@ -6773,8 +7742,8 @@ redisplay_internal (preserve_echo_area)
            }
        }
     }
-  else if (FRAME_VISIBLE_P (selected_frame)
-          && !FRAME_OBSCURED_P (selected_frame))
+  else if (FRAME_VISIBLE_P (sf)
+          && !FRAME_OBSCURED_P (sf))
     redisplay_window (selected_window, 1);
 
   
@@ -6796,19 +7765,37 @@ update:
   if (consider_all_windows_p)
     {
       Lisp_Object tail;
+      struct frame *f;
+      int hscrolled_p;
 
       pause = 0;
+      hscrolled_p = 0;
 
-      for (tail = Vframe_list; CONSP (tail); tail = XCONS (tail)->cdr)
-       {
-         struct frame *f;
+      /* See if we have to hscroll.  */
+      for (tail = Vframe_list; CONSP (tail); tail = XCDR (tail))
+       if (FRAMEP (XCAR (tail)))
+         {
+           f = XFRAME (XCAR (tail));
+           
+           if ((FRAME_WINDOW_P (f)
+                || f == sf)
+               && FRAME_VISIBLE_P (f)
+               && !FRAME_OBSCURED_P (f)
+               && hscroll_windows (f->root_window))
+             hscrolled_p = 1;
+         }
 
-         if (!FRAMEP (XCONS (tail)->car))
+      if (hscrolled_p)
+       goto retry;
+
+      for (tail = Vframe_list; CONSP (tail); tail = XCDR (tail))
+       {
+         if (!FRAMEP (XCAR (tail)))
            continue;
 
-         f = XFRAME (XCONS (tail)->car);
+         f = XFRAME (XCAR (tail));
 
-         if ((FRAME_WINDOW_P (f) || f == selected_frame)
+         if ((FRAME_WINDOW_P (f) || f == sf)
              && FRAME_VISIBLE_P (f) && !FRAME_OBSCURED_P (f))
            {
              /* Mark all windows as to be updated.  */
@@ -6816,9 +7803,6 @@ update:
              pause |= update_frame (f, 0, 0);
              if (!pause)
                {
-                 if (hscroll_windows (f->root_window))
-                   goto retry;
-
                  mark_window_display_accurate (f->root_window, 1);
                  if (frame_up_to_date_hook != 0)
                    (*frame_up_to_date_hook) (f);
@@ -6828,13 +7812,14 @@ update:
     }
   else
     {
-      if (FRAME_VISIBLE_P (selected_frame)
-         && !FRAME_OBSCURED_P (selected_frame))
+      if (FRAME_VISIBLE_P (sf)
+         && !FRAME_OBSCURED_P (sf))
        {
-         XWINDOW (selected_window)->must_be_updated_p = 1;
-         pause = update_frame (selected_frame, 0, 0);
-         if (!pause && hscroll_windows (selected_window))
+         if (hscroll_windows (selected_window))
            goto retry;
+         
+         XWINDOW (selected_window)->must_be_updated_p = 1;
+         pause = update_frame (sf, 0, 0);
        }
       else
        pause = 0;
@@ -6848,10 +7833,10 @@ update:
        Lisp_Object mini_window;
        struct frame *mini_frame;
 
-       mini_window = FRAME_MINIBUF_WINDOW (selected_frame);
+       mini_window = FRAME_MINIBUF_WINDOW (sf);
        mini_frame = XFRAME (WINDOW_FRAME (XWINDOW (mini_window)));
        
-       if (mini_frame != selected_frame && FRAME_WINDOW_P (mini_frame))
+       if (mini_frame != sf && FRAME_WINDOW_P (mini_frame))
          {
            XWINDOW (mini_window)->must_be_updated_p = 1;
            pause |= update_frame (mini_frame, 0, 0);
@@ -6890,13 +7875,13 @@ update:
     {
       register struct buffer *b = XBUFFER (w->buffer);
 
-      unchanged_modified = BUF_MODIFF (b);
-      overlay_unchanged_modified = BUF_OVERLAY_MODIFF (b);
-      beg_unchanged = BUF_GPT (b) - BUF_BEG (b);
-      end_unchanged = BUF_Z (b) - BUF_GPT (b);
+      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 (selected_frame), 1);
+       mark_window_display_accurate (FRAME_ROOT_WINDOW (sf), 1);
       else
        {
          XSETFASTINT (w->last_point, BUF_PT (b));
@@ -6904,6 +7889,7 @@ update:
          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));
@@ -6924,9 +7910,13 @@ update:
          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) (selected_frame);
+           (*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);
        }
-      
+
       update_mode_lines = 0;
       windows_or_buffers_changed = 0;
     }
@@ -6969,7 +7959,7 @@ update:
     }
 
   /* Change frame size now if a change is pending.  */
-  do_pending_window_change ();
+  do_pending_window_change (1);
 
   /* If we just did a pending size change, or have additional
      visible frames, redisplay again.  */
@@ -6977,9 +7967,8 @@ update:
     goto retry;
 
  end_of_redisplay:;
-  
-  if (--redisplaying_p < 0)
-    redisplaying_p = 0;
+
+  unbind_to (count, Qnil);
 }
 
 
@@ -6994,23 +7983,32 @@ update:
 void
 redisplay_preserve_echo_area ()
 {
-  if (!echo_area_glyphs
-      && !STRINGP (echo_area_message)
-      && (previous_echo_glyphs
-         || STRINGP (previous_echo_area_message)))
+  if (!NILP (echo_area_buffer[1]))
     {
-      echo_area_glyphs = previous_echo_glyphs;
-      echo_area_message = previous_echo_area_message;
-      echo_area_glyphs_length = previous_echo_glyphs_length;
+      /* We have a previously displayed message, but no current
+        message.  Redisplay the previous message.  */
+      display_last_displayed_message_p = 1;
       redisplay_internal (1);
-      echo_area_glyphs = NULL;
-      echo_area_message = Qnil;
+      display_last_displayed_message_p = 0;
     }
   else
     redisplay_internal (1);
 }
 
 
+/* Function registered with record_unwind_protect in
+   redisplay_internal.  Clears the flag indicating that a redisplay is
+   in progress.  */
+
+static Lisp_Object
+unwind_redisplay (old_redisplaying_p)
+     Lisp_Object old_redisplaying_p;
+{
+  redisplaying_p = XFASTINT (old_redisplaying_p);
+  return Qnil;
+}
+
+
 /* 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
@@ -7054,12 +8052,16 @@ mark_window_display_accurate (window, accurate_p)
          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 = BUF_PT (b);
+               w->last_point = make_number (BUF_PT (b));
              else
-               w->last_point = XMARKER (w->pointm)->charpos;
+               w->last_point = make_number (XMARKER (w->pointm)->charpos);
            }
        }
 
@@ -7104,14 +8106,11 @@ disp_char_vector (dp, c)
   if (SINGLE_BYTE_CHAR_P (c))
     return (dp->contents[c]);
   
-  SPLIT_NON_ASCII_CHAR (c, code[0], code[1], code[2]);
-  if (code[0] != CHARSET_COMPOSITION)
-    {
-      if (code[1] < 32)
-       code[1] = -1;
-      else if (code[2] < 32)
-       code[2] = -1;
-    }
+  SPLIT_CHAR (c, code[0], code[1], code[2]);
+  if (code[1] < 32)
+    code[1] = -1;
+  else if (code[2] < 32)
+    code[2] = -1;
   
   /* Here, the possible range of code[0] (== charset ID) is
      128..max_charset.  Since the top level char table contains data
@@ -7181,7 +8180,7 @@ set_cursor_from_row (w, row, matrix, delta, delta_bytes, dy, dvpos)
      frames.  */
   if (row->displays_text_p)
     while (glyph < end
-          && !glyph->object
+          && INTEGERP (glyph->object)
           && glyph->charpos < 0)
       {
        x += glyph->pixel_width;
@@ -7189,7 +8188,7 @@ set_cursor_from_row (w, row, matrix, delta, delta_bytes, dy, dvpos)
       }
 
   while (glyph < end
-        && glyph->object
+        && !INTEGERP (glyph->object)
         && (!BUFFERP (glyph->object)
             || glyph->charpos < pt_old))
     {
@@ -7232,7 +8231,9 @@ set_cursor_from_row (w, row, matrix, delta, delta_bytes, dy, dvpos)
 
 
 /* Run window scroll functions, if any, for WINDOW with new window
-   start STARTP.  Sets the window start of WINDOW to that position.  */
+   start STARTP.  Sets the window start of WINDOW to that position.
+
+   We assume that the window's buffer is really current.  */
 
 static INLINE struct text_pos
 run_window_scroll_functions (window, startp)
@@ -7241,12 +8242,18 @@ run_window_scroll_functions (window, startp)
 {
   struct window *w = XWINDOW (window);
   SET_MARKER_FROM_TEXT_POS (w->start, startp);
-  
+
+  if (current_buffer != XBUFFER (w->buffer))
+    abort ();
+
   if (!NILP (Vwindow_scroll_functions))
     {
       run_hook_with_args_2 (Qwindow_scroll_functions, window, 
                            make_number (CHARPOS (startp)));
       SET_TEXT_POS_FROM_MARKER (startp, w->start);
+      /* In case the hook functions switch buffers.  */
+      if (current_buffer != XBUFFER (w->buffer))
+       set_buffer_internal_1 (XBUFFER (w->buffer));
     }
 
   return startp;
@@ -7262,7 +8269,7 @@ make_cursor_line_fully_visible (w)
 {
   struct glyph_matrix *matrix;
   struct glyph_row *row;
-  int top_line_height;
+  int header_line_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.  */
@@ -7272,21 +8279,24 @@ make_cursor_line_fully_visible (w)
   matrix = w->desired_matrix;
   row = MATRIX_ROW (matrix, w->cursor.vpos);
 
-  /* If row->y == top y of window display area, the window isn't tall
-     enough to display a single line.  There is nothing we can do
-     about it.  */
-  top_line_height = WINDOW_DISPLAY_TOP_LINE_HEIGHT (w);
-  if (row->y == top_line_height)
-    return;
-
-  if (MATRIX_ROW_PARTIALLY_VISIBLE_AT_TOP_P (w, row))
+  if (MATRIX_ROW_PARTIALLY_VISIBLE_AT_TOP_P (w, row)
+      /* The row may be partially visible at the top because we
+        already have chosen a vscroll to align the bottom of the
+        row with the bottom of the window.  This happens for rows
+        taller than the window.  */
+      && row->y + row->height < window_box_height (w))
     {
       int dy = row->height - row->visible_height;
       w->vscroll = 0;
       w->cursor.y += dy;
       shift_glyph_matrix (w, matrix, 0, matrix->nrows, dy);
     }
-  else if (MATRIX_ROW_PARTIALLY_VISIBLE_AT_BOTTOM_P (w, row))
+  else if (MATRIX_ROW_PARTIALLY_VISIBLE_AT_BOTTOM_P (w, row)
+          /* The row may be partially visible at the bottom because
+             we chose a vscroll to align the row's top with the
+             window's top.  This happens for rows taller than the
+             window.  */
+          && row->y > WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w))
     {
       int dy = - (row->height - row->visible_height);
       w->vscroll = dy;
@@ -7421,7 +8431,7 @@ try_scrolling (window, just_this_one_p, scroll_conservatively,
        {
          aggressive = current_buffer->scroll_down_aggressively;
          height = (WINDOW_DISPLAY_HEIGHT_NO_MODE_LINE (w)
-                   - WINDOW_DISPLAY_TOP_LINE_HEIGHT (w));
+                   - WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w));
          if (NUMBERP (aggressive))
            amount_to_scroll = XFLOATINT (aggressive) * height;
        }
@@ -7474,7 +8484,7 @@ try_scrolling (window, just_this_one_p, scroll_conservatively,
            {
              aggressive = current_buffer->scroll_up_aggressively;
              height = (WINDOW_DISPLAY_HEIGHT_NO_MODE_LINE (w)
-                       - WINDOW_DISPLAY_TOP_LINE_HEIGHT (w));
+                       - WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w));
              if (NUMBERP (aggressive))
                amount_to_scroll = XFLOATINT (aggressive) * height;
            }
@@ -7504,7 +8514,7 @@ try_scrolling (window, just_this_one_p, scroll_conservatively,
       /* Maybe forget recorded base line for line number display.  */
       if (!just_this_one_p 
          || current_buffer->clip_changed
-         || beg_unchanged < CHARPOS (startp))
+         || BEG_UNCHANGED < CHARPOS (startp))
        w->base_line_number = Qnil;
       
       /* If cursor ends up on a partially visible line, shift display
@@ -7542,10 +8552,16 @@ compute_window_start_on_continuation_line (w)
     {
       struct it it;
       struct glyph_row *row;
+
+      /* Handle the case that the window start is out of range.  */
+      if (CHARPOS (start_pos) < BEGV)
+       SET_TEXT_POS (start_pos, BEGV, BEGV_BYTE);
+      else if (CHARPOS (start_pos) > ZV)
+       SET_TEXT_POS (start_pos, ZV, ZV_BYTE);
       
       /* Find the start of the continued line.  This should be fast
         because scan_buffer is fast (newline cache).  */
-      row = w->desired_matrix->rows + (WINDOW_WANTS_TOP_LINE_P (w) ? 1 : 0);
+      row = w->desired_matrix->rows + (WINDOW_WANTS_HEADER_LINE_P (w) ? 1 : 0);
       init_iterator (&it, w, CHARPOS (start_pos), BYTEPOS (start_pos),
                     row, DEFAULT_FACE_ID);
       reseat_at_previous_visible_line_start (&it);
@@ -7601,7 +8617,6 @@ redisplay_window (window, just_this_one_p)
   struct it it;
   /* Record it now because it's overwritten.  */
   int current_matrix_up_to_date_p = 0;
-  int really_switched_buffer = 0;
   int temp_scroll_step = 0;
   int count = specpdl_ptr - specpdl;
 
@@ -7615,7 +8630,9 @@ redisplay_window (window, just_this_one_p)
 #endif
 
   specbind (Qinhibit_point_motion_hooks, Qt);
-  
+
+  reconsider_clip_changes (w, buffer);
+    
   /* Has the mode line to be updated?  */ 
   update_mode_line = (!NILP (w->update_mode_line)
                      || update_mode_lines
@@ -7624,12 +8641,11 @@ redisplay_window (window, just_this_one_p)
   if (MINI_WINDOW_P (w))
     {
       if (w == XWINDOW (echo_area_window)
-         && (echo_area_glyphs
-             || STRINGP (echo_area_message)))
+         && !NILP (echo_area_buffer[0]))
        {
          if (update_mode_line)
            /* We may have to update a tty frame's menu bar or a
-              toolbar.  Example `M-x C-h C-h C-g'.  */
+              tool-bar.  Example `M-x C-h C-h C-g'.  */
            goto finish_menu_bars;
          else
            /* We've already displayed the echo area glyphs in this window.  */
@@ -7653,15 +8669,9 @@ redisplay_window (window, just_this_one_p)
 
   /* Otherwise set up data on this window; select its buffer and point
      value.  */
-  if (update_mode_line)
-    {
-      /* Really select the buffer, for the sake of buffer-local
-         variables.  */
-      set_buffer_internal_1 (XBUFFER (w->buffer));
-      really_switched_buffer = 1;
-    }
-  else
-    set_buffer_temp (XBUFFER (w->buffer));
+  /* Really select the buffer, for the sake of buffer-local
+     variables.  */
+  set_buffer_internal_1 (XBUFFER (w->buffer));
   SET_TEXT_POS (opoint, PT, PT_BYTE);
 
   current_matrix_up_to_date_p
@@ -7764,7 +8774,9 @@ redisplay_window (window, just_this_one_p)
 
   /* If someone specified a new starting point but did not insist,
      check whether it can be used.  */
-  if (!NILP (w->optional_new_start))
+  if (!NILP (w->optional_new_start)
+      && CHARPOS (startp) >= BEGV
+      && CHARPOS (startp) <= ZV)
     {
       w->optional_new_start = Qnil;
       /* This takes a mini-buffer prompt into account.  */
@@ -7777,7 +8789,8 @@ redisplay_window (window, just_this_one_p)
 
   /* Handle case where place to start displaying has been specified,
      unless the specified location is outside the accessible range.  */
-  if (!NILP (w->force_start))
+  if (!NILP (w->force_start)
+      || w->frozen_window_start_p)
     {
       w->force_start = Qnil;
       w->vscroll = 0;
@@ -7798,13 +8811,6 @@ redisplay_window (window, just_this_one_p)
       if (!update_mode_line
          || ! NILP (Vwindow_scroll_functions))
        {
-         if (!really_switched_buffer)
-           {
-             set_buffer_temp (old);
-             set_buffer_internal_1 (XBUFFER (w->buffer));
-             really_switched_buffer = 1;
-           }
-         
          update_mode_line = 1;
          w->update_mode_line = Qt;
          startp = run_window_scroll_functions (window, startp);
@@ -7826,7 +8832,7 @@ redisplay_window (window, just_this_one_p)
          goto restore_buffers;
        }
 
-      if (w->cursor.vpos < 0)
+      if (w->cursor.vpos < 0 && !w->frozen_window_start_p)
        {
          /* If point does not appear, or on a line that is not fully
             visible, move point so it does appear.  The desired
@@ -7886,6 +8892,7 @@ redisplay_window (window, just_this_one_p)
       && !(!NILP (Vtransient_mark_mode)
           && !NILP (current_buffer->mark_active))
       && NILP (w->region_showing)
+      && NILP (Vshow_trailing_whitespace)
       /* Right after splitting windows, last_point may be nil.  */
       && INTEGERP (w->last_point)
       /* This code is not used for mini-buffer for the sake of the case
@@ -7936,20 +8943,26 @@ redisplay_window (window, just_this_one_p)
          /* Point has moved forward.  */
          int last_y = window_text_bottom_y (w) - this_scroll_margin;
          
-         while ((MATRIX_ROW_END_CHARPOS (row) < PT
-                 /* The end position of a row equals the start
-                    position of the next row.  If PT is there, we
-                    would rather display it in the next line, except
-                    when this line ends in ZV.  */
-                 || (MATRIX_ROW_END_CHARPOS (row) == PT
-                     && (MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (row)
-                         || !row->ends_at_zv_p)))
+         while (MATRIX_ROW_END_CHARPOS (row) < PT
                 && MATRIX_ROW_BOTTOM_Y (row) < last_y)
            {
              xassert (row->enabled_p);
              ++row;
            }
 
+         /* The end position of a row equals the start position of
+            the next row.  If PT is there, we would rather display it
+            in the next line.  Exceptions are when the row ends in
+            the middle of a character, or ends in ZV.  */
+         if (MATRIX_ROW_BOTTOM_Y (row) < last_y
+             && MATRIX_ROW_END_CHARPOS (row) == PT
+             && !MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (row)
+             && !row->ends_at_zv_p)
+           {
+             xassert (row->enabled_p);
+             ++row;
+           }
+
          /* If within the scroll margin, scroll.  Note that
             MATRIX_ROW_BOTTOM_Y gives the pixel position at which the
             next line would be drawn, and that this_scroll_margin can
@@ -8038,12 +9051,12 @@ redisplay_window (window, just_this_one_p)
     }
   
   /* Try scrolling with try_window_id.  */
-  else if (!windows_or_buffers_changed
+  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))
-                  && just_this_one_p))
+              || (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)
@@ -8059,6 +9072,7 @@ redisplay_window (window, just_this_one_p)
           && !(!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)
@@ -8095,7 +9109,8 @@ redisplay_window (window, just_this_one_p)
          If point has not moved off frame, accept the results.  */
       if (!current_matrix_up_to_date_p
          /* Don't use try_window_reusing_current_matrix in this case
-            because it can have changed the buffer.  */
+            because a window scroll function can have changed the
+            buffer.  */
          || !NILP (Vwindow_scroll_functions)
          || MINI_WINDOW_P (w)
          || !try_window_reusing_current_matrix (w))
@@ -8111,7 +9126,7 @@ redisplay_window (window, just_this_one_p)
        {
          if (!just_this_one_p 
              || current_buffer->clip_changed
-             || beg_unchanged < CHARPOS (startp))
+             || BEG_UNCHANGED < CHARPOS (startp))
            /* Forget any recorded base line for line number display.  */
            w->base_line_number = Qnil;
          
@@ -8130,12 +9145,6 @@ redisplay_window (window, just_this_one_p)
   /* Redisplay the mode line.  Select the buffer properly for that.  */
   if (!update_mode_line)
     {
-      if (!really_switched_buffer)
-       {
-         set_buffer_temp (old);
-         set_buffer_internal_1 (XBUFFER (w->buffer));
-         really_switched_buffer = 1;
-       }
       update_mode_line = 1;
       w->update_mode_line = Qt;
     }
@@ -8262,13 +9271,13 @@ redisplay_window (window, just_this_one_p)
   
   make_cursor_line_fully_visible (w);
 
+ done:
+
   SET_TEXT_POS_FROM_MARKER (startp, w->start);
   w->start_at_line_beg = ((CHARPOS (startp) == BEGV
                           || FETCH_BYTE (BYTEPOS (startp) - 1) == '\n')
                          ? Qt : Qnil);
 
- done:
-
   /* Display the mode line, if we must.  */
   if ((update_mode_line
        /* If window not full width, must redo its mode line
@@ -8285,9 +9294,15 @@ redisplay_window (window, just_this_one_p)
           && XFASTINT (w->column_number_displayed) != current_column ()))
        /* This means that the window has a mode line.  */
        && (WINDOW_WANTS_MODELINE_P (w)
-          || WINDOW_WANTS_TOP_LINE_P (w)))
+          || WINDOW_WANTS_HEADER_LINE_P (w)))
     {
+      Lisp_Object old_selected_frame;
+      
+      old_selected_frame = selected_frame;
+      
+      XSETFRAME (selected_frame, f);
       display_mode_lines (w);
+      selected_frame = old_selected_frame;
 
       /* If mode line height has changed, arrange for a thorough
         immediate redisplay using the correct mode line height.  */
@@ -8301,12 +9316,12 @@ redisplay_window (window, just_this_one_p)
       
       /* If top line height has changed, arrange for a thorough
         immediate redisplay using the correct mode line height.  */
-      if (WINDOW_WANTS_TOP_LINE_P (w)
-         && CURRENT_TOP_LINE_HEIGHT (w) != DESIRED_TOP_LINE_HEIGHT (w))
+      if (WINDOW_WANTS_HEADER_LINE_P (w)
+         && CURRENT_HEADER_LINE_HEIGHT (w) != DESIRED_HEADER_LINE_HEIGHT (w))
        {
          fonts_changed_p = 1;
-         MATRIX_TOP_LINE_ROW (w->current_matrix)->height
-           = DESIRED_TOP_LINE_HEIGHT (w);
+         MATRIX_HEADER_LINE_ROW (w->current_matrix)->height
+           = DESIRED_HEADER_LINE_HEIGHT (w);
        }
 
       if (fonts_changed_p)
@@ -8343,10 +9358,10 @@ redisplay_window (window, just_this_one_p)
         display_menu_bar (w);
 
 #ifdef HAVE_WINDOW_SYSTEM
-      if (WINDOWP (f->toolbar_window)
-         && (FRAME_TOOLBAR_LINES (f) > 0
-             || auto_resize_toolbars_p))
-       redisplay_toolbar (f);
+      if (WINDOWP (f->tool_bar_window)
+         && (FRAME_TOOL_BAR_LINES (f) > 0
+             || auto_resize_tool_bars_p))
+       redisplay_tool_bar (f);
 #endif
     }
 
@@ -8363,10 +9378,9 @@ redisplay_window (window, just_this_one_p)
         visible region.
 
         Note that mini-buffers sometimes aren't displaying any text.  */
-      if (! MINI_WINDOW_P (w)
+      if (!MINI_WINDOW_P (w)
          || (w == XWINDOW (minibuf_window)
-             && !echo_area_glyphs
-             && !STRINGP (echo_area_message)))
+             && NILP (echo_area_buffer[0])))
        {
          whole = ZV - BEGV;
          start = marker_position (w->start) - BEGV;
@@ -8394,10 +9408,7 @@ redisplay_window (window, just_this_one_p)
 
   /* Restore current_buffer and value of point in it.  */
   TEMP_SET_PT_BOTH (CHARPOS (opoint), BYTEPOS (opoint));
-  if (really_switched_buffer)
-    set_buffer_internal_1 (old);
-  else
-    set_buffer_temp (old);
+  set_buffer_internal_1 (old);
   TEMP_SET_PT_BOTH (CHARPOS (lpoint), BYTEPOS (lpoint));
 
   unbind_to (count, Qnil);
@@ -8502,12 +9513,13 @@ try_window_reusing_current_matrix (w)
   /* Can't do this if region may have changed.  */
   if ((!NILP (Vtransient_mark_mode)
        && !NILP (current_buffer->mark_active))
-      || !NILP (w->region_showing))
+      || !NILP (w->region_showing)
+      || !NILP (Vshow_trailing_whitespace))
     return 0;
 
   /* If top-line visibility has changed, give up.  */
-  if (WINDOW_WANTS_TOP_LINE_P (w)
-      != MATRIX_TOP_LINE_ROW (w->current_matrix)->mode_line_p)
+  if (WINDOW_WANTS_HEADER_LINE_P (w)
+      != MATRIX_HEADER_LINE_ROW (w->current_matrix)->mode_line_p)
     return 0;
 
   /* Give up if old or new display is scrolled vertically.  We could
@@ -8592,7 +9604,8 @@ try_window_reusing_current_matrix (w)
          run.current_y = first_row_y;
          run.desired_y = it.current_y;
          run.height = it.last_visible_y - it.current_y;
-         if (run.height > 0)
+         if (run.height > 0
+             && run.current_y != run.desired_y)
            {
              update_begin (f);
              rif->update_window_begin_hook (w);
@@ -8614,7 +9627,7 @@ try_window_reusing_current_matrix (w)
          
          /* Re-compute Y positions.  */
          row = MATRIX_FIRST_TEXT_ROW (w->current_matrix) + nrows_scrolled;
-         min_y = WINDOW_DISPLAY_TOP_LINE_HEIGHT (w);
+         min_y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
          max_y = it.last_visible_y;
          while (row < bottom_row)
            {
@@ -8700,14 +9713,11 @@ try_window_reusing_current_matrix (w)
 
       /* Give up if there is no row to reuse.  */
       if (MATRIX_ROW_BOTTOM_Y (first_reusable_row) >= yb
-         || !first_reusable_row->enabled_p)
+         || !first_reusable_row->enabled_p
+         || (MATRIX_ROW_START_CHARPOS (first_reusable_row)
+             != CHARPOS (new_start)))
        return 0;
 
-      /* The row we found must start at new_start, or else something
-        is broken.  */
-      xassert (MATRIX_ROW_START_CHARPOS (first_reusable_row)
-              == CHARPOS (new_start));
-      
       /* We can reuse fully visible rows beginning with
          first_reusable_row to the end of the window.  Set
          first_row_to_display to the first row that cannot be reused.
@@ -8760,7 +9770,7 @@ try_window_reusing_current_matrix (w)
 
       /* Scroll the display.  */
       run.current_y = first_reusable_row->y;
-      run.desired_y = WINDOW_DISPLAY_TOP_LINE_HEIGHT (w);
+      run.desired_y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
       run.height = it.last_visible_y - run.current_y;
       if (run.height)
        {
@@ -8776,7 +9786,7 @@ try_window_reusing_current_matrix (w)
       bottom_row = MATRIX_BOTTOM_TEXT_ROW (w->current_matrix, w);
       row = first_reusable_row;
       dy = first_reusable_row->y;
-      min_y = WINDOW_DISPLAY_TOP_LINE_HEIGHT (w);
+      min_y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
       max_y = it.last_visible_y;
       while (row < first_row_to_display)
        {
@@ -8895,7 +9905,7 @@ static struct glyph_row *
 get_last_unchanged_at_beg_row (w)
      struct window *w;
 {
-  int first_changed_pos = BEG + beg_unchanged;
+  int first_changed_pos = BEG + BEG_UNCHANGED;
   struct glyph_row *row;
   struct glyph_row *row_found = NULL;
   int yb = window_text_bottom_y (w);
@@ -8932,14 +9942,10 @@ get_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
-   bytes by which buffer positions in unchanged text at the end of
-   current_buffer must be adjusted.  Value is null if no such row
-   exists, i.e. all rows are affected by changes.
-
-   The global variable end_unchanged is assumed to contain the number
-   of unchanged bytes at the end of current_buffer.  The buffer
-   position of the last changed byte in current_buffer is then Z -
-   end_unchanged.  */
+   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 *
 get_first_unchanged_at_end_row (w, delta, delta_bytes)
@@ -8955,17 +9961,12 @@ get_first_unchanged_at_end_row (w, delta, delta_bytes)
      end is in the range of changed text.  If so, there is no
      unchanged row at the end of W's current matrix.  */
   xassert (!NILP (w->window_end_valid));
-  if (XFASTINT (w->window_end_pos) >= end_unchanged)
+  if (XFASTINT (w->window_end_pos) >= END_UNCHANGED)
     return NULL;
 
   /* Set row to the last row in W's current matrix displaying text.  */
   row = MATRIX_ROW (w->current_matrix, XFASTINT (w->window_end_vpos));
   
-  /* End vpos should always be on text, except in an entirely empty
-     matrix.  */
-  xassert (MATRIX_ROW_DISPLAYS_TEXT_P (row)
-          || MATRIX_ROW_VPOS (row, w->current_matrix) == 0);
-
   /* If matrix is entirely empty, no unchanged row exists.  */ 
   if (MATRIX_ROW_DISPLAYS_TEXT_P (row))
     {
@@ -8989,7 +9990,7 @@ get_first_unchanged_at_end_row (w, delta, delta_bytes)
         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;
+      last_unchanged_pos = Z - END_UNCHANGED + BEG;
       last_unchanged_pos_old = last_unchanged_pos - *delta;
       
       /* Search backward from ROW for a row displaying a line that
@@ -9038,13 +10039,65 @@ sync_frame_with_window_matrix_rows (w)
   while (window_row < window_row_end)
     {
       int area;
+      
       for (area = LEFT_MARGIN_AREA; area <= LAST_AREA; ++area)
        frame_row->glyphs[area] = window_row->glyphs[area];
+
+      /* Disable frame rows whose corresponding window rows have
+        been disabled in try_window_id.  */
+      if (!window_row->enabled_p)
+       frame_row->enabled_p = 0;
+      
       ++window_row, ++frame_row;
     }
 }
 
 
+/* Find the glyph row in window W containing CHARPOS.  Consider all
+   rows between START and END (not inclusive).  END null means search
+   all rows to the end of the display area of W.  Value is the row
+   containing CHARPOS or null.  */
+
+static struct glyph_row *
+row_containing_pos (w, charpos, start, end)
+     struct window *w;
+     int charpos;
+     struct glyph_row *start, *end;
+{
+  struct glyph_row *row = start;
+  int last_y;
+
+  /* If we happen to start on a header-line, skip that.  */
+  if (row->mode_line_p)
+    ++row;
+  
+  if ((end && row >= end) || !row->enabled_p)
+    return NULL;
+  
+  last_y = window_text_bottom_y (w);
+      
+  while ((end == NULL || row < end)
+        && (MATRIX_ROW_END_CHARPOS (row) < charpos
+            /* The end position of a row equals the start
+               position of the next row.  If CHARPOS is there, we
+               would rather display it in the next line, except
+               when this line ends in ZV.  */
+            || (MATRIX_ROW_END_CHARPOS (row) == charpos
+                && (MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (row)
+                    || !row->ends_at_zv_p)))
+        && MATRIX_ROW_BOTTOM_Y (row) < last_y)
+    ++row;
+      
+  /* Give up if CHARPOS not found.  */
+  if ((end && row >= end)
+      || charpos < MATRIX_ROW_START_CHARPOS (row)
+      || charpos > MATRIX_ROW_END_CHARPOS (row))
+    row = NULL;
+
+  return row;
+}
+
+
 /* Try to redisplay window W by reusing its existing display.  W's
    current matrix must be up to date when this function is called,
    i.e. window_end_valid must not be nil.
@@ -9114,35 +10167,56 @@ try_window_id (w)
      only if buffer has really changed.  The reason is that the gap is
      initially at Z for freshly visited files.  The code below would
      set end_unchanged to 0 in that case.  */
-  if (MODIFF > SAVE_MODIFF)
+  if (MODIFF > SAVE_MODIFF
+      /* This seems to happen sometimes after saving a buffer.  */
+      || BEG_UNCHANGED + END_UNCHANGED > Z_BYTE)
     {
-      if (GPT - BEG < beg_unchanged)
-       beg_unchanged = GPT - BEG;
-      if (Z - GPT < end_unchanged)
-       end_unchanged = Z - GPT;
+      if (GPT - BEG < BEG_UNCHANGED)
+       BEG_UNCHANGED = GPT - BEG;
+      if (Z - GPT < END_UNCHANGED)
+       END_UNCHANGED = Z - GPT;
     }
-  
+
   /* 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.  */
+     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
+      && Z - END_UNCHANGED < CHARPOS (start) - 1
       && FETCH_BYTE (BYTEPOS (start) - 1) == '\n'
       && PT < MATRIX_ROW_END_CHARPOS (row))
     {
-      /* We have to update window end positions because the buffer's
-        size has changed.  */
+      struct glyph_row *r0 = MATRIX_FIRST_TEXT_ROW (current_matrix);
+      int delta = CHARPOS (start) - MATRIX_ROW_START_CHARPOS (r0);
+
+      if (delta)
+       {
+         struct glyph_row *r1 = MATRIX_BOTTOM_TEXT_ROW (current_matrix, w);
+         int delta_bytes = BYTEPOS (start) - MATRIX_ROW_START_BYTEPOS (r0);
+
+         increment_matrix_positions (w->current_matrix,
+                                     MATRIX_ROW_VPOS (r0, current_matrix),
+                                     MATRIX_ROW_VPOS (r1, current_matrix),
+                                     delta, delta_bytes);
+       }
+      
+#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
-       = make_number (Z_BYTE - MATRIX_ROW_END_BYTEPOS (row));
+       = Z_BYTE - MATRIX_ROW_END_BYTEPOS (row);
+#endif
+
       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)
+  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
@@ -9150,7 +10224,7 @@ try_window_id (w)
       w->window_end_pos
        = make_number (Z - MATRIX_ROW_END_CHARPOS (row));
       w->window_end_bytepos
-       = make_number (Z_BYTE - MATRIX_ROW_END_BYTEPOS (row));
+       = Z_BYTE - MATRIX_ROW_END_BYTEPOS (row);
       return 1;
     }
 
@@ -9162,10 +10236,6 @@ try_window_id (w)
   if (!TEXT_POS_EQUAL_P (start, row->start.pos))
     return 0;
 
-  /* Remember beg_unchanged and end_unchanged for debugging purposes.  */
-  IF_DEBUG (debug_beg_unchanged = beg_unchanged;
-           debug_end_unchanged = end_unchanged);
-
   /* Compute the position at which we have to start displaying new
      lines.  Some of the lines at the top of the window might be
      reusable because they are not displaying changed text.  Find the
@@ -9196,9 +10266,6 @@ try_window_id (w)
       start_pos = it.current.pos;
     }
 
-  bottom_row = MATRIX_BOTTOM_TEXT_ROW (current_matrix, w);
-  bottom_vpos = MATRIX_ROW_VPOS (bottom_row, current_matrix);
-  
   /* Find the first row that is not affected by changes at the end of
      the buffer.  Value will be null if there is no unchanged row, in
      which case we must redisplay to the end of the window.  delta
@@ -9241,7 +10308,7 @@ try_window_id (w)
                      + delta);
          first_unchanged_at_end_vpos
            = MATRIX_ROW_VPOS (first_unchanged_at_end_row, current_matrix);
-         xassert (stop_pos >= Z - end_unchanged);
+         xassert (stop_pos >= Z - END_UNCHANGED);
        }
     }
   else if (last_unchanged_at_beg_row == NULL)
@@ -9287,7 +10354,10 @@ try_window_id (w)
   /* Compute differences in buffer positions, y-positions etc.  for
      lines reused at the bottom of the window.  Compute what we can
      scroll.  */
-  if (first_unchanged_at_end_row)
+  if (first_unchanged_at_end_row
+      /* No lines reused because we displayed everything up to the
+         bottom of the window.  */
+      && it.current_y < it.last_visible_y)
     {
       dvpos = (it.vpos
               - MATRIX_ROW_VPOS (first_unchanged_at_end_row,
@@ -9298,10 +10368,13 @@ try_window_id (w)
       run.height = it.last_visible_y - max (run.current_y, run.desired_y);
     }
   else
-    delta = dvpos = dy = run.current_y = run.desired_y = run.height = 0;
+    {
+      delta = dvpos = dy = run.current_y = run.desired_y = run.height = 0;
+      first_unchanged_at_end_row = NULL;
+    }
   IF_DEBUG (debug_dvpos = dvpos; debug_dy = dy);
 
-  
+
   /* Find the cursor if not already found.  We have to decide whether
      PT will appear on this window (it sometimes doesn't, but this is
      not a very frequent case.)  This decision has to be made before
@@ -9312,37 +10385,25 @@ try_window_id (w)
      mentioned, this is not a frequent case.  */
   if (w->cursor.vpos < 0)
     {
-      int last_y = min (it.last_visible_y, it.last_visible_y + dy);
-
       /* Cursor in unchanged rows at the top?  */
       if (PT < CHARPOS (start_pos)
          && last_unchanged_at_beg_row)
        {
-         row = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
-         while (row <= last_unchanged_at_beg_row
-                && MATRIX_ROW_END_CHARPOS (row) <= PT)
-           ++row;
-         xassert (row <= last_unchanged_at_beg_row);
+         row = row_containing_pos (w, PT,
+                                   MATRIX_FIRST_TEXT_ROW (w->current_matrix),
+                                   last_unchanged_at_beg_row + 1);
+         xassert (row && row <= last_unchanged_at_beg_row);
          set_cursor_from_row (w, row, w->current_matrix, 0, 0, 0, 0);
        }
 
       /* Start from first_unchanged_at_end_row looking for PT.  */
       else if (first_unchanged_at_end_row)
        {
-         row = first_unchanged_at_end_row;
-         while (MATRIX_ROW_DISPLAYS_TEXT_P (row))
-           {
-             if (PT - delta >= MATRIX_ROW_START_CHARPOS (row)
-                 && PT - delta < MATRIX_ROW_END_CHARPOS (row))
-               {
-                 set_cursor_from_row (w, row, w->current_matrix, delta,
-                                      delta_bytes, dy, dvpos);
-                 break;
-               }
-             else if (MATRIX_ROW_BOTTOM_Y (row) >= last_y)
-               break;
-             ++row;
-           }
+         row = row_containing_pos (w, PT - delta,
+                                   first_unchanged_at_end_row, NULL);
+         if (row)
+           set_cursor_from_row (w, row, w->current_matrix, delta,
+                                delta_bytes, dy, dvpos);
        }
 
       /* Give up if cursor was not found.  */
@@ -9378,7 +10439,7 @@ try_window_id (w)
   /* Scroll the display.  Do it before changing the current matrix so
      that xterm.c doesn't get confused about where the cursor glyph is
      found.  */
-  if (dy)
+  if (dy && run.height)
     {
       update_begin (f);
          
@@ -9437,7 +10498,11 @@ try_window_id (w)
       update_end (f);
     }
 
-  /* Shift reused rows of the current matrix to the right position.  */
+  /* Shift reused rows of the current matrix to the right position.
+     BOTTOM_ROW is the last + 1 row in the current matrix reserved for
+     text.  */
+  bottom_row = MATRIX_BOTTOM_TEXT_ROW (current_matrix, w);
+  bottom_vpos = MATRIX_ROW_VPOS (bottom_row, current_matrix);
   if (dvpos < 0)
     {
       rotate_matrix (current_matrix, first_unchanged_at_end_vpos + dvpos,
@@ -9460,9 +10525,9 @@ try_window_id (w)
 
   /* Adjust buffer positions in reused rows.  */
   if (delta)
-    increment_glyph_matrix_buffer_positions (current_matrix,
-                                            first_unchanged_at_end_vpos + dvpos,
-                                            bottom_vpos, delta, delta_bytes);
+    increment_matrix_positions (current_matrix,
+                               first_unchanged_at_end_vpos + dvpos,
+                               bottom_vpos, delta, delta_bytes);
 
   /* Adjust Y positions.  */
   if (dy)
@@ -9571,13 +10636,13 @@ 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 top_line_p = WINDOW_WANTS_TOP_LINE_P (w) ? 1 : 0;
+      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 + top_line_p].enabled_p
-            && w->desired_matrix->rows[vpos + top_line_p].displays_text_p)
-           || (!w->desired_matrix->rows[vpos + top_line_p].enabled_p
-               && w->current_matrix->rows[vpos + top_line_p].displays_text_p))
+       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;
 
       w->window_end_vpos = make_number (vpos);
@@ -9609,7 +10674,7 @@ static void dump_glyph_matrix P_ ((struct glyph_matrix *, int));
 /* Dump the contents of glyph matrix MATRIX on stderr.  If
    WITH_GLYPHS_P is non-zero, dump glyph contents as well.  */
 
-void
+static void
 dump_glyph_matrix (matrix, with_glyphs_p)
      struct glyph_matrix *matrix;
      int with_glyphs_p;
@@ -9635,10 +10700,10 @@ dump_glyph_row (matrix, vpos, with_glyphs_p)
 
   row = MATRIX_ROW (matrix, vpos);
   
-  fprintf (stderr, "Row Start   End Used oEI><O\\CTZF    X   Y   W\n");
+  fprintf (stderr, "Row Start   End Used oEI><O\\CTZFes    X   Y   W\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 %4d %4d %4d\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\n",
           row - matrix->rows,
           MATRIX_ROW_START_CHARPOS (row),
           MATRIX_ROW_END_CHARPOS (row),
@@ -9654,6 +10719,8 @@ dump_glyph_row (matrix, vpos, with_glyphs_p)
           row->displays_text_p,
           row->ends_at_zv_p,
           row->fill_line_p,
+          row->ends_in_middle_of_char_p,
+          row->starts_in_middle_of_char_p,
           row->x,
           row->y,
           row->pixel_width);
@@ -9679,7 +10746,7 @@ dump_glyph_row (matrix, vpos, with_glyphs_p)
       
       if (glyph < glyph_end)
        {
-         fprintf (stderr, "  Glyph    Type Pos   W    Code C Face LR\n");
+         fprintf (stderr, "  Glyph    Type Pos   W    Code C Face LR\n");
          prev_had_glyphs_p = 1;
        }
       else
@@ -9690,44 +10757,59 @@ dump_glyph_row (matrix, vpos, with_glyphs_p)
          if (glyph->type == CHAR_GLYPH)
            {
              fprintf (stderr,
-                      "  %5d %4c %6d %3d 0x%05x %c %4d %1.1d%1.1d\n",
+                      "  %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.code,
-                      (glyph->u.ch.code < 0x80 && glyph->u.ch.code >= ' '
-                       ? glyph->u.ch.code
+                      glyph->u.ch,
+                      (glyph->u.ch < 0x80 && glyph->u.ch >= ' '
+                       ? glyph->u.ch
                        : '.'),
-                      glyph->u.ch.face_id,
+                      glyph->face_id,
                       glyph->left_box_line_p,
                       glyph->right_box_line_p);
            }
          else if (glyph->type == STRETCH_GLYPH)
            {
              fprintf (stderr,
-                      "  %5d %4c %6d %3d 0x%05x %c %4d %1.1d%1.1d\n",
+                      "  %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->u.stretch.face_id,
+                      glyph->face_id,
                       glyph->left_box_line_p,
                       glyph->right_box_line_p);
            }
          else if (glyph->type == IMAGE_GLYPH)
            {
              fprintf (stderr,
-                      "  %5d %4c %6d %3d 0x%05x %c %4d %1.1d%1.1d\n",
+                      "  %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->u.img_id,
                       '.',
-                      glyph->u.img.face_id,
+                      glyph->face_id,
                       glyph->left_box_line_p,
                       glyph->right_box_line_p);
            }
@@ -9743,6 +10825,7 @@ DEFUN ("dump-glyph-matrix", Fdump_glyph_matrix,
 Shows contents of glyph row structures.  With non-nil optional\n\
 parameter WITH-GLYPHS-P, dump glyphs as well.")
   (with_glyphs_p)
+     Lisp_Object with_glyphs_p;
 {
   struct window *w = XWINDOW (selected_window);
   struct buffer *buffer = XBUFFER (w->buffer);
@@ -9768,11 +10851,12 @@ DEFUN ("dump-glyph-row", Fdump_glyph_row, Sdump_glyph_row, 1, 1, "",
 }
 
 
-DEFUN ("dump-toolbar-row", Fdump_toolbar_row, Sdump_toolbar_row,
+DEFUN ("dump-tool-bar-row", Fdump_tool_bar_row, Sdump_tool_bar_row,
        0, 0, "", "")
   ()
 {
-  struct glyph_matrix *m = (XWINDOW (selected_frame->toolbar_window)
+  struct frame *sf = SELECTED_FRAME ();
+  struct glyph_matrix *m = (XWINDOW (sf->tool_bar_window)
                            ->current_matrix);
   dump_glyph_row (m, 0, 1);
   return Qnil;
@@ -9787,7 +10871,17 @@ DEFUN ("trace-redisplay-toggle", Ftrace_redisplay_toggle,
   trace_redisplay_p = !trace_redisplay_p;
   return Qnil;
 }
-       
+
+
+DEFUN ("trace-to-stderr", Ftrace_to_stderr, Strace_to_stderr, 1, 1, "",
+   "Print STRING to stderr.")
+   (string)
+     Lisp_Object string;
+{
+  CHECK_STRING (string, 0);
+  fprintf (stderr, "%s", XSTRING (string)->data);
+  return Qnil;
+}
        
 #endif /* GLYPH_DEBUG */
 
@@ -9840,6 +10934,7 @@ get_overlay_arrow_glyph_row (w)
 
       /* Compute its width, get its glyphs.  */
       n_glyphs_before = it.glyph_row->used[TEXT_AREA];
+      SET_TEXT_POS (it.position, -1, -1);
       PRODUCE_GLYPHS (&it);
 
       /* If this character doesn't fit any more in the line, we have
@@ -9873,13 +10968,12 @@ insert_left_trunc_glyphs (it)
 
   /* Get the truncation glyphs.  */
   truncate_it = *it;
-  truncate_it.charset = -1;
   truncate_it.current_x = 0;
   truncate_it.face_id = DEFAULT_FACE_ID;
   truncate_it.glyph_row = &scratch_glyph_row;
   truncate_it.glyph_row->used[TEXT_AREA] = 0;
   CHARPOS (truncate_it.position) = BYTEPOS (truncate_it.position) = -1;
-  truncate_it.object = 0;
+  truncate_it.object = make_number (0);
   produce_special_glyphs (&truncate_it, IT_TRUNCATION);
   
   /* Overwrite glyphs from IT with truncation glyphs.  */
@@ -9928,7 +11022,7 @@ compute_line_metrics (it)
 
   if (FRAME_WINDOW_P (it->f))
     {
-      int i, top_line_height;
+      int i, header_line_height;
 
       /* The line may consist of one space only, that was added to
         place the cursor on it.  If so, the row's height hasn't been
@@ -9967,9 +11061,9 @@ compute_line_metrics (it)
       /* Compute how much of the line is visible.  */
       row->visible_height = row->height;
       
-      top_line_height = WINDOW_DISPLAY_TOP_LINE_HEIGHT (it->w);
-      if (row->y < top_line_height)
-       row->visible_height -= top_line_height - row->y;
+      header_line_height = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (it->w);
+      if (row->y < header_line_height)
+       row->visible_height -= header_line_height - row->y;
       else
        {
          int max_y = WINDOW_DISPLAY_HEIGHT_NO_MODE_LINE (it->w);
@@ -9990,6 +11084,8 @@ compute_line_metrics (it)
     for (i = 0; i < row->used[area]; ++i)
       row->hash = ((((row->hash << 4) + (row->hash >> 24)) & 0x0fffffff)
                   + row->glyphs[area][i].u.val
+                  + row->glyphs[area][i].face_id
+                  + row->glyphs[area][i].padding_p
                   + (row->glyphs[area][i].type << 2));
 
   it->max_ascent = it->max_descent = 0;
@@ -10000,12 +11096,17 @@ compute_line_metrics (it)
 /* Append one space to the glyph row of iterator IT if doing a
    window-based redisplay.  DEFAULT_FACE_P non-zero means let the
    space have the default face, otherwise let it have the same face as
-   IT->face_id.  This function is called to make sure that there is
-   always one glyph at the end of a glyph row that the cursor can be
-   set on under window-systems.  (If there weren't such a glyph we
-   would not know how wide and tall the cursor should be displayed).  */
+   IT->face_id.  Value is non-zero if a space was added.
 
-static void
+   This function is called to make sure that there is always one glyph
+   at the end of a glyph row that the cursor can be set on under
+   window-systems.  (If there weren't such a glyph we would not know
+   how wide and tall a box cursor should be displayed).
+
+   At the same time this space let's a nicely handle clearing to the
+   end of the line if the row ends in italic text.  */
+
+static int
 append_space (it, default_face_p)
      struct it *it;
      int default_face_p;
@@ -10022,25 +11123,22 @@ append_space (it, default_face_p)
          struct text_pos saved_pos;
          int saved_what = it->what;
          int saved_face_id = it->face_id;
-         int saved_charset = it->charset;
          Lisp_Object saved_object;
+         struct face *face;
 
          saved_object = it->object;
          saved_pos = it->position;
          
          it->what = IT_CHARACTER;
          bzero (&it->position, sizeof it->position);
-         it->object = 0;
+         it->object = make_number (0);
          it->c = ' ';
          it->len = 1;
-         it->charset = CHARSET_ASCII;
 
          if (default_face_p)
            it->face_id = DEFAULT_FACE_ID;
-         if (it->multibyte_p)
-           it->face_id = FACE_FOR_CHARSET (it->f, it->face_id, CHARSET_ASCII);
-         else
-           it->face_id = FACE_FOR_CHARSET (it->f, it->face_id, -1);
+         face = FACE_FROM_ID (it->f, it->face_id);
+         it->face_id = FACE_FOR_CHAR (it->f, face, 0);
 
          PRODUCE_GLYPHS (it);
          
@@ -10049,9 +11147,11 @@ append_space (it, default_face_p)
          it->position = saved_pos;
          it->what = saved_what;
          it->face_id = saved_face_id;
-         it->charset = saved_charset;
+         return 1;
        }
     }
+
+  return 0;
 }
 
 
@@ -10085,15 +11185,13 @@ extend_face_to_end_of_line (it)
      in the text area has to be drawn to the end of the text area.  */
   it->glyph_row->fill_line_p = 1;
 
-  /* If current charset of IT is not ASCII, make sure we have the
-     ASCII face.  This will be automatically undone the next time
-     get_next_display_element returns a character from a different
-     charset.  Note that the charset will always be ASCII in unibyte
-     text.  */
-  if (it->charset != CHARSET_ASCII)
+  /* If current character of IT is not ASCII, make sure we have the
+         ASCII face.  This will be automatically undone the next time
+         get_next_display_element returns a multibyte character.  Note
+         that the character will always be single byte in unibyte text.  */
+  if (!SINGLE_BYTE_CHAR_P (it->c))
     {
-      it->charset = CHARSET_ASCII;
-      it->face_id = FACE_FOR_CHARSET (f, it->face_id, CHARSET_ASCII);
+      it->face_id = FACE_FOR_CHAR (f, face, 0);
     }
 
   if (FRAME_WINDOW_P (f))
@@ -10103,7 +11201,7 @@ extend_face_to_end_of_line (it)
       if (it->glyph_row->used[TEXT_AREA] == 0)
        {
          it->glyph_row->glyphs[TEXT_AREA][0] = space_glyph;
-         it->glyph_row->glyphs[TEXT_AREA][0].u.ch.face_id = it->face_id;
+         it->glyph_row->glyphs[TEXT_AREA][0].face_id = it->face_id;
          it->glyph_row->used[TEXT_AREA] = 1;
        }
     }
@@ -10120,7 +11218,7 @@ extend_face_to_end_of_line (it)
   
       it->what = IT_CHARACTER;
       bzero (&it->position, sizeof it->position);
-      it->object = 0;
+      it->object = make_number (0);
       it->c = ' ';
       it->len = 1;
       
@@ -10154,7 +11252,12 @@ trailing_whitespace_p (charpos)
             c == ' ' || c == '\t'))
     ++bytepos;
 
-  return bytepos >= ZV_BYTE || c == '\n' || c == '\r';
+  if (bytepos >= ZV_BYTE || c == '\n' || c == '\r')
+    {
+      if (bytepos != PT_BYTE)
+       return 1;
+    }
+  return 0;
 }
 
 
@@ -10175,8 +11278,8 @@ highlight_trailing_whitespace (f, row)
       /* Skip over the space glyph inserted to display the
         cursor at the end of a line.  */
       if (glyph->type == CHAR_GLYPH
-         && glyph->u.ch.code == ' '
-         && glyph->object == 0)
+         && glyph->u.ch == ' '
+         && INTEGERP (glyph->object))
        --glyph;
 
       /* If last glyph is a space or stretch, and it's trailing
@@ -10186,30 +11289,22 @@ highlight_trailing_whitespace (f, row)
          && BUFFERP (glyph->object)
          && (glyph->type == STRETCH_GLYPH
              || (glyph->type == CHAR_GLYPH
-                 && glyph->u.ch.code == ' '))
+                 && glyph->u.ch == ' '))
          && trailing_whitespace_p (glyph->charpos))
        {
-         int face_id = lookup_named_face (f, Qtrailing_whitespace,
-                                          CHARSET_ASCII);
+         int face_id = lookup_named_face (f, Qtrailing_whitespace, 0);
          
          while (glyph >= start
                 && BUFFERP (glyph->object)
                 && (glyph->type == STRETCH_GLYPH
                     || (glyph->type == CHAR_GLYPH
-                        && glyph->u.ch.code == ' ')))
-           {
-             if (glyph->type == STRETCH_GLYPH)
-               glyph->u.stretch.face_id = face_id;
-             else
-               glyph->u.ch.face_id = face_id;
-             --glyph;
-           }
+                        && glyph->u.ch == ' ')))
+           (glyph--)->face_id = face_id;
        }
     }
 }
 
 
-
 /* Construct the glyph row IT->glyph_row in the desired matrix of
    IT->w from text at the current position of IT.  See dispextern.h
    for an overview of struct it.  Value is non-zero if
@@ -10239,6 +11334,8 @@ display_line (it)
   row->start = it->current;
   row->continuation_lines_width = it->continuation_lines_width;
   row->displays_text_p = 1;
+  row->starts_in_middle_of_char_p = it->starts_in_middle_of_char_p;
+  it->starts_in_middle_of_char_p = 0;
 
   /* Arrange the overlays nicely for our purposes.  Usually, we call
      display_line on only one line at a time, in which case this
@@ -10247,45 +11344,6 @@ display_line (it)
      recenter_overlay_lists but the first will be pretty cheap.  */
   recenter_overlay_lists (current_buffer, IT_CHARPOS (*it));
 
-#if NO_PROMPT_IN_BUFFER
-  /* Show mini-buffer prompt, if at the beginning of a mini-buffer
-     window.  */
-  if (MINI_WINDOW_P (it->w) 
-      && MATRIX_ROW_START_CHARPOS (row) == BEG 
-      && it->vpos == 0)
-    {
-      if (NILP (minibuf_prompt))
-       minibuf_prompt_width = minibuf_prompt_pixel_width = 0;
-      else
-       {
-         /* We would like to truncate the prompt a little bit before
-            the right margin of the window, so that user input can
-            start on the first line.  Set max_x to this position.  */
-         int max_x = (it->last_visible_x - 4 * CANON_X_UNIT (it->f));
-
-         /* We use a temporary iterator different from IT so that
-            IT's settings are not overwritten when displaying
-            the prompt.  */
-         struct it ti;
-
-         ti = *it;
-
-         /* Display the prompt.  Set minibuf_prompt_width to the 
-            number of glyphs generated for the prompt, set
-            minibuf_prompt_pixel_width to its width in pixels.  */
-         xassert (it->current_x == 0);
-         display_string (NULL, minibuf_prompt, Qnil, 0, 0, &ti,
-                         0, 0, max_x, -1);
-         minibuf_prompt_width = ti.hpos;
-         minibuf_prompt_pixel_width = ti.current_x;
-
-         /* Transfer pixel and hpos information to IT.  */
-         it->hpos = ti.hpos;
-         it->current_x = ti.current_x;
-       }
-    }
-#endif /* NO_PROMPT_IN_BUFFER */
-
   /* Move over display elements that are not visible because we are
      hscrolled.  This may stop at an x-position < IT->first_visible_x
      if the first glyph is partially visible or if we hit a line end.  */
@@ -10306,19 +11364,18 @@ display_line (it)
     {
       int n_glyphs_before, hpos_before, x_before;
       int x, i, nglyphs;
+      int ascent, descent, phys_ascent, phys_descent;
       
       /* Retrieve the next thing to display.  Value is zero if end of
         buffer reached.  */
       if (!get_next_display_element (it))
        {
          /* Maybe add a space at the end of this line that is used to
-            display the cursor there under X.  */
-         append_space (it, 1);
-
-         /* The position -1 below indicates a blank line not
-            corresponding to any text, as opposed to an empty line
-            corresponding to a line end.  */
-         if (row->used[TEXT_AREA] <= 1)
+            display the cursor there under X.  Set the charpos of the
+            first glyph of blank lines not corresponding to any text
+            to -1.  */
+         if ((append_space (it, 1) && row->used[TEXT_AREA] == 1)
+             || row->used[TEXT_AREA] == 0)
            {
              row->glyphs[TEXT_AREA]->charpos = -1;
              row->displays_text_p = 0;
@@ -10336,6 +11393,17 @@ display_line (it)
         generates glyphs in `row' (which is IT->glyph_row).  */
       n_glyphs_before = row->used[TEXT_AREA];
       x = it->current_x;
+
+      /* Remember the line height so far in case the next element doesn't
+        fit on the line.  */
+      if (!it->truncate_lines_p)
+       {
+         ascent = it->max_ascent;
+         descent = it->max_descent;
+         phys_ascent = it->max_phys_ascent;
+         phys_descent = it->max_phys_descent;
+       }
+      
       PRODUCE_GLYPHS (it);
 
       /* If this display element was in marginal areas, continue with
@@ -10400,9 +11468,10 @@ display_line (it)
                      || (new_x == it->last_visible_x
                          && FRAME_WINDOW_P (it->f)))
                    {
-                     /* Current glyph fits exactly on the line.  We
-                        must continue the line because we can't draw
-                        the cursor after the glyph.  */
+                     /* Current glyph is the only one on the line or
+                        fits exactly on the line.  We must continue
+                        the line because we can't draw the cursor
+                        after the glyph.  */
                      row->continued_p = 1;
                      it->current_x = new_x;
                      it->continuation_lines_width += new_x;
@@ -10410,6 +11479,31 @@ display_line (it)
                      if (i == nglyphs - 1)
                        set_iterator_to_next (it);
                    }
+                 else if (CHAR_GLYPH_PADDING_P (*glyph)
+                          && !FRAME_WINDOW_P (it->f))
+                   {
+                     /* A padding glyph that doesn't fit on this line.
+                        This means the whole character doesn't fit
+                        on the line.  */
+                     row->used[TEXT_AREA] = n_glyphs_before;
+                 
+                     /* Fill the rest of the row with continuation
+                        glyphs like in 20.x.  */
+                     while (row->glyphs[TEXT_AREA] + row->used[TEXT_AREA]
+                            < row->glyphs[1 + TEXT_AREA])
+                       produce_special_glyphs (it, IT_CONTINUATION);
+                     
+                     row->continued_p = 1;
+                     it->current_x = x_before;
+                     it->continuation_lines_width += x_before;
+                     
+                     /* Restore the height to what it was before the
+                        element not fitting on the line.  */
+                     it->max_ascent = ascent;
+                     it->max_descent = descent;
+                     it->max_phys_ascent = phys_ascent;
+                     it->max_phys_descent = phys_descent;
+                   }
                  else
                    {
                      /* Display element draws past the right edge of
@@ -10426,7 +11520,20 @@ display_line (it)
                      
                      it->current_x = x;
                      it->continuation_lines_width += x;
+                     if (nglyphs > 1 && i > 0)
+                       {
+                         row->ends_in_middle_of_char_p = 1;
+                         it->starts_in_middle_of_char_p = 1;
+                       }
+                     
+                     /* Restore the height to what it was before the
+                        element not fitting on the line.  */
+                     it->max_ascent = ascent;
+                     it->max_descent = descent;
+                     it->max_phys_ascent = phys_ascent;
+                     it->max_phys_descent = phys_descent;
                    }
+
                  break;
                }
              else if (new_x > it->first_visible_x)
@@ -10569,19 +11676,23 @@ display_line (it)
   /* Remember the position at which this line ends.  */
   row->end = it->current;
 
-  /* Maybe set the cursor.  If you change this, it's probably a good
-     idea to also change the code in redisplay_window for cursor
-     movement in an unchanged window.  */
+  /* Maybe set the cursor.  */
   if (it->w->cursor.vpos < 0
       && PT >= MATRIX_ROW_START_CHARPOS (row)
-      && MATRIX_ROW_END_CHARPOS (row) >= PT
-      && !(MATRIX_ROW_END_CHARPOS (row) == PT
-          && (MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (row)
-              || !row->ends_at_zv_p)))
-    set_cursor_from_row (it->w, row, it->w->desired_matrix, 0, 0, 0, 0);
+      && PT <= MATRIX_ROW_END_CHARPOS (row))
+    {
+      /* Also see redisplay_window, case cursor movement in unchanged
+        window.  */
+      if (MATRIX_ROW_END_CHARPOS (row) == PT
+         && !MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (row)
+         && !row->ends_at_zv_p)
+       ;
+      else
+       set_cursor_from_row (it->w, row, it->w->desired_matrix, 0, 0, 0, 0);
+    }
 
   /* Highlight trailing whitespace.  */
-  if (it->show_trailing_whitespace_p)
+  if (!NILP (Vshow_trailing_whitespace))
     highlight_trailing_whitespace (it->f, it->glyph_row);
 
   /* Prepare for the next line.  This line starts horizontally at (X
@@ -10632,7 +11743,7 @@ display_menu_bar (w)
 
 #ifdef USE_X_TOOLKIT
   xassert (!FRAME_WINDOW_P (f));
-  init_iterator (&it, w, -1, -1, f->desired_matrix->rows, MODE_LINE_FACE_ID);
+  init_iterator (&it, w, -1, -1, f->desired_matrix->rows, MENU_FACE_ID);
   it.first_visible_x = 0;
   it.last_visible_x = FRAME_WINDOW_WIDTH (f) * CANON_X_UNIT (f);
 #else /* not USE_X_TOOLKIT */
@@ -10644,7 +11755,7 @@ display_menu_bar (w)
       xassert (WINDOWP (f->menu_bar_window));
       menu_w = XWINDOW (f->menu_bar_window);
       init_iterator (&it, menu_w, -1, -1, menu_w->desired_matrix->rows,
-                    MODE_LINE_FACE_ID);
+                    MENU_FACE_ID);
       it.first_visible_x = 0;
       it.last_visible_x = FRAME_WINDOW_WIDTH (f) * CANON_X_UNIT (f);
     }
@@ -10653,7 +11764,7 @@ display_menu_bar (w)
       /* This is a TTY frame, i.e. character hpos/vpos are used as
         pixel x/y.  */
       init_iterator (&it, w, -1, -1, f->desired_matrix->rows,
-                    MODE_LINE_FACE_ID);
+                    MENU_FACE_ID);
       it.first_visible_x = 0;
       it.last_visible_x = FRAME_WIDTH (f);
     }
@@ -10716,15 +11827,17 @@ display_mode_lines (w)
   w->column_number_displayed = Qnil;
 
   if (WINDOW_WANTS_MODELINE_P (w))
-    display_mode_line (w, MODE_LINE_FACE_ID, current_buffer->mode_line_format);
+    display_mode_line (w, MODE_LINE_FACE_ID,
+                      current_buffer->mode_line_format);
   
-  if (WINDOW_WANTS_TOP_LINE_P (w))
-    display_mode_line (w, TOP_LINE_FACE_ID, current_buffer->top_line_format);
+  if (WINDOW_WANTS_HEADER_LINE_P (w))
+    display_mode_line (w, HEADER_LINE_FACE_ID,
+                      current_buffer->header_line_format);
 }
 
 
 /* Display mode or top line of window W.  FACE_ID specifies which line
-   to display; it is either MODE_LINE_FACE_ID or TOP_LINE_FACE_ID.
+   to display; it is either MODE_LINE_FACE_ID or HEADER_LINE_FACE_ID.
    FORMAT is the mode line format to display.  */
 
 static void
@@ -10942,7 +12055,7 @@ display_mode_element (it, depth, field_width, precision, elt)
           to at least that many characters.
           If first element is a symbol, process the cadr or caddr recursively
           according to whether the symbol's value is non-nil or nil.  */
-       car = XCONS (elt)->car;
+       car = XCAR (elt);
        if (EQ (car, QCeval) && CONSP (XCDR (elt)))
          {
            /* An element of the form (:eval FORM) means evaluate FORM
@@ -10959,7 +12072,7 @@ display_mode_element (it, depth, field_width, precision, elt)
        else if (SYMBOLP (car))
          {
            tem = Fboundp (car);
-           elt = XCONS (elt)->cdr;
+           elt = XCDR (elt);
            if (!CONSP (elt))
              goto invalid;
            /* elt is now the cdr, and we know it is a cons cell.
@@ -10968,23 +12081,26 @@ display_mode_element (it, depth, field_width, precision, elt)
              {
                tem = Fsymbol_value (car);
                if (!NILP (tem))
-                 { elt = XCONS (elt)->car; goto tail_recurse; }
+                 {
+                   elt = XCAR (elt);
+                   goto tail_recurse;
+                 }
              }
            /* Symbol's value is nil (or symbol is unbound)
               Get the cddr of the original list
               and if possible find the caddr and use that.  */
-           elt = XCONS (elt)->cdr;
+           elt = XCDR (elt);
            if (NILP (elt))
              break;
            else if (!CONSP (elt))
              goto invalid;
-           elt = XCONS (elt)->car;
+           elt = XCAR (elt);
            goto tail_recurse;
          }
        else if (INTEGERP (car))
          {
            register int lim = XINT (car);
-           elt = XCONS (elt)->cdr;
+           elt = XCDR (elt);
            if (lim < 0)
              {
                /* Negative int means reduce maximum width.  */
@@ -11016,8 +12132,8 @@ display_mode_element (it, depth, field_width, precision, elt)
                   && (precision <= 0 || n < precision))
              {
                n += display_mode_element (it, depth, field_width - n,
-                                          precision - n, XCONS (elt)->car);
-               elt = XCONS (elt)->cdr;
+                                          precision - n, XCAR (elt));
+               elt = XCDR (elt);
              }
          }
       }
@@ -11099,9 +12215,9 @@ decode_mode_spec_coding (coding_system, buf, eol_flag)
   /* The EOL conversion we are using.  */
   Lisp_Object eoltype;
 
-  val = coding_system;
+  val = Fget (coding_system, Qcoding_system);
 
-  if (NILP (val))              /* Not yet decided.  */
+  if (!VECTORP (val))          /* Not yet decided.  */
     {
       if (multibyte)
        *buf++ = '-';
@@ -11115,13 +12231,6 @@ decode_mode_spec_coding (coding_system, buf, eol_flag)
 
       eolvalue = Fget (coding_system, Qeol_type);
 
-      while (!NILP (val) && SYMBOLP (val))
-       {
-         val = Fget (val, Qcoding_system);
-         if (NILP (eolvalue))
-           eolvalue = Fget (val, Qeol_type);
-       }
-
       if (multibyte)
        *buf++ = XFASTINT (XVECTOR (val)->contents[1]);
 
@@ -11152,10 +12261,8 @@ decode_mode_spec_coding (coding_system, buf, eol_flag)
       else if (INTEGERP (eoltype)
               && CHAR_VALID_P (XINT (eoltype), 0))
        {
-         int c = XINT (eoltype);
-         unsigned char work[4];
-
-         eol_str_len = CHAR_STRING (XINT (eoltype), work, eol_str);
+         eol_str = (unsigned char *) alloca (MAX_MULTIBYTE_LENGTH);
+         eol_str_len = CHAR_STRING (XINT (eoltype), eol_str);
        }
       else
        {
@@ -11179,7 +12286,7 @@ static char lots_of_dashes[] = "------------------------------------------------
 static char *
 decode_mode_spec (w, c, field_width, precision)
      struct window *w;
-     register char c;
+     register int c;
      int field_width, precision;
 {
   Lisp_Object obj;
@@ -11301,7 +12408,8 @@ decode_mode_spec (w, c, field_width, precision)
          w->base_line_pos = Qnil;
 
        /* If the buffer is very big, don't waste time.  */
-       if (BUF_ZV (b) - BUF_BEGV (b) > line_number_display_limit)
+       if (INTEGERP (Vline_number_display_limit)
+           && BUF_ZV (b) - BUF_BEGV (b) > XINT (Vline_number_display_limit))
          {
            w->base_line_pos = Qnil;
            w->base_line_number = Qnil;
@@ -11345,7 +12453,7 @@ decode_mode_spec (w, c, field_width, precision)
            int limit = BUF_BEGV (b);
            int limit_byte = BUF_BEGV_BYTE (b);
            int position;
-           int distance = (height * 2 + 30) * 200;
+           int distance = (height * 2 + 30) * line_number_display_limit_width;
 
            if (startpos - distance > limit)
              {
@@ -11358,7 +12466,7 @@ decode_mode_spec (w, c, field_width, precision)
                                          - (height * 2 + 30),
                                          &position);
            /* If we couldn't find the lines we wanted within 
-              200 chars per line,
+              line_number_display_limit_width chars per line,
               give up on line numbers for this window.  */
            if (position == limit_byte && limit == startpos - distance)
              {
@@ -11388,7 +12496,8 @@ decode_mode_spec (w, c, field_width, precision)
          while (pad-- > 0)
            *p++ = ' ';
          *p++ = '?';
-         *p = '?';
+         *p++ = '?';
+         *p = '\0';
          return decode_mode_spec_buf;
        }
       }
@@ -11675,6 +12784,8 @@ display_string (string, lisp_string, face_string, face_string_pos,
                start, it, field_width, precision, max_x, multibyte)
      unsigned char *string;
      Lisp_Object lisp_string;
+     Lisp_Object face_string;
+     int face_string_pos;
      int start;
      struct it *it;
      int field_width, precision, max_x;
@@ -11836,28 +12947,28 @@ invisible_p (propval, list)
      Lisp_Object list;
 {
   register Lisp_Object tail, proptail;
-  for (tail = list; CONSP (tail); tail = XCONS (tail)->cdr)
+  for (tail = list; CONSP (tail); tail = XCDR (tail))
     {
       register Lisp_Object tem;
-      tem = XCONS (tail)->car;
+      tem = XCAR (tail);
       if (EQ (propval, tem))
        return 1;
-      if (CONSP (tem) && EQ (propval, XCONS (tem)->car))
+      if (CONSP (tem) && EQ (propval, XCAR (tem)))
        return 1;
     }
   if (CONSP (propval))
     for (proptail = propval; CONSP (proptail);
-        proptail = XCONS (proptail)->cdr)
+        proptail = XCDR (proptail))
       {
        Lisp_Object propelt;
-       propelt = XCONS (proptail)->car;
-       for (tail = list; CONSP (tail); tail = XCONS (tail)->cdr)
+       propelt = XCAR (proptail);
+       for (tail = list; CONSP (tail); tail = XCDR (tail))
          {
            register Lisp_Object tem;
-           tem = XCONS (tail)->car;
+           tem = XCAR (tail);
            if (EQ (propelt, tem))
              return 1;
-           if (CONSP (tem) && EQ (propelt, XCONS (tem)->car))
+           if (CONSP (tem) && EQ (propelt, XCAR (tem)))
              return 1;
          }
       }
@@ -11877,27 +12988,29 @@ invisible_ellipsis_p (propval, list)
      Lisp_Object list;
 {
   register Lisp_Object tail, proptail;
-  for (tail = list; CONSP (tail); tail = XCONS (tail)->cdr)
+  
+  for (tail = list; CONSP (tail); tail = XCDR (tail))
     {
       register Lisp_Object tem;
-      tem = XCONS (tail)->car;
-      if (CONSP (tem) && EQ (propval, XCONS (tem)->car))
-       return ! NILP (XCONS (tem)->cdr);
+      tem = XCAR (tail);
+      if (CONSP (tem) && EQ (propval, XCAR (tem)))
+       return ! NILP (XCDR (tem));
     }
+  
   if (CONSP (propval))
-    for (proptail = propval; CONSP (proptail);
-        proptail = XCONS (proptail)->cdr)
+    for (proptail = propval; CONSP (proptail); proptail = XCDR (proptail))
       {
        Lisp_Object propelt;
-       propelt = XCONS (proptail)->car;
-       for (tail = list; CONSP (tail); tail = XCONS (tail)->cdr)
+       propelt = XCAR (proptail);
+       for (tail = list; CONSP (tail); tail = XCDR (tail))
          {
            register Lisp_Object tem;
-           tem = XCONS (tail)->car;
-           if (CONSP (tem) && EQ (propelt, XCONS (tem)->car))
-             return ! NILP (XCONS (tem)->cdr);
+           tem = XCAR (tail);
+           if (CONSP (tem) && EQ (propelt, XCAR (tem)))
+             return ! NILP (XCDR (tem));
          }
       }
+  
   return 0;
 }
 
@@ -11910,18 +13023,21 @@ invisible_ellipsis_p (propval, list)
 void
 syms_of_xdisp ()
 {
-  echo_area_message = previous_echo_area_message = Qnil;
-  staticpro (&echo_area_message);
-  staticpro (&previous_echo_area_message);
+  Vwith_echo_area_save_vector = Qnil;
+  staticpro (&Vwith_echo_area_save_vector);
 
-  staticpro (&Qinhibit_redisplay);
+  Vmessage_stack = Qnil;
+  staticpro (&Vmessage_stack);
+  
   Qinhibit_redisplay = intern ("inhibit-redisplay");
+  staticpro (&Qinhibit_redisplay);
 
 #if GLYPH_DEBUG
   defsubr (&Sdump_glyph_matrix);
   defsubr (&Sdump_glyph_row);
-  defsubr (&Sdump_toolbar_row);
+  defsubr (&Sdump_tool_bar_row);
   defsubr (&Strace_redisplay_toggle);
+  defsubr (&Strace_to_stderr);
 #endif
 
   staticpro (&Qmenu_bar_update_hook);
@@ -11942,26 +13058,26 @@ syms_of_xdisp ()
   staticpro (&Qinhibit_point_motion_hooks);
   Qinhibit_point_motion_hooks = intern ("inhibit-point-motion-hooks");
 
-  staticpro (&Qdisplay);
+  QCdata = intern (":data");
+  staticpro (&QCdata);
   Qdisplay = intern ("display");
-  staticpro (&Qleft_margin);
+  staticpro (&Qdisplay);
   Qspace_width = intern ("space-width");
   staticpro (&Qspace_width);
-  Qheight = intern ("height");
-  staticpro (&Qheight);
   Qraise = intern ("raise");
   staticpro (&Qraise);
   Qspace = intern ("space");
   staticpro (&Qspace);
+  Qmargin = intern ("margin");
+  staticpro (&Qmargin);
   Qleft_margin = intern ("left-margin");
-  staticpro (&Qright_margin);
+  staticpro (&Qleft_margin);
   Qright_margin = intern ("right-margin");
+  staticpro (&Qright_margin);
   Qalign_to = intern ("align-to");
   staticpro (&Qalign_to);
   QCalign_to = intern (":align-to");
   staticpro (&QCalign_to);
-  Qwidth = intern ("width");
-  staticpro (&Qwidth);
   Qrelative_width = intern ("relative-width");
   staticpro (&Qrelative_width);
   QCrelative_width = intern (":relative-width");
@@ -11970,23 +13086,38 @@ syms_of_xdisp ()
   staticpro (&QCrelative_height);
   QCeval = intern (":eval");
   staticpro (&QCeval);
-  QCwhen = intern (":when");
-  staticpro (&QCwhen);
+  Qwhen = intern ("when");
+  staticpro (&Qwhen);
+  QCfile = intern (":file");
+  staticpro (&QCfile);
   Qfontified = intern ("fontified");
   staticpro (&Qfontified);
   Qfontification_functions = intern ("fontification-functions");
   staticpro (&Qfontification_functions);
-  Qshow_trailing_whitespace = intern ("show-trailing-whitespace");
-  staticpro (&Qshow_trailing_whitespace);
   Qtrailing_whitespace = intern ("trailing-whitespace");
   staticpro (&Qtrailing_whitespace);
   Qimage = intern ("image");
   staticpro (&Qimage);
+  Qmessage_truncate_lines = intern ("message-truncate-lines");
+  staticpro (&Qmessage_truncate_lines);
 
-  staticpro (&last_arrow_position);
-  staticpro (&last_arrow_string);
   last_arrow_position = Qnil;
   last_arrow_string = Qnil;
+  staticpro (&last_arrow_position);
+  staticpro (&last_arrow_string);
+  
+  echo_buffer[0] = echo_buffer[1] = Qnil;
+  staticpro (&echo_buffer[0]);
+  staticpro (&echo_buffer[1]);
+
+  echo_area_buffer[0] = echo_area_buffer[1] = Qnil;
+  staticpro (&echo_area_buffer[0]);
+  staticpro (&echo_area_buffer[1]);
+
+  DEFVAR_LISP ("show-trailing-whitespace", &Vshow_trailing_whitespace,
+    "Non-nil means highlight trailing whitespace.\n\
+The face used for trailing whitespace is `trailing-whitespace'.");
+  Vshow_trailing_whitespace = Qnil;
 
   DEFVAR_LISP ("inhibit-redisplay", &Vinhibit_redisplay,
     "Non-nil means don't actually do any redisplay.\n\
@@ -12013,7 +13144,9 @@ If that fails to bring point back on frame, point is centered instead.\n\
 If this is zero, point is always centered after it moves off frame.");
 
   DEFVAR_INT ("scroll-conservatively", &scroll_conservatively,
-    "*Scroll up to this many lines, to bring point back on screen.");
+    "*Scroll up to this many lines, to bring point back on screen.\n\
+A value of zero means to scroll the text to center point vertically\n\
+in the window.");
   scroll_conservatively = 0;
 
   DEFVAR_INT ("scroll-margin", &scroll_margin,
@@ -12035,11 +13168,18 @@ of the top or bottom of the window.");
     "*Non-nil means use inverse video for the mode line.");
   mode_line_inverse_video = 1;
 
-  DEFVAR_INT ("line-number-display-limit", &line_number_display_limit,
+  DEFVAR_LISP ("line-number-display-limit", &Vline_number_display_limit,
     "*Maximum buffer size for which line number should be displayed.\n\
 If the buffer is bigger than this, the line number does not appear\n\
-in the mode line.");
-  line_number_display_limit = 1000000;
+in the mode line.  A value of nil means no limit.");
+  Vline_number_display_limit = Qnil;
+
+  DEFVAR_INT ("line-number-display-limit-width",
+             &line_number_display_limit_width,
+    "*Maximum line width (in characters) for line number display.\n\
+If the average length of the lines near point is bigger than this, then the\n\
+line number may be omitted from the mode line.");
+  line_number_display_limit_width = 200;
 
   DEFVAR_BOOL ("highlight-nonselected-windows", &highlight_nonselected_windows,
     "*Non-nil means highlight region even in nonselected windows.");
@@ -12095,24 +13235,24 @@ and its new display-start position.  Note that the value of `window-end'\n\
 is not valid when these functions are called.");
   Vwindow_scroll_functions = Qnil;
   
-  DEFVAR_BOOL ("auto-resize-toolbars", &auto_resize_toolbars_p,
-    "*Non-nil means automatically resize toolbars.\n\
-This increases a toolbar's height if not all toolbar items are visible.\n\
-It decreases a toolbar's height when it would display blank lines\n\
+  DEFVAR_BOOL ("auto-resize-tool-bars", &auto_resize_tool_bars_p,
+    "*Non-nil means automatically resize tool-bars.\n\
+This increases a tool-bar's height if not all tool-bar items are visible.\n\
+It decreases a tool-bar's height when it would display blank lines\n\
 otherwise.");
-  auto_resize_toolbars_p = 1;
+  auto_resize_tool_bars_p = 1;
   
-  DEFVAR_BOOL ("auto-raise-toolbar-buttons", &auto_raise_toolbar_buttons_p,
-    "*Non-nil means raise toolbar buttons when the mouse moves over them.");
-  auto_raise_toolbar_buttons_p = 1;
+  DEFVAR_BOOL ("auto-raise-tool-bar-buttons", &auto_raise_tool_bar_buttons_p,
+    "*Non-nil means raise tool-bar buttons when the mouse moves over them.");
+  auto_raise_tool_bar_buttons_p = 1;
 
-  DEFVAR_INT ("toolbar-button-margin", &toolbar_button_margin,
-    "*Margin around toolbar buttons in pixels.");
-  toolbar_button_margin = 1;
+  DEFVAR_INT ("tool-bar-button-margin", &tool_bar_button_margin,
+    "*Margin around tool-bar buttons in pixels.");
+  tool_bar_button_margin = 1;
 
-  DEFVAR_INT ("toolbar-button-relief", &toolbar_button_relief,
-    "Relief thickness of toolbar buttons.");
-  toolbar_button_relief = 3;
+  DEFVAR_INT ("tool-bar-button-relief", &tool_bar_button_relief,
+    "Relief thickness of tool-bar buttons.");
+  tool_bar_button_relief = 3;
 
   DEFVAR_LISP ("fontification-functions", &Vfontification_functions,
     "List of functions to call to fontify regions of text.\n\
@@ -12131,6 +13271,33 @@ are displayed by converting them to the equivalent multibyte characters\n\
 according to the current language environment.  As a result, they are\n\
 displayed according to the current fontset.");
   unibyte_display_via_language_environment = 0;
+
+  DEFVAR_LISP ("max-mini-window-height", &Vmax_mini_window_height,
+    "*Maximum height for resizing mini-windows.\n\
+If a float, it specifies a fraction of the mini-window frame's height.\n\
+If an integer, it specifies a number of lines.\n\
+If nil, don't resize.");
+  Vmax_mini_window_height = make_float (0.25);
+  
+  DEFVAR_BOOL ("cursor-in-non-selected-windows",
+              &cursor_in_non_selected_windows,
+    "*Non-nil means display a hollow cursor in non-selected windows.\n\
+Nil means don't display a cursor there.");
+  cursor_in_non_selected_windows = 1;
+  
+  DEFVAR_BOOL ("automatic-hscrolling", &automatic_hscrolling_p,
+    "*Non-nil means scroll the display automatically to make point visible.");
+  automatic_hscrolling_p = 1;
+  
+  DEFVAR_LISP ("image-types", &Vimage_types,
+    "List of supported image types.\n\
+Each element of the list is a symbol for a supported image type.");
+  Vimage_types = Qnil;
+  
+  DEFVAR_BOOL ("message-truncate-lines", &message_truncate_lines,
+    "If non-nil, messages are truncated instead of resizing the echo area.\n\
+Bind this around calls to `message' to let it take effect.");
+  message_truncate_lines = 0;
 }
 
 
@@ -12147,10 +13314,6 @@ init_xdisp ()
   mini_w = XWINDOW (minibuf_window);
   root_window = FRAME_ROOT_WINDOW (XFRAME (WINDOW_FRAME (mini_w)));
 
-  echo_area_glyphs = 0;
-  previous_echo_glyphs = 0;
-  echo_area_message = previous_echo_area_message = Qnil;
-
   if (!noninteractive)
     {
       struct frame *f = XFRAME (WINDOW_FRAME (XWINDOW (root_window)));