]> code.delx.au - gnu-emacs/blobdiff - src/dispnew.c
2002-08-10 Andrew Choi <akochoi@shaw.ca>
[gnu-emacs] / src / dispnew.c
index e7df852bcf8e3118594ac394997484c858956074..1d9ae986a374ce7523cb7df2de37de08adc95d91 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, 2000
+   Copyright (C) 1985, 86, 87, 88, 93, 94, 95, 97, 98, 1999, 2000, 2001, 2002
        Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
        Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
@@ -60,9 +60,9 @@ Boston, MA 02111-1307, USA.  */
 #include "w32term.h"
 #endif /* HAVE_NTGUI */
 
 #include "w32term.h"
 #endif /* HAVE_NTGUI */
 
-#ifdef macintosh
+#ifdef MAC_OS
 #include "macterm.h"
 #include "macterm.h"
-#endif /* macintosh */
+#endif /* MAC_OS */
 
 /* Include systime.h after xterm.h to avoid double inclusion of time.h.  */
 
 
 /* Include systime.h after xterm.h to avoid double inclusion of time.h.  */
 
@@ -75,9 +75,6 @@ Boston, MA 02111-1307, USA.  */
 #include <unistd.h>
 #endif
 
 #include <unistd.h>
 #endif
 
-#define max(a, b) ((a) > (b) ? (a) : (b))
-#define min(a, b) ((a) < (b) ? (a) : (b))
-
 /* Get number of chars of output now in the buffer of a stdio stream.
    This ought to be built in in stdio, but it isn't.  Some s- files
    override this because their stdio internals differ.  */
 /* Get number of chars of output now in the buffer of a stdio stream.
    This ought to be built in in stdio, but it isn't.  Some s- files
    override this because their stdio internals differ.  */
@@ -104,7 +101,7 @@ Boston, MA 02111-1307, USA.  */
 #endif
 #endif /* not __GNU_LIBRARY__ */
 
 #endif
 #endif /* not __GNU_LIBRARY__ */
 
-#if defined (LINUX) && defined (HAVE_LIBNCURSES)
+#if defined(HAVE_TERM_H) && defined (GNU_LINUX) && defined (HAVE_LIBNCURSES)
 #include <term.h>              /* for tgetent */
 #endif
 \f
 #include <term.h>              /* for tgetent */
 #endif
 \f
@@ -120,7 +117,8 @@ struct dim
 \f
 /* Function prototypes.  */
 
 \f
 /* Function prototypes.  */
 
-static void save_or_restore_current_matrix P_ ((struct frame *, int));
+static struct glyph_matrix *save_current_matrix P_ ((struct frame *));
+static void restore_current_matrix P_ ((struct frame *, struct glyph_matrix *));
 static void fake_current_matrices P_ ((Lisp_Object));
 static void redraw_overlapping_rows P_ ((struct window *, int));
 static void redraw_overlapped_rows P_ ((struct window *, int));
 static 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));
@@ -130,9 +128,8 @@ static int count_match P_ ((struct glyph *, struct glyph *,
 static unsigned line_draw_cost P_ ((struct glyph_matrix *, int));
 static void update_frame_line P_ ((struct frame *, int));
 static struct dim allocate_matrices_for_frame_redisplay
 static unsigned line_draw_cost P_ ((struct glyph_matrix *, int));
 static void update_frame_line P_ ((struct frame *, int));
 static struct dim allocate_matrices_for_frame_redisplay
-     P_ ((Lisp_Object, int, int, struct dim, int, int *));
-static void allocate_matrices_for_window_redisplay P_ ((struct window *,
-                                                       struct dim));
+     P_ ((Lisp_Object, int, int, int, int *));
+static void allocate_matrices_for_window_redisplay P_ ((struct window *));
 static int realloc_glyph_pool P_ ((struct glyph_pool *, struct dim));
 static void adjust_frame_glyphs P_ ((struct frame *));
 struct glyph_matrix *new_glyph_matrix P_ ((struct glyph_pool *));
 static int realloc_glyph_pool P_ ((struct glyph_pool *, struct dim));
 static void adjust_frame_glyphs P_ ((struct frame *));
 struct glyph_matrix *new_glyph_matrix P_ ((struct glyph_pool *));
@@ -214,7 +211,7 @@ int inverse_video;
 
 /* Line speed of the terminal.  */
 
 
 /* Line speed of the terminal.  */
 
-int baud_rate;
+EMACS_INT baud_rate;
 
 /* Either nil or a symbol naming the window system under which Emacs
    is running.  */
 
 /* Either nil or a symbol naming the window system under which Emacs
    is running.  */
@@ -241,7 +238,7 @@ Lisp_Object Vglyph_table;
 Lisp_Object Vstandard_display_table;
 
 /* Nonzero means reading single-character input with prompt so put
 Lisp_Object Vstandard_display_table;
 
 /* Nonzero means reading single-character input with prompt so put
-   cursor on mini-buffer after the prompt.  positive means at end of
+   cursor on mini-buffer after the prompt.  Positive means at end of
    text in echo area; negative means at beginning of line.  */
 
 int cursor_in_echo_area;
    text in echo area; negative means at beginning of line.  */
 
 int cursor_in_echo_area;
@@ -361,7 +358,7 @@ 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
 
 /* 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 constructed.  PAUSED_P non-zero means that the update
    has been interrupted for pending input.  */
 
 static void
    has been interrupted for pending input.  */
 
 static void
@@ -382,7 +379,7 @@ add_window_display_history (w, msg, paused_p)
           w,
           ((BUFFERP (w->buffer)
             && STRINGP (XBUFFER (w->buffer)->name))
           w,
           ((BUFFERP (w->buffer)
             && STRINGP (XBUFFER (w->buffer)->name))
-           ? (char *) XSTRING (XBUFFER (w->buffer)->name)->data
+           ? (char *) SDATA (XBUFFER (w->buffer)->name)
            : "???"),
           paused_p ? " ***paused***" : "");
   strcat (buf, msg);
            : "???"),
           paused_p ? " ***paused***" : "");
   strcat (buf, msg);
@@ -413,7 +410,7 @@ add_frame_display_history (f, paused_p)
 
 DEFUN ("dump-redisplay-history", Fdump_redisplay_history,
        Sdump_redisplay_history, 0, 0, "",
 
 DEFUN ("dump-redisplay-history", Fdump_redisplay_history,
        Sdump_redisplay_history, 0, 0, "",
-   "Dump redisplay history to stderr.")
+       doc: /* Dump redisplay history to stderr.  */)
      ()
 {
   int i;
      ()
 {
   int i;
@@ -443,7 +440,8 @@ DEFUN ("dump-redisplay-history", Fdump_redisplay_history,
 
 void
 safe_bcopy (from, to, size)
 
 void
 safe_bcopy (from, to, size)
-     char *from, *to;
+     const char *from;
+     char *to;
      int size;
 {
   if (size <= 0 || from == to)
      int size;
 {
   if (size <= 0 || from == to)
@@ -458,7 +456,7 @@ safe_bcopy (from, to, size)
   /* Otherwise, we'll copy from the end.  */
   else
     {
   /* Otherwise, we'll copy from the end.  */
   else
     {
-      register char *endf = from + size;
+      register const char *endf = from + size;
       register char *endt = to + size;
 
       /* If TO - FROM is large, then we should break the copy into
       register char *endt = to + size;
 
       /* If TO - FROM is large, then we should break the copy into
@@ -627,7 +625,7 @@ adjust_glyph_matrix (w, matrix, x, y, dim)
   int left = -1, right = -1;
   int window_x, window_y, window_width = -1, window_height;
 
   int left = -1, right = -1;
   int window_x, window_y, window_width = -1, window_height;
 
-  /* See if W had a top line that has disappeared now, or vice versa.  */
+  /* See if W had a header line that has disappeared now, or vice versa.  */
   if (w)
     {
       header_line_p = WINDOW_WANTS_HEADER_LINE_P (w);
   if (w)
     {
       header_line_p = WINDOW_WANTS_HEADER_LINE_P (w);
@@ -774,44 +772,62 @@ adjust_glyph_matrix (w, matrix, x, y, dim)
   matrix->nrows = dim.height;
   xassert (matrix->nrows >= 0);
 
   matrix->nrows = dim.height;
   xassert (matrix->nrows >= 0);
 
-  /* Mark rows in a current matrix of a window as not having valid
-     contents.  It's important to not do this for desired matrices.
-     When Emacs starts, it may already be building desired matrices
-     when this function runs.  */
-  if (w && matrix == w->current_matrix)
+  if (w)
     {
     {
-      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
-         && matrix->window_left_x == XFASTINT (w->left)
-         && matrix->window_top_y == XFASTINT (w->top)
-         && matrix->window_width == window_box_width (w, -1))
+      if (matrix == w->current_matrix)
        {
        {
-         i = 0;
-         while (matrix->rows[i].enabled_p
-                && (MATRIX_ROW_BOTTOM_Y (matrix->rows + i)
-                    < matrix->window_height))
-           ++i;
-
-         /* Window end is invalid, if inside of the rows that
-            are invalidated.  */
-         if (INTEGERP (w->window_end_vpos)
-             && XFASTINT (w->window_end_vpos) >= i)
-           w->window_end_valid = Qnil;
+         /* Mark rows in a current matrix of a window as not having
+            valid contents.  It's important to not do this for
+            desired matrices.  When Emacs starts, it may already be
+            building desired matrices when this function runs.  */
+         if (window_width < 0)
+           window_width = window_box_width (w, -1);
+      
+         /* Optimize the case that only the height has changed (C-x 2,
+            upper window).  Invalidate all rows that are no longer part
+            of the window.  */
+         if (!marginal_areas_changed_p
+             && !header_line_changed_p
+             && new_rows == 0
+             && dim.width == matrix->matrix_w
+             && matrix->window_left_x == XFASTINT (w->left)
+             && matrix->window_top_y == XFASTINT (w->top)
+             && matrix->window_width == window_width)
+           {
+             /* Find the last row in the window.  */
+             for (i = 0; i < matrix->nrows && matrix->rows[i].enabled_p; ++i)
+               if (MATRIX_ROW_BOTTOM_Y (matrix->rows + i) >= window_height)
+                 {
+                   ++i;
+                   break;
+                 }
+
+             /* Window end is invalid, if inside of the rows that
+                are invalidated below.  */
+             if (INTEGERP (w->window_end_vpos)
+                 && XFASTINT (w->window_end_vpos) >= i)
+               w->window_end_valid = Qnil;
          
          
-         while (i < matrix->nrows)
-           matrix->rows[i++].enabled_p = 0;
+             while (i < matrix->nrows)
+               matrix->rows[i++].enabled_p = 0;
+           }
+         else
+           {
+             for (i = 0; i < matrix->nrows; ++i)
+               matrix->rows[i].enabled_p = 0;
+           }
        }
        }
-      else
+      else if (matrix == w->desired_matrix)
        {
        {
+         /* Rows in desired matrices always have to be cleared;
+            redisplay expects this is the case when it runs, so it
+            had better be the case when we adjust matrices between
+            redisplays.  */
          for (i = 0; i < matrix->nrows; ++i)
            matrix->rows[i].enabled_p = 0;
        }
     }
          for (i = 0; i < matrix->nrows; ++i)
            matrix->rows[i].enabled_p = 0;
        }
     }
+    
   
   /* Remember last values to be able to optimize frame redraws.  */
   matrix->matrix_x = x;
   
   /* Remember last values to be able to optimize frame redraws.  */
   matrix->matrix_x = x;
@@ -975,13 +991,12 @@ shift_glyph_matrix (w, matrix, start, end, dy)
       struct glyph_row *row = &matrix->rows[start];
       
       row->y += dy;
       struct glyph_row *row = &matrix->rows[start];
       
       row->y += dy;
+      row->visible_height = row->height;
       
       if (row->y < min_y)
       
       if (row->y < min_y)
-       row->visible_height = row->height - (min_y - row->y);
-      else if (row->y + row->height > max_y)
-       row->visible_height = row->height - (row->y + row->height - max_y);
-      else
-       row->visible_height = row->height;
+       row->visible_height -= min_y - row->y;
+      if (row->y + row->height > max_y)
+       row->visible_height -= row->y + row->height - max_y;
     }
 }
 
     }
 }
 
@@ -1110,7 +1125,7 @@ clear_glyph_row (row)
         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
         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
+        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
         are that the flickering has the same reason as here.  */
   bzero (p[0], (char *) p[LAST_AREA] - (char *) p[0]);
 #endif
@@ -1135,13 +1150,12 @@ blank_row (w, row, y)
   row->y = y;
   row->ascent = row->phys_ascent = 0;
   row->height = row->phys_height = CANON_Y_UNIT (XFRAME (w->frame));
   row->y = y;
   row->ascent = row->phys_ascent = 0;
   row->height = row->phys_height = CANON_Y_UNIT (XFRAME (w->frame));
-  
+  row->visible_height = row->height;
+      
   if (row->y < min_y)
   if (row->y < min_y)
-    row->visible_height = row->height - (min_y - row->y);
-  else if (row->y + row->height > max_y)
-    row->visible_height = row->height - (row->y + row->height - max_y);
-  else
-    row->visible_height = row->height;
+    row->visible_height -= min_y - row->y;
+  if (row->y + row->height > max_y)
+    row->visible_height -= row->y + row->height - max_y;
 
   row->enabled_p = 1;
 }
 
   row->enabled_p = 1;
 }
@@ -1372,38 +1386,29 @@ line_hash_code (row)
   
   if (row->enabled_p)
     {
   
   if (row->enabled_p)
     {
-      if (row->inverse_p)
-        {
-          /* Give all highlighted lines the same hash code
-            so as to encourage scrolling to leave them in place.  */
-          hash = -1;
-        }
-      else
-        {
-          struct glyph *glyph = row->glyphs[TEXT_AREA];
-         struct glyph *end = glyph + row->used[TEXT_AREA];
-
-          while (glyph < end)
-            {
-             int c = glyph->u.ch;
-             int face_id = glyph->face_id;
-             if (must_write_spaces)
-               c -= SPACEGLYPH;
-             hash = (((hash << 4) + (hash >> 24)) & 0x0fffffff) + c;
-             hash = (((hash << 4) + (hash >> 24)) & 0x0fffffff) + face_id;
-             ++glyph;
-           }
+      struct glyph *glyph = row->glyphs[TEXT_AREA];
+      struct glyph *end = glyph + row->used[TEXT_AREA];
 
 
-          if (hash == 0)
-           hash = 1;
-        }
+      while (glyph < end)
+       {
+         int c = glyph->u.ch;
+         int face_id = glyph->face_id;
+         if (must_write_spaces)
+           c -= SPACEGLYPH;
+         hash = (((hash << 4) + (hash >> 24)) & 0x0fffffff) + c;
+         hash = (((hash << 4) + (hash >> 24)) & 0x0fffffff) + face_id;
+         ++glyph;
+       }
+
+      if (hash == 0)
+       hash = 1;
     }
 
   return hash;
 }
 
 
     }
 
   return hash;
 }
 
 
