Initial check-in: changes for building Emacs under Mac OS.
[bpt/emacs.git] / src / dispnew.c
index 87ad3de..14e4d96 100644 (file)
@@ -1,5 +1,5 @@
 /* Updating of data structures for redisplay.
-   Copyright (C) 1985, 86, 87, 88, 93, 94, 95, 97, 1998
+   Copyright (C) 1985, 86, 87, 88, 93, 94, 95, 97, 98, 1999
        Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
@@ -19,8 +19,8 @@ along with GNU Emacs; see the file COPYING.  If not, write to
 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 Boston, MA 02111-1307, USA.  */
 
-#include <signal.h>
 #include <config.h>
+#include <signal.h>
 #include <stdio.h>
 #include <ctype.h>
 
@@ -37,6 +37,7 @@ Boston, MA 02111-1307, USA.  */
 #include "cm.h"
 #include "buffer.h"
 #include "charset.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"
@@ -91,11 +95,18 @@ Boston, MA 02111-1307, USA.  */
 #define        PENDING_OUTPUT_COUNT(FILE) ((FILE)->__bufp - (FILE)->__buffer)
 #endif
 #else /* not __GNU_LIBRARY__ */
+#if !defined (PENDING_OUTPUT_COUNT) && HAVE_STDIO_EXT_H && HAVE___FPENDING
+#include <stdio_ext.h>
+#define PENDING_OUTPUT_COUNT(FILE) __fpending (FILE)
+#endif
 #ifndef PENDING_OUTPUT_COUNT
 #define PENDING_OUTPUT_COUNT(FILE) ((FILE)->_ptr - (FILE)->_base)
 #endif
 #endif /* not __GNU_LIBRARY__ */
 
+#if defined (LINUX) && defined (HAVE_LIBNCURSES)
+#include <term.h>              /* for tgetent */
+#endif
 \f
 /* Structure to pass dimensions around.  Used for character bounding
    boxes, glyph matrix dimensions and alike.  */
@@ -127,9 +138,10 @@ static void free_glyph_matrix P_ ((struct glyph_matrix *));
 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_glyphs_in_rows P_ ((struct glyph_row *, struct glyph_row *));
 static void swap_glyph_pointers P_ ((struct glyph_row *, struct glyph_row *));
+#ifdef 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 *));
@@ -148,7 +160,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 *,
@@ -165,11 +177,13 @@ 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));
 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
@@ -231,7 +245,7 @@ Lisp_Object Vstandard_display_table;
 
 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
@@ -657,6 +671,7 @@ 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.
@@ -775,8 +790,7 @@ rotate_matrix (matrix, first, last, by)
    DELTA_BYTES.  */
 
 void
-increment_glyph_matrix_buffer_positions (matrix, start, end, delta,
-                                        delta_bytes)
+increment_matrix_positions (matrix, start, end, delta, delta_bytes)
      struct glyph_matrix *matrix;
      int start, end, delta, delta_bytes;
 {
@@ -786,8 +800,7 @@ increment_glyph_matrix_buffer_positions (matrix, start, end, delta,
   xassert (start <= end);
 
   for (; start < end; ++start)
-    increment_glyph_row_buffer_positions (matrix->rows + start,
-                                         delta, delta_bytes);
+    increment_row_positions (matrix->rows + start, delta, delta_bytes);
 }
 
 
@@ -984,6 +997,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
 }
 
 
@@ -1024,7 +1047,7 @@ blank_row (w, row, y)
    ends.  */
 
 void
-increment_glyph_row_buffer_positions (row, delta, delta_bytes)
+increment_row_positions (row, delta, delta_bytes)
      struct glyph_row *row;
      int delta, delta_bytes;
 {
@@ -1050,6 +1073,7 @@ increment_glyph_row_buffer_positions (row, delta, delta_bytes)
 }
 
 
+#if 0
 /* Swap glyphs between two glyph rows A and B.  This exchanges glyph
    contents, i.e. glyph structure contents are exchanged between A and
    B without changing glyph pointers in A and B.  */
