Include "character.h" instead of "charset.h".
[bpt/emacs.git] / src / dispnew.c
index c114849..196429f 100644 (file)
@@ -1,5 +1,5 @@
 /* Updating of data structures for redisplay.
-   Copyright (C) 1985, 86, 87, 88, 93, 94, 95, 97, 98, 1999
+   Copyright (C) 1985, 86, 87, 88, 93, 94, 95, 97, 98, 1999, 2000, 2001
        Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
@@ -36,7 +36,8 @@ Boston, MA 02111-1307, USA.  */
 #include "dispextern.h"
 #include "cm.h"
 #include "buffer.h"
-#include "charset.h"
+#include "character.h"
+#include "keyboard.h"
 #include "frame.h"
 #include "window.h"
 #include "commands.h"
@@ -45,7 +46,6 @@ Boston, MA 02111-1307, USA.  */
 #include "intervals.h"
 #include "blockinput.h"
 #include "process.h"
-#include "keyboard.h"
 
 /* I don't know why DEC Alpha OSF1 fail to compile this file if we
    include the following file.  */
@@ -60,6 +60,10 @@ Boston, MA 02111-1307, USA.  */
 #include "w32term.h"
 #endif /* HAVE_NTGUI */
 
+#ifdef macintosh
+#include "macterm.h"
+#endif /* macintosh */
+
 /* Include systime.h after xterm.h to avoid double inclusion of time.h.  */
 
 #include "systime.h"
@@ -71,9 +75,6 @@ Boston, MA 02111-1307, USA.  */
 #include <unistd.h>
 #endif
 
-#define max(a, b) ((a) > (b) ? (a) : (b))
-#define min(a, b) ((a) < (b) ? (a) : (b))
-
 /* Get number of chars of output now in the buffer of a stdio stream.
    This ought to be built in in stdio, but it isn't.  Some s- files
    override this because their stdio internals differ.  */
@@ -100,7 +101,7 @@ Boston, MA 02111-1307, USA.  */
 #endif
 #endif /* not __GNU_LIBRARY__ */
 
-#if defined (LINUX) && defined (HAVE_LIBNCURSES)
+#if defined(HAVE_TERM_H) && defined (GNU_LINUX) && defined (HAVE_LIBNCURSES)
 #include <term.h>              /* for tgetent */
 #endif
 \f
@@ -116,6 +117,9 @@ struct dim
 \f
 /* Function prototypes.  */
 
+static struct glyph_matrix *save_current_matrix P_ ((struct frame *));
+static void restore_current_matrix P_ ((struct frame *, struct glyph_matrix *));
+static void fake_current_matrices P_ ((Lisp_Object));
 static void redraw_overlapping_rows P_ ((struct window *, int));
 static void redraw_overlapped_rows P_ ((struct window *, int));
 static int count_blanks P_ ((struct glyph *, int));
