]> code.delx.au - gnu-emacs/blobdiff - src/dispnew.c
Fix last change.
[gnu-emacs] / src / dispnew.c
index 14e4d968760a63dc2f844b2247596bad045d1b6d..dff5c91719df6370c92474170b3b6f2238440794 100644 (file)
@@ -1,5 +1,5 @@
 /* Updating of data structures for redisplay.
 /* 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
        Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
        Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
@@ -120,6 +120,8 @@ struct dim
 \f
 /* Function prototypes.  */
 
 \f
 /* Function prototypes.  */
 
+static void save_or_restore_current_matrix P_ ((struct frame *, int));
+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));
 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));
@@ -139,7 +141,7 @@ 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 *));
                                     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 *));
-#ifdef GLYPH_DEBUG
+#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 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));
@@ -185,7 +187,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));
 
 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
 \f
 /* Non-zero means don't pause redisplay for pending input.  (This is
    for debugging and for a future implementation of EDT-like
@@ -329,6 +330,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))
 
 #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 contructed.  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, "",
+   "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))
 #else /* GLYPH_DEBUG == 0 */
 
 #define WINDOW_TO_FRAME_VPOS(W, VPOS) ((VPOS) + XFASTINT ((W)->top))
@@ -525,7 +625,7 @@ 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 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.  */
   if (w)
 
   /* See if W had a top line that has disappeared now, or vice versa.  */
   if (w)
@@ -550,6 +650,7 @@ adjust_glyph_matrix (w, matrix, x, y, dim)
       if (!marginal_areas_changed_p
          && !fonts_changed_p
          && !header_line_changed_p
       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
          && matrix->window_top_y == XFASTINT (w->top)
          && matrix->window_height == window_height
          && matrix->window_vscroll == w->vscroll
@@ -679,12 +780,16 @@ adjust_glyph_matrix (w, matrix, x, y, dim)
      when this function runs.  */
   if (w && matrix == w->current_matrix)
     {
      when this function runs.  */
   if (w && matrix == w->current_matrix)
     {
+      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
       /* 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_left_x == XFASTINT (w->left)
          && matrix->window_top_y == XFASTINT (w->top)
          && matrix->window_top_y == XFASTINT (w->top)
-         && matrix->window_width == window_width)
+         && matrix->window_width == window_box_width (w, -1))
        {
          i = 0;
          while (matrix->rows[i].enabled_p
        {
          i = 0;
          while (matrix->rows[i].enabled_p
@@ -718,6 +823,7 @@ adjust_glyph_matrix (w, matrix, x, y, dim)
      was last adjusted.  This is used to optimize redisplay above.  */
   if (w)
     {
      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;
       matrix->window_top_y = XFASTINT (w->top);
       matrix->window_height = window_height;
       matrix->window_width = window_width;
@@ -976,12 +1082,13 @@ clear_window_matrices (w, desired_p)
    changes in the glyph_row structure, i.e. addition or removal of
    structure members.  */
 
    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];
 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];
 
   /* Save pointers.  */
   p[LEFT_MARGIN_AREA] = row->glyphs[LEFT_MARGIN_AREA];
@@ -1197,7 +1304,7 @@ assign_row (to, from)
    is non-zero if the glyph memory of WINDOW_ROW is part of the glyph
    memory of FRAME_ROW.  */
 
    is non-zero if the glyph memory of WINDOW_ROW is part of the glyph
    memory of FRAME_ROW.  */
 
-#ifdef GLYPH_DEBUG
+#if GLYPH_DEBUG
 
 static int
 glyph_row_slice_p (window_row, frame_row)
 
 static int
 glyph_row_slice_p (window_row, frame_row)
@@ -1316,7 +1423,7 @@ line_draw_cost (matrix, vpos)
   if (!must_write_spaces)
     {
       /* Skip from the end over trailing spaces.  */
   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.  */      
        --end;
 
       /* All blank line.  */      
@@ -1994,6 +2101,90 @@ 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;
+                 r->inverse_p = fr->inverse_p;
+               }
+           }
+       }
+    }
+}
+
+
+/* Save or restore the contents of frame F's current frame matrix.
+   SAVE_P non-zero means save it.  */
+
+static void
+save_or_restore_current_matrix (f, save_p)
+     struct frame *f;
+     int save_p;
+{
+  struct glyph_row *from, *to, *end;
+
+  if (save_p)
+    {
+      from = f->current_matrix->rows;
+      end = from + f->current_matrix->nrows;
+      to = f->desired_matrix->rows;
+    }
+  else
+    {
+      from = f->desired_matrix->rows;
+      end = from + f->desired_matrix->nrows;
+      to = f->current_matrix->rows;
+    }
+  
+  for (; from < end; ++from, ++to)
+    {
+      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];
+    }
+}
+
+
 /* Allocate/reallocate glyph matrices of a single frame F for
    frame-based redisplay.  */
 
 /* Allocate/reallocate glyph matrices of a single frame F for
    frame-based redisplay.  */
 