@@ -1088,6 +1112,7 @@ swap_glyphs_in_rows (a, b)
     }
 }
 
+#endif /* 0 */
 
 /* Exchange pointers to glyph memory between glyph rows A and B.  */
 
@@ -1148,7 +1173,7 @@ copy_glyph_row_contents (to, from, delta, delta_bytes)
             from->used[area] * sizeof (struct glyph));
 
   /* Increment buffer positions in TO by DELTA.  */
-  increment_glyph_row_buffer_positions (to, delta, delta_bytes);
+  increment_row_positions (to, delta, delta_bytes);
 }
 
 
@@ -1172,6 +1197,8 @@ assign_row (to, from)
    is non-zero if the glyph memory of WINDOW_ROW is part of the glyph
    memory of FRAME_ROW.  */
 
+#ifdef GLYPH_DEBUG
+
 static int
 glyph_row_slice_p (window_row, frame_row)
      struct glyph_row *window_row, *frame_row;
@@ -1184,6 +1211,9 @@ glyph_row_slice_p (window_row, frame_row)
          && window_glyph_start < frame_glyph_end);
 }
 
+#endif /* GLYPH_DEBUG */
+
+#if 0
 
 /* Find the row in the window glyph matrix WINDOW_MATRIX being a slice
    of ROW in the frame matrix FRAME_MATRIX.  Value is null if no row
@@ -1206,6 +1236,7 @@ find_glyph_row_slice (window_matrix, frame_matrix, row)
   return i < window_matrix->nrows ? window_matrix->rows + i : 0;
 }
 
+#endif /* 0 */
 
 /* Prepare ROW for display.  Desired rows are cleared lazily,
    i.e. they are only marked as to be cleared by setting their
@@ -1247,10 +1278,12 @@ line_hash_code (row)
 
           while (glyph < end)
             {
-             GLYPH g = GLYPH_FROM_CHAR_GLYPH (*glyph);
+             int c = glyph->u.ch;
+             int face_id = glyph->face_id;
              if (must_write_spaces)
-               g -= SPACEGLYPH;
-             hash = (((hash << 4) + (hash >> 24)) & 0x0fffffff) + g;
+               c -= SPACEGLYPH;
+             hash = (((hash << 4) + (hash >> 24)) & 0x0fffffff) + c;
+             hash = (((hash << 4) + (hash >> 24)) & 0x0fffffff) + face_id;
              ++glyph;
            }
 
@@ -1308,7 +1341,8 @@ line_draw_cost (matrix, vpos)
        {
          GLYPH g = GLYPH_FROM_CHAR_GLYPH (*beg);
          
-         if (GLYPH_SIMPLE_P (glyph_table_base, glyph_table_len, g))
+         if (g < 0
+             || GLYPH_SIMPLE_P (glyph_table_base, glyph_table_len, g))
            len += 1;
          else
            len += GLYPH_LENGTH (glyph_table_base, g);
@@ -1324,12 +1358,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;
@@ -1340,6 +1376,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)
        {
@@ -1488,6 +1527,17 @@ realloc_glyph_pool (pool, matrix_dim)
 
 #if GLYPH_DEBUG
 
+
+/* Flush standard output.  This is sometimes useful to call from
+   the debugger.  */
+
+void
+flush_stdout ()
+{
+  fflush (stdout);
+}
+
+
 /* Check that no glyph pointers have been lost in MATRIX.  If a
    pointer has been lost, e.g. by using a structure assignment between
    rows, at least one pointer must occur more than once in the rows of
@@ -1736,8 +1786,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 = w->width;
-         dim.height = w->height;
+         dim.width = XINT (w->width);
+         dim.height = XINT (w->height);
 
          /* Will matrix be re-allocated?  */
          if (x != w->desired_matrix->matrix_x
@@ -2150,6 +2200,9 @@ free_glyphs (f)
 {
   if (f && f->glyphs_initialized_p)
     {
+      /* Block interrupt input so that we don't get surprised by an X
+         event while we're in an inconsistent state.  */
+      BLOCK_INPUT;
       f->glyphs_initialized_p = 0;
       
       /* Release window sub-matrices.  */
@@ -2193,6 +2246,8 @@ free_glyphs (f)
          free_glyph_pool (f->current_pool);
          f->desired_pool = f->current_pool = NULL;
        }
+      
+      UNBLOCK_INPUT;
     }
 }
 