@@ -124,9 +128,8 @@ static int count_match P_ ((struct glyph *, struct glyph *,
 static unsigned line_draw_cost P_ ((struct glyph_matrix *, int));
 static void update_frame_line P_ ((struct frame *, int));
 static struct dim allocate_matrices_for_frame_redisplay
-     P_ ((Lisp_Object, int, int, struct dim, int, int *));
-static void allocate_matrices_for_window_redisplay P_ ((struct window *,
-                                                       struct dim));
+     P_ ((Lisp_Object, int, int, int, int *));
+static void allocate_matrices_for_window_redisplay P_ ((struct window *));
 static int realloc_glyph_pool P_ ((struct glyph_pool *, struct dim));
 static void adjust_frame_glyphs P_ ((struct frame *));
 struct glyph_matrix *new_glyph_matrix P_ ((struct glyph_pool *));
@@ -135,7 +138,9 @@ static void adjust_glyph_matrix P_ ((struct window *, struct glyph_matrix *,
                                     int, int, struct dim));
 static void change_frame_size_1 P_ ((struct frame *, int, int, int, int, int));
 static void swap_glyph_pointers P_ ((struct glyph_row *, struct glyph_row *));
+#if GLYPH_DEBUG
 static int glyph_row_slice_p P_ ((struct glyph_row *, struct glyph_row *));
+#endif
 static void fill_up_frame_row_with_spaces P_ ((struct glyph_row *, int));
 static void build_frame_matrix_from_window_tree P_ ((struct glyph_matrix *,
                                                     struct window *));
@@ -154,7 +159,7 @@ void scroll_glyph_matrix_range P_ ((struct glyph_matrix *, int, int,
 static void clear_window_matrices P_ ((struct window *, int));
 static void fill_up_glyph_row_area_with_spaces P_ ((struct glyph_row *, int));
 static int scrolling_window P_ ((struct window *, int));
-static int update_window_line P_ ((struct window *, int));
+static int update_window_line P_ ((struct window *, int, int *));
 static void update_marginal_area P_ ((struct window *, int, int));
 static int update_text_area P_ ((struct window *, int));
 static void make_current P_ ((struct glyph_matrix *, struct glyph_matrix *,
@@ -171,7 +176,7 @@ static int update_window P_ ((struct window *, int));
 static int update_frame_1 P_ ((struct frame *, int, int));
 static void set_window_cursor_after_update P_ ((struct window *));
 static int row_equal_p P_ ((struct window *, struct glyph_row *,
-                           struct glyph_row *));
+                           struct glyph_row *, int));
 static void adjust_frame_glyphs_for_window_redisplay P_ ((struct frame *));
 static void adjust_frame_glyphs_for_frame_redisplay P_ ((struct frame *));
 static void reverse_rows P_ ((struct glyph_matrix *, int, int));
@@ -179,7 +184,6 @@ static int margin_glyphs_to_reserve P_ ((struct window *, int, Lisp_Object));
 static void sync_window_with_frame_matrix_rows P_ ((struct window *));
 struct window *frame_row_to_window P_ ((struct window *, int));
 
-
 \f
 /* Non-zero means don't pause redisplay for pending input.  (This is
    for debugging and for a future implementation of EDT-like
@@ -234,12 +238,12 @@ Lisp_Object Vglyph_table;
 Lisp_Object Vstandard_display_table;
 
 /* Nonzero means reading single-character input with prompt so put
-   cursor on mini-buffer after the prompt.  positive means at end of
+   cursor on mini-buffer after the prompt.  Positive means at end of
    text in echo area; negative means at beginning of line.  */
 
 int cursor_in_echo_area;
 
-Lisp_Object Qdisplay_table;
+Lisp_Object Qdisplay_table, Qredisplay_dont_pause;
 
 \f
 /* The currently selected frame.  In a single-frame version, this
@@ -323,6 +327,105 @@ static int window_to_frame_hpos P_ ((struct window *, int));
 #define WINDOW_TO_FRAME_VPOS(W, VPOS) window_to_frame_vpos ((W), (VPOS))
 #define WINDOW_TO_FRAME_HPOS(W, HPOS) window_to_frame_hpos ((W), (HPOS))
 
+/* One element of the ring buffer containing redisplay history
+   information.  */
+
+struct redisplay_history
+{
+  char trace[512 + 100];
+};
+
+/* The size of the history buffer.  */
+
+#define REDISPLAY_HISTORY_SIZE 30
+
+/* The redisplay history buffer.  */
+
+static struct redisplay_history redisplay_history[REDISPLAY_HISTORY_SIZE];
+
+/* Next free entry in redisplay_history.  */
+
+static int history_idx;
+
+/* A tick that's incremented each time something is added to the
+   history.  */
+
+static unsigned history_tick;
+
+static void add_frame_display_history P_ ((struct frame *, int));
+static void add_window_display_history P_ ((struct window *, char *, int));
+
+
+/* Add to the redisplay history how window W has been displayed.
+   MSG is a trace containing the information how W's glyph matrix
+   has been constructed.  PAUSED_P non-zero means that the update
+   has been interrupted for pending input.  */
+
+static void
+add_window_display_history (w, msg, paused_p)
+     struct window *w;
+     char *msg;
+     int paused_p;
+{
+  char *buf;
+  
+  if (history_idx >= REDISPLAY_HISTORY_SIZE)
+    history_idx = 0;
+  buf = redisplay_history[history_idx].trace;
+  ++history_idx;
+  
+  sprintf (buf, "%d: window %p (`%s')%s\n",
+          history_tick++,
+          w,
+          ((BUFFERP (w->buffer)
+            && STRINGP (XBUFFER (w->buffer)->name))
+           ? (char *) XSTRING (XBUFFER (w->buffer)->name)->data
+           : "???"),
+          paused_p ? " ***paused***" : "");
+  strcat (buf, msg);
+}
+
+
+/* Add to the redisplay history that frame F has been displayed.
+   PAUSED_P non-zero means that the update has been interrupted for
+   pending input.  */
+
+static void
+add_frame_display_history (f, paused_p)
+     struct frame *f;
+     int paused_p;
+{
+  char *buf;
+  
+  if (history_idx >= REDISPLAY_HISTORY_SIZE)
+    history_idx = 0;
+  buf = redisplay_history[history_idx].trace;
+  ++history_idx;
+  
+  sprintf (buf, "%d: update frame %p%s",
+          history_tick++,
+          f, paused_p ? " ***paused***" : "");
+}
+
+
+DEFUN ("dump-redisplay-history", Fdump_redisplay_history,
+       Sdump_redisplay_history, 0, 0, "",
+       doc: /* Dump redisplay history to stderr.  */)
+     ()
+{
+  int i;
+
+  for (i = history_idx - 1; i != history_idx; --i)
+    {
+      if (i < 0)
+       i = REDISPLAY_HISTORY_SIZE - 1;
+      fprintf (stderr, "%s\n", redisplay_history[i].trace);
+    }
+
+  return Qnil;
+}
+
+
 #else /* GLYPH_DEBUG == 0 */
 
 #define WINDOW_TO_FRAME_VPOS(W, VPOS) ((VPOS) + XFASTINT ((W)->top))
@@ -519,9 +622,9 @@ adjust_glyph_matrix (w, matrix, x, y, dim)
   int header_line_changed_p = 0;
   int header_line_p = 0;
   int left = -1, right = -1;
-  int window_x, window_y, window_width, window_height;
+  int window_x, window_y, window_width = -1, window_height;
 
-  /* See if W had a top line that has disappeared now, or vice versa.  */
+  /* See if W had a header line that has disappeared now, or vice versa.  */
   if (w)
     {
       header_line_p = WINDOW_WANTS_HEADER_LINE_P (w);
@@ -544,6 +647,7 @@ adjust_glyph_matrix (w, matrix, x, y, dim)
       if (!marginal_areas_changed_p
          && !fonts_changed_p
          && !header_line_changed_p
+         && matrix->window_left_x == XFASTINT (w->left)
          && matrix->window_top_y == XFASTINT (w->top)
          && matrix->window_height == window_height
          && matrix->window_vscroll == w->vscroll
@@ -665,41 +769,64 @@ adjust_glyph_matrix (w, matrix, x, y, dim)
   
   /* Number of rows to be used by MATRIX.  */
   matrix->nrows = dim.height;
+  xassert (matrix->nrows >= 0);
 
-  /* Mark rows in a current matrix of a window as not having valid
-     contents.  It's important to not do this for desired matrices.
-     When Emacs starts, it may already be building desired matrices
-     when this function runs.  */
-  if (w && matrix == w->current_matrix)
+  if (w)
     {
-      /* Optimize the case that only the height has changed (C-x 2,
-         upper window).  Invalidate all rows that are no longer part
-         of the window.  */
-      if (!marginal_areas_changed_p
-         && matrix->window_top_y == XFASTINT (w->top)
-         && matrix->window_width == window_width)
+      if (matrix == w->current_matrix)
        {
-         i = 0;
-         while (matrix->rows[i].enabled_p
-                && (MATRIX_ROW_BOTTOM_Y (matrix->rows + i)
-                    < matrix->window_height))
-           ++i;
-
-         /* Window end is invalid, if inside of the rows that
-            are invalidated.  */
-         if (INTEGERP (w->window_end_vpos)
-             && XFASTINT (w->window_end_vpos) >= i)
-           w->window_end_valid = Qnil;
+         /* Mark rows in a current matrix of a window as not having
+            valid contents.  It's important to not do this for
+            desired matrices.  When Emacs starts, it may already be
+            building desired matrices when this function runs.  */
+         if (window_width < 0)
+           window_width = window_box_width (w, -1);
+      
+         /* Optimize the case that only the height has changed (C-x 2,
+            upper window).  Invalidate all rows that are no longer part
+            of the window.  */
+         if (!marginal_areas_changed_p
+             && !header_line_changed_p
+             && new_rows == 0
+             && dim.width == matrix->matrix_w
+             && matrix->window_left_x == XFASTINT (w->left)
+             && matrix->window_top_y == XFASTINT (w->top)
+             && matrix->window_width == window_width)
+           {
+             /* Find the last row in the window.  */
+             for (i = 0; i < matrix->nrows && matrix->rows[i].enabled_p; ++i)
+               if (MATRIX_ROW_BOTTOM_Y (matrix->rows + i) >= window_height)
+                 {
+                   ++i;
+                   break;
+                 }
+
+             /* Window end is invalid, if inside of the rows that
+                are invalidated below.  */
+             if (INTEGERP (w->window_end_vpos)
+                 && XFASTINT (w->window_end_vpos) >= i)
+               w->window_end_valid = Qnil;
          
-         while (i < matrix->nrows)
-           matrix->rows[i++].enabled_p = 0;
+             while (i < matrix->nrows)
+               matrix->rows[i++].enabled_p = 0;
+           }
+         else
+           {
+             for (i = 0; i < matrix->nrows; ++i)
+               matrix->rows[i].enabled_p = 0;
+           }
        }
-      else
+      else if (matrix == w->desired_matrix)
        {
+         /* Rows in desired matrices always have to be cleared;
+            redisplay expects this is the case when it runs, so it
+            had better be the case when we adjust matrices between
+            redisplays.  */
          for (i = 0; i < matrix->nrows; ++i)
            matrix->rows[i].enabled_p = 0;
        }
     }
+    
   
   /* Remember last values to be able to optimize frame redraws.  */
   matrix->matrix_x = x;
@@ -711,6 +838,7 @@ adjust_glyph_matrix (w, matrix, x, y, dim)
      was last adjusted.  This is used to optimize redisplay above.  */
   if (w)
     {
+      matrix->window_left_x = XFASTINT (w->left);
       matrix->window_top_y = XFASTINT (w->top);
       matrix->window_height = window_height;
       matrix->window_width = window_width;
@@ -862,13 +990,12 @@ shift_glyph_matrix (w, matrix, start, end, dy)
       struct glyph_row *row = &matrix->rows[start];
       
       row->y += dy;
+      row->visible_height = row->height;
       
       if (row->y < min_y)
-       row->visible_height = row->height - (min_y - row->y);
-      else if (row->y + row->height > max_y)
-       row->visible_height = row->height - (row->y + row->height - max_y);
-      else
-       row->visible_height = row->height;
+       row->visible_height -= min_y - row->y;
+      if (row->y + row->height > max_y)
+       row->visible_height -= row->y + row->height - max_y;
     }
 }
 
@@ -969,12 +1096,13 @@ clear_window_matrices (w, desired_p)
    changes in the glyph_row structure, i.e. addition or removal of
    structure members.  */
 
+static struct glyph_row null_row;
+
 void
 clear_glyph_row (row)
      struct glyph_row *row;
 {
   struct glyph *p[1 + LAST_AREA];
-  static struct glyph_row null_row;
 
   /* Save pointers.  */
   p[LEFT_MARGIN_AREA] = row->glyphs[LEFT_MARGIN_AREA];
@@ -990,6 +1118,16 @@ clear_glyph_row (row)
   row->glyphs[TEXT_AREA] = p[TEXT_AREA];
   row->glyphs[RIGHT_MARGIN_AREA] = p[RIGHT_MARGIN_AREA];
   row->glyphs[LAST_AREA] = p[LAST_AREA];
+
+#if 0 /* At some point, some bit-fields of struct glyph were not set,
+        which made glyphs unequal when compared with GLYPH_EQUAL_P.
+        Redisplay outputs such glyphs, and flickering effects were
+        the result.  This also depended on the contents of memory
+        returned by xmalloc.  If flickering happens again, activate
+        the code below.  If the flickering is gone with that, chances
+        are that the flickering has the same reason as here.  */
+  bzero (p[0], (char *) p[LAST_AREA] - (char *) p[0]);
+#endif
 }
 
 
@@ -1011,13 +1149,12 @@ blank_row (w, row, y)
   row->y = y;
   row->ascent = row->phys_ascent = 0;
   row->height = row->phys_height = CANON_Y_UNIT (XFRAME (w->frame));
-  
+  row->visible_height = row->height;
+      
   if (row->y < min_y)
-    row->visible_height = row->height - (min_y - row->y);
-  else if (row->y + row->height > max_y)
-    row->visible_height = row->height - (row->y + row->height - max_y);
-  else
-    row->visible_height = row->height;
+    row->visible_height -= min_y - row->y;
+  if (row->y + row->height > max_y)
+    row->visible_height -= row->y + row->height - max_y;
 
   row->enabled_p = 1;
 }
@@ -1180,6 +1317,8 @@ assign_row (to, from)
    is non-zero if the glyph memory of WINDOW_ROW is part of the glyph
    memory of FRAME_ROW.  */
 
+#if GLYPH_DEBUG
+
 static int
 glyph_row_slice_p (window_row, frame_row)
      struct glyph_row *window_row, *frame_row;
@@ -1192,6 +1331,7 @@ glyph_row_slice_p (window_row, frame_row)
          && window_glyph_start < frame_glyph_end);
 }
 
+#endif /* GLYPH_DEBUG */
 
 #if 0
 
@@ -1245,38 +1385,29 @@ line_hash_code (row)
   
   if (row->enabled_p)
     {
-      if (row->inverse_p)
-        {
-          /* Give all highlighted lines the same hash code
-            so as to encourage scrolling to leave them in place.  */
-          hash = -1;
-        }
-      else
-        {
-          struct glyph *glyph = row->glyphs[TEXT_AREA];
-         struct glyph *end = glyph + row->used[TEXT_AREA];
-
-          while (glyph < end)
-            {
-             int c = glyph->u.ch;
-             int face_id = glyph->face_id;
-             if (must_write_spaces)
-               c -= SPACEGLYPH;
-             hash = (((hash << 4) + (hash >> 24)) & 0x0fffffff) + c;
-             hash = (((hash << 4) + (hash >> 24)) & 0x0fffffff) + face_id;
-             ++glyph;
-           }
+      struct glyph *glyph = row->glyphs[TEXT_AREA];
+      struct glyph *end = glyph + row->used[TEXT_AREA];
+
+      while (glyph < end)
+       {
+         int c = glyph->u.ch;
+         int face_id = glyph->face_id;
+         if (must_write_spaces)
+           c -= SPACEGLYPH;
+         hash = (((hash << 4) + (hash >> 24)) & 0x0fffffff) + c;
+         hash = (((hash << 4) + (hash >> 24)) & 0x0fffffff) + face_id;
+         ++glyph;
+       }
 
-          if (hash == 0)
-           hash = 1;
-        }
+      if (hash == 0)
+       hash = 1;
     }
 
   return hash;
 }
 
 
-/* Return the cost of drawing line VPOS In MATRIX.  The cost equals
+/* Return the cost of drawing line VPOS in MATRIX.  The cost equals
    the number of characters in the line.  If must_write_spaces is
    zero, leading and trailing spaces are ignored.  */
 
@@ -1296,7 +1427,7 @@ line_draw_cost (matrix, vpos)
   if (!must_write_spaces)
     {
       /* Skip from the end over trailing spaces.  */
-      while (end != beg && CHAR_GLYPH_SPACE_P (*end))
+      while (end > beg && CHAR_GLYPH_SPACE_P (*(end - 1)))
        --end;
 
       /* All blank line.  */      
@@ -1338,12 +1469,14 @@ line_draw_cost (matrix, vpos)
 /* Test two glyph rows A and B for equality.  Value is non-zero if A
    and B have equal contents.  W is the window to which the glyphs
    rows A and B belong.  It is needed here to test for partial row
-   visibility.  */
+   visibility.  MOUSE_FACE_P non-zero means compare the mouse_face_p
+   flags of A and B, too.  */
 
 static INLINE int 
-row_equal_p (w, a, b)
+row_equal_p (w, a, b, mouse_face_p)
      struct window *w;
      struct glyph_row *a, *b;
+     int mouse_face_p;
 {
   if (a == b)
     return 1;
@@ -1354,6 +1487,9 @@ row_equal_p (w, a, b)
       struct glyph *a_glyph, *b_glyph, *a_end;
       int area;
 
+      if (mouse_face_p && a->mouse_face_p != b->mouse_face_p)
+       return 0;
+
       /* Compare glyphs.  */
       for (area = LEFT_MARGIN_AREA; area < LAST_AREA; ++area)
        {
@@ -1373,7 +1509,6 @@ row_equal_p (w, a, b)
        }
 
       if (a->truncated_on_left_p != b->truncated_on_left_p
-         || a->inverse_p != b->inverse_p
          || a->fill_line_p != b->fill_line_p
          || a->truncated_on_right_p != b->truncated_on_right_p
          || a->overlay_arrow_p != b->overlay_arrow_p
@@ -1436,7 +1571,7 @@ free_glyph_pool (pool)
 {
   if (pool)
     {
-      /* More freed than allocated? */
+      /* More freed than allocated?  */
       --glyph_pool_count;
       xassert (glyph_pool_count >= 0);
 
@@ -1484,7 +1619,7 @@ realloc_glyph_pool (pool, matrix_dim)
       pool->nglyphs = needed;
     }
 
-  /* Remember the number of rows and columns because (a) we use then
+  /* Remember the number of rows and columns because (a) we use them
      to do sanity checks, and (b) the number of columns determines
      where rows in the frame matrix start---this must be available to
      determine pointers to rows of window sub-matrices.  */
@@ -1647,7 +1782,7 @@ check_matrix_invariants (w)
 
    CHANGED_LEAF_MATRIX set if the dimension or location of a matrix of
    any window in the tree will be changed or have been changed (see
-   DIM_ONLY_P).
+   DIM_ONLY_P)
 
    *WINDOW_CHANGE_FLAGS must be initialized by the caller of this
    function.
@@ -1708,11 +1843,10 @@ check_matrix_invariants (w)
 #define CHANGED_LEAF_MATRIX    (1 << 1)
 
 static struct dim
-allocate_matrices_for_frame_redisplay (window, x, y, ch_dim,
-                                      dim_only_p, window_change_flags)
+allocate_matrices_for_frame_redisplay (window, x, y, dim_only_p,
+                                      window_change_flags)
      Lisp_Object window;
      int x, y;
-     struct dim ch_dim;
      int dim_only_p;
      int *window_change_flags;
 {
@@ -1740,13 +1874,13 @@ allocate_matrices_for_frame_redisplay (window, x, y, ch_dim,
       w = XWINDOW (window);
 
       /* Get the dimension of the window sub-matrix for W, depending
-        on whether this a combination or a leaf window.  */
+        on whether this is a combination or a leaf window.  */
       if (!NILP (w->hchild))
-       dim = allocate_matrices_for_frame_redisplay (w->hchild, x, y, ch_dim,
+       dim = allocate_matrices_for_frame_redisplay (w->hchild, x, y, 
                                                     dim_only_p,
                                                     window_change_flags);
       else if (!NILP (w->vchild))
-       dim = allocate_matrices_for_frame_redisplay (w->vchild, x, y, ch_dim,
+       dim = allocate_matrices_for_frame_redisplay (w->vchild, x, y, 
                                                     dim_only_p,
                                                     window_change_flags);
       else
@@ -1761,8 +1895,8 @@ allocate_matrices_for_frame_redisplay (window, x, y, ch_dim,
   
          /* Width and height MUST be chosen so that there are no
             holes in the frame matrix.  */
-         dim.width = XINT (w->width);
-         dim.height = XINT (w->height);
+         dim.width = required_matrix_width (w);
+         dim.height = required_matrix_height (w);
 
          /* Will matrix be re-allocated?  */
          if (x != w->desired_matrix->matrix_x
@@ -1827,28 +1961,78 @@ allocate_matrices_for_frame_redisplay (window, x, y, ch_dim,
 }
 
 
+/* Return the required height of glyph matrices for window W.  */
+
+int
+required_matrix_height (w)
+     struct window *w;
+{
+#ifdef HAVE_WINDOW_SYSTEM
+  struct frame *f = XFRAME (w->frame);
+  
+  if (FRAME_WINDOW_P (f))
+    {
+      int ch_height = FRAME_SMALLEST_FONT_HEIGHT (f);
+      int window_pixel_height = window_box_height (w) + abs (w->vscroll);
+      return (((window_pixel_height + ch_height - 1)
+              / ch_height)
+             /* One partially visible line at the top and
+                bottom of the window.  */
+             + 2
+             /* 2 for header and mode line.  */
+             + 2);
+    }
+#endif /* HAVE_WINDOW_SYSTEM */
+      
+  return XINT (w->height);
+}
+
+
+/* Return the required width of glyph matrices for window W.  */
+
+int
+required_matrix_width (w)
+     struct window *w;
+{
+#ifdef HAVE_WINDOW_SYSTEM
+  struct frame *f = XFRAME (w->frame);
+  if (FRAME_WINDOW_P (f))
+    {
+      int ch_width = FRAME_SMALLEST_CHAR_WIDTH (f);
+      int window_pixel_width = XFLOATINT (w->width) * CANON_X_UNIT (f);
+  
+      /* Compute number of glyphs needed in a glyph row.  */
+      return (((window_pixel_width + ch_width - 1)
+              / ch_width)
+             /* 2 partially visible columns in the text area.  */
+             + 2
+             /* One partially visible column at the right
+                edge of each marginal area.  */
+             + 1 + 1);
+    }
+#endif /* HAVE_WINDOW_SYSTEM */
+
+  return XINT (w->width);
+}
+
+
 /* Allocate window matrices for window-based redisplay.  W is the
    window whose matrices must be allocated/reallocated.  CH_DIM is the
    size of the smallest character that could potentially be used on W.  */
    
 static void
-allocate_matrices_for_window_redisplay (w, ch_dim)
+allocate_matrices_for_window_redisplay (w)
      struct window *w;
-     struct dim ch_dim;
 {
-  struct frame *f = XFRAME (w->frame);
-  
   while (w)
     {
       if (!NILP (w->vchild))
-       allocate_matrices_for_window_redisplay (XWINDOW (w->vchild), ch_dim);
+       allocate_matrices_for_window_redisplay (XWINDOW (w->vchild));
       else if (!NILP (w->hchild))
-       allocate_matrices_for_window_redisplay (XWINDOW (w->hchild), ch_dim);
+       allocate_matrices_for_window_redisplay (XWINDOW (w->hchild));
       else
        {
          /* W is a leaf window.  */
-         int window_pixel_width = XFLOATINT (w->width) * CANON_X_UNIT (f);
-         int window_pixel_height = window_box_height (w) + abs (w->vscroll);
          struct dim dim;
 
          /* If matrices are not yet allocated, allocate them now.  */
@@ -1858,25 +2042,8 @@ allocate_matrices_for_window_redisplay (w, ch_dim)
              w->current_matrix = new_glyph_matrix (NULL);
            }
 
-         /* Compute number of glyphs needed in a glyph row.  */
-         dim.width = (((window_pixel_width + ch_dim.width - 1)
-                       / ch_dim.width)
-                      /* 2 partially visible columns in the text area.  */
-                      + 2
-                      /* One partially visible column at the right
-                         edge of each marginal area.  */
-                      + 1 + 1);
-
-         /* Compute number of glyph rows needed.  */
-         dim.height = (((window_pixel_height + ch_dim.height - 1)
-                        / ch_dim.height)
-                       /* One partially visible line at the top and
-                          bottom of the window.  */
-                       + 2
-                       /* 2 for top and mode line.  */
-                       + 2);
-
-         /* Change matrices.  */
+         dim.width = required_matrix_width (w);
+         dim.height = required_matrix_height (w);
          adjust_glyph_matrix (w, w->desired_matrix, 0, 0, dim);
          adjust_glyph_matrix (w, w->current_matrix, 0, 0, dim);
        }
@@ -1969,6 +2136,114 @@ adjust_frame_glyphs (f)
 }
 
 
+/* In the window tree with root W, build current matrices of leaf
+   windows from the frame's current matrix.  */
+
+static void
+fake_current_matrices (window)
+     Lisp_Object window;
+{
+  struct window *w;
+      
+  for (; !NILP (window); window = w->next)
+    {
+      w = XWINDOW (window);
+      
+      if (!NILP (w->hchild))
+       fake_current_matrices (w->hchild);
+      else if (!NILP (w->vchild))
+       fake_current_matrices (w->vchild);
+      else
+       {
+         int i;
+         struct frame *f = XFRAME (w->frame);
+         struct glyph_matrix *m = w->current_matrix;
+         struct glyph_matrix *fm = f->current_matrix;
+
+         xassert (m->matrix_h == XFASTINT (w->height));
+         xassert (m->matrix_w == XFASTINT (w->width));
+         
+         for (i = 0; i < m->matrix_h; ++i)
+           {
+             struct glyph_row *r = m->rows + i;
+             struct glyph_row *fr = fm->rows + i + XFASTINT (w->top);
+
+             xassert (r->glyphs[TEXT_AREA] >= fr->glyphs[TEXT_AREA]
+                      && r->glyphs[LAST_AREA] <= fr->glyphs[LAST_AREA]);
+
+             r->enabled_p = fr->enabled_p;
+             if (r->enabled_p)
+               {
+                 r->used[LEFT_MARGIN_AREA] = m->left_margin_glyphs;
+                 r->used[RIGHT_MARGIN_AREA] = m->right_margin_glyphs;
+                 r->used[TEXT_AREA] = (m->matrix_w
+                                       - r->used[LEFT_MARGIN_AREA]
+                                       - r->used[RIGHT_MARGIN_AREA]);
+                 r->mode_line_p = 0;
+               }
+           }
+       }
+    }
+}
+
+
+/* Save away the contents of frame F's current frame matrix.  Value is
+   a glyph matrix holding the contents of F's current frame matrix.  */
+
+static struct glyph_matrix *
+save_current_matrix (f)
+     struct frame *f;
+{
+  int i;
+  struct glyph_matrix *saved;
+
+  saved = (struct glyph_matrix *) xmalloc (sizeof *saved);
+  bzero (saved, sizeof *saved);
+  saved->nrows = f->current_matrix->nrows;
+  saved->rows = (struct glyph_row *) xmalloc (saved->nrows
+                                             * sizeof *saved->rows);
+  bzero (saved->rows, saved->nrows * sizeof *saved->rows);
+
+  for (i = 0; i < saved->nrows; ++i)
+    {
+      struct glyph_row *from = f->current_matrix->rows + i;
+      struct glyph_row *to = saved->rows + i;
+      size_t nbytes = from->used[TEXT_AREA] * sizeof (struct glyph);
+      to->glyphs[TEXT_AREA] = (struct glyph *) xmalloc (nbytes);
+      bcopy (from->glyphs[TEXT_AREA], to->glyphs[TEXT_AREA], nbytes);
+      to->used[TEXT_AREA] = from->used[TEXT_AREA];
+    }
+
+  return saved;
+}
+
+
+/* Restore the contents of frame F's current frame matrix from SAVED,
+   and free memory associated with SAVED.  */
+
+static void
+restore_current_matrix (f, saved)
+     struct frame *f;
+     struct glyph_matrix *saved;
+{
+  int i;
+
+  for (i = 0; i < saved->nrows; ++i)
+    {
+      struct glyph_row *from = saved->rows + i;
+      struct glyph_row *to = f->current_matrix->rows + i;
+      size_t nbytes = from->used[TEXT_AREA] * sizeof (struct glyph);
+      bcopy (from->glyphs[TEXT_AREA], to->glyphs[TEXT_AREA], nbytes);
+      to->used[TEXT_AREA] = from->used[TEXT_AREA];
+      xfree (from->glyphs[TEXT_AREA]);
+    }
+  
+  xfree (saved->rows);
+  xfree (saved);
+}
+
+
+
 /* Allocate/reallocate glyph matrices of a single frame F for
    frame-based redisplay.  */
 
@@ -2004,7 +2279,7 @@ adjust_frame_glyphs_for_frame_redisplay (f)
       f->desired_matrix = new_glyph_matrix (f->desired_pool);
       f->current_matrix = new_glyph_matrix (f->current_pool);
     }
-      
+  
   /* Compute window glyph matrices.  (This takes the mini-buffer
      window into account).  The result is the size of the frame glyph
      matrix needed.  The variable window_change_flags is set to a bit
@@ -2015,7 +2290,7 @@ adjust_frame_glyphs_for_frame_redisplay (f)
   matrix_dim
     = allocate_matrices_for_frame_redisplay (FRAME_ROOT_WINDOW (f),
                                             0, top_window_y,
-                                            ch_dim, 1,
+                                            1,
                                             &window_change_flags);
 
   /* Add in menu bar lines, if any.  */
@@ -2031,7 +2306,7 @@ adjust_frame_glyphs_for_frame_redisplay (f)
     {
       /* Do it for window matrices.  */
       allocate_matrices_for_frame_redisplay (FRAME_ROOT_WINDOW (f),
-                                            0, top_window_y, ch_dim, 0,
+                                            0, top_window_y, 0,
                                             &window_change_flags);
 
       /* Size of frame matrices must equal size of frame.  Note
@@ -2040,14 +2315,32 @@ adjust_frame_glyphs_for_frame_redisplay (f)
       xassert (matrix_dim.width == FRAME_WIDTH (f)
               && matrix_dim.height == FRAME_HEIGHT (f));
   
-      /* Resize frame matrices.  */
-      adjust_glyph_matrix (NULL, f->desired_matrix, 0, 0, matrix_dim);
-      adjust_glyph_matrix (NULL, f->current_matrix, 0, 0, matrix_dim);
-
-      /* Since location and size of sub-matrices within the pool may
-        have changed, and current matrices don't have meaningful
-        contents anymore, mark the frame garbaged.  */
-      SET_FRAME_GARBAGED (f);
+      /* Pointers to glyph memory in glyph rows are exchanged during
+        the update phase of redisplay, which means in general that a
+        frame's current matrix consists of pointers into both the
+        desired and current glyph pool of the frame.  Adjusting a
+        matrix sets the frame matrix up so that pointers are all into
+        the same pool.  If we want to preserve glyph contents of the
+        current matrix over a call to adjust_glyph_matrix, we must
+        make a copy of the current glyphs, and restore the current
+        matrix' contents from that copy.  */
+      if (display_completed
+         && !FRAME_GARBAGED_P (f)
+         && matrix_dim.width == f->current_matrix->matrix_w
+         && matrix_dim.height == f->current_matrix->matrix_h)
+       {
+         struct glyph_matrix *copy = save_current_matrix (f);
+         adjust_glyph_matrix (NULL, f->desired_matrix, 0, 0, matrix_dim);
+         adjust_glyph_matrix (NULL, f->current_matrix, 0, 0, matrix_dim);
+         restore_current_matrix (f, copy);
+         fake_current_matrices (FRAME_ROOT_WINDOW (f));
+       }
+      else
+       {
+         adjust_glyph_matrix (NULL, f->desired_matrix, 0, 0, matrix_dim);
+         adjust_glyph_matrix (NULL, f->current_matrix, 0, 0, matrix_dim);
+         SET_FRAME_GARBAGED (f);
+       }
     }
 }
 
@@ -2073,8 +2366,7 @@ adjust_frame_glyphs_for_window_redisplay (f)
 #endif
     
   /* Allocate/reallocate window matrices.  */
-  allocate_matrices_for_window_redisplay (XWINDOW (FRAME_ROOT_WINDOW (f)),
-                                         ch_dim);
+  allocate_matrices_for_window_redisplay (XWINDOW (FRAME_ROOT_WINDOW (f)));
 
   /* Allocate/ reallocate matrices of the dummy window used to display
      the menu bar under X when no X toolkit support is available.  */
@@ -2097,7 +2389,7 @@ adjust_frame_glyphs_for_window_redisplay (f)
     XSETFASTINT (w->left, 0);
     XSETFASTINT (w->height, FRAME_MENU_BAR_LINES (f));
     XSETFASTINT (w->width, FRAME_WINDOW_WIDTH (f));
-    allocate_matrices_for_window_redisplay (w, ch_dim);
+    allocate_matrices_for_window_redisplay (w);
   }
 #endif /* not USE_X_TOOLKIT */
 
@@ -2117,7 +2409,7 @@ adjust_frame_glyphs_for_window_redisplay (f)
   XSETFASTINT (w->left, 0);
   XSETFASTINT (w->height, FRAME_TOOL_BAR_LINES (f));
   XSETFASTINT (w->width, FRAME_WINDOW_WIDTH (f));
-  allocate_matrices_for_window_redisplay (w, ch_dim);
+  allocate_matrices_for_window_redisplay (w);
 }
 
 
@@ -2434,6 +2726,7 @@ build_frame_matrix_from_leaf_window (frame_matrix, w)
     {
       struct glyph_row *frame_row = frame_matrix->rows + frame_y;
       struct glyph_row *window_row = window_matrix->rows + window_y;
+      int current_row_p = window_matrix == w->current_matrix;
 
       /* Fill up the frame row with spaces up to the left margin of the
         window row.  */
@@ -2441,19 +2734,32 @@ build_frame_matrix_from_leaf_window (frame_matrix, w)
 
       /* Fill up areas in the window matrix row with spaces.  */
       fill_up_glyph_row_with_spaces (window_row);
+
+      /* If only part of W's desired matrix has been built, and
+         window_row wasn't displayed, use the corresponding current
+         row instead.  */
+      if (window_matrix == w->desired_matrix
+         && !window_row->enabled_p)
+       {
+         window_row = w->current_matrix->rows + window_y;
+         current_row_p = 1;
+       }
       
-      if (window_matrix == w->current_matrix)
+      if (current_row_p)
        {
-         /* We have to copy W's current matrix.  Copy window
-            row to frame row.  */
+         /* Copy window row to frame row.  */
          bcopy (window_row->glyphs[0],
                 frame_row->glyphs[TEXT_AREA] + window_matrix->matrix_x,
                 window_matrix->matrix_w * sizeof (struct glyph));
        }
       else
        {
-         /* Copy W's desired matrix.  */
-
+         xassert (window_row->enabled_p);
+         
+         /* Only when a desired row has been displayed, we want
+            the corresponding frame row to be updated.  */
+         frame_row->enabled_p = 1;
+         
           /* Maybe insert a vertical border between horizontally adjacent
             windows.  */
           if (right_border_glyph)
@@ -2462,29 +2768,6 @@ build_frame_matrix_from_leaf_window (frame_matrix, w)
              SET_CHAR_GLYPH_FROM_GLYPH (*border, right_border_glyph);
            }
 
-#if 0 /* This shouldn't be necessary.  Let's check it.  */
-         /* Due to hooks installed, it normally doesn't happen that
-            window rows and frame rows of the same matrix are out of
-            sync, i.e. have a different understanding of where to
-            find glyphs for the row.  The following is a safety-belt
-            that doesn't cost much and makes absolutely sure that
-            window and frame matrices are in sync.  */
-         if (!glyph_row_slice_p (window_row, frame_row))
-           {
-             /* Find the row in the window being a slice.  There
-                should exist one from program logic.  */
-             struct glyph_row *slice_row
-               = find_glyph_row_slice (window_matrix, frame_matrix, frame_y);
-             xassert (slice_row != 0);
-             
-             /* Exchange glyphs between both window rows.  */
-             swap_glyphs_in_rows (window_row, slice_row);
-             
-             /* Exchange pointers between both rows.  */
-             swap_glyph_pointers (window_row, slice_row);
-           }
-#endif
-
          /* Window row window_y must be a slice of frame row
             frame_y.  */
          xassert (glyph_row_slice_p (window_row, frame_row));
@@ -2494,6 +2777,7 @@ build_frame_matrix_from_leaf_window (frame_matrix, w)
          
 #if GLYPH_DEBUG
          strcpy (w->current_matrix->method, w->desired_matrix->method);
+         add_window_display_history (w, w->current_matrix->method, 0);
 #endif
        }
 
@@ -2503,10 +2787,6 @@ build_frame_matrix_from_leaf_window (frame_matrix, w)
       frame_row->used[TEXT_AREA] 
        = window_matrix->matrix_x + window_matrix->matrix_w;
 
-      /* Or in flags.  */
-      frame_row->enabled_p |= window_row->enabled_p;
-      frame_row->inverse_p |= window_row->inverse_p;
-
       /* Next row.  */
       ++window_y;
       ++frame_y;
@@ -2610,6 +2890,7 @@ make_current (desired_matrix, current_matrix, row)
 {
   struct glyph_row *current_row = MATRIX_ROW (current_matrix, row);
   struct glyph_row *desired_row = MATRIX_ROW (desired_matrix, row);
+  int mouse_face_p = current_row->mouse_face_p;
 
   /* Do current_row = desired_row.  This exchanges glyph pointers
      between both rows, and does a structure assignment otherwise.  */
@@ -2617,6 +2898,7 @@ make_current (desired_matrix, current_matrix, row)
 
   /* Enable current_row to mark it as valid.  */
   current_row->enabled_p = 1;
+  current_row->mouse_face_p = mouse_face_p;
 
   /* If we are called on frame matrices, perform analogous operations
      for window matrices.  */
@@ -2715,7 +2997,7 @@ mirrored_line_dance (matrix, unchanged_at_top, nlines, copy_from,
        new_rows[i].enabled_p = 0;
     }
 
-  /* Do the same for window matrices, if MATRIX Is a frame matrix.  */
+  /* Do the same for window matrices, if MATRIX is a frame matrix.  */
   if (frame_matrix_frame)
     mirror_line_dance (XWINDOW (frame_matrix_frame->root_window),
                       unchanged_at_top, nlines, copy_from, retained_p);
@@ -2723,8 +3005,7 @@ mirrored_line_dance (matrix, unchanged_at_top, nlines, copy_from,
 
 
 /* Synchronize glyph pointers in the current matrix of window W with
-   the current frame matrix.  W must be full-width, and be on a tty
-   frame.  */
+   the current frame matrix.  */
 
 static void
 sync_window_with_frame_matrix_rows (w)
@@ -2732,27 +3013,31 @@ sync_window_with_frame_matrix_rows (w)
 {
   struct frame *f = XFRAME (w->frame);
   struct glyph_row *window_row, *window_row_end, *frame_row;
+  int left, right, x, width;
 
-  /* Preconditions: W must be a leaf window and full-width.  Its frame
-     must have a frame matrix.  */
+  /* Preconditions: W must be a leaf window on a tty frame.  */
   xassert (NILP (w->hchild) && NILP (w->vchild));
-  xassert (WINDOW_FULL_WIDTH_P (w));
   xassert (!FRAME_WINDOW_P (f));
 
-  /* If W is a full-width window, glyph pointers in W's current matrix
-     have, by definition, to be the same as glyph pointers in the
-     corresponding frame matrix.  */
+  left = margin_glyphs_to_reserve (w, 1, w->left_margin_width);
+  right = margin_glyphs_to_reserve (w, 1, w->right_margin_width);
+  x = w->current_matrix->matrix_x;
+  width = w->current_matrix->matrix_w;
+
   window_row = w->current_matrix->rows;
   window_row_end = window_row + w->current_matrix->nrows;
   frame_row = f->current_matrix->rows + XFASTINT (w->top);
-  while (window_row < window_row_end)
+  
+  for (; window_row < window_row_end; ++window_row, ++frame_row)
     {
-      int area;
-      
-      for (area = LEFT_MARGIN_AREA; area <= LAST_AREA; ++area)
-       window_row->glyphs[area] = frame_row->glyphs[area];
-
-      ++window_row, ++frame_row;
+      window_row->glyphs[LEFT_MARGIN_AREA]
+       = frame_row->glyphs[0] + x;
+      window_row->glyphs[TEXT_AREA]
+       = window_row->glyphs[LEFT_MARGIN_AREA] + left;
+      window_row->glyphs[LAST_AREA]
+       = window_row->glyphs[LEFT_MARGIN_AREA] + width;
+      window_row->glyphs[RIGHT_MARGIN_AREA]
+       = window_row->glyphs[LAST_AREA] - right;
     }
 }
 
@@ -2986,7 +3271,7 @@ window_to_frame_vpos (w, vpos)
 
 
 /* Translate horizontal position HPOS which is relative to window W to
-   a vertical position relative to W's frame.  */
+   a horizontal position relative to W's frame.  */
 
 static int
 window_to_frame_hpos (w, hpos)
@@ -3009,13 +3294,13 @@ window_to_frame_hpos (w, hpos)
  **********************************************************************/
 
 DEFUN ("redraw-frame", Fredraw_frame, Sredraw_frame, 1, 1, 0,
-  "Clear frame FRAME and output again what is supposed to appear on it.")
-  (frame)
+       doc: /* Clear frame FRAME and output again what is supposed to appear on it.  */)
+     (frame)
      Lisp_Object frame;
 {
   struct frame *f;
 
-  CHECK_LIVE_FRAME (frame, 0);
+  CHECK_LIVE_FRAME (frame);
   f = XFRAME (frame);
 
   /* Ignore redraw requests, if frame has no glyphs yet.
@@ -3055,8 +3340,8 @@ redraw_frame (f)
 
 
 DEFUN ("redraw-display", Fredraw_display, Sredraw_display, 0, 0, "",
-  "Clear and redisplay all visible frames.")
-  ()
+       doc: /* Clear and redisplay all visible frames.  */)
+     ()
 {
   Lisp_Object tail, frame;
 
@@ -3112,7 +3397,7 @@ direct_output_for_insert (g)
   struct glyph_row *glyph_row;
   struct glyph *glyphs, *glyph, *end;
   int n;
-  /* Non-null means that Redisplay of W is based on window matrices.  */
+  /* Non-null means that redisplay of W is based on window matrices.  */
   int window_redisplay_p = FRAME_WINDOW_P (f);
   /* Non-null means we are in overwrite mode.  */
   int overwrite_p = !NILP (current_buffer->overwrite_mode);
@@ -3133,8 +3418,10 @@ direct_output_for_insert (g)
       || !display_completed
       /* Give up if buffer appears in two places.  */
       || buffer_shared > 1
-      /* Give up if w is mini-buffer and a message is being displayed there */
-      || (MINI_WINDOW_P (w) && !NILP (echo_area_buffer[0]))
+      /* Give up if currently displaying a message instead of the
+        minibuffer contents.  */
+      || (EQ (selected_window, minibuf_window)
+         && EQ (minibuf_window, echo_area_window))
       /* Give up for hscrolled mini-buffer because display of the prompt
         is handled specially there (see display_line).  */
       || (MINI_WINDOW_P (w) && XFASTINT (w->hscroll))
@@ -3148,6 +3435,10 @@ direct_output_for_insert (g)
       || g == '\r'
       /* Give up if unable to display the cursor in the window.  */
       || w->cursor.vpos < 0
+      /* Give up if we are showing a message or just cleared the message
+        because we might need to resize the echo area window.  */
+      || !NILP (echo_area_buffer[0])
+      || !NILP (echo_area_buffer[1])
       || (glyph_row = MATRIX_ROW (w->current_matrix, w->cursor.vpos),
          /* Can't do it in a continued line because continuation
             lines would change.  */
@@ -3162,6 +3453,12 @@ direct_output_for_insert (g)
       || (!window_redisplay_p && !WINDOW_FULL_WIDTH_P (w)))
     return 0;
 
+  /* If we can't insert glyphs, we can use this method only
+     at the end of a line.  */
+  if (!char_ins_del_ok)
+    if (PT != ZV && FETCH_BYTE (PT_BYTE) != '\n')
+      return 0;
+
   /* Set up a display iterator structure for W.  Glyphs will be
      produced in scratch_glyph_row.  Current position is W's cursor
      position.  */
@@ -3172,6 +3469,8 @@ direct_output_for_insert (g)
                 DEFAULT_FACE_ID);
 
   glyph_row = MATRIX_ROW (w->current_matrix, w->cursor.vpos);
+  if (glyph_row->mouse_face_p)
+    return 0;
   
   /* Give up if highlighting trailing whitespace and we have trailing
      whitespace in glyph_row.  We would have to remove the trailing
@@ -3199,6 +3498,7 @@ direct_output_for_insert (g)
   it.current_y = w->cursor.y;
   it.end_charpos = PT;
   it.stop_charpos = min (PT, it.stop_charpos);
+  it.stop_charpos = max (IT_CHARPOS (it), it.stop_charpos);
 
   /* More than one display element may be returned for PT - 1 if
      (i) it's a control character which is translated into `\003' or
@@ -3224,7 +3524,7 @@ direct_output_for_insert (g)
 
       delta += 1;
       delta_bytes += it.len;
-      set_iterator_to_next (&it);
+      set_iterator_to_next (&it, 1);
     }
 
   /* Give up if we hit the right edge of the window.  We would have
@@ -3242,7 +3542,7 @@ direct_output_for_insert (g)
     {
       if (it2.c == '\t')
        return 0;
-      set_iterator_to_next (&it2);
+      set_iterator_to_next (&it2, 1);
     }
 
   /* Number of new glyphs produced.  */
@@ -3303,12 +3603,16 @@ direct_output_for_insert (g)
      implemented for X frames.  The implementation uses updated_window
      and updated_row.  */
   updated_row = glyph_row;
+  updated_area = TEXT_AREA;
   update_begin (f);
   if (rif)
     {
       rif->update_window_begin_hook (w);
       
-      if (glyphs == end - n)
+      if (glyphs == end - n
+         /* In front of a space added by append_space.  */
+         || (glyphs == end - n - 1
+             && (end - n)->charpos <= 0))
        rif->write_glyphs (glyphs, n);
       else
        rif->insert_glyphs (glyphs, n);
@@ -3345,7 +3649,7 @@ direct_output_for_insert (g)
     }
 
   if (rif)
-    rif->update_window_end_hook (w, 1);
+    rif->update_window_end_hook (w, 1, 0);
   update_end (f);
   updated_row = NULL;
   fflush (stdout);
@@ -3407,17 +3711,25 @@ direct_output_forward_char (n)
   if (!NILP (echo_area_buffer[0]) || !NILP (echo_area_buffer[1]))
     return 0;
 
+  /* Give up if currently displaying a message instead of the
+     minibuffer contents.  */
+  if (XWINDOW (minibuf_window) == w
+      && EQ (minibuf_window, echo_area_window))
+    return 0;
+  
   /* Give up if we don't know where the cursor is.  */
   if (w->cursor.vpos < 0)
     return 0;
 
   row = MATRIX_ROW (w->current_matrix, w->cursor.vpos);
 
-  if (PT <= MATRIX_ROW_START_BYTEPOS (row)
-      || PT >= MATRIX_ROW_END_BYTEPOS (row))
+  /* Give up if PT is outside of the last known cursor row.  */
+  if (PT <= MATRIX_ROW_START_CHARPOS (row)
+      || PT >= MATRIX_ROW_END_CHARPOS (row))
     return 0;
 
   set_cursor_from_row (w, row, w->current_matrix, 0, 0, 0, 0);
+  
   w->last_cursor = w->cursor;
   XSETFASTINT (w->last_point, PT);
 
@@ -3487,12 +3799,13 @@ update_frame (f, force_p, inhibit_hairy_id_p)
       /* Update the tool-bar window, if present.  */
       if (WINDOWP (f->tool_bar_window))
        {
-         Lisp_Object tem;
          struct window *w = XWINDOW (f->tool_bar_window);
 
          /* Update tool-bar window.  */
          if (w->must_be_updated_p)
            {
+             Lisp_Object tem;
+
              update_window (w, 1);
              w->must_be_updated_p = 0;
 
@@ -3501,13 +3814,6 @@ update_frame (f, force_p, inhibit_hairy_id_p)
              tem = f->current_tool_bar_string;
              f->current_tool_bar_string = f->desired_tool_bar_string;
              f->desired_tool_bar_string = tem;
-             f->n_current_tool_bar_items = f->n_desired_tool_bar_items;
-             
-             /* Swap tool-bar items.  We swap because we want to
-                reuse vectors.  */
-             tem = f->current_tool_bar_items;
-             f->current_tool_bar_items = f->desired_tool_bar_items;
-             f->desired_tool_bar_items = tem;
            }
        }
   
@@ -3515,10 +3821,9 @@ update_frame (f, force_p, inhibit_hairy_id_p)
       /* Update windows.  */
       paused_p = update_window_tree (root_window, force_p);
       update_end (f);
-      display_completed = !paused_p;
-
-      /* The flush is a performance bottleneck under X.  */
-#if 0
+      
+#if 0 /* This flush is a performance bottleneck under X,
+        and it doesn't seem to be necessary anyway.  */
       rif->flush_display (f);
 #endif
     }
@@ -3528,21 +3833,29 @@ update_frame (f, force_p, inhibit_hairy_id_p)
         frame matrix we operate.  */
       set_frame_matrix_frame (f);
 
-      /* Build F's desired matrix from window matrices.  For windows
-        whose must_be_updated_p flag is set, desired matrices are
-        made part of the desired frame matrix.  For other windows,
-        the current matrix is copied.  */
+      /* Build F's desired matrix from window matrices.  */
       build_frame_matrix (f);
       
-      /* Do the update on the frame desired matrix.  */
+      /* Update the display  */
+      update_begin (f);
       paused_p = update_frame_1 (f, force_p, inhibit_hairy_id_p);
-      
+      update_end (f);
+
+      if (termscript)
+       fflush (termscript);
+      fflush (stdout);
+
       /* Check window matrices for lost pointers.  */
-      IF_DEBUG (check_window_matrix_pointers (root_window));
+#if GLYPH_DEBUG
+      check_window_matrix_pointers (root_window);
+      add_frame_display_history (f, paused_p);
+#endif
     }
 
   /* Reset flags indicating that a window should be updated.  */
   set_window_update_flags (root_window, 0);
+  
+  display_completed = !paused_p;
   return paused_p;
 }
 
@@ -3612,8 +3925,7 @@ redraw_overlapped_rows (w, yb)
      struct window *w;
      int yb;
 {
-  int i, bottom_y;
-  struct glyph_row *row;
+  int i;
   
   /* If rows overlapping others have been changed, the rows being
      overlapped have to be redrawn.  This won't draw lines that have
@@ -3622,7 +3934,7 @@ redraw_overlapped_rows (w, yb)
      current rows is 0.  */
   for (i = 0; i < w->current_matrix->nrows; ++i)
     {
-      row = w->current_matrix->rows + i;
+      struct glyph_row *row = w->current_matrix->rows + i;
 
       if (!row->enabled_p)
        break;
@@ -3646,8 +3958,7 @@ redraw_overlapped_rows (w, yb)
          row->overlapped_p = 0;
        }
 
-      bottom_y = MATRIX_ROW_BOTTOM_Y (row);
-      if (bottom_y >= yb)
+      if (MATRIX_ROW_BOTTOM_Y (row) >= yb)
        break;
     }
 }
@@ -3686,7 +3997,7 @@ redraw_overlapping_rows (w, yb)
          if (row->used[RIGHT_MARGIN_AREA])
            rif->fix_overlapping_area (w, row, RIGHT_MARGIN_AREA);
 
-         /* Record in neighbor rows that ROW overwrites part of their
+         /* Record in neighbour rows that ROW overwrites part of their
             display.  */
          if (row->phys_ascent > row->ascent && i > 0)
            MATRIX_ROW (w->current_matrix, i - 1)->overlapped_p = 1;
@@ -3702,6 +4013,31 @@ redraw_overlapping_rows (w, yb)
 }
 
 
+#ifdef GLYPH_DEBUG
+
+/* Check that no row in the current matrix of window W is enabled
+   which is below what's displayed in the window.  */
+
+void
+check_current_matrix_flags (w)
+     struct window *w;
+{
+  int last_seen_p = 0;
+  int i, yb = window_text_bottom_y (w);
+
+  for (i = 0; i < w->current_matrix->nrows - 1; ++i)
+    {
+      struct glyph_row *row = MATRIX_ROW (w->current_matrix, i);
+      if (!last_seen_p && MATRIX_ROW_BOTTOM_Y (row) >= yb)
+       last_seen_p = 1;
+      else if (last_seen_p && row->enabled_p)
+       abort ();
+    }
+}
+
+#endif /* GLYPH_DEBUG */
+
+
 /* Update display of window W.  FORCE_P non-zero means that we should
    not stop when detecting pending input.  */
 
@@ -3714,6 +4050,7 @@ update_window (w, force_p)
   int paused_p;
   int preempt_count = baud_rate / 2400 + 1;
   extern int input_pending;
+  extern Lisp_Object do_mouse_tracking;
 #if GLYPH_DEBUG
   struct frame *f = XFRAME (WINDOW_FRAME (w));
   extern struct frame *updating_frame;
@@ -3731,22 +4068,28 @@ update_window (w, force_p)
 
   /* If forced to complete the update, or if no input is pending, do
      the update.  */
-  if (force_p || !input_pending)
+  if (force_p || !input_pending || !NILP (do_mouse_tracking))
     {
       struct glyph_row *row, *end;
       struct glyph_row *mode_line_row;
-      struct glyph_row *header_line_row = NULL;
-      int yb, changed_p = 0;
+      struct glyph_row *header_line_row;
+      int yb, changed_p = 0, mouse_face_overwritten_p = 0, n_updated;
 
       rif->update_window_begin_hook (w);
       yb = window_text_bottom_y (w);
 
-      /* If window has a top line, update it before everything else.
-        Adjust y-positions of other rows by the top line height.  */
+      /* If window has a header line, update it before everything else.
+        Adjust y-positions of other rows by the header line height.  */
       row = desired_matrix->rows;
       end = row + desired_matrix->nrows - 1;
+      
       if (row->mode_line_p)
-       header_line_row = row++;
+       {
+         header_line_row = row;
+         ++row;
+       }
+      else
+       header_line_row = NULL;
 
       /* Update the mode line, if necessary.  */
       mode_line_row = MATRIX_MODE_LINE_ROW (desired_matrix);
@@ -3754,7 +4097,8 @@ update_window (w, force_p)
        {
          mode_line_row->y = yb;
          update_window_line (w, MATRIX_ROW_VPOS (mode_line_row,
-                                                 desired_matrix));
+                                                 desired_matrix),
+                             &mouse_face_overwritten_p);
          changed_p = 1;
        }
 
@@ -3764,7 +4108,7 @@ update_window (w, force_p)
       while (row < end && !row->enabled_p)
        ++row;
       
-      /* Try reusing part of the display by inserting/deleting lines.  */
+      /* Try reusing part of the display by copying.  */
       if (row < end && !desired_matrix->no_scrolling_p)
        {
          int rc = scrolling_window (w, header_line_row != NULL);
@@ -3775,39 +4119,37 @@ update_window (w, force_p)
              goto set_cursor;
            }
          else if (rc > 0)
+           /* We've scrolled the display.  */
            force_p = 1;
          changed_p = 1;
        }
 