@@ -2029,7 +2220,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);
     }
       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
   /* 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
@@ -2067,12 +2258,31 @@ adjust_frame_glyphs_for_frame_redisplay (f)
   
       /* Resize frame matrices.  */
       adjust_glyph_matrix (NULL, f->desired_matrix, 0, 0, matrix_dim);
   
       /* 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)
+       {
+         save_or_restore_current_matrix (f, 1);
+         adjust_glyph_matrix (NULL, f->current_matrix, 0, 0, matrix_dim);
+         save_or_restore_current_matrix (f, 0);
+         fake_current_matrices (FRAME_ROOT_WINDOW (f));
+       }
+      else
+       {
+         adjust_glyph_matrix (NULL, f->current_matrix, 0, 0, matrix_dim);
+         SET_FRAME_GARBAGED (f);
+       }
     }
 }
 
     }
 }
 
@@ -2501,29 +2711,6 @@ build_frame_matrix_from_leaf_window (frame_matrix, w)
              SET_CHAR_GLYPH_FROM_GLYPH (*border, right_border_glyph);
            }
 
              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));
          /* Window row window_y must be a slice of frame row
             frame_y.  */
          xassert (glyph_row_slice_p (window_row, frame_row));
@@ -2533,6 +2720,7 @@ build_frame_matrix_from_leaf_window (frame_matrix, w)
          
 #if GLYPH_DEBUG
          strcpy (w->current_matrix->method, w->desired_matrix->method);
          
 #if GLYPH_DEBUG
          strcpy (w->current_matrix->method, w->desired_matrix->method);
+         add_window_display_history (w, w->current_matrix->method, 0);
 #endif
        }
 
 #endif
        }
 
@@ -3065,7 +3253,7 @@ DEFUN ("redraw-frame", Fredraw_frame, Sredraw_frame, 1, 1, 0,
     return Qnil;
 
   update_begin (f);
     return Qnil;
 
   update_begin (f);
-  if (FRAME_MSDOS_P (f))
+  if (FRAME_MSDOS_P (f) || FRAME_W32_CONSOLE_P (f))
     set_terminal_modes ();
   clear_frame ();
   clear_current_matrices (f);
     set_terminal_modes ();
   clear_frame ();
   clear_current_matrices (f);
@@ -3173,8 +3361,10 @@ direct_output_for_insert (g)
       || !display_completed
       /* Give up if buffer appears in two places.  */
       || buffer_shared > 1
       || !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))
       /* 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))
@@ -3551,13 +3741,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;
              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;
            }
        }
   
            }
        }
   
@@ -3590,7 +3773,10 @@ update_frame (f, force_p, inhibit_hairy_id_p)
       fflush (stdout);
 
       /* Check window matrices for lost pointers.  */
       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.  */
     }
 
   /* Reset flags indicating that a window should be updated.  */
@@ -3754,6 +3940,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.  */
 
 /* Update display of window W.  FORCE_P non-zero means that we should
    not stop when detecting pending input.  */
 
@@ -3766,6 +3977,7 @@ update_window (w, force_p)
   int paused_p;
   int preempt_count = baud_rate / 2400 + 1;
   extern int input_pending;
   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;
 #if GLYPH_DEBUG
   struct frame *f = XFRAME (WINDOW_FRAME (w));
   extern struct frame *updating_frame;