@@ -2404,6 +2459,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.  */
@@ -2411,19 +2467,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)
@@ -2432,6 +2501,7 @@ 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
@@ -2452,11 +2522,12 @@ build_frame_matrix_from_leaf_window (frame_matrix, w)
              /* Exchange pointers between both rows.  */
              swap_glyph_pointers (window_row, slice_row);
            }
+#endif
 
-         /* Now, we are sure that window row window_y is a slice of
-            the frame row frame_y.  But, lets check that assumption.  */
+         /* Window row window_y must be a slice of frame row
+            frame_y.  */
          xassert (glyph_row_slice_p (window_row, frame_row));
-
+         
          /* If rows are in sync, we don't have to copy glyphs because
             frame and window share glyphs.  */
          
@@ -2471,8 +2542,7 @@ 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;
+      /* Or in other flags.  */
       frame_row->inverse_p |= window_row->inverse_p;
 
       /* Next row.  */
@@ -2578,6 +2648,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.  */
@@ -2585,6 +2656,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.  */
@@ -2690,6 +2762,68 @@ 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.  */
+
+static void
+sync_window_with_frame_matrix_rows (w)
+     struct window *w;
+{
+  struct frame *f = XFRAME (w->frame);
+  struct glyph_row *window_row, *window_row_end, *frame_row;
+
+  /* Preconditions: W must be a leaf window and full-width.  Its frame
+     must have a frame matrix.  */
+  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.  */
+  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)
+    {
+      int area;
+      
+      for (area = LEFT_MARGIN_AREA; area <= LAST_AREA; ++area)
+       window_row->glyphs[area] = frame_row->glyphs[area];
+
+      ++window_row, ++frame_row;
+    }
+}
+
+
+/* Return the window in the window tree rooted in W containing frame
+   row ROW.  Value is null if none is found.  */
+
+struct window *
+frame_row_to_window (w, row)
+     struct window *w;
+     int row;
+{
+  struct window *found = NULL;
+  
+  while (w && !found)
+    {
+      if (!NILP (w->hchild))
+       found = frame_row_to_window (XWINDOW (w->hchild), row);
+      else if (!NILP (w->vchild))
+       found = frame_row_to_window (XWINDOW (w->vchild), row);
+      else if (row >= XFASTINT (w->top)
+              && row < XFASTINT (w->top) + XFASTINT (w->height))
+       found = w;
+      
+      w = NILP (w->next) ? 0 : XWINDOW (w->next);
+    }
+
+  return found;
+}
+
+
 /* Perform a line dance in the window tree rooted at W, after
    scrolling a frame matrix in mirrored_line_dance.
 
@@ -2721,9 +2855,7 @@ mirror_line_dance (w, unchanged_at_top, nlines, copy_from, retained_p)
          /* W is a leaf window, and we are working on its current
             matrix m.  */
          struct glyph_matrix *m = w->current_matrix;
-         
-         int i;
-         
+         int i, sync_p = 0;
          struct glyph_row *old_rows;
 
          /* Make a copy of the original rows of matrix m.  */
@@ -2748,21 +2880,15 @@ mirror_line_dance (w, unchanged_at_top, nlines, copy_from, retained_p)
              int from_inside_window_p
                = window_from >= 0 && window_from < m->matrix_h;
              