-      /* Update the top mode line after scrolling because a new top
+      /* Update the header line after scrolling because a new header
         line would otherwise overwrite lines at the top of the window
         that can be scrolled.  */
       if (header_line_row && header_line_row->enabled_p)
        {
          header_line_row->y = 0;
-         update_window_line (w, 0);
+         update_window_line (w, 0, &mouse_face_overwritten_p);
          changed_p = 1;
        }
 
       /* Update the rest of the lines.  */
-      for (; row < end && (force_p || !input_pending); ++row)
-       if (row->enabled_p
-           /* A row can be completely invisible in case a desired
-              matrix was built with a vscroll and then
-              make_cursor_line_fully_visible shifts the matrix.  */
-           && row->visible_height > 0)
+      for (n_updated = 0; row < end && (force_p || !input_pending); ++row)
+       if (row->enabled_p)
          {
            int vpos = MATRIX_ROW_VPOS (row, desired_matrix);
            int i;
            
-           /* We'll Have to play a little bit with when to
+           /* We'll have to play a little bit with when to
               detect_input_pending.  If it's done too often,
               scrolling large windows with repeated scroll-up
               commands will too quickly pause redisplay.  */
-           if (!force_p && vpos % preempt_count == 0)
+           if (!force_p && ++n_updated % preempt_count == 0)
              detect_input_pending ();
 
-           changed_p |= update_window_line (w, vpos);
+           changed_p |= update_window_line (w, vpos,
+                                            &mouse_face_overwritten_p);
 
            /* Mark all rows below the last visible one in the current
               matrix as invalid.  This is necessary because of
@@ -3828,25 +4170,20 @@ update_window (w, force_p)
       
     set_cursor:
       
-      /* Fix the appearance of overlapping(overlapped rows.  */
-      if (rif->fix_overlapping_area
-         && !w->pseudo_window_p
-         && changed_p
-         && !paused_p)
-       {
-         redraw_overlapped_rows (w, yb);
-         redraw_overlapping_rows (w, yb);
-       }
-      
+      /* Fix the appearance of overlapping/overlapped rows.  */
       if (!paused_p && !w->pseudo_window_p)
        {
+         if (changed_p && rif->fix_overlapping_area)
+           {
+             redraw_overlapped_rows (w, yb);
+             redraw_overlapping_rows (w, yb);
+           }
+      
          /* Make cursor visible at cursor position of W.  */
          set_window_cursor_after_update (w);
 
-#if 0
-         /* Check that current matrix invariants are satisfied.  This
-            is for debugging only.  See the comment around
-            check_matrix_invariants.  */
+#if 0 /* Check that current matrix invariants are satisfied.  This is
+        for debugging only.  See the comment of check_matrix_invariants.  */
          IF_DEBUG (check_matrix_invariants (w));
 #endif
        }
@@ -3856,13 +4193,20 @@ update_window (w, force_p)
       strcpy (w->current_matrix->method, w->desired_matrix->method);
 #endif
 
-      /* End of update of window W.  */
-      rif->update_window_end_hook (w, 1);
-
+      /* End the update of window W.  Don't set the cursor if we
+         paused updating the display because in this case,
+         set_window_cursor_after_update hasn't been called, and
+         output_cursor doesn't contain the cursor location.  */
+      rif->update_window_end_hook (w, !paused_p, mouse_face_overwritten_p);
     }
   else
     paused_p = 1;
 