-/* Return the cost of drawing line VPOS In MATRIX.  The cost equals
+/* Return the cost of drawing line VPOS in MATRIX.  The cost equals
    the number of characters in the line.  If must_write_spaces is
    zero, leading and trailing spaces are ignored.  */
 
    the number of characters in the line.  If must_write_spaces is
    zero, leading and trailing spaces are ignored.  */
 
@@ -1505,7 +1510,6 @@ row_equal_p (w, a, b, mouse_face_p)
        }
 
       if (a->truncated_on_left_p != b->truncated_on_left_p
        }
 
       if (a->truncated_on_left_p != b->truncated_on_left_p
-         || a->inverse_p != b->inverse_p
          || a->fill_line_p != b->fill_line_p
          || a->truncated_on_right_p != b->truncated_on_right_p
          || a->overlay_arrow_p != b->overlay_arrow_p
          || a->fill_line_p != b->fill_line_p
          || a->truncated_on_right_p != b->truncated_on_right_p
          || a->overlay_arrow_p != b->overlay_arrow_p
@@ -1568,7 +1572,7 @@ free_glyph_pool (pool)
 {
   if (pool)
     {
 {
   if (pool)
     {
-      /* More freed than allocated? */
+      /* More freed than allocated?  */
       --glyph_pool_count;
       xassert (glyph_pool_count >= 0);
 
       --glyph_pool_count;
       xassert (glyph_pool_count >= 0);
 
@@ -1616,7 +1620,7 @@ realloc_glyph_pool (pool, matrix_dim)
       pool->nglyphs = needed;
     }
 
       pool->nglyphs = needed;
     }
 
-  /* Remember the number of rows and columns because (a) we use then
+  /* Remember the number of rows and columns because (a) we use them
      to do sanity checks, and (b) the number of columns determines
      where rows in the frame matrix start---this must be available to
      determine pointers to rows of window sub-matrices.  */
      to do sanity checks, and (b) the number of columns determines
      where rows in the frame matrix start---this must be available to
      determine pointers to rows of window sub-matrices.  */
@@ -1779,7 +1783,7 @@ check_matrix_invariants (w)
 
    CHANGED_LEAF_MATRIX set if the dimension or location of a matrix of
    any window in the tree will be changed or have been changed (see
 
    CHANGED_LEAF_MATRIX set if the dimension or location of a matrix of
    any window in the tree will be changed or have been changed (see
-   DIM_ONLY_P).
+   DIM_ONLY_P)
 
    *WINDOW_CHANGE_FLAGS must be initialized by the caller of this
    function.
 
    *WINDOW_CHANGE_FLAGS must be initialized by the caller of this
    function.
@@ -1840,11 +1844,10 @@ check_matrix_invariants (w)
 #define CHANGED_LEAF_MATRIX    (1 << 1)
 
 static struct dim
 #define CHANGED_LEAF_MATRIX    (1 << 1)
 
 static struct dim
-allocate_matrices_for_frame_redisplay (window, x, y, ch_dim,
-                                      dim_only_p, window_change_flags)
+allocate_matrices_for_frame_redisplay (window, x, y, dim_only_p,
+                                      window_change_flags)
      Lisp_Object window;
      int x, y;
      Lisp_Object window;
      int x, y;
-     struct dim ch_dim;
      int dim_only_p;
      int *window_change_flags;
 {
      int dim_only_p;
      int *window_change_flags;
 {
@@ -1872,13 +1875,13 @@ allocate_matrices_for_frame_redisplay (window, x, y, ch_dim,
       w = XWINDOW (window);
 
       /* Get the dimension of the window sub-matrix for W, depending
       w = XWINDOW (window);
 
       /* Get the dimension of the window sub-matrix for W, depending
-        on whether this a combination or a leaf window.  */
+        on whether this is a combination or a leaf window.  */
       if (!NILP (w->hchild))
       if (!NILP (w->hchild))
-       dim = allocate_matrices_for_frame_redisplay (w->hchild, x, y, ch_dim,
+       dim = allocate_matrices_for_frame_redisplay (w->hchild, x, y, 
                                                     dim_only_p,
                                                     window_change_flags);
       else if (!NILP (w->vchild))
                                                     dim_only_p,
                                                     window_change_flags);
       else if (!NILP (w->vchild))
-       dim = allocate_matrices_for_frame_redisplay (w->vchild, x, y, ch_dim,
+       dim = allocate_matrices_for_frame_redisplay (w->vchild, x, y, 
                                                     dim_only_p,
                                                     window_change_flags);
       else
                                                     dim_only_p,
                                                     window_change_flags);
       else
@@ -1893,8 +1896,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.  */
   
          /* Width and height MUST be chosen so that there are no
             holes in the frame matrix.  */
-         dim.width = XINT (w->width);
-         dim.height = XINT (w->height);
+         dim.width = required_matrix_width (w);
+         dim.height = required_matrix_height (w);
 
          /* Will matrix be re-allocated?  */
          if (x != w->desired_matrix->matrix_x
 
          /* Will matrix be re-allocated?  */
          if (x != w->desired_matrix->matrix_x
@@ -1959,28 +1962,78 @@ allocate_matrices_for_frame_redisplay (window, x, y, ch_dim,
 }
 
 
 }
 
 
+/* Return the required height of glyph matrices for window W.  */
+
+int
+required_matrix_height (w)
+     struct window *w;
+{
+#ifdef HAVE_WINDOW_SYSTEM
+  struct frame *f = XFRAME (w->frame);
+  
+  if (FRAME_WINDOW_P (f))
+    {
+      int ch_height = FRAME_SMALLEST_FONT_HEIGHT (f);
+      int window_pixel_height = window_box_height (w) + abs (w->vscroll);
+      return (((window_pixel_height + ch_height - 1)
+              / ch_height)
+             /* One partially visible line at the top and
+                bottom of the window.  */
+             + 2
+             /* 2 for header and mode line.  */
+             + 2);
+    }
+#endif /* HAVE_WINDOW_SYSTEM */
+      
+  return XINT (w->height);
+}
+
+
+/* Return the required width of glyph matrices for window W.  */
+
+int
+required_matrix_width (w)
+     struct window *w;
+{
+#ifdef HAVE_WINDOW_SYSTEM
+  struct frame *f = XFRAME (w->frame);
+  if (FRAME_WINDOW_P (f))
+    {
+      int ch_width = FRAME_SMALLEST_CHAR_WIDTH (f);
+      int window_pixel_width = XFLOATINT (w->width) * CANON_X_UNIT (f);
+  
+      /* Compute number of glyphs needed in a glyph row.  */
+      return (((window_pixel_width + ch_width - 1)
+              / ch_width)
+             /* 2 partially visible columns in the text area.  */
+             + 2
+             /* One partially visible column at the right
+                edge of each marginal area.  */
+             + 1 + 1);
+    }
+#endif /* HAVE_WINDOW_SYSTEM */
+
+  return XINT (w->width);
+}
+
+
 /* Allocate window matrices for window-based redisplay.  W is the
    window whose matrices must be allocated/reallocated.  CH_DIM is the
    size of the smallest character that could potentially be used on W.  */
    
 static void
 /* Allocate window matrices for window-based redisplay.  W is the
    window whose matrices must be allocated/reallocated.  CH_DIM is the
    size of the smallest character that could potentially be used on W.  */
    
 static void
-allocate_matrices_for_window_redisplay (w, ch_dim)
+allocate_matrices_for_window_redisplay (w)
      struct window *w;
      struct window *w;
-     struct dim ch_dim;
 {
 {
-  struct frame *f = XFRAME (w->frame);
-  
   while (w)
     {
       if (!NILP (w->vchild))
   while (w)
     {
       if (!NILP (w->vchild))
-       allocate_matrices_for_window_redisplay (XWINDOW (w->vchild), ch_dim);
+       allocate_matrices_for_window_redisplay (XWINDOW (w->vchild));
       else if (!NILP (w->hchild))
       else if (!NILP (w->hchild))
-       allocate_matrices_for_window_redisplay (XWINDOW (w->hchild), ch_dim);
+       allocate_matrices_for_window_redisplay (XWINDOW (w->hchild));
       else
        {
          /* W is a leaf window.  */
       else
        {
          /* W is a leaf window.  */
-         int window_pixel_width = XFLOATINT (w->width) * CANON_X_UNIT (f);
-         int window_pixel_height = window_box_height (w) + abs (w->vscroll);
          struct dim dim;
 
          /* If matrices are not yet allocated, allocate them now.  */
          struct dim dim;
 
          /* If matrices are not yet allocated, allocate them now.  */
@@ -1990,25 +2043,8 @@ allocate_matrices_for_window_redisplay (w, ch_dim)
              w->current_matrix = new_glyph_matrix (NULL);
            }
 
              w->current_matrix = new_glyph_matrix (NULL);
            }
 
-         /* Compute number of glyphs needed in a glyph row.  */
-         dim.width = (((window_pixel_width + ch_dim.width - 1)
-                       / ch_dim.width)
-                      /* 2 partially visible columns in the text area.  */
-                      + 2
-                      /* One partially visible column at the right
-                         edge of each marginal area.  */
-                      + 1 + 1);
-
-         /* Compute number of glyph rows needed.  */
-         dim.height = (((window_pixel_height + ch_dim.height - 1)
-                        / ch_dim.height)
-                       /* One partially visible line at the top and
-                          bottom of the window.  */
-                       + 2
-                       /* 2 for top and mode line.  */
-                       + 2);
-
-         /* Change matrices.  */
+         dim.width = required_matrix_width (w);
+         dim.height = required_matrix_height (w);
          adjust_glyph_matrix (w, w->desired_matrix, 0, 0, dim);
          adjust_glyph_matrix (w, w->current_matrix, 0, 0, dim);
        }
          adjust_glyph_matrix (w, w->desired_matrix, 0, 0, dim);
          adjust_glyph_matrix (w, w->current_matrix, 0, 0, dim);
        }
@@ -2145,7 +2181,6 @@ fake_current_matrices (window)
                                        - r->used[LEFT_MARGIN_AREA]
                                        - r->used[RIGHT_MARGIN_AREA]);
                  r->mode_line_p = 0;
                                        - r->used[LEFT_MARGIN_AREA]
                                        - r->used[RIGHT_MARGIN_AREA]);
                  r->mode_line_p = 0;
-                 r->inverse_p = fr->inverse_p;
                }
            }
        }
                }
            }
        }
@@ -2153,38 +2188,63 @@ fake_current_matrices (window)
 }
 
 
 }
 
 