-             if (from_inside_window_p)
+             /* Is assigned to line inside window?  */
+             int to_inside_window_p
+               = window_to >= 0 && window_to < m->matrix_h;
+             
+             if (from_inside_window_p && to_inside_window_p)
                {
-#if GLYPH_DEBUG
-                 /* Is assigned to line inside window?  */
-                 int to_inside_window_p
-                   = window_to >= 0 && window_to < m->matrix_h;
-#endif
-                 
                  /* Enabled setting before assignment.  */
                  int enabled_before_p;
                  
-                 /* If not both lines inside the window, we have a
-                    serious problem.  */
-                 xassert (to_inside_window_p);
-                 
                  /* Do the assignment.  The enabled_p flag is saved
                     over the assignment because the old redisplay did
                     that.  */
@@ -2774,7 +2900,35 @@ mirror_line_dance (w, unchanged_at_top, nlines, copy_from, retained_p)
                  if (!retained_p[copy_from[i]])
                    m->rows[window_to].enabled_p = 0;
                }
+             else if (to_inside_window_p)
+               {
+                 /* A copy between windows.  This is an infrequent
+                    case not worth optimizing.  */
+                 struct frame *f = XFRAME (w->frame);
+                 struct window *root = XWINDOW (FRAME_ROOT_WINDOW (f));
+                 struct window *w2;
+                 struct glyph_matrix *m2;
+                 int m2_from;
+
+                 w2 = frame_row_to_window (root, frame_to);
+                 m2 = w2->current_matrix;
+                 m2_from = frame_from - m2->matrix_y;
+                 copy_row_except_pointers (m->rows + window_to,
+                                           m2->rows + m2_from);
+                 
+                 /* If frame line is empty, window line is empty, too.  */
+                 if (!retained_p[copy_from[i]])
+                   m->rows[window_to].enabled_p = 0;
+                 sync_p = 1;
+               }
+             else if (from_inside_window_p)
+               sync_p = 1;
            }
+
+         /* If there was a copy between windows, make sure glyph
+            pointers are in sync with the frame matrix.  */
+         if (sync_p)
+           sync_window_with_frame_matrix_rows (w);
          
          /* Check that no pointers are lost.  */
          CHECK_MATRIX (m);
@@ -3053,11 +3207,13 @@ direct_output_for_insert (g)
      position.  */
   clear_glyph_row (&scratch_glyph_row);
   SET_TEXT_POS (pos, PT, PT_BYTE);
-  DEC_TEXT_POS (pos);
+  DEC_TEXT_POS (pos, !NILP (current_buffer->enable_multibyte_characters));
   init_iterator (&it, w, CHARPOS (pos), BYTEPOS (pos), &scratch_glyph_row,
                 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
@@ -3070,7 +3226,7 @@ direct_output_for_insert (g)
       last = glyph_row->glyphs[TEXT_AREA] + glyph_row->used[TEXT_AREA] - 1;
       if (last->type == STRETCH_GLYPH
          || (last->type == CHAR_GLYPH
-             && last->u.ch.code == ' '))
+             && last->u.ch == ' '))
        return 0;
     }
 
@@ -3110,7 +3266,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
@@ -3128,7 +3284,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.  */
@@ -3140,7 +3296,8 @@ direct_output_for_insert (g)
 
   /* Make room for new glyphs, then insert them.  */
   xassert (end - glyphs - n >= 0);
-  safe_bcopy (glyphs, glyphs + n, (end - glyphs - n) * sizeof (*end));
+  safe_bcopy ((char *) glyphs, (char *) (glyphs + n),
+             (end - glyphs - n) * sizeof (*end));
   bcopy (it.glyph_row->glyphs[TEXT_AREA], glyphs, n * sizeof *glyphs);
   glyph_row->used[TEXT_AREA] = min (glyph_row->used[TEXT_AREA] + n,
                                    end - glyph_row->glyphs[TEXT_AREA]);
@@ -3158,7 +3315,7 @@ direct_output_for_insert (g)
   /* Increment buffer positions for glyphs following the newly 
      inserted ones.  */
   for (glyph = glyphs + n; glyph < end; ++glyph)
-    if (glyph->charpos > 0)
+    if (glyph->charpos > 0 && BUFFERP (glyph->object))
       glyph->charpos += delta;
   
   if (MATRIX_ROW_END_CHARPOS (glyph_row) > 0)
@@ -3168,14 +3325,18 @@ direct_output_for_insert (g)
     }
       
   /* Adjust positions in lines following the one we are in.  */