+#if GLYPH_DEBUG
+  /* check_current_matrix_flags (w); */
+  add_window_display_history (w, w->current_matrix->method, paused_p);
+#endif
+  
   clear_glyph_matrix (desired_matrix);
 
   return paused_p;
@@ -3918,6 +4262,7 @@ update_text_area (w, vpos)
       || desired_row->phys_height != current_row->phys_height
       || desired_row->visible_height != current_row->visible_height
       || current_row->overlapped_p
+      || current_row->mouse_face_p
       || current_row->x != desired_row->x)
     {
       rif->cursor_to (vpos, 0, desired_row->y, desired_row->x);
@@ -3935,49 +4280,76 @@ update_text_area (w, vpos)
       int stop, i, x;
       struct glyph *current_glyph = current_row->glyphs[TEXT_AREA];
       struct glyph *desired_glyph = desired_row->glyphs[TEXT_AREA];
+      int overlapping_glyphs_p = current_row->contains_overlapping_glyphs_p;
+      int desired_stop_pos = desired_row->used[TEXT_AREA];
 
       /* If the desired row extends its face to the text area end,
         make sure we write at least one glyph, so that the face
         extension actually takes place.  */
-      int desired_stop_pos = (desired_row->used[TEXT_AREA]
-                             - (MATRIX_ROW_EXTENDS_FACE_P (desired_row)
-                                ? 1 : 0));
+      if (MATRIX_ROW_EXTENDS_FACE_P (desired_row))
+       --desired_stop_pos;
       
       stop = min (current_row->used[TEXT_AREA], desired_stop_pos);
       i = 0;
       x = desired_row->x;
-      
+
+      /* Loop over glyphs that current and desired row may have
+        in common.  */
       while (i < stop)
        {
+         int can_skip_p = 1;
+         
          /* Skip over glyphs that both rows have in common.  These
-            don't have to be written.  */
-         while (i < stop
-                && GLYPH_EQUAL_P (desired_glyph, current_glyph))
-           {
-             x += desired_glyph->pixel_width;
-             ++desired_glyph, ++current_glyph, ++i;
-           }
-
-         /* Consider the case that the current row contains "xxx ppp
-            ggg" in italic Courier font, and the desired row is "xxx
-            ggg".  The character `p' has lbearing, `g' has not.  The
-            loop above will stop in front of the first `p' in the
-            current row.  If we would start writing glyphs there, we
-            wouldn't erase the lbearing of the `p'.  The rest of the
-            lbearing problem is then taken care of by x_draw_glyphs.  */
-         if (current_row->contains_overlapping_glyphs_p
-             && i > 0
-             && i < current_row->used[TEXT_AREA]
-             && current_row->used[TEXT_AREA] != desired_row->used[TEXT_AREA])
+            don't have to be written.  We can't skip if the last
+            current glyph overlaps the glyph to its right.  For
+            example, consider a current row of `if ' with the `f' in
+            Courier bold so that it overlaps the ` ' to its right.
+            If the desired row is ` ', we would skip over the space
+            after the `if' and there would remain a pixel from the
+            `f' on the screen.  */
+         if (overlapping_glyphs_p && i > 0)
            {
+             struct glyph *glyph = &current_row->glyphs[TEXT_AREA][i - 1];
              int left, right;
-             rif->get_glyph_overhangs (current_glyph, XFRAME (w->frame),
+             
+             rif->get_glyph_overhangs (glyph, XFRAME (w->frame),
                                        &left, &right);
-             while (left > 0 && i > 0)
+             can_skip_p = right == 0;
+           }
+         
+         if (can_skip_p)
+           {
+             while (i < stop
+                    && GLYPH_EQUAL_P (desired_glyph, current_glyph))
                {
-                 --i, --desired_glyph, --current_glyph;
-                 x -= desired_glyph->pixel_width;
-                 left -= desired_glyph->pixel_width;
+                 x += desired_glyph->pixel_width;
+                 ++desired_glyph, ++current_glyph, ++i;
+               }
+
+             /* Consider the case that the current row contains "xxx
+                ppp ggg" in italic Courier font, and the desired row
+                is "xxx ggg".  The character `p' has lbearing, `g'
+                has not.  The loop above will stop in front of the
+                first `p' in the current row.  If we would start
+                writing glyphs there, we wouldn't erase the lbearing
+                of the `p'.  The rest of the lbearing problem is then
+                taken care of by x_draw_glyphs.  */
+             if (overlapping_glyphs_p
+                 && i > 0
+                 && i < current_row->used[TEXT_AREA]
+                 && (current_row->used[TEXT_AREA]
+                     != desired_row->used[TEXT_AREA]))
+               {
+                 int left, right;
+             
+                 rif->get_glyph_overhangs (current_glyph, XFRAME (w->frame),
+                                           &left, &right);
+                 while (left > 0 && i > 0)
+                   {
+                     --i, --desired_glyph, --current_glyph;
+                     x -= desired_glyph->pixel_width;
+                     left -= desired_glyph->pixel_width;
+                   }
                }
            }
          
@@ -3990,15 +4362,18 @@ update_text_area (w, vpos)
              int start_x = x, start_hpos = i;
              struct glyph *start = desired_glyph;
              int current_x = x;
-             
+             int skip_first_p = !can_skip_p;
+
              /* Find the next glyph that's equal again.  */
              while (i < stop
-                    && !GLYPH_EQUAL_P (desired_glyph, current_glyph)
+                    && (skip_first_p
+                        || !GLYPH_EQUAL_P (desired_glyph, current_glyph))
                     && x == current_x)
                {
                  x += desired_glyph->pixel_width;
                  current_x += current_glyph->pixel_width;
                  ++desired_glyph, ++current_glyph, ++i;
+                 skip_first_p = 0;
                }
 
              if (i == start_hpos || x != current_x)
@@ -4008,7 +4383,7 @@ update_text_area (w, vpos)
                  desired_glyph = start;
                  break;
                }
-             
+
              rif->cursor_to (vpos, start_hpos, desired_row->y, start_x);
              rif->write_glyphs (start, i - start_hpos);
              changed_p = 1;
@@ -4077,54 +4452,67 @@ update_text_area (w, vpos)
    changed.  */
 
 static int
-update_window_line (w, vpos)
+update_window_line (w, vpos, mouse_face_overwritten_p)
      struct window *w;
-     int vpos;
+     int vpos, *mouse_face_overwritten_p;
 {
   struct glyph_row *current_row = MATRIX_ROW (w->current_matrix, vpos);
   struct glyph_row *desired_row = MATRIX_ROW (w->desired_matrix, vpos);
   int changed_p = 0;
 
-  xassert (desired_row->enabled_p);
-
   /* Set the row being updated.  This is important to let xterm.c
      know what line height values are in effect.  */
   updated_row = desired_row;
 
-  /* Update display of the left margin area, if there is one.  */
-  if (!desired_row->full_width_p
-      && !NILP (w->left_margin_width))
+  /* A row can be completely invisible in case a desired matrix was 
+     built with a vscroll and then make_cursor_line_fully_visible shifts 
+     the matrix.  Make sure to make such rows current anyway, since
+     we need the correct y-position, for example, in the current matrix.  */
+  if (desired_row->mode_line_p
+      || desired_row->visible_height > 0)
     {
-      update_marginal_area (w, LEFT_MARGIN_AREA, vpos);
-      changed_p = 1;
-    }
-  
-  /* Update the display of the text area.  */
-  changed_p |= update_text_area (w, vpos);
-  
-  /* Update display of the right margin area, if there is one.  */
-  if (!desired_row->full_width_p
-      && !NILP (w->right_margin_width))
-    {
-      changed_p = 1;
-      update_marginal_area (w, RIGHT_MARGIN_AREA, vpos);
+      xassert (desired_row->enabled_p);
+
+      /* Update display of the left margin area, if there is one.  */
+      if (!desired_row->full_width_p
+         && !NILP (w->left_margin_width))
+       {
+         changed_p = 1;
+         update_marginal_area (w, LEFT_MARGIN_AREA, vpos);
+       }
+      
+      /* Update the display of the text area.  */
+      if (update_text_area (w, vpos))
+       {
+         changed_p = 1;
+         if (current_row->mouse_face_p)
+           *mouse_face_overwritten_p = 1;
+       }
+      
+      /* Update display of the right margin area, if there is one.  */
+      if (!desired_row->full_width_p
+         && !NILP (w->right_margin_width))
+       {
+         changed_p = 1;
+         update_marginal_area (w, RIGHT_MARGIN_AREA, vpos);
+       }
+      
+      /* Draw truncation marks etc.  */
+      if (!current_row->enabled_p
+         || desired_row->y != current_row->y
+         || desired_row->visible_height != current_row->visible_height
+         || desired_row->overlay_arrow_p != current_row->overlay_arrow_p
+         || desired_row->truncated_on_left_p != current_row->truncated_on_left_p
+         || desired_row->truncated_on_right_p != current_row->truncated_on_right_p
+         || desired_row->continued_p != current_row->continued_p
+         || desired_row->mode_line_p != current_row->mode_line_p
+         || (desired_row->indicate_empty_line_p
+             != current_row->indicate_empty_line_p)
+         || (MATRIX_ROW_CONTINUATION_LINE_P (desired_row)
+             != MATRIX_ROW_CONTINUATION_LINE_P (current_row)))
+       rif->after_update_window_line_hook (desired_row);
     }
   
-  /* Draw truncation marks etc.  */
-  if (!current_row->enabled_p
-      || desired_row->y != current_row->y
-      || desired_row->visible_height != current_row->visible_height
-      || desired_row->overlay_arrow_p != current_row->overlay_arrow_p
-      || desired_row->truncated_on_left_p != current_row->truncated_on_left_p
-      || desired_row->truncated_on_right_p != current_row->truncated_on_right_p
-      || desired_row->continued_p != current_row->continued_p
-      || desired_row->mode_line_p != current_row->mode_line_p
-      || (desired_row->indicate_empty_line_p
-         != current_row->indicate_empty_line_p)
-      || (MATRIX_ROW_CONTINUATION_LINE_P (desired_row)
-         != MATRIX_ROW_CONTINUATION_LINE_P (current_row)))
-    rif->after_update_window_line_hook (desired_row);
-  
   /* Update current_row from desired_row.  */
   make_current (w->desired_matrix, w->current_matrix, vpos);
   updated_row = NULL;
@@ -4169,22 +4557,21 @@ set_window_cursor_after_update (w)
          int yb = window_text_bottom_y (w);
 
          last_row = NULL;
-         for (row = MATRIX_ROW (w->current_matrix, 0);
-              row->enabled_p;
-              ++row)
+         row = w->current_matrix->rows;
+         while (row->enabled_p
+                && (last_row == NULL
+                    || MATRIX_ROW_BOTTOM_Y (row) <= yb))
            {
              if (row->used[TEXT_AREA]
                  && row->glyphs[TEXT_AREA][0].charpos >= 0)
                last_row = row;
-
-             if (MATRIX_ROW_BOTTOM_Y (row) >= yb)
-               break;
+             ++row;
            }
          
          if (last_row)
            {
-             struct glyph *start = row->glyphs[TEXT_AREA];
-             struct glyph *last = start + row->used[TEXT_AREA] - 1;
+             struct glyph *start = last_row->glyphs[TEXT_AREA];
+             struct glyph *last = start + last_row->used[TEXT_AREA] - 1;
 
              while (last > start && last->charpos < 0)
                --last;
@@ -4217,8 +4604,118 @@ set_window_cursor_after_update (w)
 }
 
 
+/* Set WINDOW->must_be_updated_p to ON_P for all windows in the window
+   tree rooted at W.  */
+
+void
+set_window_update_flags (w, on_p)
+     struct window *w;
+     int on_p;
+{
+  while (w)
+    {
+      if (!NILP (w->hchild))
+       set_window_update_flags (XWINDOW (w->hchild), on_p);
+      else if (!NILP (w->vchild))
+       set_window_update_flags (XWINDOW (w->vchild), on_p);
+      else
+       w->must_be_updated_p = on_p;
+
+      w = NILP (w->next) ? 0 : XWINDOW (w->next);
+    }
+}    
+
+
+\f
+/***********************************************************************
+                       Window-Based Scrolling
+ ***********************************************************************/
+
+/* Structure describing rows in scrolling_window.  */
+
+struct row_entry
+{
+  /* Number of occurrences of this row in desired and current matrix.  */
+  int old_uses, new_uses;
+    
+  /* Vpos of row in new matrix.  */
+  int new_line_number;
+
+  /* Bucket index of this row_entry in the hash table row_table.  */
+  int bucket;
+    
+  /* The row described by this entry.  */
+  struct glyph_row *row;
+    
+  /* Hash collision chain.  */
+  struct row_entry *next;
+};
+
+/* A pool to allocate row_entry structures from, and the size of the
+   pool.  The pool is reallocated in scrolling_window when we find
+   that we need a larger one.  */
+
+static struct row_entry *row_entry_pool;
+static int row_entry_pool_size;
+
+/* Index of next free entry in row_entry_pool.  */
+
+static int row_entry_idx;
+
+/* The hash table used during scrolling, and the table's size.  This
+   table is used to quickly identify equal rows in the desired and
+   current matrix.  */
+
+static struct row_entry **row_table;
+static int row_table_size;
+
+/* Vectors of pointers to row_entry structures belonging to the
+   current and desired matrix, and the size of the vectors.  */
+
+static struct row_entry **old_lines, **new_lines;
+static int old_lines_size, new_lines_size;
+
+/* A pool to allocate run structures from, and its size.  */
+
+static struct run *run_pool;
+static int runs_size;
+
+/* A vector of runs of lines found during scrolling.  */
+
+static struct run **runs;
+
+/* Add glyph row ROW to the scrolling hash table during the scrolling
+   of window W.  */
+
+static INLINE struct row_entry *
+add_row_entry (w, row)
+     struct window *w;
+     struct glyph_row *row;
+{
+  struct row_entry *entry;
+  int i = row->hash % row_table_size;
+  
+  entry = row_table[i];
+  while (entry && !row_equal_p (w, entry->row, row, 1))
+    entry = entry->next;
+  
+  if (entry == NULL)
+    {
+      entry = row_entry_pool + row_entry_idx++;
+      entry->row = row;
+      entry->old_uses = entry->new_uses = 0;
+      entry->new_line_number = 0;
+      entry->bucket = i;
+      entry->next = row_table[i];
+      row_table[i] = entry;
+    }
+
+  return entry;
+}
+
+
 /* Try to reuse part of the current display of W by scrolling lines.
-   HEADER_LINE_P non-zero means W has a top mode line.
+   HEADER_LINE_P non-zero means W has a header line.
 
    The algorithm is taken from Communications of the ACM, Apr78 "A
    Technique for Isolating Differences Between Files."  It should take
@@ -4248,47 +4745,31 @@ scrolling_window (w, header_line_p)
      struct window *w;
      int header_line_p;
 {
-  struct symbol 
-  {
-    /* Number of occurrences of this line in old and new matrix.  */
-    short old_uses, new_uses;
-    
-    /* Vpos of line in new matrix.  */
-    short new_line_number;
-    
-    /* The line itself.  */
-    struct glyph_row *row;
-    
-    /* Hash collision chain.  */
-    struct symbol *next;
-  };
-
-  int SYMBOL_TABLE_SIZE = 101;
-  struct symbol **table;
-  struct symbol **old_line_syms, **new_line_syms;
-  int i, j, first_old, first_new, last_old, last_new;
-  struct symbol *sym;
-  struct run **runs;
-  int nruns;
   struct glyph_matrix *desired_matrix = w->desired_matrix;
   struct glyph_matrix *current_matrix = w->current_matrix;
   int yb = window_text_bottom_y (w);
+  int i, j, first_old, first_new, last_old, last_new;
+  int nruns, nbytes, n, run_idx;
+  struct row_entry *entry;
 
   /* Skip over rows equal at the start.  */
-  i = header_line_p ? 1 : 0;
-  while (i < current_matrix->nrows - 1
-         && MATRIX_ROW_ENABLED_P (current_matrix, i)
-        && MATRIX_ROW_ENABLED_P (desired_matrix, i)
-        && MATRIX_ROW_BOTTOM_Y (MATRIX_ROW (desired_matrix, i)) < yb
-        && MATRIX_ROW_BOTTOM_Y (MATRIX_ROW (current_matrix, i)) < yb
-         && row_equal_p (w,
-                        MATRIX_ROW (desired_matrix, i),
-                         MATRIX_ROW (current_matrix, i)))
+  for (i = header_line_p ? 1 : 0; i < current_matrix->nrows - 1; ++i)
     {
-      assign_row (MATRIX_ROW (current_matrix, i),
-                 MATRIX_ROW (desired_matrix, i));
-      MATRIX_ROW (desired_matrix, i)->enabled_p = 0;
-      ++i;
+      struct glyph_row *d = MATRIX_ROW (desired_matrix, i);
+      struct glyph_row *c = MATRIX_ROW (current_matrix, i);
+
+      if (c->enabled_p
+         && d->enabled_p
+         && c->y == d->y
+         && MATRIX_ROW_BOTTOM_Y (c) <= yb
+         && MATRIX_ROW_BOTTOM_Y (d) <= yb
+         && row_equal_p (w, c, d, 1))
+       {
+         assign_row (c, d);
+         d->enabled_p = 0;
+       }
+      else
+       break;
     }
 
   /* Give up if some rows in the desired matrix are not enabled.  */
@@ -4302,7 +4783,7 @@ scrolling_window (w, header_line_p)
   i = first_new + 1;
   while (i < desired_matrix->nrows - 1
         && MATRIX_ROW (desired_matrix, i)->enabled_p
-        && MATRIX_ROW_BOTTOM_Y (MATRIX_ROW (desired_matrix, i)) < yb)
+        && MATRIX_ROW_BOTTOM_Y (MATRIX_ROW (desired_matrix, i)) <= yb)
     ++i;
 
   if (!MATRIX_ROW (desired_matrix, i)->enabled_p)
@@ -4315,9 +4796,15 @@ scrolling_window (w, header_line_p)
      we plan to reuse part of the display even if other parts are
      disabled.  */
   i = first_old + 1;
-  while (i < current_matrix->nrows - 1
-        && MATRIX_ROW_BOTTOM_Y (MATRIX_ROW (current_matrix, i)) < yb)
-    ++i;
+  while (i < current_matrix->nrows - 1)
+    {
+      int bottom = MATRIX_ROW_BOTTOM_Y (MATRIX_ROW (current_matrix, i));
+      if (bottom <= yb)
+       ++i;
+      if (bottom >= yb)
+       break;
+    }
+
   last_old = i;
 
   /* Skip over rows equal at the bottom.  */
@@ -4330,7 +4817,7 @@ scrolling_window (w, header_line_p)
             == MATRIX_ROW (desired_matrix, j - 1)->y)
          && row_equal_p (w,
                         MATRIX_ROW (desired_matrix, i - 1),
-                         MATRIX_ROW (current_matrix, j - 1)))
+                         MATRIX_ROW (current_matrix, j - 1), 1))
     --i, --j;
   last_new = i;
   last_old = j;