-/* Save or restore the contents of frame F's current frame matrix.
-   SAVE_P non-zero means save it.  */
+/* Save away the contents of frame F's current frame matrix.  Value is
+   a glyph matrix holding the contents of F's current frame matrix.  */
 
 
-static void
-save_or_restore_current_matrix (f, save_p)
+static struct glyph_matrix *
+save_current_matrix (f)
      struct frame *f;
      struct frame *f;
-     int save_p;
 {
 {
-  struct glyph_row *from, *to, *end;
+  int i;
+  struct glyph_matrix *saved;
 
 
-  if (save_p)
-    {
-      from = f->current_matrix->rows;
-      end = from + f->current_matrix->nrows;
-      to = f->desired_matrix->rows;
-    }
-  else
+  saved = (struct glyph_matrix *) xmalloc (sizeof *saved);
+  bzero (saved, sizeof *saved);
+  saved->nrows = f->current_matrix->nrows;
+  saved->rows = (struct glyph_row *) xmalloc (saved->nrows
+                                             * sizeof *saved->rows);
+  bzero (saved->rows, saved->nrows * sizeof *saved->rows);
+
+  for (i = 0; i < saved->nrows; ++i)
     {
     {
-      from = f->desired_matrix->rows;
-      end = from + f->desired_matrix->nrows;
-      to = f->current_matrix->rows;
+      struct glyph_row *from = f->current_matrix->rows + i;
+      struct glyph_row *to = saved->rows + i;
+      size_t nbytes = from->used[TEXT_AREA] * sizeof (struct glyph);
+      to->glyphs[TEXT_AREA] = (struct glyph *) xmalloc (nbytes);
+      bcopy (from->glyphs[TEXT_AREA], to->glyphs[TEXT_AREA], nbytes);
+      to->used[TEXT_AREA] = from->used[TEXT_AREA];
     }
     }
-  
-  for (; from < end; ++from, ++to)
+
+  return saved;
+}
+
+
+/* Restore the contents of frame F's current frame matrix from SAVED,
+   and free memory associated with SAVED.  */
+
+static void
+restore_current_matrix (f, saved)
+     struct frame *f;
+     struct glyph_matrix *saved;
+{
+  int i;
+
+  for (i = 0; i < saved->nrows; ++i)
     {
     {
+      struct glyph_row *from = saved->rows + i;
+      struct glyph_row *to = f->current_matrix->rows + i;
       size_t nbytes = from->used[TEXT_AREA] * sizeof (struct glyph);
       bcopy (from->glyphs[TEXT_AREA], to->glyphs[TEXT_AREA], nbytes);
       to->used[TEXT_AREA] = from->used[TEXT_AREA];
       size_t nbytes = from->used[TEXT_AREA] * sizeof (struct glyph);
       bcopy (from->glyphs[TEXT_AREA], to->glyphs[TEXT_AREA], nbytes);
       to->used[TEXT_AREA] = from->used[TEXT_AREA];
+      xfree (from->glyphs[TEXT_AREA]);
     }
     }
+  
+  xfree (saved->rows);
+  xfree (saved);
 }
 
 
 }
 
 
+
 /* Allocate/reallocate glyph matrices of a single frame F for
    frame-based redisplay.  */
 
 /* Allocate/reallocate glyph matrices of a single frame F for
    frame-based redisplay.  */
 
@@ -2231,7 +2291,7 @@ adjust_frame_glyphs_for_frame_redisplay (f)
   matrix_dim
     = allocate_matrices_for_frame_redisplay (FRAME_ROOT_WINDOW (f),
                                             0, top_window_y,
   matrix_dim
     = allocate_matrices_for_frame_redisplay (FRAME_ROOT_WINDOW (f),
                                             0, top_window_y,
-                                            ch_dim, 1,
+                                            1,
                                             &window_change_flags);
 
   /* Add in menu bar lines, if any.  */
                                             &window_change_flags);
 
   /* Add in menu bar lines, if any.  */
@@ -2247,7 +2307,7 @@ adjust_frame_glyphs_for_frame_redisplay (f)
     {
       /* Do it for window matrices.  */
       allocate_matrices_for_frame_redisplay (FRAME_ROOT_WINDOW (f),
     {
       /* Do it for window matrices.  */
       allocate_matrices_for_frame_redisplay (FRAME_ROOT_WINDOW (f),
-                                            0, top_window_y, ch_dim, 0,
+                                            0, top_window_y, 0,
                                             &window_change_flags);
 
       /* Size of frame matrices must equal size of frame.  Note
                                             &window_change_flags);
 
       /* Size of frame matrices must equal size of frame.  Note
@@ -2256,9 +2316,6 @@ adjust_frame_glyphs_for_frame_redisplay (f)
       xassert (matrix_dim.width == FRAME_WIDTH (f)
               && matrix_dim.height == FRAME_HEIGHT (f));
   
       xassert (matrix_dim.width == FRAME_WIDTH (f)
               && matrix_dim.height == FRAME_HEIGHT (f));
   
-      /* Resize frame matrices.  */
-      adjust_glyph_matrix (NULL, f->desired_matrix, 0, 0, matrix_dim);
-
       /* 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
       /* 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
@@ -2273,13 +2330,15 @@ adjust_frame_glyphs_for_frame_redisplay (f)
          && matrix_dim.width == f->current_matrix->matrix_w
          && matrix_dim.height == f->current_matrix->matrix_h)
        {
          && matrix_dim.width == f->current_matrix->matrix_w
          && matrix_dim.height == f->current_matrix->matrix_h)
        {
-         save_or_restore_current_matrix (f, 1);
+         struct glyph_matrix *copy = save_current_matrix (f);
+         adjust_glyph_matrix (NULL, f->desired_matrix, 0, 0, matrix_dim);
          adjust_glyph_matrix (NULL, f->current_matrix, 0, 0, matrix_dim);
          adjust_glyph_matrix (NULL, f->current_matrix, 0, 0, matrix_dim);
-         save_or_restore_current_matrix (f, 0);
+         restore_current_matrix (f, copy);
          fake_current_matrices (FRAME_ROOT_WINDOW (f));
        }
       else
        {
          fake_current_matrices (FRAME_ROOT_WINDOW (f));
        }
       else
        {
+         adjust_glyph_matrix (NULL, f->desired_matrix, 0, 0, matrix_dim);
          adjust_glyph_matrix (NULL, f->current_matrix, 0, 0, matrix_dim);
          SET_FRAME_GARBAGED (f);
        }
          adjust_glyph_matrix (NULL, f->current_matrix, 0, 0, matrix_dim);
          SET_FRAME_GARBAGED (f);
        }
@@ -2308,8 +2367,7 @@ adjust_frame_glyphs_for_window_redisplay (f)
 #endif
     
   /* Allocate/reallocate window matrices.  */
 #endif
     
   /* Allocate/reallocate window matrices.  */
-  allocate_matrices_for_window_redisplay (XWINDOW (FRAME_ROOT_WINDOW (f)),
-                                         ch_dim);
+  allocate_matrices_for_window_redisplay (XWINDOW (FRAME_ROOT_WINDOW (f)));
 
   /* Allocate/ reallocate matrices of the dummy window used to display
      the menu bar under X when no X toolkit support is available.  */
 
   /* Allocate/ reallocate matrices of the dummy window used to display
      the menu bar under X when no X toolkit support is available.  */
@@ -2332,7 +2390,7 @@ adjust_frame_glyphs_for_window_redisplay (f)
     XSETFASTINT (w->left, 0);
     XSETFASTINT (w->height, FRAME_MENU_BAR_LINES (f));
     XSETFASTINT (w->width, FRAME_WINDOW_WIDTH (f));
     XSETFASTINT (w->left, 0);
     XSETFASTINT (w->height, FRAME_MENU_BAR_LINES (f));
     XSETFASTINT (w->width, FRAME_WINDOW_WIDTH (f));
-    allocate_matrices_for_window_redisplay (w, ch_dim);
+    allocate_matrices_for_window_redisplay (w);
   }
 #endif /* not USE_X_TOOLKIT */
 
   }
 #endif /* not USE_X_TOOLKIT */
 
@@ -2352,7 +2410,7 @@ adjust_frame_glyphs_for_window_redisplay (f)
   XSETFASTINT (w->left, 0);
   XSETFASTINT (w->height, FRAME_TOOL_BAR_LINES (f));
   XSETFASTINT (w->width, FRAME_WINDOW_WIDTH (f));
   XSETFASTINT (w->left, 0);
   XSETFASTINT (w->height, FRAME_TOOL_BAR_LINES (f));
   XSETFASTINT (w->width, FRAME_WINDOW_WIDTH (f));
-  allocate_matrices_for_window_redisplay (w, ch_dim);
+  allocate_matrices_for_window_redisplay (w);
 }
 
 
 }
 
 
@@ -2730,9 +2788,6 @@ build_frame_matrix_from_leaf_window (frame_matrix, w)
       frame_row->used[TEXT_AREA] 
        = window_matrix->matrix_x + window_matrix->matrix_w;
 
       frame_row->used[TEXT_AREA] 
        = window_matrix->matrix_x + window_matrix->matrix_w;
 
-      /* Or in other flags.  */
-      frame_row->inverse_p |= window_row->inverse_p;
-
       /* Next row.  */
       ++window_y;
       ++frame_y;
       /* Next row.  */
       ++window_y;
       ++frame_y;
@@ -2943,7 +2998,7 @@ mirrored_line_dance (matrix, unchanged_at_top, nlines, copy_from,
        new_rows[i].enabled_p = 0;
     }
 
        new_rows[i].enabled_p = 0;
     }
 
-  /* Do the same for window matrices, if MATRIX Is a frame matrix.  */
+  /* Do the same for window matrices, if MATRIX is a frame matrix.  */
   if (frame_matrix_frame)
     mirror_line_dance (XWINDOW (frame_matrix_frame->root_window),
                       unchanged_at_top, nlines, copy_from, retained_p);
   if (frame_matrix_frame)
     mirror_line_dance (XWINDOW (frame_matrix_frame->root_window),
                       unchanged_at_top, nlines, copy_from, retained_p);