-  increment_glyph_matrix_buffer_positions (w->current_matrix,
-                                          w->cursor.vpos + 1,
-                                          w->current_matrix->nrows,
-                                          delta, delta_bytes);
+  increment_matrix_positions (w->current_matrix,
+                             w->cursor.vpos + 1,
+                             w->current_matrix->nrows,
+                             delta, delta_bytes);
 
   glyph_row->contains_overlapping_glyphs_p
     |= it.glyph_row->contains_overlapping_glyphs_p;
 
+  glyph_row->displays_text_p = 1;
+  w->window_end_vpos = make_number (max (w->cursor.vpos,
+                                        XFASTINT (w->window_end_vpos)));
+
   if (!NILP (Vshow_trailing_whitespace))
     highlight_trailing_whitespace (it.f, glyph_row);
 
@@ -3226,7 +3387,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);
@@ -3257,6 +3418,11 @@ direct_output_forward_char (n)
   struct window *w = XWINDOW (selected_window);
   struct glyph_row *row;
 
+  /* Give up if point moved out of or into a composition.  */
+  if (check_point_in_composition (current_buffer, XINT (w->last_point),
+                                 current_buffer, PT))
+    return 0;
+
   /* Give up if face attributes have been changed.  */
   if (face_change_count)
     return 0;
@@ -3278,13 +3444,30 @@ direct_output_forward_char (n)
   if (!NILP (Vshow_trailing_whitespace))
     return 0;
 
+  /* Give up if we are showing a message or just cleared the message
+     because we might need to resize the echo area window.  */
+  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);
 
+  /* Give up if PT is outside of the last known cursor row.  */
   if (PT <= MATRIX_ROW_START_BYTEPOS (row)
       || PT >= MATRIX_ROW_END_BYTEPOS (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);
 
@@ -3382,10 +3565,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
     }
@@ -3395,21 +3577,26 @@ 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));
     }
 
   /* Reset flags indicating that a window should be updated.  */
   set_window_update_flags (root_window, 0);
+  
+  display_completed = !paused_p;
   return paused_p;
 }
 
@@ -3479,8 +3666,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
@@ -3489,7 +3675,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;
@@ -3513,8 +3699,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;
     }
 }
@@ -3603,7 +3788,7 @@ update_window (w, force_p)
       struct glyph_row *row, *end;
       struct glyph_row *mode_line_row;
       struct glyph_row *header_line_row = NULL;
-      int yb, changed_p = 0;
+      int yb, changed_p = 0, mouse_face_overwritten_p = 0;
 
       rif->update_window_begin_hook (w);
       yb = window_text_bottom_y (w);
@@ -3621,7 +3806,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;
        }
 
@@ -3631,7 +3817,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);
@@ -3652,17 +3838,13 @@ update_window (w, force_p)
       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)
+       if (row->enabled_p)
          {
            int vpos = MATRIX_ROW_VPOS (row, desired_matrix);
            int i;
@@ -3674,7 +3856,8 @@ update_window (w, force_p)
            if (!force_p && vpos % 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
@@ -3696,24 +3879,19 @@ 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);
-       }
-      
       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
        }
@@ -3724,8 +3902,7 @@ update_window (w, force_p)
 #endif
 
       /* End of update of window W.  */
-      rif->update_window_end_hook (w, 1);
-
+      rif->update_window_end_hook (w, 1, mouse_face_overwritten_p);
     }
   else
     paused_p = 1;
@@ -3785,6 +3962,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);
@@ -3944,54 +4122,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))
-    {
-      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))
+  /* 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)
     {
-      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;
@@ -4084,6 +4275,120 @@ 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;
+
+static struct row_entry *add_row_entry P_ ((struct window *,
+                                           struct glyph_row *));
+
+
+/* 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.
 
@@ -4115,47 +4420,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.  */
@@ -4169,7 +4458,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)
@@ -4183,7 +4472,7 @@ scrolling_window (w, header_line_p)
      disabled.  */
   i = first_old + 1;
   while (i < current_matrix->nrows - 1
-        && MATRIX_ROW_BOTTOM_Y (MATRIX_ROW (current_matrix, i)) < yb)
+        && MATRIX_ROW_BOTTOM_Y (MATRIX_ROW (current_matrix, i)) <= yb)
     ++i;
   last_old = i;
 