@@ -4339,76 +4826,84 @@ scrolling_window (w, header_line_p)
   if (last_new == first_new)
     return 0;
 
-  /* Allocate a hash table in which all rows will be inserted.  */
-  table = (struct symbol **) alloca (SYMBOL_TABLE_SIZE * sizeof *table);
-  bzero (table, SYMBOL_TABLE_SIZE * sizeof *table);
-
-  /* For each row in the current matrix, record the symbol belonging
-     to the row in OLD_LINE_SYMS.  */
-  old_line_syms = (struct symbol **) alloca (current_matrix->nrows
-                                            * sizeof *old_line_syms);
-  new_line_syms = (struct symbol **) alloca (desired_matrix->nrows
-                                            * sizeof *new_line_syms);
-
-#define ADDSYM(ROW)                                            \
-  do                                                           \
-    {                                                          \
-      struct glyph_row *row_ = (ROW);                          \
-      int i_ = row_->hash % SYMBOL_TABLE_SIZE;                 \
-      sym = table[i_];                                         \
-      while (sym && !row_equal_p (w, sym->row, row_))          \
-        sym = sym->next;                                       \
-      if (sym == NULL)                                         \
-       {                                                       \
-         sym = (struct symbol *) alloca (sizeof *sym);         \
-         sym->row = row_;                                      \
-         sym->old_uses = sym->new_uses = 0;                    \
-         sym->next = table[i_];                                \
-         table[i_] = sym;                                      \
-       }                                                       \
-    }                                                          \
-  while (0)
-
-  /* Add current rows to the symbol table.  */
+  /* Reallocate vectors, tables etc. if necessary.  */
+  
+  if (current_matrix->nrows > old_lines_size)
+    {
+      old_lines_size = current_matrix->nrows;
+      nbytes = old_lines_size * sizeof *old_lines;
+      old_lines = (struct row_entry **) xrealloc (old_lines, nbytes);
+    }
+  
+  if (desired_matrix->nrows > new_lines_size)
+    {
+      new_lines_size = desired_matrix->nrows;
+      nbytes = new_lines_size * sizeof *new_lines;
+      new_lines = (struct row_entry **) xrealloc (new_lines, nbytes);
+    }
+
+  n = desired_matrix->nrows + current_matrix->nrows;
+  if (3 * n > row_table_size)
+    {
+      row_table_size = next_almost_prime (3 * n);
+      nbytes = row_table_size * sizeof *row_table;
+      row_table = (struct row_entry **) xrealloc (row_table, nbytes);
+      bzero (row_table, nbytes);
+    }
+
+  if (n > row_entry_pool_size)
+    {
+      row_entry_pool_size = n;
+      nbytes = row_entry_pool_size * sizeof *row_entry_pool;
+      row_entry_pool = (struct row_entry *) xrealloc (row_entry_pool, nbytes);
+    }
+
+  if (desired_matrix->nrows > runs_size)
+    {
+      runs_size = desired_matrix->nrows;
+      nbytes = runs_size * sizeof *runs;
+      runs = (struct run **) xrealloc (runs, nbytes);
+      nbytes = runs_size * sizeof *run_pool;
+      run_pool = (struct run *) xrealloc (run_pool, nbytes);
+    }
+
+  nruns = run_idx = 0;
+  row_entry_idx = 0;
+
+  /* Add rows from the current and desired matrix to the hash table
+     row_hash_table to be able to find equal ones quickly.  */
+  
   for (i = first_old; i < last_old; ++i)
     {
       if (MATRIX_ROW (current_matrix, i)->enabled_p)
        {
-         ADDSYM (MATRIX_ROW (current_matrix, i));
-         old_line_syms[i] = sym;
-         ++sym->old_uses;
+         entry = add_row_entry (w, MATRIX_ROW (current_matrix, i));
+         old_lines[i] = entry;
+         ++entry->old_uses;
        }
       else
-       old_line_syms[i] = NULL;
+       old_lines[i] = NULL;
     }
 