@@ -2951,8 +3006,7 @@ mirrored_line_dance (matrix, unchanged_at_top, nlines, copy_from,
 
 
 /* Synchronize glyph pointers in the current matrix of window W with
 
 
 /* Synchronize glyph pointers in the current matrix of window W with
-   the current frame matrix.  W must be full-width, and be on a tty
-   frame.  */
+   the current frame matrix.  */
 
 static void
 sync_window_with_frame_matrix_rows (w)
 
 static void
 sync_window_with_frame_matrix_rows (w)
@@ -2960,27 +3014,31 @@ sync_window_with_frame_matrix_rows (w)
 {
   struct frame *f = XFRAME (w->frame);
   struct glyph_row *window_row, *window_row_end, *frame_row;
 {
   struct frame *f = XFRAME (w->frame);
   struct glyph_row *window_row, *window_row_end, *frame_row;
+  int left, right, x, width;
 
 
-  /* Preconditions: W must be a leaf window and full-width.  Its frame
-     must have a frame matrix.  */
+  /* Preconditions: W must be a leaf window on a tty frame.  */
   xassert (NILP (w->hchild) && NILP (w->vchild));
   xassert (NILP (w->hchild) && NILP (w->vchild));
-  xassert (WINDOW_FULL_WIDTH_P (w));
   xassert (!FRAME_WINDOW_P (f));
 
   xassert (!FRAME_WINDOW_P (f));
 
-  /* If W is a full-width window, glyph pointers in W's current matrix
-     have, by definition, to be the same as glyph pointers in the
-     corresponding frame matrix.  */
+  left = margin_glyphs_to_reserve (w, 1, w->left_margin_width);
+  right = margin_glyphs_to_reserve (w, 1, w->right_margin_width);
+  x = w->current_matrix->matrix_x;
+  width = w->current_matrix->matrix_w;
+
   window_row = w->current_matrix->rows;
   window_row_end = window_row + w->current_matrix->nrows;
   frame_row = f->current_matrix->rows + XFASTINT (w->top);
   window_row = w->current_matrix->rows;
   window_row_end = window_row + w->current_matrix->nrows;
   frame_row = f->current_matrix->rows + XFASTINT (w->top);
-  while (window_row < window_row_end)
+  
+  for (; window_row < window_row_end; ++window_row, ++frame_row)
     {
     {
-      int area;
-      
-      for (area = LEFT_MARGIN_AREA; area <= LAST_AREA; ++area)
-       window_row->glyphs[area] = frame_row->glyphs[area];
-
-      ++window_row, ++frame_row;
+      window_row->glyphs[LEFT_MARGIN_AREA]
+       = frame_row->glyphs[0] + x;
+      window_row->glyphs[TEXT_AREA]
+       = window_row->glyphs[LEFT_MARGIN_AREA] + left;
+      window_row->glyphs[LAST_AREA]
+       = window_row->glyphs[LEFT_MARGIN_AREA] + width;
+      window_row->glyphs[RIGHT_MARGIN_AREA]
+       = window_row->glyphs[LAST_AREA] - right;
     }
 }
 
     }
 }
 
@@ -3214,7 +3272,7 @@ window_to_frame_vpos (w, vpos)
 
 
 /* Translate horizontal position HPOS which is relative to window W to
 
 
 /* Translate horizontal position HPOS which is relative to window W to
-   a vertical position relative to W's frame.  */
+   a horizontal position relative to W's frame.  */
 
 static int
 window_to_frame_hpos (w, hpos)
 
 static int
 window_to_frame_hpos (w, hpos)
@@ -3237,13 +3295,13 @@ window_to_frame_hpos (w, hpos)
  **********************************************************************/
 
 DEFUN ("redraw-frame", Fredraw_frame, Sredraw_frame, 1, 1, 0,
  **********************************************************************/
 
 DEFUN ("redraw-frame", Fredraw_frame, Sredraw_frame, 1, 1, 0,
-  "Clear frame FRAME and output again what is supposed to appear on it.")
-  (frame)
+       doc: /* Clear frame FRAME and output again what is supposed to appear on it.  */)
+     (frame)
      Lisp_Object frame;
 {
   struct frame *f;
 
      Lisp_Object frame;
 {
   struct frame *f;
 
-  CHECK_LIVE_FRAME (frame, 0);
+  CHECK_LIVE_FRAME (frame);
   f = XFRAME (frame);
 
   /* Ignore redraw requests, if frame has no glyphs yet.
   f = XFRAME (frame);
 
   /* Ignore redraw requests, if frame has no glyphs yet.
@@ -3283,8 +3341,8 @@ redraw_frame (f)
 
 
 DEFUN ("redraw-display", Fredraw_display, Sredraw_display, 0, 0, "",
 
 
 DEFUN ("redraw-display", Fredraw_display, Sredraw_display, 0, 0, "",
-  "Clear and redisplay all visible frames.")
-  ()
+       doc: /* Clear and redisplay all visible frames.  */)
+     ()
 {
   Lisp_Object tail, frame;
 
 {
   Lisp_Object tail, frame;
 
@@ -3340,7 +3398,7 @@ direct_output_for_insert (g)
   struct glyph_row *glyph_row;
   struct glyph *glyphs, *glyph, *end;
   int n;
   struct glyph_row *glyph_row;
   struct glyph *glyphs, *glyph, *end;
   int n;
-  /* Non-null means that Redisplay of W is based on window matrices.  */
+  /* Non-null means that redisplay of W is based on window matrices.  */
   int window_redisplay_p = FRAME_WINDOW_P (f);
   /* Non-null means we are in overwrite mode.  */
   int overwrite_p = !NILP (current_buffer->overwrite_mode);
   int window_redisplay_p = FRAME_WINDOW_P (f);
   /* Non-null means we are in overwrite mode.  */
   int overwrite_p = !NILP (current_buffer->overwrite_mode);
@@ -3378,6 +3436,10 @@ direct_output_for_insert (g)
       || g == '\r'
       /* Give up if unable to display the cursor in the window.  */
       || w->cursor.vpos < 0
       || g == '\r'
       /* Give up if unable to display the cursor in the window.  */
       || w->cursor.vpos < 0
+      /* Give up if we are showing a message or just cleared the message
+        because we might need to resize the echo area window.  */
+      || !NILP (echo_area_buffer[0])
+      || !NILP (echo_area_buffer[1])
       || (glyph_row = MATRIX_ROW (w->current_matrix, w->cursor.vpos),
          /* Can't do it in a continued line because continuation
             lines would change.  */
       || (glyph_row = MATRIX_ROW (w->current_matrix, w->cursor.vpos),
          /* Can't do it in a continued line because continuation
             lines would change.  */
@@ -3392,6 +3454,12 @@ direct_output_for_insert (g)
       || (!window_redisplay_p && !WINDOW_FULL_WIDTH_P (w)))
     return 0;
 
       || (!window_redisplay_p && !WINDOW_FULL_WIDTH_P (w)))
     return 0;
 
+  /* If we can't insert glyphs, we can use this method only
+     at the end of a line.  */
+  if (!char_ins_del_ok)
+    if (PT != ZV && FETCH_BYTE (PT_BYTE) != '\n')
+      return 0;
+
   /* Set up a display iterator structure for W.  Glyphs will be
      produced in scratch_glyph_row.  Current position is W's cursor
      position.  */
   /* Set up a display iterator structure for W.  Glyphs will be
      produced in scratch_glyph_row.  Current position is W's cursor
      position.  */
@@ -3431,6 +3499,7 @@ direct_output_for_insert (g)
   it.current_y = w->cursor.y;
   it.end_charpos = PT;
   it.stop_charpos = min (PT, it.stop_charpos);
   it.current_y = w->cursor.y;
   it.end_charpos = PT;
   it.stop_charpos = min (PT, it.stop_charpos);
+  it.stop_charpos = max (IT_CHARPOS (it), it.stop_charpos);
 
   /* More than one display element may be returned for PT - 1 if
      (i) it's a control character which is translated into `\003' or
 
   /* More than one display element may be returned for PT - 1 if
      (i) it's a control character which is translated into `\003' or
@@ -3535,12 +3604,16 @@ direct_output_for_insert (g)
      implemented for X frames.  The implementation uses updated_window
      and updated_row.  */
   updated_row = glyph_row;
      implemented for X frames.  The implementation uses updated_window
      and updated_row.  */
   updated_row = glyph_row;
+  updated_area = TEXT_AREA;
   update_begin (f);
   if (rif)
     {
       rif->update_window_begin_hook (w);
       
   update_begin (f);
   if (rif)
     {
       rif->update_window_begin_hook (w);
       
-      if (glyphs == end - n)
+      if (glyphs == end - n
+         /* In front of a space added by append_space.  */
+         || (glyphs == end - n - 1
+             && (end - n)->charpos <= 0))
        rif->write_glyphs (glyphs, n);
       else
        rif->insert_glyphs (glyphs, n);
        rif->write_glyphs (glyphs, n);
       else
        rif->insert_glyphs (glyphs, n);
@@ -3583,14 +3656,7 @@ direct_output_for_insert (g)
   fflush (stdout);
 
   TRACE ((stderr, "direct output for insert\n"));
   fflush (stdout);
 
   TRACE ((stderr, "direct output for insert\n"));
-
-  UNCHANGED_MODIFIED = MODIFF;
-  BEG_UNCHANGED = GPT - BEG;
-  XSETFASTINT (w->last_point, PT);
-  w->last_cursor = w->cursor;
-  XSETFASTINT (w->last_modified, MODIFF);
-  XSETFASTINT (w->last_overlay_modified, OVERLAY_MODIFF);
-
+  mark_window_display_accurate (it.window, 1);
   redisplay_performed_directly_p = 1;
   return 1;
 }
   redisplay_performed_directly_p = 1;
   return 1;
 }
@@ -3652,8 +3718,8 @@ direct_output_forward_char (n)
   row = MATRIX_ROW (w->current_matrix, w->cursor.vpos);
 
   /* Give up if PT is outside of the last known cursor row.  */
   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))
+  if (PT <= MATRIX_ROW_START_CHARPOS (row)
+      || PT >= MATRIX_ROW_END_CHARPOS (row))
     return 0;
 
   set_cursor_from_row (w, row, w->current_matrix, 0, 0, 0, 0);
     return 0;
 
   set_cursor_from_row (w, row, w->current_matrix, 0, 0, 0, 0);
@@ -3727,12 +3793,13 @@ update_frame (f, force_p, inhibit_hairy_id_p)
       /* Update the tool-bar window, if present.  */
       if (WINDOWP (f->tool_bar_window))
        {
       /* Update the tool-bar window, if present.  */
       if (WINDOWP (f->tool_bar_window))
        {
-         Lisp_Object tem;
          struct window *w = XWINDOW (f->tool_bar_window);
 
          /* Update tool-bar window.  */
          if (w->must_be_updated_p)
            {
          struct window *w = XWINDOW (f->tool_bar_window);
 
          /* Update tool-bar window.  */
          if (w->must_be_updated_p)
            {
+             Lisp_Object tem;
+
              update_window (w, 1);
              w->must_be_updated_p = 0;
 
              update_window (w, 1);
              w->must_be_updated_p = 0;
 
@@ -3924,7 +3991,7 @@ redraw_overlapping_rows (w, yb)
          if (row->used[RIGHT_MARGIN_AREA])
            rif->fix_overlapping_area (w, row, RIGHT_MARGIN_AREA);
 
          if (row->used[RIGHT_MARGIN_AREA])
            rif->fix_overlapping_area (w, row, RIGHT_MARGIN_AREA);
 
-         /* Record in neighbor rows that ROW overwrites part of their
+         /* Record in neighbour rows that ROW overwrites part of their
             display.  */
          if (row->phys_ascent > row->ascent && i > 0)
            MATRIX_ROW (w->current_matrix, i - 1)->overlapped_p = 1;
             display.  */
          if (row->phys_ascent > row->ascent && i > 0)
            MATRIX_ROW (w->current_matrix, i - 1)->overlapped_p = 1;
@@ -3999,18 +4066,24 @@ update_window (w, force_p)
     {
       struct glyph_row *row, *end;
       struct glyph_row *mode_line_row;
     {
       struct glyph_row *row, *end;
       struct glyph_row *mode_line_row;
-      struct glyph_row *header_line_row = NULL;
+      struct glyph_row *header_line_row;
       int yb, changed_p = 0, mouse_face_overwritten_p = 0, n_updated;
 
       rif->update_window_begin_hook (w);
       yb = window_text_bottom_y (w);
 
       int yb, changed_p = 0, mouse_face_overwritten_p = 0, n_updated;
 
       rif->update_window_begin_hook (w);
       yb = window_text_bottom_y (w);
 
-      /* If window has a top line, update it before everything else.
-        Adjust y-positions of other rows by the top line height.  */
+      /* If window has a header line, update it before everything else.
+        Adjust y-positions of other rows by the header line height.  */
       row = desired_matrix->rows;
       end = row + desired_matrix->nrows - 1;
       row = desired_matrix->rows;
       end = row + desired_matrix->nrows - 1;
+      
       if (row->mode_line_p)
       if (row->mode_line_p)
-       header_line_row = row++;
+       {
+         header_line_row = row;
+         ++row;
+       }
+      else
+       header_line_row = NULL;
 
       /* Update the mode line, if necessary.  */
       mode_line_row = MATRIX_MODE_LINE_ROW (desired_matrix);
 
       /* Update the mode line, if necessary.  */
       mode_line_row = MATRIX_MODE_LINE_ROW (desired_matrix);
@@ -4040,11 +4113,12 @@ update_window (w, force_p)
              goto set_cursor;
            }
          else if (rc > 0)
              goto set_cursor;
            }
          else if (rc > 0)
+           /* We've scrolled the display.  */
            force_p = 1;
          changed_p = 1;
        }
 
            force_p = 1;
          changed_p = 1;
        }
 
-      /* Update the top mode line after scrolling because a new top
+      /* Update the header line after scrolling because a new header
         line would otherwise overwrite lines at the top of the window
         that can be scrolled.  */
       if (header_line_row && header_line_row->enabled_p)
         line would otherwise overwrite lines at the top of the window
         that can be scrolled.  */
       if (header_line_row && header_line_row->enabled_p)
@@ -4061,7 +4135,7 @@ update_window (w, force_p)
            int vpos = MATRIX_ROW_VPOS (row, desired_matrix);
            int i;
            
            int vpos = MATRIX_ROW_VPOS (row, desired_matrix);
            int i;
            
-           /* We'll Have to play a little bit with when to
+           /* We'll have to play a little bit with when to
               detect_input_pending.  If it's done too often,
               scrolling large windows with repeated scroll-up
               commands will too quickly pause redisplay.  */
               detect_input_pending.  If it's done too often,
               scrolling large windows with repeated scroll-up
               commands will too quickly pause redisplay.  */
@@ -4090,7 +4164,7 @@ update_window (w, force_p)
       
     set_cursor:
       
       
     set_cursor:
       
-      /* Fix the appearance of overlapping(overlapped rows.  */
+      /* Fix the appearance of overlapping/overlapped rows.  */
       if (!paused_p && !w->pseudo_window_p)
        {
          if (changed_p && rif->fix_overlapping_area)
       if (!paused_p && !w->pseudo_window_p)
        {
          if (changed_p && rif->fix_overlapping_area)
@@ -4113,14 +4187,17 @@ update_window (w, force_p)
       strcpy (w->current_matrix->method, w->desired_matrix->method);
 #endif
 
       strcpy (w->current_matrix->method, w->desired_matrix->method);
 #endif
 
-      /* End of update of window W.  */
-      rif->update_window_end_hook (w, 1, mouse_face_overwritten_p);
+      /* End the update of window W.  Don't set the cursor if we
+         paused updating the display because in this case,
+         set_window_cursor_after_update hasn't been called, and
+         output_cursor doesn't contain the cursor location.  */
+      rif->update_window_end_hook (w, !paused_p, mouse_face_overwritten_p);
     }
   else
     paused_p = 1;
 
 #if GLYPH_DEBUG
     }
   else
     paused_p = 1;
 
 #if GLYPH_DEBUG
-  check_current_matrix_flags (w);
+  /* check_current_matrix_flags (w); */
   add_window_display_history (w, w->current_matrix->method, paused_p);
 #endif
   
   add_window_display_history (w, w->current_matrix->method, paused_p);
 #endif
   
@@ -4191,6 +4268,16 @@ update_text_area (w, vpos)
       /* Clear to end of window.  */
       rif->clear_end_of_line (-1);
       changed_p = 1;
       /* Clear to end of window.  */
       rif->clear_end_of_line (-1);
       changed_p = 1;
+
+      /* This erases the cursor.  We do this here because
+         notice_overwritten_cursor cannot easily check this, which
+         might indicate that the whole functionality of
+         notice_overwritten_cursor would better be implemented here.
+         On the other hand, we need notice_overwritten_cursor as long
+         as mouse highlighting is done asynchronously outside of
+         redisplay.  */
+      if (vpos == w->phys_cursor.vpos)
+       w->phys_cursor_on_p = 0;
     }
   else
     {
     }
   else
     {
@@ -4198,18 +4285,20 @@ update_text_area (w, vpos)
       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;
       struct glyph *current_glyph = current_row->glyphs[TEXT_AREA];
       struct glyph *desired_glyph = desired_row->glyphs[TEXT_AREA];
       int overlapping_glyphs_p = current_row->contains_overlapping_glyphs_p;
+      int desired_stop_pos = desired_row->used[TEXT_AREA];
 
       /* If the desired row extends its face to the text area end,
         make sure we write at least one glyph, so that the face
         extension actually takes place.  */
 
       /* If the desired row extends its face to the text area end,
         make sure we write at least one glyph, so that the face
         extension actually takes place.  */
-      int desired_stop_pos = (desired_row->used[TEXT_AREA]
-                             - (MATRIX_ROW_EXTENDS_FACE_P (desired_row)
-                                ? 1 : 0));
+      if (MATRIX_ROW_EXTENDS_FACE_P (desired_row))
+       --desired_stop_pos;
       
       stop = min (current_row->used[TEXT_AREA], desired_stop_pos);
       i = 0;
       x = desired_row->x;
       
       stop = min (current_row->used[TEXT_AREA], desired_stop_pos);
       i = 0;
       x = desired_row->x;
-      
+
+      /* Loop over glyphs that current and desired row may have
+        in common.  */
       while (i < stop)
        {
          int can_skip_p = 1;
       while (i < stop)
        {
          int can_skip_p = 1;
@@ -4472,22 +4561,21 @@ set_window_cursor_after_update (w)
          int yb = window_text_bottom_y (w);
 
          last_row = NULL;
          int yb = window_text_bottom_y (w);
 
          last_row = NULL;
-         for (row = MATRIX_ROW (w->current_matrix, 0);
-              row->enabled_p;
-              ++row)
+         row = w->current_matrix->rows;
+         while (row->enabled_p
+                && (last_row == NULL
+                    || MATRIX_ROW_BOTTOM_Y (row) <= yb))
            {
              if (row->used[TEXT_AREA]
                  && row->glyphs[TEXT_AREA][0].charpos >= 0)
                last_row = row;
            {
              if (row->used[TEXT_AREA]
                  && row->glyphs[TEXT_AREA][0].charpos >= 0)
                last_row = row;
-
-             if (MATRIX_ROW_BOTTOM_Y (row) >= yb)
-               break;
+             ++row;
            }
          
          if (last_row)
            {
            }
          
          if (last_row)
            {
-             struct glyph *start = row->glyphs[TEXT_AREA];
-             struct glyph *last = start + row->used[TEXT_AREA] - 1;
+             struct glyph *start = last_row->glyphs[TEXT_AREA];
+             struct glyph *last = start + last_row->used[TEXT_AREA] - 1;
 
              while (last > start && last->charpos < 0)
                --last;
 
              while (last > start && last->charpos < 0)
                --last;
@@ -4600,10 +4688,6 @@ static int runs_size;
 
 static struct run **runs;
 
 
 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.  */
 
 /* Add glyph row ROW to the scrolling hash table during the scrolling
    of window W.  */
 
@@ -4635,7 +4719,7 @@ add_row_entry (w, row)
 
 
 /* Try to reuse part of the current display of W by scrolling lines.
 
 
 /* Try to reuse part of the current display of W by scrolling lines.
-   HEADER_LINE_P non-zero means W has a top mode line.
+   HEADER_LINE_P non-zero means W has a header line.
 
    The algorithm is taken from Communications of the ACM, Apr78 "A
    Technique for Isolating Differences Between Files."  It should take
 
    The algorithm is taken from Communications of the ACM, Apr78 "A
    Technique for Isolating Differences Between Files."  It should take
@@ -5024,7 +5108,7 @@ update_frame_1 (f, force_p, inhibit_id_p)
 #ifdef EMACS_OUTQSIZE
                      if (EMACS_OUTQSIZE (0, &outq) < 0)
                        /* Probably not a tty.  Ignore the error and reset
 #ifdef EMACS_OUTQSIZE
                      if (EMACS_OUTQSIZE (0, &outq) < 0)
                        /* Probably not a tty.  Ignore the error and reset
-                        * the outq count.  */
+                          the outq count.  */
                        outq = PENDING_OUTPUT_COUNT (stdout);
 #endif
                      outq *= 10;
                        outq = PENDING_OUTPUT_COUNT (stdout);
 #endif
                      outq *= 10;
@@ -5286,35 +5370,25 @@ extern int *char_ins_del_vector;
 /* Perform a frame-based update on line VPOS in frame FRAME.  */
 
 static void
 /* Perform a frame-based update on line VPOS in frame FRAME.  */
 
 static void
-update_frame_line (frame, vpos)
-     register struct frame *frame;
+update_frame_line (f, vpos)
+     struct frame *f;
      int vpos;
 {
   struct glyph *obody, *nbody, *op1, *op2, *np1, *nend;
   int tem;
   int osp, nsp, begmatch, endmatch, olen, nlen;
      int vpos;
 {
   struct glyph *obody, *nbody, *op1, *op2, *np1, *nend;
   int tem;
   int osp, nsp, begmatch, endmatch, olen, nlen;
-  struct glyph_matrix *current_matrix = frame->current_matrix;
-  struct glyph_matrix *desired_matrix = frame->desired_matrix;
+  struct glyph_matrix *current_matrix = f->current_matrix;
+  struct glyph_matrix *desired_matrix = f->desired_matrix;
   struct glyph_row *current_row = MATRIX_ROW (current_matrix, vpos);
   struct glyph_row *desired_row = MATRIX_ROW (desired_matrix, vpos);
   int must_write_whole_line_p;
   int write_spaces_p = must_write_spaces;
   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
+  int colored_spaces_p = (FACE_FROM_ID (f, DEFAULT_FACE_ID)->background
                          != FACE_TTY_DEFAULT_BG_COLOR);
 
   if (colored_spaces_p)
     write_spaces_p = 1;
 
                          != 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))
-    {
-      int n = current_row->enabled_p ? current_row->used[TEXT_AREA] : 0;
-      change_line_highlight (desired_row->inverse_p, vpos, vpos, n);
-      current_row->enabled_p = 0;
-    }
-  else
-    reassert_line_highlight (desired_row->inverse_p, vpos);
-
   /* Current row not enabled means it has unknown contents.  We must
      write the whole desired line in that case.  */
   must_write_whole_line_p = !current_row->enabled_p;
   /* Current row not enabled means it has unknown contents.  We must
      write the whole desired line in that case.  */
   must_write_whole_line_p = !current_row->enabled_p;
@@ -5328,26 +5402,14 @@ 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)
-       {
-         /* Ignore trailing spaces, if we can.  */
-         if (!write_spaces_p)
-           while (olen > 0 && CHAR_GLYPH_SPACE_P (obody[olen-1]))
-             olen--;
-       }
-      else
-       {
-         /* For an inverse-video line, make sure it's filled with
-            spaces all the way to the frame edge so that the reverse
-            video extends all the way across.  */
-         while (olen < FRAME_WIDTH (frame) - 1)
-           obody[olen++] = space_glyph;
-       }
+      /* Ignore trailing spaces, if we can.  */
+      if (!write_spaces_p)
+       while (olen > 0 && CHAR_GLYPH_SPACE_P (obody[olen-1]))
+         olen--;
     }
 
   current_row->enabled_p = 1;
   current_row->used[TEXT_AREA] = desired_row->used[TEXT_AREA];
     }
 
   current_row->enabled_p = 1;
   current_row->used[TEXT_AREA] = desired_row->used[TEXT_AREA];
-  current_row->inverse_p = desired_row->inverse_p;
 
   /* If desired line is empty, just clear the line.  */
   if (!desired_row->enabled_p)
 
   /* If desired line is empty, just clear the line.  */
   if (!desired_row->enabled_p)
@@ -5378,10 +5440,10 @@ update_frame_line (frame, vpos)
       /* Don't call clear_end_of_line if we already wrote the whole
         line.  The cursor will not be at the right margin in that
         case but in the line below.  */
       /* Don't call clear_end_of_line if we already wrote the whole
         line.  The cursor will not be at the right margin in that
         case but in the line below.  */
-      if (nlen < FRAME_WINDOW_WIDTH (frame))
+      if (nlen < FRAME_WINDOW_WIDTH (f))
        {
          cursor_to (vpos, nlen);
        {
          cursor_to (vpos, nlen);
-          clear_end_of_line (FRAME_WINDOW_WIDTH (frame));
+          clear_end_of_line (FRAME_WINDOW_WIDTH (f));
        }
       else
        /* Make sure we are in the right row, otherwise cursor movement
        }
       else
        /* Make sure we are in the right row, otherwise cursor movement
@@ -5394,20 +5456,9 @@ update_frame_line (frame, vpos)
 
   /* Pretend trailing spaces are not there at all,
      unless for one reason or another we must write all spaces.  */
 
   /* Pretend trailing spaces are not there at all,
      unless for one reason or another we must write all spaces.  */
-  if (!desired_row->inverse_p)
-    {
-      if (!write_spaces_p)
-       while (nlen > 0 && CHAR_GLYPH_SPACE_P (nbody[nlen - 1]))
-         nlen--;
-    }
-  else
-    {
-      /* For an inverse-video line, give it extra trailing spaces all
-        the way to the frame edge so that the reverse video extends
-        all the way across.  */
-      while (nlen < FRAME_WIDTH (frame) - 1)
-       nbody[nlen++] = space_glyph;
-    }
+  if (!write_spaces_p)
+    while (nlen > 0 && CHAR_GLYPH_SPACE_P (nbody[nlen - 1]))
+      nlen--;
 
   /* If there's no i/d char, quickly do the best we can without it.  */
   if (!char_ins_del_ok)
 
   /* If there's no i/d char, quickly do the best we can without it.  */
   if (!char_ins_del_ok)
@@ -5456,7 +5507,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 (write_spaces_p || desired_row->inverse_p)
+      if (write_spaces_p)
        nsp = 0;
       else
        nsp = count_blanks (nbody, nlen);
        nsp = 0;
       else
        nsp = count_blanks (nbody, nlen);
@@ -5474,9 +5525,7 @@ 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 || colored_spaces_p
-        ? 0
-        : count_blanks (nbody, nlen));
+  nsp = (colored_spaces_p ? 0 : count_blanks (nbody, nlen));
 
   /* Compute number of matching chars starting with first non-blank.  */
   begmatch = count_match (obody + osp, obody + olen,
 
   /* Compute number of matching chars starting with first non-blank.  */
   begmatch = count_match (obody + osp, obody + olen,
@@ -5515,7 +5564,7 @@ update_frame_line (frame, vpos)
 
   tem = (nlen - nsp) - (olen - osp);
   if (endmatch && tem
 
   tem = (nlen - nsp) - (olen - osp);
   if (endmatch && tem
-      && (!char_ins_del_ok || endmatch <= char_ins_del_cost (frame)[tem]))
+      && (!char_ins_del_ok || endmatch <= char_ins_del_cost (f)[tem]))
     endmatch = 0;
 
   /* nsp - osp is the distance to insert or delete.
     endmatch = 0;
 
   /* nsp - osp is the distance to insert or delete.
@@ -5525,7 +5574,7 @@ update_frame_line (frame, vpos)
 
   if (nsp != osp
       && (!char_ins_del_ok
 
   if (nsp != osp
       && (!char_ins_del_ok
-         || begmatch + endmatch <= char_ins_del_cost (frame)[nsp - osp]))
+         || begmatch + endmatch <= char_ins_del_cost (f)[nsp - osp]))
     {
       begmatch = 0;
       endmatch = 0;
     {
       begmatch = 0;
       endmatch = 0;
@@ -5559,16 +5608,23 @@ update_frame_line (frame, vpos)
   tem = nsp + begmatch + endmatch;
   if (nlen != tem || olen != tem)
     {
   tem = nsp + begmatch + endmatch;
   if (nlen != tem || olen != tem)
     {
-      cursor_to (vpos, nsp + begmatch);
       if (!endmatch || nlen == olen)
        {
       if (!endmatch || nlen == olen)
        {
-         /* If new text being written reaches right margin,
-            there is no need to do clear-to-eol at the end.
-            (and it would not be safe, since cursor is not
-            going to be "at the margin" after the text is done) */
-         if (nlen == FRAME_WINDOW_WIDTH (frame))
+         /* If new text being written reaches right margin, there is
+            no need to do clear-to-eol at the end of this function
+            (and it would not be safe, since cursor is not going to
+            be "at the margin" after the text is done).  */
+         if (nlen == FRAME_WINDOW_WIDTH (f))
            olen = 0;
            olen = 0;
-         write_glyphs (nbody + nsp + begmatch, nlen - tem);
+
+         /* Function write_glyphs is prepared to do nothing
+            if passed a length <= 0.  Check it here to avoid
+            unnecessary cursor movement.  */
+         if (nlen - tem > 0)
+           {
+             cursor_to (vpos, nsp + begmatch);
+             write_glyphs (nbody + nsp + begmatch, nlen - tem);
+           }
        }
       else if (nlen > olen)
        {
        }
       else if (nlen > olen)
        {
@@ -5582,18 +5638,25 @@ update_frame_line (frame, vpos)
          int out = olen - tem; /* Columns to be overwritten originally.  */
          int del;
 
          int out = olen - tem; /* Columns to be overwritten originally.  */
          int del;
 
+         cursor_to (vpos, nsp + begmatch);
+         
          /* Calculate columns we can actually overwrite.  */
          /* Calculate columns we can actually overwrite.  */
-         while (CHAR_GLYPH_PADDING_P (nbody[nsp + begmatch + out])) out--;
+         while (CHAR_GLYPH_PADDING_P (nbody[nsp + begmatch + out]))
+           out--;
          write_glyphs (nbody + nsp + begmatch, out);
          write_glyphs (nbody + nsp + begmatch, out);
+         
          /* If we left columns to be overwritten, we must delete them.  */
          del = olen - tem - out;
          /* If we left columns to be overwritten, we must delete them.  */
          del = olen - tem - out;
-         if (del > 0) delete_glyphs (del);
+         if (del > 0)
+           delete_glyphs (del);
+         
          /* At last, we insert columns not yet written out.  */
          insert_glyphs (nbody + nsp + begmatch + out, nlen - olen + del);
          olen = nlen;
        }
       else if (olen > nlen)
        {
          /* At last, we insert columns not yet written out.  */
          insert_glyphs (nbody + nsp + begmatch + out, nlen - olen + del);
          olen = nlen;
        }
       else if (olen > nlen)
        {
+         cursor_to (vpos, nsp + begmatch);
          write_glyphs (nbody + nsp + begmatch, nlen - tem);
          delete_glyphs (olen - nlen);
          olen = nlen;
          write_glyphs (nbody + nsp + begmatch, nlen - tem);
          delete_glyphs (olen - nlen);
          olen = nlen;
@@ -5618,14 +5681,17 @@ update_frame_line (frame, vpos)
                   X/Y Position -> Buffer Position
  ***********************************************************************/
 
                   X/Y Position -> Buffer Position
  ***********************************************************************/
 
-/* Return the character position of the character at window relative
-   pixel position (*X, *Y).  *X and *Y are adjusted to character
-   boundaries.  */
+/* Determine what's under window-relative pixel position (*X, *Y).
+   Return in *OBJECT the object (string or buffer) that's there.
+   Return in *POS the position in that object. Adjust *X and *Y
+   to character boundaries.  */
 
 
-int
-buffer_posn_from_coords (w, x, y)
+void
+buffer_posn_from_coords (w, x, y, object, pos)
      struct window *w;
      int *x, *y;
      struct window *w;
      int *x, *y;
+     Lisp_Object *object;
+     struct display_pos *pos;
 {
   struct it it;
   struct buffer *old_current_buffer = current_buffer;
 {
   struct it it;
   struct buffer *old_current_buffer = current_buffer;
@@ -5645,12 +5711,14 @@ buffer_posn_from_coords (w, x, y)
   *x = it.current_x - it.first_visible_x + left_area_width;
   *y = it.current_y;
   current_buffer = old_current_buffer;
   *x = it.current_x - it.first_visible_x + left_area_width;
   *y = it.current_y;
   current_buffer = old_current_buffer;
-  return IT_CHARPOS (it);
+
+  *object = STRINGP (it.string) ? it.string : w->buffer;
+  *pos = it.current;
 }
 
 
 /* Value is the string under window-relative coordinates X/Y in the
 }
 
 
 /* Value is the string under window-relative coordinates X/Y in the
-   mode or top line of window W, or nil if none.  MODE_LINE_P non-zero
+   mode or header line of window W, or nil if none.  MODE_LINE_P non-zero
    means look at the mode line.  *CHARPOS is set to the position in
    the string returned.  */
 
    means look at the mode line.  *CHARPOS is set to the position in
    the string returned.  */
 
@@ -5673,12 +5741,12 @@ mode_line_string (w, x, y, mode_line_p, charpos)
 
   if (row->mode_line_p && row->enabled_p)
     {
 
   if (row->mode_line_p && row->enabled_p)
     {
-      /* The mode lines are displayed over scroll bars and bitmap
-        areas, and X is window-relative.  Correct X by the scroll bar
-        and bitmap area width.  */
+      /* The mode lines are displayed over scroll bars and fringes,
+        and X is window-relative.  Correct X by the scroll bar
+        and fringe width.  */
       if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (f))
        x += FRAME_SCROLL_BAR_COLS (f) * CANON_X_UNIT (f);
       if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (f))
        x += FRAME_SCROLL_BAR_COLS (f) * CANON_X_UNIT (f);
-      x += FRAME_LEFT_FLAGS_AREA_WIDTH (f);
+      x += FRAME_LEFT_FRINGE_WIDTH (f);
 
       /* Find the glyph under X.  If we find one with a string object,
          it's the one we were looking for.  */
 
       /* Find the glyph under X.  If we find one with a string object,
          it's the one we were looking for.  */
@@ -5697,6 +5765,57 @@ mode_line_string (w, x, y, mode_line_p, charpos)
 }
 
 
 }
 
 
+/* Value is the string under window-relative coordinates X/Y in either
+   marginal area, or nil if none.  *CHARPOS is set to the position in
+   the string returned.  */
+
+Lisp_Object
+marginal_area_string (w, x, y, area, charpos)
+     struct window *w;
+     int x, y;
+     int area;
+     int *charpos;
+{
+  struct glyph_row *row = w->current_matrix->rows;
+  struct glyph *glyph, *end;
+  int x0, i, wy = y;
+  Lisp_Object string = Qnil;
+
+  if (area == 6)
+    area = LEFT_MARGIN_AREA;
+  else if (area == 7)
+    area = RIGHT_MARGIN_AREA;
+  else
+    abort ();
+
+  for (i = 0; row->enabled_p && i < w->current_matrix->nrows; ++i, ++row)
+    if (wy >= row->y && wy < MATRIX_ROW_BOTTOM_Y (row))
+      break;
+
+  if (row->enabled_p)
+    {
+      /* Find the glyph under X.  If we find one with a string object,
+        it's the one we were looking for.  */
+      glyph = row->glyphs[area];
+      end = glyph + row->used[area];
+      if (area == RIGHT_MARGIN_AREA)
+       x0 = (window_box_width (w, TEXT_AREA)
+             + window_box_width (w, LEFT_MARGIN_AREA));
+      else
+       x0 = 0;
+      for (; glyph < end; x0 += glyph->pixel_width, ++glyph)
+       if (x >= x0 && x < x0 + glyph->pixel_width)
+         {
+           string = glyph->object;
+           *charpos = glyph->charpos;
+           break;
+         }
+    }
+
+  return string;
+}
+
+
 /***********************************************************************
                         Changing Frame Sizes
  ***********************************************************************/
 /***********************************************************************
                         Changing Frame Sizes
  ***********************************************************************/
@@ -5810,7 +5929,7 @@ change_frame_size_1 (f, newheight, newwidth, pretend, delay, safe)
      int newheight, newwidth, pretend, delay, safe;
 {
   int new_frame_window_width;
      int newheight, newwidth, pretend, delay, safe;
 {
   int new_frame_window_width;
-  int count = specpdl_ptr - specpdl;
+  int count = SPECPDL_INDEX ();
 
   /* If we can't deal with the change now, queue it for later.  */
   if (delay || (redisplaying_p && !safe))
 
   /* If we can't deal with the change now, queue it for later.  */
   if (delay || (redisplaying_p && !safe))
@@ -5906,8 +6025,9 @@ change_frame_size_1 (f, newheight, newwidth, pretend, delay, safe)
   }
 
   adjust_glyphs (f);
   }
 
   adjust_glyphs (f);
-  SET_FRAME_GARBAGED (f);
   calculate_costs (f);
   calculate_costs (f);
+  SET_FRAME_GARBAGED (f);
+  f->resized_p = 1;
 
   UNBLOCK_INPUT;
 
 
   UNBLOCK_INPUT;
 
@@ -5927,10 +6047,10 @@ change_frame_size_1 (f, newheight, newwidth, pretend, delay, safe)
  ***********************************************************************/
 
 DEFUN ("open-termscript", Fopen_termscript, Sopen_termscript,
  ***********************************************************************/
 
 DEFUN ("open-termscript", Fopen_termscript, Sopen_termscript,
-  1, 1, "FOpen termscript file: ",
-  "Start writing all terminal output to FILE as well as the terminal.\n\
-FILE = nil means just close any termscript file currently open.")
-  (file)
+       1, 1, "FOpen termscript file: ",
+       doc: /* Start writing all terminal output to FILE as well as the terminal.
+FILE = nil means just close any termscript file currently open.  */)
+     (file)
      Lisp_Object file;
 {
   if (termscript != 0) fclose (termscript);
      Lisp_Object file;
 {
   if (termscript != 0) fclose (termscript);
@@ -5939,7 +6059,7 @@ FILE = nil means just close any termscript file currently open.")
   if (! NILP (file))
     {
       file = Fexpand_file_name (file, Qnil);
   if (! NILP (file))
     {
       file = Fexpand_file_name (file, Qnil);
-      termscript = fopen (XSTRING (file)->data, "w");
+      termscript = fopen (SDATA (file), "w");
       if (termscript == 0)
        report_file_error ("Opening termscript", Fcons (file, Qnil));
     }
       if (termscript == 0)
        report_file_error ("Opening termscript", Fcons (file, Qnil));
     }
@@ -5948,19 +6068,19 @@ FILE = nil means just close any termscript file currently open.")
 
 
 DEFUN ("send-string-to-terminal", Fsend_string_to_terminal,
 
 
 DEFUN ("send-string-to-terminal", Fsend_string_to_terminal,
-  Ssend_string_to_terminal, 1, 1, 0,
-  "Send STRING to the terminal without alteration.\n\
-Control characters in STRING will have terminal-dependent effects.")
-  (string)
+       Ssend_string_to_terminal, 1, 1, 0,
+       doc: /* Send STRING to the terminal without alteration.
+Control characters in STRING will have terminal-dependent effects.  */)
+     (string)
      Lisp_Object string;
 {
   /* ??? Perhaps we should do something special for multibyte strings here.  */
      Lisp_Object string;
 {
   /* ??? Perhaps we should do something special for multibyte strings here.  */
-  CHECK_STRING (string, 0);
-  fwrite (XSTRING (string)->data, 1, STRING_BYTES (XSTRING (string)), stdout);
+  CHECK_STRING (string);
+  fwrite (SDATA (string), 1, SBYTES (string), stdout);
   fflush (stdout);
   if (termscript)
     {
   fflush (stdout);
   if (termscript)
     {
-      fwrite (XSTRING (string)->data, 1, STRING_BYTES (XSTRING (string)),
+      fwrite (SDATA (string), 1, SBYTES (string),
              termscript);
       fflush (termscript);
     }
              termscript);
       fflush (termscript);
     }
@@ -5969,10 +6089,10 @@ Control characters in STRING will have terminal-dependent effects.")
 
 
 DEFUN ("ding", Fding, Sding, 0, 1, 0,
 
 
 DEFUN ("ding", Fding, Sding, 0, 1, 0,
-  "Beep, or flash the screen.\n\
-Also, unless an argument is given,\n\
-terminate any keyboard macro currently executing.")
-  (arg)
+       doc: /* Beep, or flash the screen.
+Also, unless an argument is given,
+terminate any keyboard macro currently executing.  */)
+     (arg)
   Lisp_Object arg;
 {
   if (!NILP (arg))
   Lisp_Object arg;
 {
   if (!NILP (arg))
@@ -6008,13 +6128,13 @@ bitch_at_user ()
  ***********************************************************************/
 
 DEFUN ("sleep-for", Fsleep_for, Ssleep_for, 1, 2, 0,
  ***********************************************************************/
 
 DEFUN ("sleep-for", Fsleep_for, Ssleep_for, 1, 2, 0,
-  "Pause, without updating display, for SECONDS seconds.\n\
-SECONDS may be a floating-point value, meaning that you can wait for a\n\
-fraction of a second.  Optional second arg MILLISECONDS specifies an\n\
-additional wait period, in milliseconds; this may be useful if your\n\
-Emacs was built without floating point support.\n\
-\(Not all operating systems support waiting for a fraction of a second.)")
-  (seconds, milliseconds)
+       doc: /* Pause, without updating display, for SECONDS seconds.
+SECONDS may be a floating-point value, meaning that you can wait for a
+fraction of a second.  Optional second arg MILLISECONDS specifies an
+additional wait period, in milliseconds; this may be useful if your
+Emacs was built without floating point support.
+\(Not all operating systems support waiting for a fraction of a second.)  */)
+     (seconds, milliseconds)
      Lisp_Object seconds, milliseconds;
 {
   int sec, usec;
      Lisp_Object seconds, milliseconds;
 {
   int sec, usec;
@@ -6022,7 +6142,7 @@ Emacs was built without floating point support.\n\
   if (NILP (milliseconds))
     XSETINT (milliseconds, 0);
   else
   if (NILP (milliseconds))
     XSETINT (milliseconds, 0);
   else
-    CHECK_NUMBER (milliseconds, 1);
+    CHECK_NUMBER (milliseconds);
   usec = XINT (milliseconds) * 1000;
 
   {
   usec = XINT (milliseconds) * 1000;
 
   {
@@ -6039,7 +6159,7 @@ Emacs was built without floating point support.\n\
   /* Assure that 0 <= usec < 1000000.  */
   if (usec < 0)
     {
   /* Assure that 0 <= usec < 1000000.  */
   if (usec < 0)
     {
-      /* We can't rely on the rounding being correct if user is negative.  */
+      /* We can't rely on the rounding being correct if usec is negative.  */
       if (-1000000 < usec)
        sec--, usec += 1000000;
       else
       if (-1000000 < usec)
        sec--, usec += 1000000;
       else
@@ -6070,7 +6190,7 @@ Emacs was built without floating point support.\n\
 #else /* not VMS */
 /* The reason this is done this way 
     (rather than defined (H_S) && defined (H_T))
 #else /* not VMS */
 /* The reason this is done this way 
     (rather than defined (H_S) && defined (H_T))
-   is because the VMS preprocessor doesn't grok `defined' */
+   is because the VMS preprocessor doesn't grok `defined' */
 #ifdef HAVE_SELECT
   EMACS_GET_TIME (end_time);
   EMACS_SET_SECS_USECS (timeout, sec, usec);
 #ifdef HAVE_SELECT
   EMACS_GET_TIME (end_time);
   EMACS_SET_SECS_USECS (timeout, sec, usec);
@@ -6110,11 +6230,11 @@ sit_for (sec, usec, reading, display, initial_display)
 
   swallow_events (display);
 
 
   swallow_events (display);
 
-  if (detect_input_pending_run_timers (display))
+  if (detect_input_pending_run_timers (display) || !NILP (Vexecuting_macro))
     return Qnil;
 
   if (initial_display)
     return Qnil;
 
   if (initial_display)
-    redisplay_preserve_echo_area ();
+    redisplay_preserve_echo_area (2);
 
   if (sec == 0 && usec == 0)
     return Qt;
 
   if (sec == 0 && usec == 0)
     return Qt;
@@ -6131,17 +6251,17 @@ sit_for (sec, usec, reading, display, initial_display)
 
 
 DEFUN ("sit-for", Fsit_for, Ssit_for, 1, 3, 0,
 
 
 DEFUN ("sit-for", Fsit_for, Ssit_for, 1, 3, 0,
-  "Perform redisplay, then wait for SECONDS seconds or until input is available.\n\
-SECONDS may be a floating-point value, meaning that you can wait for a\n\
-fraction of a second.  Optional second arg MILLISECONDS specifies an\n\
-additional wait period, in milliseconds; this may be useful if your\n\
-Emacs was built without floating point support.\n\
-\(Not all operating systems support waiting for a fraction of a second.)\n\
-Optional third arg NODISP non-nil means don't redisplay, just wait for input.\n\
-Redisplay is preempted as always if input arrives, and does not happen\n\
-if input is available before it starts.\n\
-Value is t if waited the full time with no input arriving.")
-  (seconds, milliseconds, nodisp)
+       doc: /* Perform redisplay, then wait for SECONDS seconds or until input is available.
+SECONDS may be a floating-point value, meaning that you can wait for a
+fraction of a second.  Optional second arg MILLISECONDS specifies an
+additional wait period, in milliseconds; this may be useful if your
+Emacs was built without floating point support.
+\(Not all operating systems support waiting for a fraction of a second.)
+Optional third arg NODISP non-nil means don't redisplay, just wait for input.
+Redisplay is preempted as always if input arrives, and does not happen
+if input is available before it starts.
+Value is t if waited the full time with no input arriving.  */)
+     (seconds, milliseconds, nodisp)
      Lisp_Object seconds, milliseconds, nodisp;
 {
   int sec, usec;
      Lisp_Object seconds, milliseconds, nodisp;
 {
   int sec, usec;
@@ -6149,7 +6269,7 @@ Value is t if waited the full time with no input arriving.")
   if (NILP (milliseconds))
     XSETINT (milliseconds, 0);
   else
   if (NILP (milliseconds))
     XSETINT (milliseconds, 0);
   else
-    CHECK_NUMBER (milliseconds, 1);
+    CHECK_NUMBER (milliseconds);
   usec = XINT (milliseconds) * 1000;
 
   {
   usec = XINT (milliseconds) * 1000;
 
   {
@@ -6181,15 +6301,15 @@ static Lisp_Object frame_and_buffer_state;
 
 
 DEFUN ("frame-or-buffer-changed-p", Fframe_or_buffer_changed_p,
 
 
 DEFUN ("frame-or-buffer-changed-p", Fframe_or_buffer_changed_p,
-  Sframe_or_buffer_changed_p, 0, 0, 0,
-  "Return non-nil if the frame and buffer state appears to have changed.\n\
-The state variable is an internal vector containing all frames and buffers,\n\
-aside from buffers whose names start with space,\n\
-along with the buffers' read-only and modified flags, which allows a fast\n\
-check to see whether the menu bars might need to be recomputed.\n\
-If this function returns non-nil, it updates the internal vector to reflect\n\
-the current state.\n")
-  ()
+       Sframe_or_buffer_changed_p, 0, 0, 0,
+       doc: /* Return non-nil if the frame and buffer state appears to have changed.
+The state variable is an internal vector containing all frames and buffers,
+aside from buffers whose names start with space,
+along with the buffers' read-only and modified flags, which allows a fast
+check to see whether the menu bars might need to be recomputed.
+If this function returns non-nil, it updates the internal vector to reflect
+the current state.  */)
+     ()
 {
   Lisp_Object tail, frame, buf;
   Lisp_Object *vecp;
 {
   Lisp_Object tail, frame, buf;
   Lisp_Object *vecp;
@@ -6211,7 +6331,7 @@ the current state.\n")
     {
       buf = XCDR (XCAR (tail));
       /* Ignore buffers that aren't included in buffer lists.  */
     {
       buf = XCDR (XCAR (tail));
       /* Ignore buffers that aren't included in buffer lists.  */
-      if (XSTRING (XBUFFER (buf)->name)->data[0] == ' ')
+      if (SREF (XBUFFER (buf)->name, 0) == ' ')
        continue;
       if (!EQ (*vecp++, buf))
        goto changed;
        continue;
       if (!EQ (*vecp++, buf))
        goto changed;
@@ -6245,7 +6365,7 @@ the current state.\n")
     {
       buf = XCDR (XCAR (tail));
       /* Ignore buffers that aren't included in buffer lists.  */
     {
       buf = XCDR (XCAR (tail));
       /* Ignore buffers that aren't included in buffer lists.  */
-      if (XSTRING (XBUFFER (buf)->name)->data[0] == ' ')
+      if (SREF (XBUFFER (buf)->name, 0) == ' ')
        continue;
       *vecp++ = buf;
       *vecp++ = XBUFFER (buf)->read_only;
        continue;
       *vecp++ = buf;
       *vecp++ = XBUFFER (buf)->read_only;
@@ -6329,7 +6449,7 @@ init_display ()
 #else
       Vwindow_system_version = make_number (10);
 #endif
 #else
       Vwindow_system_version = make_number (10);
 #endif
-#if defined (LINUX) && defined (HAVE_LIBNCURSES)
+#if defined (GNU_LINUX) && defined (HAVE_LIBNCURSES)
       /* In some versions of ncurses,
         tputs crashes if we have not called tgetent.
         So call tgetent.  */
       /* In some versions of ncurses,
         tputs crashes if we have not called tgetent.
         So call tgetent.  */
@@ -6350,7 +6470,7 @@ init_display ()
     }
 #endif /* HAVE_NTGUI */
 
     }
 #endif /* HAVE_NTGUI */
 
-#ifdef macintosh
+#ifdef MAC_OS
   if (!inhibit_window_system) 
     {
       Vwindow_system = intern ("mac");
   if (!inhibit_window_system) 
     {
       Vwindow_system = intern ("mac");
@@ -6358,7 +6478,7 @@ init_display ()
       adjust_frame_glyphs_initially ();
       return;
     }
       adjust_frame_glyphs_initially ();
       return;
     }
-#endif /* macintosh */
+#endif /* MAC_OS */
 
   /* If no window system has been specified, try to use the terminal.  */
   if (! isatty (0))
 
   /* If no window system has been specified, try to use the terminal.  */
   if (! isatty (0))
@@ -6367,7 +6487,7 @@ init_display ()
       exit (1);
     }
 
       exit (1);
     }
 
-  /* Look at the TERM variable */
+  /* Look at the TERM variable */
   terminal_type = (char *) getenv ("TERM");
   if (!terminal_type)
     {
   terminal_type = (char *) getenv ("TERM");
   if (!terminal_type)
     {
@@ -6454,11 +6574,11 @@ For types not defined in VMS, use  define emacs_term \"TYPE\".\n\
 
 DEFUN ("internal-show-cursor", Finternal_show_cursor,
        Sinternal_show_cursor, 2, 2, 0,
 
 DEFUN ("internal-show-cursor", Finternal_show_cursor,
        Sinternal_show_cursor, 2, 2, 0,
-  "Set the cursor-visibility flag of WINDOW to SHOW.\n\
-WINDOW nil means use the selected window.  SHOW non-nil means\n\
-show a cursor in WINDOW in the next redisplay.  SHOW nil means\n\
-don't show a cursor.")
-  (window, show)
+       doc: /* Set the cursor-visibility flag of WINDOW to SHOW.
+WINDOW nil means use the selected window.  SHOW non-nil means
+show a cursor in WINDOW in the next redisplay.  SHOW nil means
+don't show a cursor.  */)
+     (window, show)
      Lisp_Object window, show;
 {
   /* Don't change cursor state while redisplaying.  This could confuse
      Lisp_Object window, show;
 {
   /* Don't change cursor state while redisplaying.  This could confuse
@@ -6468,7 +6588,7 @@ don't show a cursor.")
       if (NILP (window))
        window = selected_window;
       else
       if (NILP (window))
        window = selected_window;
       else
-       CHECK_WINDOW (window, 2);
+       CHECK_WINDOW (window);
       
       XWINDOW (window)->cursor_off_p = NILP (show);
     }
       
       XWINDOW (window)->cursor_off_p = NILP (show);
     }
@@ -6479,9 +6599,9 @@ don't show a cursor.")
 
 DEFUN ("internal-show-cursor-p", Finternal_show_cursor_p,
        Sinternal_show_cursor_p, 0, 1, 0,
 
 DEFUN ("internal-show-cursor-p", Finternal_show_cursor_p,
        Sinternal_show_cursor_p, 0, 1, 0,
-  "Value is non-nil if next redisplay will display a cursor in WINDOW.\n\
-WINDOW nil or omitted means report on the selected window.")
-  (window)
+       doc: /* Value is non-nil if next redisplay will display a cursor in WINDOW.
+WINDOW nil or omitted means report on the selected window.  */)
+     (window)
      Lisp_Object window;
 {
   struct window *w;
      Lisp_Object window;
 {
   struct window *w;
@@ -6489,7 +6609,7 @@ WINDOW nil or omitted means report on the selected window.")
   if (NILP (window))
     window = selected_window;
   else
   if (NILP (window))
     window = selected_window;
   else
-    CHECK_WINDOW (window, 2);
+    CHECK_WINDOW (window);
   
   w = XWINDOW (window);
   return w->cursor_off_p ? Qnil : Qt;    
   
   w = XWINDOW (window);
   return w->cursor_off_p ? Qnil : Qt;    
@@ -6527,51 +6647,55 @@ syms_of_display ()
   staticpro (&Qredisplay_dont_pause);
 
   DEFVAR_INT ("baud-rate", &baud_rate,
   staticpro (&Qredisplay_dont_pause);
 
   DEFVAR_INT ("baud-rate", &baud_rate,
-    "*The output baud rate of the terminal.\n\
-On most systems, changing this value will affect the amount of padding\n\
-and the other strategic decisions made during redisplay.");
+             doc: /* *The output baud rate of the terminal.
+On most systems, changing this value will affect the amount of padding
+and the other strategic decisions made during redisplay.  */);
   
   DEFVAR_BOOL ("inverse-video", &inverse_video,
   
   DEFVAR_BOOL ("inverse-video", &inverse_video,
-    "*Non-nil means invert the entire frame display.\n\
-This means everything is in inverse video which otherwise would not be.");
+              doc: /* *Non-nil means invert the entire frame display.
+This means everything is in inverse video which otherwise would not be.  */);
   
   DEFVAR_BOOL ("visible-bell", &visible_bell,
   
   DEFVAR_BOOL ("visible-bell", &visible_bell,
-    "*Non-nil means try to flash the frame to represent a bell.");
+              doc: /* *Non-nil means try to flash the frame to represent a bell.
+
+See also `ring-bell-function'.  */);
   
   DEFVAR_BOOL ("no-redraw-on-reenter", &no_redraw_on_reenter,
   
   DEFVAR_BOOL ("no-redraw-on-reenter", &no_redraw_on_reenter,
-    "*Non-nil means no need to redraw entire frame after suspending.\n\
-A non-nil value is useful if the terminal can automatically preserve\n\
-Emacs's frame display when you reenter Emacs.\n\
-It is up to you to set this variable if your terminal can do that.");
+              doc: /* *Non-nil means no need to redraw entire frame after suspending.
+A non-nil value is useful if the terminal can automatically preserve
+Emacs's frame display when you reenter Emacs.
+It is up to you to set this variable if your terminal can do that.  */);
   
   DEFVAR_LISP ("window-system", &Vwindow_system,
   
   DEFVAR_LISP ("window-system", &Vwindow_system,
-    "A symbol naming the window-system under which Emacs is running\n\
-\(such as `x'), or nil if emacs is running on an ordinary terminal.");
+              doc: /* Name of window system that Emacs is displaying through.
+The value is a symbol--for instance, `x' for X windows.
+The value is nil if Emacs is using a text-only terminal.  */);
   
   DEFVAR_LISP ("window-system-version", &Vwindow_system_version,
   
   DEFVAR_LISP ("window-system-version", &Vwindow_system_version,
-    "The version number of the window system in use.\n\
-For X windows, this is 10 or 11.");
+              doc: /* The version number of the window system in use.
+For X windows, this is 10 or 11.  */);
   
   DEFVAR_BOOL ("cursor-in-echo-area", &cursor_in_echo_area,
   
   DEFVAR_BOOL ("cursor-in-echo-area", &cursor_in_echo_area,
-    "Non-nil means put cursor in minibuffer, at end of any message there.");
+              doc: /* Non-nil means put cursor in minibuffer, at end of any message there.  */);
   
   DEFVAR_LISP ("glyph-table", &Vglyph_table,
   
   DEFVAR_LISP ("glyph-table", &Vglyph_table,
-    "Table defining how to output a glyph code to the frame.\n\
-If not nil, this is a vector indexed by glyph code to define the glyph.\n\
-Each element can be:\n\
- integer: a glyph code which this glyph is an alias for.\n\
- string: output this glyph using that string (not impl. in X windows).\n\
- nil: this glyph mod 256 is char code to output,\n\
-    and this glyph / 256 is face code for X windows (see `face-id').");
+              doc: /* Table defining how to output a glyph code to the frame.
+If not nil, this is a vector indexed by glyph code to define the glyph.
+Each element can be:
+ integer: a glyph code which this glyph is an alias for.
+ string: output this glyph using that string (not impl. in X windows).
+ nil: this glyph mod 524288 is the code of a character to output,
+    and this glyph / 524288 is the face number (see `face-id') to use
+    while outputting it.  */);
   Vglyph_table = Qnil;
 
   DEFVAR_LISP ("standard-display-table", &Vstandard_display_table,
   Vglyph_table = Qnil;
 
   DEFVAR_LISP ("standard-display-table", &Vstandard_display_table,
-    "Display table to use for buffers that specify none.\n\
-See `buffer-display-table' for more information.");
+              doc: /* Display table to use for buffers that specify none.
+See `buffer-display-table' for more information.  */);
   Vstandard_display_table = Qnil;
 
   DEFVAR_BOOL ("redisplay-dont-pause", &redisplay_dont_pause,
   Vstandard_display_table = Qnil;
 
   DEFVAR_BOOL ("redisplay-dont-pause", &redisplay_dont_pause,
-    "*Non-nil means update isn't paused when input is detected.");
+              doc: /* *Non-nil means update isn't paused when input is detected.  */);
   redisplay_dont_pause = 0;
 
   /* Initialize `window-system', unless init_display already decided it.  */
   redisplay_dont_pause = 0;
 
   /* Initialize `window-system', unless init_display already decided it.  */