@@ -4197,7 +4486,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;
@@ -4206,76 +4495,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;
@@ -4290,7 +4587,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; 
@@ -4307,7 +4604,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; 
@@ -4375,43 +4672,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
@@ -4447,15 +4726,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;
@@ -4591,7 +4869,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);
@@ -4605,15 +4889,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;
 }
@@ -4742,7 +5019,7 @@ count_match (str1, end1, str2, end2)
   
   while (p1 < end1
         && p2 < end2
-        && GLYPH_FROM_CHAR_GLYPH (*p1) == GLYPH_FROM_CHAR_GLYPH (*p2))
+        && GLYPH_CHAR_AND_FACE_EQUAL_P (p1, p2))
     ++p1, ++p2;
   
   return p1 - str1;
@@ -4849,7 +5126,11 @@ update_frame_line (frame, vpos)
          cursor_to (vpos, nlen);
           clear_end_of_line (FRAME_WINDOW_WIDTH (frame));
        }
-
+      else
+       /* Make sure we are in the right row, otherwise cursor movement
+          with cmgoto might use `ch' in the wrong row.  */
+       cursor_to (vpos, 0);
+      
       make_current (desired_matrix, current_matrix, vpos);
       return;
     }
@@ -5117,7 +5398,7 @@ buffer_posn_from_coords (w, x, y)
 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;
@@ -5126,10 +5407,6 @@ mode_line_string (w, x, y, mode_line_p, charpos)
   int x0;
   Lisp_Object string = Qnil;
 
-  /* Only do this for frames under a window system.  */
-  if (!FRAME_WINDOW_P (f))
-    return Qnil;
-
   if (mode_line_p)
     row = MATRIX_MODE_LINE_ROW (w->current_matrix);
   else
@@ -5172,7 +5449,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);
@@ -5487,16 +5766,11 @@ Emacs was built without floating point support.\n\
     CHECK_NUMBER (milliseconds, 1);
   usec = XINT (milliseconds) * 1000;
 
-#ifdef LISP_FLOAT_TYPE
   {
     double duration = extract_float (seconds);
     sec = (int) duration;
     usec += (duration - sec) * 1000000;
   }
-#else
-  CHECK_NUMBER (seconds, 0);
-  sec = XINT (seconds);
-#endif
 
 #ifndef EMACS_HAS_USECS
   if (sec == 0 && usec != 0)
@@ -5619,16 +5893,11 @@ Value is t if waited the full time with no input arriving.")
     CHECK_NUMBER (milliseconds, 1);
   usec = XINT (milliseconds) * 1000;
 
-#ifdef LISP_FLOAT_TYPE
   {
     double duration = extract_float (seconds);
     sec = (int) duration;
     usec += (duration - sec) * 1000000;
   }
-#else
-  CHECK_NUMBER (seconds, 0);
-  sec = XINT (seconds);
-#endif
 
 #ifndef EMACS_HAS_USECS
   if (usec != 0 && sec == 0)
@@ -5679,9 +5948,9 @@ the current state.\n")
      No need to test for the end of the vector
      because the last element of the vector is lambda
      and that will always cause a mismatch.  */