-  /* Add desired rows to the symbol table.  */
   for (i = first_new; i < last_new; ++i)
     {
       xassert (MATRIX_ROW_ENABLED_P (desired_matrix, i));
-      ADDSYM (MATRIX_ROW (desired_matrix, i));
-      ++sym->new_uses;
-      new_line_syms[i] = sym;
-      sym->new_line_number = i;
+      entry = add_row_entry (w, MATRIX_ROW (desired_matrix, i));
+      ++entry->new_uses;
+      entry->new_line_number = i;
+      new_lines[i] = entry;
     }
 
-#undef ADDSYM
-
-  /* Record in runs which moves were found, ordered by pixel
-     height of copied areas.  */
-  nruns = 0;
-  runs = (struct run **) alloca (desired_matrix->nrows * sizeof *runs);
-
   /* Identify moves based on lines that are unique and equal
      in both matrices.  */
   for (i = first_old; i < last_old;)
-    if (old_line_syms[i]
-       && old_line_syms[i]->old_uses == 1
-        && old_line_syms[i]->new_uses == 1)
+    if (old_lines[i]
+       && old_lines[i]->old_uses == 1
+        && old_lines[i]->new_uses == 1)
       {
        int j, k;
-       int new_line = old_line_syms[i]->new_line_number;
-       struct run *run = (struct run *) alloca (sizeof *run);
+       int new_line = old_lines[i]->new_line_number;
+       struct run *run = run_pool + run_idx++;
 
        /* Record move.  */
        run->current_vpos = i;
@@ -4423,7 +4918,7 @@ scrolling_window (w, header_line_p)
        k = new_line - 1;
        while (j > first_old
               && k > first_new
-              && old_line_syms[j] == new_line_syms[k])
+              && old_lines[j] == new_lines[k])
          {
            int h = MATRIX_ROW (current_matrix, j)->height;
            --run->current_vpos; 
@@ -4440,7 +4935,7 @@ scrolling_window (w, header_line_p)
        k = new_line + 1;
        while (j < last_old
               && k < last_new
-              && old_line_syms[j] == new_line_syms[k])
+              && old_lines[j] == new_lines[k])
          {
            int h = MATRIX_ROW (current_matrix, j)->height;
            ++run->nrows; 
@@ -4455,7 +4950,7 @@ scrolling_window (w, header_line_p)
           case.  */
        for (j = 0; j < nruns && runs[j]->height > run->height; ++j)
          ;
-       for (k = nruns; k >= j; --k)
+       for (k = nruns; k > j; --k)
          runs[k] = runs[k - 1];
        runs[j] = run;
        ++nruns;
@@ -4508,43 +5003,25 @@ scrolling_window (w, header_line_p)
          {
            struct glyph_row *from, *to;
            int to_overlapped_p;
-           
+
            to = MATRIX_ROW (current_matrix, r->desired_vpos + j);
-           to_overlapped_p = to->overlapped_p;
            from = MATRIX_ROW (desired_matrix, r->desired_vpos + j);
+           to_overlapped_p = to->overlapped_p;
            assign_row (to, from);
            to->enabled_p = 1, from->enabled_p = 0;
            to->overlapped_p = to_overlapped_p;
          }
       }
 
+  /* Clear the hash table, for the next time.  */
+  for (i = 0; i < row_entry_idx; ++i)
+    row_table[row_entry_pool[i].bucket] = NULL;
+
   /* Value is non-zero to indicate that we scrolled the display.  */
   return 1;
 }
 
 
-/* Set WINDOW->must_be_updated_p TO ON_P for all windows WINDOW in the
-   window tree rooted at W.  */
-
-void
-set_window_update_flags (w, on_p)
-     struct window *w;
-     int on_p;
-{
-  while (w)
-    {
-      if (!NILP (w->hchild))
-       set_window_update_flags (XWINDOW (w->hchild), on_p);
-      else if (!NILP (w->vchild))
-       set_window_update_flags (XWINDOW (w->vchild), on_p);
-      else
-       w->must_be_updated_p = on_p;
-
-      w = NILP (w->next) ? 0 : XWINDOW (w->next);
-    }
-}    
-
-
 \f
 /************************************************************************
                         Frame-Based Updates
@@ -4580,15 +5057,14 @@ update_frame_1 (f, force_p, inhibit_id_p)
   if (preempt_count <= 0)
     preempt_count = 1;
 
-  detect_input_pending ();
-  if (input_pending && !force_p)
+  if (redisplay_dont_pause)
+    force_p = 1;
+  else if (!force_p && detect_input_pending ())
     {
       pause = 1;
       goto do_pause;
     }
 
-  update_begin (f);
-
   /* If we cannot insert/delete lines, it's no use trying it.  */
   if (!line_ins_del_ok)
     inhibit_id_p = 1;