@@ -3783,12 +3995,12 @@ update_window (w, force_p)
 
   /* If forced to complete the update, or if no input is pending, do
      the update.  */
 
   /* 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;
     {
       struct glyph_row *row, *end;
       struct glyph_row *mode_line_row;
       struct glyph_row *header_line_row = NULL;
-      int yb, changed_p = 0, mouse_face_overwritten_p = 0;
+      int yb, changed_p = 0, mouse_face_overwritten_p = 0, n_updated;
 
       rif->update_window_begin_hook (w);
       yb = window_text_bottom_y (w);
 
       rif->update_window_begin_hook (w);
       yb = window_text_bottom_y (w);
@@ -3843,7 +4055,7 @@ update_window (w, force_p)
        }
 
       /* Update the rest of the lines.  */
        }
 
       /* Update the rest of the lines.  */
-      for (; row < end && (force_p || !input_pending); ++row)
+      for (n_updated = 0; row < end && (force_p || !input_pending); ++row)
        if (row->enabled_p)
          {
            int vpos = MATRIX_ROW_VPOS (row, desired_matrix);
        if (row->enabled_p)
          {
            int vpos = MATRIX_ROW_VPOS (row, desired_matrix);
@@ -3853,7 +4065,7 @@ update_window (w, force_p)
               detect_input_pending.  If it's done too often,
               scrolling large windows with repeated scroll-up
               commands will too quickly pause redisplay.  */
               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,
              detect_input_pending ();
 
            changed_p |= update_window_line (w, vpos,
@@ -3907,6 +4119,11 @@ update_window (w, force_p)
   else
     paused_p = 1;
 
   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;
   clear_glyph_matrix (desired_matrix);
 
   return paused_p;
@@ -3980,13 +4197,16 @@ 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 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 0 /* This shouldn't be necessary.  Let's check it.  */
       /* 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.  */
       /* 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;
+#endif
       
       stop = min (current_row->used[TEXT_AREA], desired_stop_pos);
       i = 0;
       
       stop = min (current_row->used[TEXT_AREA], desired_stop_pos);
       i = 0;
@@ -3994,35 +4214,59 @@ update_text_area (w, vpos)
       
       while (i < stop)
        {
       
       while (i < stop)
        {
+         int can_skip_p = 1;
+         
          /* Skip over glyphs that both rows have in common.  These
          /* 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;
              int left, right;
-             rif->get_glyph_overhangs (current_glyph, XFRAME (w->frame),
+             
+             rif->get_glyph_overhangs (glyph, XFRAME (w->frame),
                                        &left, &right);
                                        &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;
+                   }
                }
            }
          
                }
            }
          
@@ -4035,15 +4279,18 @@ update_text_area (w, vpos)
              int start_x = x, start_hpos = i;
              struct glyph *start = desired_glyph;
              int current_x = x;
              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
              /* 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;
                     && 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)
                }
 
              if (i == start_hpos || x != current_x)
@@ -4053,7 +4300,7 @@ update_text_area (w, vpos)
                  desired_glyph = start;
                  break;
                }
                  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;
              rif->cursor_to (vpos, start_hpos, desired_row->y, start_x);
              rif->write_glyphs (start, i - start_hpos);
              changed_p = 1;
@@ -4071,11 +4318,13 @@ update_text_area (w, vpos)
       /* Maybe clear to end of line.  */
       if (MATRIX_ROW_EXTENDS_FACE_P (desired_row))
        {
       /* Maybe clear to end of line.  */
       if (MATRIX_ROW_EXTENDS_FACE_P (desired_row))
        {
+#if 0 
          /* If new row extends to the end of the text area, nothing
             has to be cleared, if and only if we did a write_glyphs
             above.  This is made sure by setting desired_stop_pos
             appropriately above.  */
          xassert (i < desired_row->used[TEXT_AREA]);
          /* If new row extends to the end of the text area, nothing
             has to be cleared, if and only if we did a write_glyphs
             above.  This is made sure by setting desired_stop_pos
             appropriately above.  */
          xassert (i < desired_row->used[TEXT_AREA]);
+#endif
        }
       else if (MATRIX_ROW_EXTENDS_FACE_P (current_row))
        {
        }
       else if (MATRIX_ROW_EXTENDS_FACE_P (current_row))
        {
@@ -4471,9 +4720,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;
      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.  */
   last_old = i;
 
   /* Skip over rows equal at the bottom.  */
@@ -4619,7 +4874,7 @@ scrolling_window (w, header_line_p)
           case.  */
        for (j = 0; j < nruns && runs[j]->height > run->height; ++j)
          ;
           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;
          runs[k] = runs[k - 1];
        runs[j] = run;
        ++nruns;
@@ -4997,7 +5252,7 @@ count_blanks (r, len)
      int len;
 {
   int i;
      int len;
 {
   int i;
-
+  
   for (i = 0; i < len; ++i)
     if (!CHAR_GLYPH_SPACE_P (r[i]))
       break;
   for (i = 0; i < len; ++i)
     if (!CHAR_GLYPH_SPACE_P (r[i]))
       break;
@@ -5047,6 +5302,12 @@ update_frame_line (frame, vpos)
   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;
   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 (frame, DEFAULT_FACE_ID)->background
+                         != FACE_TTY_DEFAULT_BG_COLOR);
+
+  if (colored_spaces_p)
+    write_spaces_p = 1;
 
   if (desired_row->inverse_p
       != (current_row->enabled_p && current_row->inverse_p))
 
   if (desired_row->inverse_p
       != (current_row->enabled_p && current_row->inverse_p))
@@ -5071,10 +5332,10 @@ update_frame_line (frame, vpos)
       obody = MATRIX_ROW_GLYPH_START (current_matrix, vpos);
       olen = current_row->used[TEXT_AREA];
       
       obody = MATRIX_ROW_GLYPH_START (current_matrix, vpos);
       olen = current_row->used[TEXT_AREA];
       
-      if (! current_row->inverse_p)
+      if (!current_row->inverse_p)
        {
          /* Ignore trailing spaces, if we can.  */
        {
          /* Ignore trailing spaces, if we can.  */
-         if (!must_write_spaces)
+         if (!write_spaces_p)
            while (olen > 0 && CHAR_GLYPH_SPACE_P (obody[olen-1]))
              olen--;
        }
            while (olen > 0 && CHAR_GLYPH_SPACE_P (obody[olen-1]))
              olen--;
        }
@@ -5107,7 +5368,7 @@ update_frame_line (frame, vpos)
   if (must_write_whole_line_p)
     {
       /* Ignore spaces at the end, if we can.  */
   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;
 
        while (nlen > 0 && CHAR_GLYPH_SPACE_P (nbody[nlen - 1]))
          --nlen;
 
@@ -5139,7 +5400,7 @@ update_frame_line (frame, vpos)
      unless for one reason or another we must write all spaces.  */
   if (!desired_row->inverse_p)
     {
      unless for one reason or another we must write all spaces.  */
   if (!desired_row->inverse_p)
     {
-      if (!must_write_spaces)
+      if (!write_spaces_p)
        while (nlen > 0 && CHAR_GLYPH_SPACE_P (nbody[nlen - 1]))
          nlen--;
     }
        while (nlen > 0 && CHAR_GLYPH_SPACE_P (nbody[nlen - 1]))
          nlen--;
     }
@@ -5199,7 +5460,7 @@ update_frame_line (frame, vpos)
     {
       /* If current line is blank, skip over initial spaces, if
         possible, and write the rest.  */
     {
       /* 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 || desired_row->inverse_p)
        nsp = 0;
       else
        nsp = count_blanks (nbody, nlen);
        nsp = 0;
       else
        nsp = count_blanks (nbody, nlen);
@@ -5217,7 +5478,9 @@ update_frame_line (frame, vpos)
 
   /* Compute number of leading blanks in old and new contents.  */
   osp = count_blanks (obody, olen);
 
   /* 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 = (desired_row->inverse_p || 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,
 
   /* Compute number of matching chars starting with first non-blank.  */
   begmatch = count_match (obody + osp, obody + olen,
@@ -5225,7 +5488,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.  */
 
   /* 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]))
     {
       np1 = nbody + nsp;
       while (np1 + begmatch < nend && CHAR_GLYPH_SPACE_P (np1[begmatch]))
@@ -6255,6 +6518,10 @@ syms_of_display ()
   defsubr (&Sinternal_show_cursor);
   defsubr (&Sinternal_show_cursor_p);
 
   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);
 
   frame_and_buffer_state = Fmake_vector (make_number (20), Qlambda);
   staticpro (&frame_and_buffer_state);