-  for (tail = Vbuffer_alist; CONSP (tail); tail = XCONS (tail)->cdr)
+  for (tail = Vbuffer_alist; CONSP (tail); tail = XCDR (tail))
     {
-      buf = XCONS (XCONS (tail)->car)->cdr;
+      buf = XCDR (XCAR (tail));
       /* Ignore buffers that aren't included in buffer lists.  */
       if (XSTRING (XBUFFER (buf)->name)->data[0] == ' ')
        continue;
@@ -5700,7 +5969,7 @@ the current state.\n")
   n = 1;
   FOR_EACH_FRAME (tail, frame)
     n += 2;
-  for (tail = Vbuffer_alist; CONSP (tail); tail = XCONS (tail)->cdr)
+  for (tail = Vbuffer_alist; CONSP (tail); tail = XCDR (tail))
     n += 3;
   /* Reallocate the vector if it's grown, or if it's shrunk a lot.  */
   if (n > XVECTOR (frame_and_buffer_state)->size
@@ -5713,9 +5982,9 @@ the current state.\n")
       *vecp++ = frame;
       *vecp++ = XFRAME (frame)->name;
     }
-  for (tail = Vbuffer_alist; CONSP (tail); tail = XCONS (tail)->cdr)
+  for (tail = Vbuffer_alist; CONSP (tail); tail = XCDR (tail))
     {
-      buf = XCONS (XCONS (tail)->car)->cdr;
+      buf = XCDR (XCAR (tail));
       /* Ignore buffers that aren't included in buffer lists.  */
       if (XSTRING (XBUFFER (buf)->name)->data[0] == ' ')
        continue;
@@ -5822,6 +6091,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))
     {
@@ -5897,7 +6176,15 @@ For types not defined in VMS, use  define emacs_term \"TYPE\".\n\
       && (strcmp (terminal_type, "internal") != 0 || inhibit_window_system)
 #endif
       && NILP (Vwindow_system))
-    call0 (intern ("tty-set-up-initial-frame-faces"));
+    {
+      /* For the initial frame, we don't have any way of knowing what
+        are the foreground and background colors of the terminal.  */
+      struct frame *sf = SELECTED_FRAME();
+
+      FRAME_FOREGROUND_PIXEL (sf) = FACE_TTY_DEFAULT_FG_COLOR;
+      FRAME_BACKGROUND_PIXEL (sf) = FACE_TTY_DEFAULT_BG_COLOR;
+      call0 (intern ("tty-set-up-initial-frame-faces"));
+    }
 }
 
 
@@ -5906,17 +6193,15 @@ For types not defined in VMS, use  define emacs_term \"TYPE\".\n\
                           Blinking cursor
  ***********************************************************************/
 
-DEFUN ("show-cursor", Fshow_cursor, Sshow_cursor, 0, 2, 0,
-  "Change visibility flag of the text cursor of WINDOW.\n\
-ON_P nil means toggle the flag.  Otherwise, ON_P must be an integer,\n\
-and the flag is set according to the value of ON_P.  WINDOW nil or\n\
-omitted means use the selected window.  The new cursor state takes effect\n\
-with the next redisplay.")
-  (on_p, window)
-     Lisp_Object on_p, window;
+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)
+     Lisp_Object window, show;
 {
-  struct window *w;
-
   /* Don't change cursor state while redisplaying.  This could confuse
      output routines.  */
   if (!redisplaying_p)
@@ -5925,21 +6210,32 @@ with the next redisplay.")
        window = selected_window;
       else
        CHECK_WINDOW (window, 2);
-      w = XWINDOW (window);
       
-      if (NILP (on_p))
-       w->cursor_off_p = !w->cursor_off_p;
-      else
-       {
-         CHECK_NUMBER (on_p, 1);
-         w->cursor_off_p = XINT (on_p) != 0;
-       }
+      XWINDOW (window)->cursor_off_p = NILP (show);
     }
 
   return Qnil;
 }
 
 
+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)
+     Lisp_Object window;
+{
+  struct window *w;
+  
+  if (NILP (window))
+    window = selected_window;
+  else
+    CHECK_WINDOW (window, 2);
+  
+  w = XWINDOW (window);
+  return w->cursor_off_p ? Qnil : Qt;    
+}
+
 \f
 /***********************************************************************
                            Initialization
@@ -5956,13 +6252,16 @@ syms_of_display ()
   defsubr (&Ssit_for);
   defsubr (&Ssleep_for);
   defsubr (&Ssend_string_to_terminal);
-  defsubr (&Sshow_cursor);
+  defsubr (&Sinternal_show_cursor);
+  defsubr (&Sinternal_show_cursor_p);
 
   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\