@@ -4628,7 +5104,7 @@ update_frame_1 (f, force_p, inhibit_id_p)
 #ifdef EMACS_OUTQSIZE
                      if (EMACS_OUTQSIZE (0, &outq) < 0)
                        /* Probably not a tty.  Ignore the error and reset
-                        * the outq count.  */
+                          the outq count.  */
                        outq = PENDING_OUTPUT_COUNT (stdout);
 #endif
                      outq *= 10;
@@ -4724,7 +5200,13 @@ update_frame_1 (f, force_p, inhibit_id_p)
          /* We have only one cursor on terminal frames.  Use it to
             display the cursor of the selected window.  */
          struct window *w = XWINDOW (FRAME_SELECTED_WINDOW (f));
-         if (w->cursor.vpos >= 0)
+         if (w->cursor.vpos >= 0
+             /* The cursor vpos may be temporarily out of bounds
+                in the following situation:  There is one window,
+                with the cursor in the lower half of it.  The window
+                is split, and a message causes a redisplay before
+                a new cursor position has been computed.  */
+             && w->cursor.vpos < XFASTINT (w->height))
            {
              int x = WINDOW_TO_FRAME_HPOS (w, w->cursor.hpos);
              int y = WINDOW_TO_FRAME_VPOS (w, w->cursor.vpos);
@@ -4738,15 +5220,8 @@ update_frame_1 (f, force_p, inhibit_id_p)
        }
     }
 
-  update_end (f);
-
-  if (termscript)
-    fflush (termscript);
-  fflush (stdout);
-
  do_pause:
 
-  display_completed = !pause;
   clear_desired_matrices (f);
   return pause;
 }
@@ -4853,7 +5328,7 @@ count_blanks (r, len)
      int len;
 {
   int i;
-
+  
   for (i = 0; i < len; ++i)
     if (!CHAR_GLYPH_SPACE_P (r[i]))
       break;
@@ -4891,28 +5366,24 @@ extern int *char_ins_del_vector;
 /* Perform a frame-based update on line VPOS in frame FRAME.  */
 
 static void
-update_frame_line (frame, vpos)
-     register struct frame *frame;
+update_frame_line (f, vpos)
+     struct frame *f;
      int vpos;
 {
   struct glyph *obody, *nbody, *op1, *op2, *np1, *nend;
   int tem;
   int osp, nsp, begmatch, endmatch, olen, nlen;
-  struct glyph_matrix *current_matrix = frame->current_matrix;
-  struct glyph_matrix *desired_matrix = frame->desired_matrix;
+  struct glyph_matrix *current_matrix = f->current_matrix;
+  struct glyph_matrix *desired_matrix = f->desired_matrix;
   struct glyph_row *current_row = MATRIX_ROW (current_matrix, vpos);
   struct glyph_row *desired_row = MATRIX_ROW (desired_matrix, vpos);
   int must_write_whole_line_p;
+  int write_spaces_p = must_write_spaces;
+  int colored_spaces_p = (FACE_FROM_ID (f, DEFAULT_FACE_ID)->background
+                         != FACE_TTY_DEFAULT_BG_COLOR);
 
-  if (desired_row->inverse_p
-      != (current_row->enabled_p && current_row->inverse_p))
-    {
-      int n = current_row->enabled_p ? current_row->used[TEXT_AREA] : 0;
-      change_line_highlight (desired_row->inverse_p, vpos, vpos, n);
-      current_row->enabled_p = 0;
-    }
-  else
-    reassert_line_highlight (desired_row->inverse_p, vpos);
+  if (colored_spaces_p)
+    write_spaces_p = 1;
 
   /* Current row not enabled means it has unknown contents.  We must
      write the whole desired line in that case.  */
@@ -4927,26 +5398,14 @@ update_frame_line (frame, vpos)
       obody = MATRIX_ROW_GLYPH_START (current_matrix, vpos);
       olen = current_row->used[TEXT_AREA];
       
-      if (! current_row->inverse_p)
-       {
-         /* Ignore trailing spaces, if we can.  */
-         if (!must_write_spaces)
-           while (olen > 0 && CHAR_GLYPH_SPACE_P (obody[olen-1]))
-             olen--;
-       }
-      else
-       {
-         /* For an inverse-video line, make sure it's filled with
-            spaces all the way to the frame edge so that the reverse
-            video extends all the way across.  */
-         while (olen < FRAME_WIDTH (frame) - 1)
-           obody[olen++] = space_glyph;
-       }
+      /* Ignore trailing spaces, if we can.  */
+      if (!write_spaces_p)
+       while (olen > 0 && CHAR_GLYPH_SPACE_P (obody[olen-1]))
+         olen--;
     }
 
   current_row->enabled_p = 1;
   current_row->used[TEXT_AREA] = desired_row->used[TEXT_AREA];
-  current_row->inverse_p = desired_row->inverse_p;
 
   /* If desired line is empty, just clear the line.  */
   if (!desired_row->enabled_p)
@@ -4963,7 +5422,7 @@ update_frame_line (frame, vpos)
   if (must_write_whole_line_p)
     {
       /* Ignore spaces at the end, if we can.  */
-      if (!must_write_spaces)
+      if (!write_spaces_p)
        while (nlen > 0 && CHAR_GLYPH_SPACE_P (nbody[nlen - 1]))
          --nlen;
 
@@ -4977,10 +5436,10 @@ update_frame_line (frame, vpos)
       /* Don't call clear_end_of_line if we already wrote the whole
         line.  The cursor will not be at the right margin in that
         case but in the line below.  */
-      if (nlen < FRAME_WINDOW_WIDTH (frame))
+      if (nlen < FRAME_WINDOW_WIDTH (f))
        {
          cursor_to (vpos, nlen);
-          clear_end_of_line (FRAME_WINDOW_WIDTH (frame));
+          clear_end_of_line (FRAME_WINDOW_WIDTH (f));
        }
       else
        /* Make sure we are in the right row, otherwise cursor movement
@@ -4993,20 +5452,9 @@ update_frame_line (frame, vpos)
 
   /* Pretend trailing spaces are not there at all,
      unless for one reason or another we must write all spaces.  */
-  if (!desired_row->inverse_p)
-    {
-      if (!must_write_spaces)
-       while (nlen > 0 && CHAR_GLYPH_SPACE_P (nbody[nlen - 1]))
-         nlen--;
-    }
-  else
-    {
-      /* For an inverse-video line, give it extra trailing spaces all
-        the way to the frame edge so that the reverse video extends
-        all the way across.  */
-      while (nlen < FRAME_WIDTH (frame) - 1)
-       nbody[nlen++] = space_glyph;
-    }
+  if (!write_spaces_p)
+    while (nlen > 0 && CHAR_GLYPH_SPACE_P (nbody[nlen - 1]))
+      nlen--;
 
   /* If there's no i/d char, quickly do the best we can without it.  */
   if (!char_ins_del_ok)
@@ -5055,7 +5503,7 @@ update_frame_line (frame, vpos)
     {
       /* If current line is blank, skip over initial spaces, if
         possible, and write the rest.  */
-      if (must_write_spaces || desired_row->inverse_p)
+      if (write_spaces_p)
        nsp = 0;
       else
        nsp = count_blanks (nbody, nlen);
@@ -5073,7 +5521,7 @@ update_frame_line (frame, vpos)
 
   /* Compute number of leading blanks in old and new contents.  */
   osp = count_blanks (obody, olen);
-  nsp = desired_row->inverse_p ? 0 : count_blanks (nbody, nlen);
+  nsp = (colored_spaces_p ? 0 : count_blanks (nbody, nlen));
 
   /* Compute number of matching chars starting with first non-blank.  */
   begmatch = count_match (obody + osp, obody + olen,
@@ -5081,7 +5529,7 @@ update_frame_line (frame, vpos)
 
   /* Spaces in new match implicit space past the end of old.  */
   /* A bug causing this to be a no-op was fixed in 18.29.  */
-  if (!must_write_spaces && osp + begmatch == olen)
+  if (!write_spaces_p && osp + begmatch == olen)
     {
       np1 = nbody + nsp;
       while (np1 + begmatch < nend && CHAR_GLYPH_SPACE_P (np1[begmatch]))
@@ -5112,7 +5560,7 @@ update_frame_line (frame, vpos)
 
   tem = (nlen - nsp) - (olen - osp);
   if (endmatch && tem
-      && (!char_ins_del_ok || endmatch <= char_ins_del_cost (frame)[tem]))
+      && (!char_ins_del_ok || endmatch <= char_ins_del_cost (f)[tem]))
     endmatch = 0;
 
   /* nsp - osp is the distance to insert or delete.
@@ -5122,7 +5570,7 @@ update_frame_line (frame, vpos)
 
   if (nsp != osp
       && (!char_ins_del_ok
-         || begmatch + endmatch <= char_ins_del_cost (frame)[nsp - osp]))
+         || begmatch + endmatch <= char_ins_del_cost (f)[nsp - osp]))
     {
       begmatch = 0;
       endmatch = 0;
@@ -5156,16 +5604,23 @@ update_frame_line (frame, vpos)
   tem = nsp + begmatch + endmatch;
   if (nlen != tem || olen != tem)
     {
-      cursor_to (vpos, nsp + begmatch);
       if (!endmatch || nlen == olen)
        {
-         /* If new text being written reaches right margin,
-            there is no need to do clear-to-eol at the end.
-            (and it would not be safe, since cursor is not
-            going to be "at the margin" after the text is done) */
-         if (nlen == FRAME_WINDOW_WIDTH (frame))
+         /* If new text being written reaches right margin, there is
+            no need to do clear-to-eol at the end of this function
+            (and it would not be safe, since cursor is not going to
+            be "at the margin" after the text is done).  */
+         if (nlen == FRAME_WINDOW_WIDTH (f))
            olen = 0;
-         write_glyphs (nbody + nsp + begmatch, nlen - tem);
+
+         /* Function write_glyphs is prepared to do nothing
+            if passed a length <= 0.  Check it here to avoid
+            unnecessary cursor movement.  */
+         if (nlen - tem > 0)
+           {
+             cursor_to (vpos, nsp + begmatch);
+             write_glyphs (nbody + nsp + begmatch, nlen - tem);
+           }
        }
       else if (nlen > olen)
        {
@@ -5179,18 +5634,25 @@ update_frame_line (frame, vpos)
          int out = olen - tem; /* Columns to be overwritten originally.  */
          int del;
 
+         cursor_to (vpos, nsp + begmatch);
+         
          /* Calculate columns we can actually overwrite.  */
-         while (CHAR_GLYPH_PADDING_P (nbody[nsp + begmatch + out])) out--;
+         while (CHAR_GLYPH_PADDING_P (nbody[nsp + begmatch + out]))
+           out--;
          write_glyphs (nbody + nsp + begmatch, out);
+         
          /* If we left columns to be overwritten, we must delete them.  */
          del = olen - tem - out;
-         if (del > 0) delete_glyphs (del);
+         if (del > 0)
+           delete_glyphs (del);
+         
          /* At last, we insert columns not yet written out.  */
          insert_glyphs (nbody + nsp + begmatch + out, nlen - olen + del);
          olen = nlen;
        }
       else if (olen > nlen)
        {
+         cursor_to (vpos, nsp + begmatch);
          write_glyphs (nbody + nsp + begmatch, nlen - tem);
          delete_glyphs (olen - nlen);
          olen = nlen;
@@ -5215,14 +5677,17 @@ update_frame_line (frame, vpos)
                   X/Y Position -> Buffer Position
  ***********************************************************************/
 
-/* Return the character position of the character at window relative
-   pixel position (*X, *Y).  *X and *Y are adjusted to character
-   boundaries.  */
+/* Determine what's under window-relative pixel position (*X, *Y).
+   Return in *OBJECT the object (string or buffer) that's there.
+   Return in *POS the position in that object. Adjust *X and *Y
+   to character boundaries.  */
 
-int
-buffer_posn_from_coords (w, x, y)
+void
+buffer_posn_from_coords (w, x, y, object, pos)
      struct window *w;
      int *x, *y;
+     Lisp_Object *object;
+     struct display_pos *pos;
 {
   struct it it;
   struct buffer *old_current_buffer = current_buffer;
@@ -5242,19 +5707,21 @@ buffer_posn_from_coords (w, x, y)
   *x = it.current_x - it.first_visible_x + left_area_width;
   *y = it.current_y;
   current_buffer = old_current_buffer;
-  return IT_CHARPOS (it);
+
+  *object = STRINGP (it.string) ? it.string : w->buffer;
+  *pos = it.current;
 }
 
 
 /* Value is the string under window-relative coordinates X/Y in the
-   mode or top line of window W, or nil if none.  MODE_LINE_P non-zero
+   mode or header line of window W, or nil if none.  MODE_LINE_P non-zero
    means look at the mode line.  *CHARPOS is set to the position in
    the string returned.  */
 
 Lisp_Object
 mode_line_string (w, x, y, mode_line_p, charpos)
      struct window *w;
-     int x, y;
+     int x, y, mode_line_p;
      int *charpos;
 {
   struct glyph_row *row;
@@ -5270,12 +5737,12 @@ mode_line_string (w, x, y, mode_line_p, charpos)
 
   if (row->mode_line_p && row->enabled_p)
     {
-      /* The mode lines are displayed over scroll bars and bitmap
-        areas, and X is window-relative.  Correct X by the scroll bar
-        and bitmap area width.  */
+      /* The mode lines are displayed over scroll bars and fringes,
+        and X is window-relative.  Correct X by the scroll bar
+        and fringe width.  */
       if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (f))
        x += FRAME_SCROLL_BAR_COLS (f) * CANON_X_UNIT (f);
-      x += FRAME_LEFT_FLAGS_AREA_WIDTH (f);
+      x += FRAME_LEFT_FRINGE_WIDTH (f);
 
       /* Find the glyph under X.  If we find one with a string object,
          it's the one we were looking for.  */
@@ -5305,7 +5772,9 @@ window_change_signal (signalnum) /* If we don't have an argument, */
      int signalnum;            /* some compilers complain in signal calls.  */
 {
   int width, height;
+#ifndef USE_CRT_DLL
   extern int errno;
+#endif
   int old_errno = errno;
 
   get_frame_size (&width, &height);
@@ -5501,8 +5970,9 @@ change_frame_size_1 (f, newheight, newwidth, pretend, delay, safe)
   }
 
   adjust_glyphs (f);
-  SET_FRAME_GARBAGED (f);
   calculate_costs (f);
+  SET_FRAME_GARBAGED (f);
+  f->resized_p = 1;
 
   UNBLOCK_INPUT;
 
@@ -5522,10 +5992,10 @@ change_frame_size_1 (f, newheight, newwidth, pretend, delay, safe)
  ***********************************************************************/
 
 DEFUN ("open-termscript", Fopen_termscript, Sopen_termscript,
-  1, 1, "FOpen termscript file: ",
-  "Start writing all terminal output to FILE as well as the terminal.\n\
-FILE = nil means just close any termscript file currently open.")
-  (file)
+       1, 1, "FOpen termscript file: ",
+       doc: /* Start writing all terminal output to FILE as well as the terminal.
+FILE = nil means just close any termscript file currently open.  */)
+     (file)
      Lisp_Object file;
 {
   if (termscript != 0) fclose (termscript);
@@ -5543,14 +6013,14 @@ FILE = nil means just close any termscript file currently open.")
 
 
 DEFUN ("send-string-to-terminal", Fsend_string_to_terminal,
-  Ssend_string_to_terminal, 1, 1, 0,
-  "Send STRING to the terminal without alteration.\n\
-Control characters in STRING will have terminal-dependent effects.")
-  (string)
+       Ssend_string_to_terminal, 1, 1, 0,
+       doc: /* Send STRING to the terminal without alteration.
+Control characters in STRING will have terminal-dependent effects.  */)
+     (string)
      Lisp_Object string;
 {
   /* ??? Perhaps we should do something special for multibyte strings here.  */
-  CHECK_STRING (string, 0);
+  CHECK_STRING (string);
   fwrite (XSTRING (string)->data, 1, STRING_BYTES (XSTRING (string)), stdout);
   fflush (stdout);
   if (termscript)
@@ -5564,10 +6034,10 @@ Control characters in STRING will have terminal-dependent effects.")
 
 
 DEFUN ("ding", Fding, Sding, 0, 1, 0,
-  "Beep, or flash the screen.\n\
-Also, unless an argument is given,\n\
-terminate any keyboard macro currently executing.")
-  (arg)
+       doc: /* Beep, or flash the screen.
+Also, unless an argument is given,
+terminate any keyboard macro currently executing.  */)
+     (arg)
   Lisp_Object arg;
 {
   if (!NILP (arg))
@@ -5603,13 +6073,13 @@ bitch_at_user ()
  ***********************************************************************/
 
 DEFUN ("sleep-for", Fsleep_for, Ssleep_for, 1, 2, 0,
-  "Pause, without updating display, for SECONDS seconds.\n\
-SECONDS may be a floating-point value, meaning that you can wait for a\n\
-fraction of a second.  Optional second arg MILLISECONDS specifies an\n\
-additional wait period, in milliseconds; this may be useful if your\n\
-Emacs was built without floating point support.\n\
-\(Not all operating systems support waiting for a fraction of a second.)")
-  (seconds, milliseconds)
+       doc: /* Pause, without updating display, for SECONDS seconds.
+SECONDS may be a floating-point value, meaning that you can wait for a
+fraction of a second.  Optional second arg MILLISECONDS specifies an
+additional wait period, in milliseconds; this may be useful if your
+Emacs was built without floating point support.
+\(Not all operating systems support waiting for a fraction of a second.)  */)
+     (seconds, milliseconds)
      Lisp_Object seconds, milliseconds;
 {
   int sec, usec;
@@ -5617,7 +6087,7 @@ Emacs was built without floating point support.\n\
   if (NILP (milliseconds))
     XSETINT (milliseconds, 0);
   else
-    CHECK_NUMBER (milliseconds, 1);
+    CHECK_NUMBER (milliseconds);
   usec = XINT (milliseconds) * 1000;
 
   {
@@ -5634,7 +6104,7 @@ Emacs was built without floating point support.\n\
   /* Assure that 0 <= usec < 1000000.  */
   if (usec < 0)
     {
-      /* We can't rely on the rounding being correct if user is negative.  */
+      /* We can't rely on the rounding being correct if usec is negative.  */
       if (-1000000 < usec)
        sec--, usec += 1000000;
       else
@@ -5665,7 +6135,7 @@ Emacs was built without floating point support.\n\
 #else /* not VMS */
 /* The reason this is done this way 
     (rather than defined (H_S) && defined (H_T))
-   is because the VMS preprocessor doesn't grok `defined' */
+   is because the VMS preprocessor doesn't grok `defined' */
 #ifdef HAVE_SELECT
   EMACS_GET_TIME (end_time);
   EMACS_SET_SECS_USECS (timeout, sec, usec);
@@ -5709,7 +6179,7 @@ sit_for (sec, usec, reading, display, initial_display)
     return Qnil;
 
   if (initial_display)
-    redisplay_preserve_echo_area ();
+    redisplay_preserve_echo_area (2);
 
   if (sec == 0 && usec == 0)
     return Qt;
@@ -5726,17 +6196,17 @@ sit_for (sec, usec, reading, display, initial_display)
 
 
 DEFUN ("sit-for", Fsit_for, Ssit_for, 1, 3, 0,
-  "Perform redisplay, then wait for SECONDS seconds or until input is available.\n\
-SECONDS may be a floating-point value, meaning that you can wait for a\n\
-fraction of a second.  Optional second arg MILLISECONDS specifies an\n\
-additional wait period, in milliseconds; this may be useful if your\n\
-Emacs was built without floating point support.\n\
-\(Not all operating systems support waiting for a fraction of a second.)\n\
-Optional third arg NODISP non-nil means don't redisplay, just wait for input.\n\
-Redisplay is preempted as always if input arrives, and does not happen\n\
-if input is available before it starts.\n\
-Value is t if waited the full time with no input arriving.")
-  (seconds, milliseconds, nodisp)
+       doc: /* Perform redisplay, then wait for SECONDS seconds or until input is available.
+SECONDS may be a floating-point value, meaning that you can wait for a
+fraction of a second.  Optional second arg MILLISECONDS specifies an
+additional wait period, in milliseconds; this may be useful if your
+Emacs was built without floating point support.
+\(Not all operating systems support waiting for a fraction of a second.)
+Optional third arg NODISP non-nil means don't redisplay, just wait for input.
+Redisplay is preempted as always if input arrives, and does not happen
+if input is available before it starts.
+Value is t if waited the full time with no input arriving.  */)
+     (seconds, milliseconds, nodisp)
      Lisp_Object seconds, milliseconds, nodisp;
 {
   int sec, usec;
@@ -5744,7 +6214,7 @@ Value is t if waited the full time with no input arriving.")
   if (NILP (milliseconds))
     XSETINT (milliseconds, 0);
   else
-    CHECK_NUMBER (milliseconds, 1);
+    CHECK_NUMBER (milliseconds);
   usec = XINT (milliseconds) * 1000;
 
   {
@@ -5776,15 +6246,15 @@ static Lisp_Object frame_and_buffer_state;
 
 
 DEFUN ("frame-or-buffer-changed-p", Fframe_or_buffer_changed_p,
-  Sframe_or_buffer_changed_p, 0, 0, 0,
-  "Return non-nil if the frame and buffer state appears to have changed.\n\
-The state variable is an internal vector containing all frames and buffers,\n\
-aside from buffers whose names start with space,\n\
-along with the buffers' read-only and modified flags, which allows a fast\n\
-check to see whether the menu bars might need to be recomputed.\n\
-If this function returns non-nil, it updates the internal vector to reflect\n\
-the current state.\n")
-  ()
+       Sframe_or_buffer_changed_p, 0, 0, 0,
+       doc: /* Return non-nil if the frame and buffer state appears to have changed.
+The state variable is an internal vector containing all frames and buffers,
+aside from buffers whose names start with space,
+along with the buffers' read-only and modified flags, which allows a fast
+check to see whether the menu bars might need to be recomputed.
+If this function returns non-nil, it updates the internal vector to reflect
+the current state.  */)
+     ()
 {
   Lisp_Object tail, frame, buf;
   Lisp_Object *vecp;
@@ -5924,7 +6394,7 @@ init_display ()
 #else
       Vwindow_system_version = make_number (10);
 #endif
-#if defined (LINUX) && defined (HAVE_LIBNCURSES)
+#if defined (GNU_LINUX) && defined (HAVE_LIBNCURSES)
       /* In some versions of ncurses,
         tputs crashes if we have not called tgetent.
         So call tgetent.  */
@@ -5945,6 +6415,16 @@ init_display ()
     }
 #endif /* HAVE_NTGUI */
 
+#ifdef macintosh
+  if (!inhibit_window_system) 
+    {
+      Vwindow_system = intern ("mac");
+      Vwindow_system_version = make_number (1);
+      adjust_frame_glyphs_initially ();
+      return;
+    }
+#endif /* macintosh */
+
   /* If no window system has been specified, try to use the terminal.  */
   if (! isatty (0))
     {
@@ -5952,7 +6432,7 @@ init_display ()
       exit (1);
     }
 
-  /* Look at the TERM variable */
+  /* Look at the TERM variable */
   terminal_type = (char *) getenv ("TERM");
   if (!terminal_type)
     {
@@ -6039,11 +6519,11 @@ For types not defined in VMS, use  define emacs_term \"TYPE\".\n\
 
 DEFUN ("internal-show-cursor", Finternal_show_cursor,
        Sinternal_show_cursor, 2, 2, 0,
-  "Set the cursor-visibility flag of WINDOW to SHOW.\n\
-WINDOW nil means use the selected window.  SHOW non-nil means\n\
-show a cursor in WINDOW in the next redisplay.  SHOW nil means\n\
-don't show a cursor.")
-  (window, show)
+       doc: /* Set the cursor-visibility flag of WINDOW to SHOW.
+WINDOW nil means use the selected window.  SHOW non-nil means
+show a cursor in WINDOW in the next redisplay.  SHOW nil means
+don't show a cursor.  */)
+     (window, show)
      Lisp_Object window, show;
 {
   /* Don't change cursor state while redisplaying.  This could confuse
@@ -6053,7 +6533,7 @@ don't show a cursor.")
       if (NILP (window))
        window = selected_window;
       else
-       CHECK_WINDOW (window, 2);
+       CHECK_WINDOW (window);
       
       XWINDOW (window)->cursor_off_p = NILP (show);
     }
@@ -6064,9 +6544,9 @@ don't show a cursor.")
 
 DEFUN ("internal-show-cursor-p", Finternal_show_cursor_p,
        Sinternal_show_cursor_p, 0, 1, 0,
-  "Value is non-nil if next redisplay will display a cursor in WINDOW.\n\
-WINDOW nil or omitted means report on the selected window.")
-  (window)
+       doc: /* Value is non-nil if next redisplay will display a cursor in WINDOW.
+WINDOW nil or omitted means report on the selected window.  */)
+     (window)
      Lisp_Object window;
 {
   struct window *w;
@@ -6074,7 +6554,7 @@ WINDOW nil or omitted means report on the selected window.")
   if (NILP (window))
     window = selected_window;
   else
-    CHECK_WINDOW (window, 2);
+    CHECK_WINDOW (window);
   
   w = XWINDOW (window);
   return w->cursor_off_p ? Qnil : Qt;    
@@ -6099,58 +6579,68 @@ syms_of_display ()
   defsubr (&Sinternal_show_cursor);
   defsubr (&Sinternal_show_cursor_p);
 
+#if GLYPH_DEBUG
+  defsubr (&Sdump_redisplay_history);
+#endif
+
   frame_and_buffer_state = Fmake_vector (make_number (20), Qlambda);
   staticpro (&frame_and_buffer_state);
 
   Qdisplay_table = intern ("display-table");
   staticpro (&Qdisplay_table);
+  Qredisplay_dont_pause = intern ("redisplay-dont-pause");
+  staticpro (&Qredisplay_dont_pause);
 
   DEFVAR_INT ("baud-rate", &baud_rate,
-    "*The output baud rate of the terminal.\n\
-On most systems, changing this value will affect the amount of padding\n\
-and the other strategic decisions made during redisplay.");
+             doc: /* *The output baud rate of the terminal.
+On most systems, changing this value will affect the amount of padding
+and the other strategic decisions made during redisplay.  */);
   
   DEFVAR_BOOL ("inverse-video", &inverse_video,
-    "*Non-nil means invert the entire frame display.\n\
-This means everything is in inverse video which otherwise would not be.");
+              doc: /* *Non-nil means invert the entire frame display.
+This means everything is in inverse video which otherwise would not be.  */);
   
   DEFVAR_BOOL ("visible-bell", &visible_bell,
-    "*Non-nil means try to flash the frame to represent a bell.");
+              doc: /* *Non-nil means try to flash the frame to represent a bell.
+
+See also `ring-bell-function'.  */);
   
   DEFVAR_BOOL ("no-redraw-on-reenter", &no_redraw_on_reenter,
-    "*Non-nil means no need to redraw entire frame after suspending.\n\
-A non-nil value is useful if the terminal can automatically preserve\n\
-Emacs's frame display when you reenter Emacs.\n\
-It is up to you to set this variable if your terminal can do that.");
+              doc: /* *Non-nil means no need to redraw entire frame after suspending.
+A non-nil value is useful if the terminal can automatically preserve
+Emacs's frame display when you reenter Emacs.
+It is up to you to set this variable if your terminal can do that.  */);
   
   DEFVAR_LISP ("window-system", &Vwindow_system,
-    "A symbol naming the window-system under which Emacs is running\n\
-\(such as `x'), or nil if emacs is running on an ordinary terminal.");
+              doc: /* Name of window system that Emacs is displaying through.
+The value is a symbol--for instance, `x' for X windows.
+The value is nil if Emacs is using a text-only terminal.  */);
   
   DEFVAR_LISP ("window-system-version", &Vwindow_system_version,
-    "The version number of the window system in use.\n\
-For X windows, this is 10 or 11.");
+              doc: /* The version number of the window system in use.
+For X windows, this is 10 or 11.  */);
   
   DEFVAR_BOOL ("cursor-in-echo-area", &cursor_in_echo_area,
-    "Non-nil means put cursor in minibuffer, at end of any message there.");
+              doc: /* Non-nil means put cursor in minibuffer, at end of any message there.  */);
   
   DEFVAR_LISP ("glyph-table", &Vglyph_table,
-    "Table defining how to output a glyph code to the frame.\n\
-If not nil, this is a vector indexed by glyph code to define the glyph.\n\
-Each element can be:\n\
- integer: a glyph code which this glyph is an alias for.\n\
- string: output this glyph using that string (not impl. in X windows).\n\
- nil: this glyph mod 256 is char code to output,\n\
-    and this glyph / 256 is face code for X windows (see `face-id').");
+              doc: /* Table defining how to output a glyph code to the frame.
+If not nil, this is a vector indexed by glyph code to define the glyph.
+Each element can be:
+ integer: a glyph code which this glyph is an alias for.
+ string: output this glyph using that string (not impl. in X windows).
+ nil: this glyph mod 524288 is the code of a character to output,
+    and this glyph / 524288 is the face number (see `face-id') to use
+    while outputting it.  */);
   Vglyph_table = Qnil;
 
   DEFVAR_LISP ("standard-display-table", &Vstandard_display_table,
-    "Display table to use for buffers that specify none.\n\
-See `buffer-display-table' for more information.");
+              doc: /* Display table to use for buffers that specify none.
+See `buffer-display-table' for more information.  */);
   Vstandard_display_table = Qnil;
 
   DEFVAR_BOOL ("redisplay-dont-pause", &redisplay_dont_pause,
-    "*Non-nil means update isn't paused when input is detected.");
+              doc: /* *Non-nil means update isn't paused when input is detected.  */);
   redisplay_dont_pause = 0;
 
   /* Initialize `window-system', unless init_display already decided it.  */