(change_frame_size_1): Save current buffer
[bpt/emacs.git] / src / dispnew.c
index d061f2c..a7441b9 100644 (file)
@@ -1,6 +1,6 @@
 /* Updating of data structures for redisplay.
-   Copyright (C) 1985, 1986, 1987, 1988, 1990, 
-   1992, 1993 Free Software Foundation, Inc.
+   Copyright (C) 1985, 86, 87, 88, 93, 94, 95, 1997
+       Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -16,44 +16,75 @@ GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
 along with GNU Emacs; see the file COPYING.  If not, write to
-the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
 
 
 #include <signal.h>
 
-#include "config.h"
+#include <config.h>
+
 #include <stdio.h>
 #include <ctype.h>
 
+#include "lisp.h"
 #include "termchar.h"
 #include "termopts.h"
 #include "termhooks.h"
-#include "cm.h"
-#include "lisp.h"
+/* cm.h must come after dispextern.h on Windows.  */
 #include "dispextern.h"
+#include "cm.h"
 #include "buffer.h"
+#include "charset.h"
 #include "frame.h"
 #include "window.h"
 #include "commands.h"
 #include "disptab.h"
 #include "indent.h"
+#include "intervals.h"
+#include "blockinput.h"
 
-#include "systty.h"
-#include "systime.h"
+/* I don't know why DEC Alpha OSF1 fail to compile this file if we
+   include the following file.  */
+/* #include "systty.h" */
+#include "syssignal.h"
 
 #ifdef HAVE_X_WINDOWS
 #include "xterm.h"
 #endif /* HAVE_X_WINDOWS */
 
+#ifdef HAVE_NTGUI
+#include "w32term.h"
+#endif /* HAVE_NTGUI */
+
+/* Include systime.h after xterm.h to avoid double inclusion of time.h. */
+#include "systime.h"
+
+#include <errno.h>
+
 #define max(a, b) ((a) > (b) ? (a) : (b))
 #define min(a, b) ((a) < (b) ? (a) : (b))
 
-#ifndef PENDING_OUTPUT_COUNT
 /* 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.  */
+#ifdef __GNU_LIBRARY__
+/* The s- file might have overridden the definition with one that works for
+   the system's C library.  But we are using the GNU C library, so this is
+   the right definition for every system.  */
+#ifdef GNU_LIBRARY_PENDING_OUTPUT_COUNT
+#define PENDING_OUTPUT_COUNT GNU_LIBRARY_PENDING_OUTPUT_COUNT
+#else
+#undef PENDING_OUTPUT_COUNT
+#define        PENDING_OUTPUT_COUNT(FILE) ((FILE)->__bufp - (FILE)->__buffer)
+#endif
+#else /* not __GNU_LIBRARY__ */
+#ifndef PENDING_OUTPUT_COUNT
 #define PENDING_OUTPUT_COUNT(FILE) ((FILE)->_ptr - (FILE)->_base)
 #endif
+#endif
+
+static void change_frame_size_1 ();
 
 /* Nonzero upon entry to redisplay means do not assume anything about
    current contents of actual terminal frame; clear and redraw it.  */
@@ -102,29 +133,21 @@ Lisp_Object Vstandard_display_table;
    positive means at end of text in echo area;
    negative means at beginning of line.  */
 int cursor_in_echo_area;
+
+Lisp_Object Qdisplay_table;
 \f
 /* The currently selected frame.
-   In a single-frame version, this variable always remains 0.  */
+   In a single-frame version, this variable always holds the address of
+   the_only_frame.  */
 
 FRAME_PTR selected_frame;
 
 /* A frame which is not just a minibuffer, or 0 if there are no such
    frames.  This is usually the most recent such frame that was
-   selected.  In a single-frame version, this variable always remains 0.  */
+   selected.  In a single-frame version, this variable always holds
+   the address of the_only_frame.  */
 FRAME_PTR last_nonminibuf_frame;
 
-/* In a single-frame version, the information that would otherwise
-   exist inside frame objects lives in the following structure instead.
-
-   NOTE: the_only_frame is not checked for garbage collection; don't
-   store collectable objects in any of its fields!
-
-   You're not/The only frame in town/...  */
-
-#ifndef MULTI_FRAME
-struct frame the_only_frame;
-#endif
-
 /* This is a vector, made larger whenever it isn't large enough,
    which is used inside `update_frame' to hold the old contents
    of the FRAME_PHYS_LINES of the frame being updated.  */
@@ -136,12 +159,8 @@ FILE *termscript;  /* Stdio stream being used for copy of all output.  */
 
 struct cm Wcm;         /* Structure for info on cursor positioning */
 
-extern short ospeed;   /* Output speed (from sg_ospeed) */
-
 int delayed_size_change;  /* 1 means SIGWINCH happened when not safe.  */
 \f
-#ifdef MULTI_FRAME
-
 DEFUN ("redraw-frame", Fredraw_frame, Sredraw_frame, 1, 1, 0,
   "Clear frame FRAME and output again what is supposed to appear on it.")
   (frame)
@@ -152,7 +171,8 @@ DEFUN ("redraw-frame", Fredraw_frame, Sredraw_frame, 1, 1, 0,
   CHECK_LIVE_FRAME (frame, 0);
   f = XFRAME (frame);
   update_begin (f);
-  /*  set_terminal_modes (); */
+  if (FRAME_MSDOS_P (f))
+    set_terminal_modes ();
   clear_frame ();
   clear_frame_records (f);
   update_end (f);
@@ -169,57 +189,35 @@ redraw_frame (f)
      FRAME_PTR f;
 {
   Lisp_Object frame;
-  XSET (frame, Lisp_Frame, f);
+  XSETFRAME (frame, f);
   Fredraw_frame (frame);
 }
 
-#else
-
-DEFUN ("redraw-frame", Fredraw_frame, Sredraw_frame, 1, 1, "",
-  "Clear frame FRAME and output again what is supposed to appear on it.")
-  (frame)
-     Lisp_Object frame;
+DEFUN ("redraw-display", Fredraw_display, Sredraw_display, 0, 0, "",
+  "Clear and redisplay all visible frames.")
+  ()
 {
-  update_begin (0);
-  set_terminal_modes ();
-  clear_frame ();
-  update_end (0);
-  fflush (stdout);
-  clear_frame_records (0);
-  windows_or_buffers_changed++;
-  /* Mark all windows as INaccurate,
-     so that every window will have its redisplay done.  */
-  mark_window_display_accurate (FRAME_ROOT_WINDOW (0), 0);
+  Lisp_Object tail, frame;
+
+  FOR_EACH_FRAME (tail, frame)
+    if (FRAME_VISIBLE_P (XFRAME (frame)))
+      Fredraw_frame (frame);
+
   return Qnil;
 }
 
-#endif
+/* This is used when frame_garbaged is set.
+   Redraw the individual frames marked as garbaged.  */
 
-DEFUN ("redraw-display", Fredraw_display, Sredraw_display, 0, 0, "",
-  "Clear and redisplay all visible frames.")
-  ()
+void
+redraw_garbaged_frames ()
 {
   Lisp_Object tail, frame;
 
   FOR_EACH_FRAME (tail, frame)
-    /* If we simply redrew all visible frames, whether or not they
-       were garbaged, then this would make all frames clear and
-       nredraw whenever a new frame is created or an existing frame
-       is de-iconified; those events set the global frame_garbaged
-       flag, to which redisplay responds by calling this function.
-       
-       This used to redraw all visible frames; the only advantage of
-       that approach is that if a frame changes from invisible to
-       visible without setting its garbaged flag, it still gets
-       redisplayed.  But that should never happen; since invisible
-       frames are not updated, they should always be marked as
-       garbaged when they become visible again.  If that doesn't
-       happen, it's a bug in the visibility code, not a bug here.  */
     if (FRAME_VISIBLE_P (XFRAME (frame))
        && FRAME_GARBAGED_P (XFRAME (frame)))
       Fredraw_frame (frame);
-
-  return Qnil;
 }
 
 \f
@@ -229,23 +227,24 @@ make_frame_glyphs (frame, empty)
      int empty;
 {
   register int i;
-  register width = FRAME_WIDTH (frame);
+  register width = FRAME_WINDOW_WIDTH (frame);
   register height = FRAME_HEIGHT (frame);
-  register struct frame_glyphs *new =
-    (struct frame_glyphs *) xmalloc (sizeof (struct frame_glyphs));
+  register struct frame_glyphs *new
+    (struct frame_glyphs *) xmalloc (sizeof (struct frame_glyphs));
 
   SET_GLYPHS_FRAME (new, frame);
   new->height = height;
   new->width = width;
   new->used = (int *) xmalloc (height * sizeof (int));
   new->glyphs = (GLYPH **) xmalloc (height * sizeof (GLYPH *));
+  new->charstarts = (int **) xmalloc (height * sizeof (int *));
   new->highlight = (char *) xmalloc (height * sizeof (char));
   new->enable = (char *) xmalloc (height * sizeof (char));
   bzero (new->enable, height * sizeof (char));
   new->bufp = (int *) xmalloc (height * sizeof (int));
 
-#ifdef HAVE_X_WINDOWS
-  if (FRAME_X_P (frame))
+#ifdef HAVE_WINDOW_SYSTEM
+  if (FRAME_WINDOW_P (frame))
     {
       new->top_left_x = (short *) xmalloc (height * sizeof (short));
       new->top_left_y = (short *) xmalloc (height * sizeof (short));
@@ -253,16 +252,20 @@ make_frame_glyphs (frame, empty)
       new->pix_height = (short *) xmalloc (height * sizeof (short));
       new->max_ascent = (short *) xmalloc (height * sizeof (short));
     }
-#endif
+#endif /* HAVE_WINDOW_SYSTEM */
 
   if (empty)
     {
       /* Make the buffer used by decode_mode_spec.  This buffer is also
          used as temporary storage when updating the frame.  See scroll.c. */
       unsigned int total_glyphs = (width + 2) * sizeof (GLYPH);
+      unsigned int total_charstarts = (width + 2) * sizeof (int);
 
       new->total_contents = (GLYPH *) xmalloc (total_glyphs);
       bzero (new->total_contents, total_glyphs);
+
+      new->total_charstarts = (int *) xmalloc (total_charstarts);
+      bzero (new->total_charstarts, total_charstarts);
     }
   else
     {
@@ -272,40 +275,63 @@ make_frame_glyphs (frame, empty)
       bzero (new->total_contents, total_glyphs);
       for (i = 0; i < height; i++)
        new->glyphs[i] = new->total_contents + i * (width + 2) + 1;
+
+      if (!FRAME_TERMCAP_P (frame))
+       {
+         unsigned int total_charstarts = height * (width + 2) * sizeof (int);
+
+         new->total_charstarts = (int *) xmalloc (total_charstarts);
+         bzero (new->total_charstarts, total_charstarts);
+         for (i = 0; i < height; i++)
+           new->charstarts[i] = new->total_charstarts + i * (width + 2) + 1;
+       }
+      else
+       {
+         /* Without a window system, we don't really need charstarts.
+            So use a small amount of space to make enough data structure
+            to prevent crashes in display_text_line.  */
+         new->total_charstarts = (int *) xmalloc ((width + 2) * sizeof (int));
+         for (i = 0; i < height; i++)
+           new->charstarts[i] = new->total_charstarts;
+       }
     }
 
   return new;
 }
 
-static void
+void
 free_frame_glyphs (frame, glyphs)
      FRAME_PTR frame;
      struct frame_glyphs *glyphs;
 {
   if (glyphs->total_contents)
-    free (glyphs->total_contents);
-
-  free (glyphs->used);
-  free (glyphs->glyphs);
-  free (glyphs->highlight);
-  free (glyphs->enable);
-  free (glyphs->bufp);
-
-#ifdef HAVE_X_WINDOWS
-  if (FRAME_X_P (frame))
+    xfree (glyphs->total_contents);
+  if (glyphs->total_charstarts)
+    xfree (glyphs->total_charstarts);
+
+  xfree (glyphs->used);
+  xfree (glyphs->glyphs);
+  xfree (glyphs->highlight);
+  xfree (glyphs->enable);
+  xfree (glyphs->bufp);
+  if (glyphs->charstarts)
+    xfree (glyphs->charstarts);
+
+#ifdef HAVE_WINDOW_SYSTEM
+  if (FRAME_WINDOW_P (frame))
     {
-      free (glyphs->top_left_x);
-      free (glyphs->top_left_y);
-      free (glyphs->pix_width);
-      free (glyphs->pix_height);
-      free (glyphs->max_ascent);
+      xfree (glyphs->top_left_x);
+      xfree (glyphs->top_left_y);
+      xfree (glyphs->pix_width);
+      xfree (glyphs->pix_height);
+      xfree (glyphs->max_ascent);
     }
-#endif
+#endif /* HAVE_WINDOW_SYSTEM */
 
-  free (glyphs);
+  xfree (glyphs);
 }
 
-static void
+void
 remake_frame_glyphs (frame)
      FRAME_PTR frame;
 {
@@ -324,7 +350,7 @@ remake_frame_glyphs (frame)
 
       FRAME_MESSAGE_BUF (frame)
        = (char *) xrealloc (FRAME_MESSAGE_BUF (frame),
-                            FRAME_WIDTH (frame) + 1);
+                            FRAME_MESSAGE_BUF_SIZE (frame) + 1);
 
       if (echo_area_glyphs == old_message_buf)
        echo_area_glyphs = FRAME_MESSAGE_BUF (frame);
@@ -333,12 +359,13 @@ remake_frame_glyphs (frame)
     }
   else
     FRAME_MESSAGE_BUF (frame)
-      = (char *) xmalloc (FRAME_WIDTH (frame) + 1);
+      = (char *) xmalloc (FRAME_MESSAGE_BUF_SIZE (frame) + 1);
 
   FRAME_CURRENT_GLYPHS (frame) = make_frame_glyphs (frame, 0);
   FRAME_DESIRED_GLYPHS (frame) = make_frame_glyphs (frame, 0);
   FRAME_TEMP_GLYPHS (frame) = make_frame_glyphs (frame, 1);
-  SET_FRAME_GARBAGED (frame);
+  if (FRAME_WINDOW_P (frame) || frame == selected_frame)
+    SET_FRAME_GARBAGED (frame);
 }
 \f
 /* Return the hash code of contents of line VPOS in frame-matrix M.  */
@@ -452,6 +479,20 @@ clear_frame_records (frame)
   bzero (FRAME_CURRENT_GLYPHS (frame)->enable, FRAME_HEIGHT (frame));
 }
 
+/* Clear out all display lines for a coming redisplay.  */
+
+void
+init_desired_glyphs (frame)
+     register FRAME_PTR frame;
+{
+  register struct frame_glyphs *desired_glyphs = FRAME_DESIRED_GLYPHS (frame);
+  int vpos;
+  int height = FRAME_HEIGHT (frame);
+
+  for (vpos = 0; vpos < height; vpos++)
+    desired_glyphs->enable[vpos] = 0;
+}
+
 /* Prepare to display on line VPOS starting at HPOS within it.  */
 
 void
@@ -467,9 +508,6 @@ get_display_line (frame, vpos, hpos)
   if (vpos < 0)
     abort ();
 
-  if ((desired_glyphs->enable[vpos]) && desired_glyphs->used[vpos] > hpos)
-    abort ();
-
   if (! desired_glyphs->enable[vpos])
     {
       desired_glyphs->used[vpos] = 0;
@@ -567,13 +605,15 @@ rotate_vector (vector, size, distance)
    Returns nonzero if done, zero if terminal cannot scroll them.  */
 
 int
-scroll_frame_lines (frame, from, end, amount)
+scroll_frame_lines (frame, from, end, amount, newpos)
      register FRAME_PTR frame;
-     int from, end, amount;
+     int from, end, amount, newpos;
 {
   register int i;
   register struct frame_glyphs *current_frame
     = FRAME_CURRENT_GLYPHS (frame);
+  int pos_adjust;
+  int width = FRAME_WINDOW_WIDTH (frame);
 
   if (!line_ins_del_ok)
     return 0;
@@ -594,6 +634,10 @@ scroll_frame_lines (frame, from, end, amount)
                     sizeof (GLYPH *) * (end + amount - from),
                     amount * sizeof (GLYPH *));
 
+      rotate_vector (current_frame->charstarts + from,
+                    sizeof (int *) * (end + amount - from),
+                    amount * sizeof (int *));
+
       safe_bcopy (current_frame->used + from,
                  current_frame->used + from + amount,
                  (end - from) * sizeof current_frame->used[0]);
@@ -606,6 +650,29 @@ scroll_frame_lines (frame, from, end, amount)
                  current_frame->enable + from + amount,
                  (end - from) * sizeof current_frame->enable[0]);
 
+      /* Adjust the lines by an amount
+        that puts the first of them at NEWPOS.  */
+      pos_adjust = newpos - current_frame->charstarts[from + amount][0];
+
+      /* Offset each char position in the charstarts lines we moved
+        by pos_adjust.  */
+      for (i = from + amount; i < end + amount; i++)
+       {
+         int *line = current_frame->charstarts[i];
+         int col;
+         for (col = 0; col < width; col++)
+           if (line[col] > 0)
+             line[col] += pos_adjust;
+       }
+      for (i = from; i < from + amount; i++)
+       {
+         int *line = current_frame->charstarts[i];
+         int col;
+         line[0] = -1;
+         for (col = 0; col < width; col++)
+           line[col] = 0;
+       }
+
       /* Mark the lines made empty by scrolling as enabled, empty and
         normal video.  */
       bzero (current_frame->used + from,
@@ -615,6 +682,7 @@ scroll_frame_lines (frame, from, end, amount)
       for (i = from; i < from + amount; i++)
        {
          current_frame->glyphs[i][0] = '\0';
+         current_frame->charstarts[i][0] = -1;
          current_frame->enable[i] = 1;
        }
 
@@ -622,8 +690,8 @@ scroll_frame_lines (frame, from, end, amount)
                  current_frame->bufp + from + amount,
                  (end - from) * sizeof current_frame->bufp[0]);
 
-#ifdef HAVE_X_WINDOWS
-      if (FRAME_X_P (frame))
+#ifdef HAVE_WINDOW_SYSTEM
+      if (FRAME_WINDOW_P (frame))
        {
          safe_bcopy (current_frame->top_left_x + from,
                      current_frame->top_left_x + from + amount,
@@ -645,7 +713,7 @@ scroll_frame_lines (frame, from, end, amount)
                      current_frame->max_ascent + from + amount,
                      (end - from) * sizeof current_frame->max_ascent[0]);
        }
-#endif                         /* HAVE_X_WINDOWS */
+#endif /* HAVE_WINDOW_SYSTEM */
 
       update_end (frame);
     }
@@ -662,6 +730,10 @@ scroll_frame_lines (frame, from, end, amount)
                     sizeof (GLYPH *) * (end - from - amount),
                     amount * sizeof (GLYPH *));
 
+      rotate_vector (current_frame->charstarts + from + amount,
+                    sizeof (int *) * (end - from - amount),
+                    amount * sizeof (int *));
+
       safe_bcopy (current_frame->used + from,
                  current_frame->used + from + amount,
                  (end - from) * sizeof current_frame->used[0]);
@@ -674,6 +746,29 @@ scroll_frame_lines (frame, from, end, amount)
                  current_frame->enable + from + amount,
                  (end - from) * sizeof current_frame->enable[0]);
 
+      /* Adjust the lines by an amount
+        that puts the first of them at NEWPOS.  */
+      pos_adjust = newpos - current_frame->charstarts[from + amount][0];
+
+      /* Offset each char position in the charstarts lines we moved
+        by pos_adjust.  */
+      for (i = from + amount; i < end + amount; i++)
+       {
+         int *line = current_frame->charstarts[i];
+         int col;
+         for (col = 0; col < width; col++)
+           if (line[col] > 0)
+             line[col] += pos_adjust;
+       }
+      for (i = end + amount; i < end; i++)
+       {
+         int *line = current_frame->charstarts[i];
+         int col;
+         line[0] = -1;
+         for (col = 0; col < width; col++)
+           line[col] = 0;
+       }
+
       /* Mark the lines made empty by scrolling as enabled, empty and
         normal video.  */
       bzero (current_frame->used + end + amount,
@@ -683,6 +778,7 @@ scroll_frame_lines (frame, from, end, amount)
       for (i = end + amount; i < end; i++)
        {
          current_frame->glyphs[i][0] = '\0';
+         current_frame->charstarts[i][0] = 0;
          current_frame->enable[i] = 1;
        }
 
@@ -690,8 +786,8 @@ scroll_frame_lines (frame, from, end, amount)
                  current_frame->bufp + from + amount,
                  (end - from) * sizeof current_frame->bufp[0]);
 
-#ifdef HAVE_X_WINDOWS
-      if (FRAME_X_P (frame))
+#ifdef HAVE_WINDOW_SYSTEM
+      if (FRAME_WINDOW_P (frame))
        {
          safe_bcopy (current_frame->top_left_x + from,
                      current_frame->top_left_x + from + amount,
@@ -713,7 +809,7 @@ scroll_frame_lines (frame, from, end, amount)
                      current_frame->max_ascent + from + amount,
                      (end - from) * sizeof current_frame->max_ascent[0]);
        }
-#endif                         /* HAVE_X_WINDOWS */
+#endif /* HAVE_WINDOW_SYSTEM */
 
       update_end (frame);
     }
@@ -731,8 +827,8 @@ preserve_other_columns (w)
   register int vpos;
   register struct frame_glyphs *current_frame, *desired_frame;
   register FRAME_PTR frame = XFRAME (w->frame);
-  int start = XFASTINT (w->left);
-  int end = XFASTINT (w->left) + XFASTINT (w->width);
+  int start = WINDOW_LEFT_MARGIN (w);
+  int end = WINDOW_RIGHT_EDGE (w);
   int bot = XFASTINT (w->top) + XFASTINT (w->height);
 
   current_frame = FRAME_CURRENT_GLYPHS (frame);
@@ -747,7 +843,11 @@ preserve_other_columns (w)
              int len;
 
              bcopy (current_frame->glyphs[vpos],
-                    desired_frame->glyphs[vpos], start);
+                    desired_frame->glyphs[vpos],
+                    start * sizeof (current_frame->glyphs[vpos][0]));
+             bcopy (current_frame->charstarts[vpos],
+                    desired_frame->charstarts[vpos],
+                    start * sizeof (current_frame->charstarts[vpos][0]));
              len = min (start, current_frame->used[vpos]);
              if (desired_frame->used[vpos] < len)
                desired_frame->used[vpos] = len;
@@ -756,11 +856,19 @@ preserve_other_columns (w)
              && desired_frame->used[vpos] < current_frame->used[vpos])
            {
              while (desired_frame->used[vpos] < end)
-               desired_frame->glyphs[vpos][desired_frame->used[vpos]++]
-                 = SPACEGLYPH;
+               {
+                 int used = desired_frame->used[vpos]++;
+                 desired_frame->glyphs[vpos][used] = SPACEGLYPH;
+                 desired_frame->glyphs[vpos][used] = 0;
+               }
              bcopy (current_frame->glyphs[vpos] + end,
                     desired_frame->glyphs[vpos] + end,
-                    current_frame->used[vpos] - end);
+                    ((current_frame->used[vpos] - end)
+                     * sizeof (current_frame->glyphs[vpos][0])));
+             bcopy (current_frame->charstarts[vpos] + end,
+                    desired_frame->charstarts[vpos] + end,
+                    ((current_frame->used[vpos] - end)
+                     * sizeof (current_frame->charstarts[vpos][0])));
              desired_frame->used[vpos] = current_frame->used[vpos];
            }
        }
@@ -782,8 +890,8 @@ preserve_my_columns (w)
   register int vpos, fin;
   register struct frame_glyphs *l1, *l2;
   register FRAME_PTR frame = XFRAME (w->frame);
-  int start = XFASTINT (w->left);
-  int end = XFASTINT (w->left) + XFASTINT (w->width);
+  int start = WINDOW_LEFT_MARGIN (w);
+  int end = WINDOW_RIGHT_EDGE (w);
   int bot = XFASTINT (w->top) + XFASTINT (w->height);
 
   for (vpos = XFASTINT (w->top); vpos < bot; vpos++)
@@ -806,6 +914,89 @@ preserve_my_columns (w)
 
 #endif
 \f
+/* Adjust by ADJUST the charstart values in window W
+   after vpos VPOS, which counts relative to the frame
+   (not relative to W itself).  */
+
+void
+adjust_window_charstarts (w, vpos, adjust)
+     struct window *w;
+     int vpos;
+     int adjust;
+{
+  int left = WINDOW_LEFT_MARGIN (w);
+  int top = XFASTINT (w->top);
+  int right = left + window_internal_width (w);
+  int bottom = top + window_internal_height (w);
+  int i;
+
+  for (i = vpos + 1; i < bottom; i++)
+    {
+      int *charstart
+       = FRAME_CURRENT_GLYPHS (XFRAME (WINDOW_FRAME (w)))->charstarts[i];
+      int j;
+      for (j = left; j < right; j++)
+       if (charstart[j] > 0)
+         charstart[j] += adjust;
+    }
+}
+
+/* Check the charstarts values in the area of window W
+   for internal consistency.  We cannot check that they are "right";
+   we can only look for something nonsensical.  */
+
+verify_charstarts (w)
+     struct window *w;
+{
+  FRAME_PTR f = XFRAME (WINDOW_FRAME (w));
+  int i;
+  int top = XFASTINT (w->top);
+  int bottom = top + window_internal_height (w);
+  int left = WINDOW_LEFT_MARGIN (w);
+  int right = left + window_internal_width (w);
+  int next_line;
+  int truncate = (XINT (w->hscroll)
+                 || (truncate_partial_width_windows
+                     && !WINDOW_FULL_WIDTH_P (w))
+                 || !NILP (XBUFFER (w->buffer)->truncate_lines));
+
+  for (i = top; i < bottom; i++)
+    {
+      int j;
+      int last;
+      int *charstart = FRAME_CURRENT_GLYPHS (f)->charstarts[i];
+
+      if (i != top)
+       {
+         if (truncate)
+           {
+             /* If we are truncating lines, allow a jump
+                in charstarts from one line to the next.  */
+             if (charstart[left] < next_line)
+               abort ();
+           }
+         else
+           {
+             if (charstart[left] != next_line)
+               abort ();
+           }
+       }
+
+      for (j = left; j < right; j++)
+       if (charstart[j] > 0)
+         last = charstart[j];
+      /* Record where the next line should start.  */
+      next_line = last;
+      if (BUF_ZV (XBUFFER (w->buffer)) != last)
+       {
+         /* If there's a newline between the two lines, count that.  */
+         int endchar = *BUF_CHAR_ADDRESS (XBUFFER (w->buffer), last);
+         if (endchar == '\n')
+           next_line++;
+       }
+    }
+}
+\f
 /* On discovering that the redisplay for a window was no good,
    cancel the columns of that window, so that when the window is
    displayed over again get_display_line will not complain.  */
@@ -814,9 +1005,9 @@ cancel_my_columns (w)
      struct window *w;
 {
   register int vpos;
-  register struct frame_glyphs *desired_glyphs =
-    FRAME_DESIRED_GLYPHS (XFRAME (w->frame));
-  register int start = XFASTINT (w->left);
+  register struct frame_glyphs *desired_glyphs
+    FRAME_DESIRED_GLYPHS (XFRAME (w->frame));
+  register int start = WINDOW_LEFT_MARGIN (w);
   register int bot = XFASTINT (w->top) + XFASTINT (w->height);
 
   for (vpos = XFASTINT (w->top); vpos < bot; vpos++)
@@ -855,10 +1046,10 @@ direct_output_for_insert (g)
     int vpos = FRAME_CURSOR_Y (frame);
 
   /* Give up if about to continue line.  */
-  if (hpos >= XFASTINT (w->left) + window_internal_width (w) - 1
+  if (hpos >= WINDOW_LEFT_MARGIN (w) + window_internal_width (w) - 1
     
   /* Avoid losing if cursor is in invisible text off left margin */
-      || (XINT (w->hscroll) && hpos == XFASTINT (w->left))
+      || (XINT (w->hscroll) && hpos == WINDOW_LEFT_MARGIN (w))
     
   /* Give up if cursor outside window (in minibuf, probably) */
       || cursor_in_echo_area
@@ -871,16 +1062,41 @@ direct_output_for_insert (g)
   /* Give up if buffer appears in two places.  */
       || buffer_shared > 1
 
+#ifdef USE_TEXT_PROPERTIES
+  /* Intervals have already been adjusted, point is after the
+     character that was just inserted. */
+  /* Give up if character is invisible. */
+  /* Give up if character has a face property.
+     At the moment we only lose at end of line or end of buffer
+     and only with faces that have some background */
+  /* Instead of wasting time, give up if character has any text properties */
+      || ! NILP (Ftext_properties_at (make_number (PT - 1), Qnil))
+#endif
+
   /* Give up if w is minibuffer and a message is being displayed there */
       || (MINI_WINDOW_P (w) && echo_area_glyphs))
     return 0;
 
-  current_frame->glyphs[vpos][hpos] = g;
+  {
+    int face = 0;
+#ifdef HAVE_FACES
+    int dummy;
+
+    if (FRAME_WINDOW_P (frame) || FRAME_MSDOS_P (frame))
+      face = compute_char_face (frame, w, PT - 1, -1, -1, &dummy, PT, 0);
+#endif
+    current_frame->glyphs[vpos][hpos] = MAKE_GLYPH (frame, g, face);
+    current_frame->charstarts[vpos][hpos] = PT - 1;
+    /* Record the entry for after the newly inserted character.  */
+    current_frame->charstarts[vpos][hpos + 1] = PT;
+    adjust_window_charstarts (w, vpos, 1);
+  }
   unchanged_modified = MODIFF;
   beg_unchanged = GPT - BEG;
-  XFASTINT (w->last_point) = point;
-  XFASTINT (w->last_point_x) = hpos;
-  XFASTINT (w->last_modified) = MODIFF;
+  XSETFASTINT (w->last_point, PT);
+  XSETFASTINT (w->last_point_x, hpos + 1);
+  XSETFASTINT (w->last_modified, MODIFF);
+  XSETFASTINT (w->last_overlay_modified, OVERLAY_MODIFF);
 
   reassert_line_highlight (0, vpos);
   write_glyphs (&current_frame->glyphs[vpos][hpos], 1);
@@ -901,21 +1117,65 @@ direct_output_forward_char (n)
 {
   register FRAME_PTR frame = selected_frame;
   register struct window *w = XWINDOW (selected_window);
+  Lisp_Object position;
+  int hpos = FRAME_CURSOR_X (frame);
+
+  /* Give up if in truncated text at end of line.  */
+  /* This check is not redundant.  */
+  if (hpos >= WINDOW_LEFT_MARGIN (w) + window_internal_width (w) - 1)
+    return 0;
+
+  /* Give up if the buffer's direction is reversed (i.e. right-to-left).  */
+  if (!NILP (XBUFFER(w->buffer)->direction_reversed))
+    return 0;
 
   /* Avoid losing if cursor is in invisible text off left margin
      or about to go off either side of window.  */
-  if ((FRAME_CURSOR_X (frame) == XFASTINT (w->left)
+  if ((FRAME_CURSOR_X (frame) == WINDOW_LEFT_MARGIN (w)
        && (XINT (w->hscroll) || n < 0))
       || (n > 0
-         && (FRAME_CURSOR_X (frame) + 1 >= window_internal_width (w) - 1))
+         && (FRAME_CURSOR_X (frame) + 1 
+             >= XFASTINT (w->left) + window_internal_width (w) - 1))
+      /* BUG FIX: Added "XFASTINT (w->left)".  Without this,
+        direct_output_forward_char() always fails on "the right"
+        window.  */
       || cursor_in_echo_area)
     return 0;
 
+  /* Can't use direct output if highlighting a region.  */
+  if (!NILP (Vtransient_mark_mode) && !NILP (current_buffer->mark_active))
+    return 0;
+
+  /* Can't use direct output at an overlay boundary; it might have
+     before-string or after-string properties.  */
+  if (overlay_touches_p (PT) || overlay_touches_p (PT - n))
+    return 0;
+
+#ifdef USE_TEXT_PROPERTIES
+  /* Don't use direct output next to an invisible character
+     since we might need to do something special.  */
+
+  XSETFASTINT (position, PT);
+  if (XFASTINT (position) < ZV
+      && ! NILP (Fget_char_property (position,
+                                    Qinvisible,
+                                    selected_window)))
+    return 0;
+
+  XSETFASTINT (position, PT - 1);
+  if (XFASTINT (position) >= BEGV
+      && ! NILP (Fget_char_property (position,
+                                    Qinvisible,
+                                    selected_window)))
+    return 0;
+#endif
+
   FRAME_CURSOR_X (frame) += n;
-  XFASTINT (w->last_point_x) = FRAME_CURSOR_X (frame);
-  XFASTINT (w->last_point) = point;
+  XSETFASTINT (w->last_point_x, FRAME_CURSOR_X (frame));
+  XSETFASTINT (w->last_point, PT);
   cursor_to (FRAME_CURSOR_Y (frame), FRAME_CURSOR_X (frame));
   fflush (stdout);
+
   return 1;
 }
 \f
@@ -931,16 +1191,22 @@ update_frame (f, force, inhibit_hairy_id)
      int force;
      int inhibit_hairy_id;
 {
-  register struct frame_glyphs *current_frame = FRAME_CURRENT_GLYPHS (f);
-  register struct frame_glyphs *desired_frame = FRAME_DESIRED_GLYPHS (f);
+  register struct frame_glyphs *current_frame;
+  register struct frame_glyphs *desired_frame = 0;
   register int i;
   int pause;
   int preempt_count = baud_rate / 2400 + 1;
   extern input_pending;
-#ifdef HAVE_X_WINDOWS
+#ifdef HAVE_WINDOW_SYSTEM
   register int downto, leftmost;
 #endif
 
+  if (baud_rate != FRAME_COST_BAUD_RATE (f))
+    calculate_costs (f);
+
+  if (preempt_count <= 0)
+    preempt_count = 1;
+
   if (FRAME_HEIGHT (f) == 0) abort (); /* Some bug zeros some core */
 
   detect_input_pending ();
@@ -955,6 +1221,10 @@ update_frame (f, force, inhibit_hairy_id)
   if (!line_ins_del_ok)
     inhibit_hairy_id = 1;
 
+  /* These are separate to avoid a possible bug in the AIX C compiler.  */
+  current_frame = FRAME_CURRENT_GLYPHS (f);
+  desired_frame = FRAME_DESIRED_GLYPHS (f);
+
   /* See if any of the desired lines are enabled; don't compute for
      i/d line if just want cursor motion. */
   for (i = 0; i < FRAME_HEIGHT (f); i++)
@@ -970,21 +1240,21 @@ update_frame (f, force, inhibit_hairy_id)
   if (desired_frame->enable[FRAME_HEIGHT (f) - 1])
     update_line (f, FRAME_HEIGHT (f) - 1);
 
-#ifdef HAVE_X_WINDOWS
-  if (FRAME_X_P (f))
+#ifdef HAVE_WINDOW_SYSTEM
+  if (FRAME_WINDOW_P (f))
     {
-      leftmost = downto = f->display.x->internal_border_width;
+      leftmost = downto = FRAME_INTERNAL_BORDER_WIDTH (f);
       if (desired_frame->enable[0])
        {
          current_frame->top_left_x[FRAME_HEIGHT (f) - 1] = leftmost;
          current_frame->top_left_y[FRAME_HEIGHT (f) - 1]
-           = PIXEL_HEIGHT (f) - f->display.x->internal_border_width
+           = PIXEL_HEIGHT (f) - FRAME_INTERNAL_BORDER_WIDTH (f)
              - current_frame->pix_height[FRAME_HEIGHT (f) - 1];
          current_frame->top_left_x[0] = leftmost;
          current_frame->top_left_y[0] = downto;
        }
     }
-#endif /* HAVE_X_WINDOWS */
+#endif /* HAVE_WINDOW_SYSTEM */
 
   /* Now update the rest of the lines. */
   for (i = 0; i < FRAME_HEIGHT (f) - 1 && (force || !input_pending); i++)
@@ -1011,35 +1281,46 @@ update_frame (f, force, inhibit_hairy_id)
                        outq = PENDING_OUTPUT_COUNT (stdout);
 #endif
                      outq *= 10;
-                     sleep (outq / baud_rate);
+                     if (baud_rate <= outq && baud_rate > 0)
+                       sleep (outq / baud_rate);
                    }
                }
-             if ((i - 1) % preempt_count == 0)
-               detect_input_pending ();
            }
 
+         if ((i - 1) % preempt_count == 0)
+           detect_input_pending ();
+
          update_line (f, i);
-#ifdef HAVE_X_WINDOWS
-         if (FRAME_X_P (f))
+#ifdef HAVE_WINDOW_SYSTEM
+         if (FRAME_WINDOW_P (f))
            {
              current_frame->top_left_y[i] = downto;
              current_frame->top_left_x[i] = leftmost;
            }
-#endif /* HAVE_X_WINDOWS */
+#endif /* HAVE_WINDOW_SYSTEM */
        }
 
-#ifdef HAVE_X_WINDOWS
-      if (FRAME_X_P (f))
+#ifdef HAVE_WINDOW_SYSTEM
+      if (FRAME_WINDOW_P (f))
        downto += current_frame->pix_height[i];
-#endif
+#endif /* HAVE_WINDOW_SYSTEM */
     }
   pause = (i < FRAME_HEIGHT (f) - 1) ? i : 0;
 
   /* Now just clean up termcap drivers and set cursor, etc.  */
   if (!pause)
     {
-      if (cursor_in_echo_area
-         && FRAME_HAS_MINIBUF_P (f))
+      if ((cursor_in_echo_area
+          /* If we are showing a message instead of the minibuffer,
+             show the cursor for the message instead of for the
+             (now hidden) minibuffer contents.  */
+          || (EQ (minibuf_window, selected_window)
+              && EQ (minibuf_window, echo_area_window)
+              && echo_area_glyphs != 0))
+         /* These cases apply only to the frame that contains
+            the active minibuffer window.  */
+         && FRAME_HAS_MINIBUF_P (f)
+         && EQ (FRAME_MINIBUF_WINDOW (f), echo_area_window))
        {
          int top = XINT (XWINDOW (FRAME_MINIBUF_WINDOW (f))->top);
          int row, col;
@@ -1064,7 +1345,7 @@ update_frame (f, force, inhibit_hairy_id)
                }
              while (row > top && col == 0);
 
-             if (col >= FRAME_WIDTH (f))
+             if (col >= FRAME_WINDOW_WIDTH (f))
                {
                  col = 0;
                  if (row < FRAME_HEIGHT (f) - 1)
@@ -1075,8 +1356,9 @@ update_frame (f, force, inhibit_hairy_id)
          cursor_to (row, col);
        }
       else
-       cursor_to (FRAME_CURSOR_Y (f), max (min (FRAME_CURSOR_X (f),
-                                                 FRAME_WIDTH (f) - 1), 0));
+       cursor_to (FRAME_CURSOR_Y (f), 
+                  max (min (FRAME_CURSOR_X (f),
+                            FRAME_WINDOW_WIDTH (f) - 1), 0));
     }
 
   update_end (f);
@@ -1091,7 +1373,7 @@ update_frame (f, force, inhibit_hairy_id)
   if (FRAME_HEIGHT (f) == 0) abort (); /* Some bug zeros some core */
   display_completed = !pause;
 
-  bzero (desired_frame->enable, FRAME_HEIGHT (f));
+  bzero (FRAME_DESIRED_GLYPHS (f)->enable, FRAME_HEIGHT (f));
   return pause;
 }
 
@@ -1101,12 +1383,14 @@ update_frame (f, force, inhibit_hairy_id)
 void
 quit_error_check ()
 {
+#if 0
   if (FRAME_DESIRED_GLYPHS (selected_frame) == 0)
     return;
   if (FRAME_DESIRED_GLYPHS (selected_frame)->enable[0])
     abort ();
   if (FRAME_DESIRED_GLYPHS (selected_frame)->enable[FRAME_HEIGHT (selected_frame) - 1])
     abort ();
+#endif
 }
 \f
 /* Decide what insert/delete line to do, and do it */
@@ -1122,6 +1406,7 @@ scrolling (frame)
   int *old_hash = (int *) alloca (FRAME_HEIGHT (frame) * sizeof (int));
   int *new_hash = (int *) alloca (FRAME_HEIGHT (frame) * sizeof (int));
   int *draw_cost = (int *) alloca (FRAME_HEIGHT (frame) * sizeof (int));
+  int *old_draw_cost = (int *) alloca (FRAME_HEIGHT (frame) * sizeof (int));
   register int i;
   int free_at_end_vpos = FRAME_HEIGHT (frame);
   register struct frame_glyphs *current_frame = FRAME_CURRENT_GLYPHS (frame);
@@ -1142,9 +1427,17 @@ scrolling (frame)
        return 0;
       old_hash[i] = line_hash_code (current_frame, i);
       if (! desired_frame->enable[i])
-       new_hash[i] = old_hash[i];
+       {
+         /* This line cannot be redrawn, so don't let scrolling mess it.  */
+         new_hash[i] = old_hash[i];
+#define INFINITY 1000000       /* Taken from scroll.c */
+         draw_cost[i] = INFINITY;
+       }
       else
-       new_hash[i] = line_hash_code (desired_frame, i);
+       {
+         new_hash[i] = line_hash_code (desired_frame, i);
+         draw_cost[i] = line_draw_cost (desired_frame, i);
+       }
 
       if (old_hash[i] != new_hash[i])
        {
@@ -1153,11 +1446,11 @@ scrolling (frame)
        }
       else if (i == unchanged_at_top)
        unchanged_at_top++;
-      draw_cost[i] = line_draw_cost (desired_frame, i);
+      old_draw_cost[i] = line_draw_cost (current_frame, i);
     }
 
   /* If changed lines are few, don't allow preemption, don't scroll.  */
-  if (changed_lines < baud_rate / 2400
+  if (!scroll_region_ok && changed_lines < baud_rate / 2400
       || unchanged_at_bottom == FRAME_HEIGHT (frame))
     return 1;
 
@@ -1171,7 +1464,7 @@ scrolling (frame)
 
   /* If large window, fast terminal and few lines in common between
      current frame and desired frame, don't bother with i/d calc. */
-  if (window_size >= 18 && baud_rate > 2400
+  if (!scroll_region_ok && window_size >= 18 && baud_rate > 2400
       && (window_size >=
          10 * scrolling_max_lines_saved (unchanged_at_top,
                                          FRAME_HEIGHT (frame) - unchanged_at_bottom,
@@ -1180,6 +1473,7 @@ scrolling (frame)
 
   scrolling_1 (frame, window_size, unchanged_at_top, unchanged_at_bottom,
               draw_cost + unchanged_at_top - 1,
+              old_draw_cost + unchanged_at_top - 1,
               old_hash + unchanged_at_top - 1,
               new_hash + unchanged_at_top - 1,
               free_at_end_vpos - unchanged_at_top);
@@ -1194,7 +1488,8 @@ buffer_posn_from_coords (window, col, line)
      struct window *window;
      int col, line;
 {
-  int window_left = XFASTINT (window->left);
+  int hscroll = XINT (window->hscroll);
+  int window_left = WINDOW_LEFT_MARGIN (window);
 
   /* The actual width of the window is window->width less one for the
      DISP_CONTINUE_GLYPH, and less one if it's not the rightmost
@@ -1210,15 +1505,22 @@ buffer_posn_from_coords (window, col, line)
 
   current_buffer = XBUFFER (window->buffer);
 
+  /* We can't get a correct result in this case,
+     but at least prevent compute_motion from crashing.  */
+  if (startp < BEGV)
+    startp = BEGV;
+
   /* It would be nice if we could use FRAME_CURRENT_GLYPHS (XFRAME
      (window->frame))->bufp to avoid scanning from the very top of
      the window, but it isn't maintained correctly, and I'm not even
      sure I will keep it.  */
   posn = compute_motion (startp, 0,
-                        (window == XWINDOW (minibuf_window) && startp == 1
-                         ? minibuf_prompt_width : 0),
-                        ZV, line, col - window_left,
-                        window_width, XINT (window->hscroll), 0);
+                        ((window == XWINDOW (minibuf_window) && startp == BEG
+                          ? minibuf_prompt_width : 0)
+                         + (hscroll ? 1 - hscroll : 0)),
+                        0,
+                        ZV, line, col,
+                        window_width, hscroll, 0, window);
 
   current_buffer = old_current_buffer;
 
@@ -1254,7 +1556,7 @@ count_match (str1, str2)
 /* Char insertion/deletion cost vector, from term.c */
 extern int *char_ins_del_vector;
 
-#define char_ins_del_cost(f) (&char_ins_del_vector[FRAME_WIDTH((f))])
+#define char_ins_del_cost(f) (&char_ins_del_vector[FRAME_WINDOW_WIDTH((f))])
 
 static void
 update_line (frame, vpos)
@@ -1262,9 +1564,10 @@ update_line (frame, vpos)
      int vpos;
 {
   register GLYPH *obody, *nbody, *op1, *op2, *np1, *temp;
+  int *temp1;
   int tem;
   int osp, nsp, begmatch, endmatch, olen, nlen;
-  int save;
+  GLYPH save;
   register struct frame_glyphs *current_frame
     = FRAME_CURRENT_GLYPHS (frame);
   register struct frame_glyphs *desired_frame
@@ -1292,7 +1595,7 @@ update_line (frame, vpos)
       if (! current_frame->highlight[vpos])
        {
          if (!must_write_spaces)
-           while (obody[olen - 1] == SPACEGLYPH && olen > 0)
+           while (olen > 0 && obody[olen - 1] == SPACEGLYPH)
              olen--;
        }
       else
@@ -1301,7 +1604,7 @@ update_line (frame, vpos)
             spaces all the way to the frame edge
             so that the reverse video extends all the way across.  */
 
-         while (olen < FRAME_WIDTH (frame) - 1)
+         while (olen < FRAME_WINDOW_WIDTH (frame) - 1)
            obody[olen++] = SPACEGLYPH;
        }
     }
@@ -1312,16 +1615,16 @@ update_line (frame, vpos)
   current_frame->highlight[vpos] = desired_frame->highlight[vpos];
   current_frame->bufp[vpos] = desired_frame->bufp[vpos];
 
-#ifdef HAVE_X_WINDOWS
-  if (FRAME_X_P (frame))
+#ifdef HAVE_WINDOW_SYSTEM
+  if (FRAME_WINDOW_P (frame))
     {
       current_frame->pix_width[vpos]
        = current_frame->used[vpos]
-         * FONT_WIDTH (frame->display.x->font);
+         * FONT_WIDTH (FRAME_FONT (frame));
       current_frame->pix_height[vpos]
-       = FONT_HEIGHT (frame->display.x->font);
+       = FRAME_LINE_HEIGHT (frame);
     }
-#endif /* HAVE_X_WINDOWS */
+#endif /* HAVE_WINDOW_SYSTEM */
 
   if (!desired_frame->enable[vpos])
     {
@@ -1347,7 +1650,7 @@ update_line (frame, vpos)
         all the way to the frame edge
         so that the reverse video extends all the way across.  */
 
-      while (nlen < FRAME_WIDTH (frame) - 1)
+      while (nlen < FRAME_WINDOW_WIDTH (frame) - 1)
        nbody[nlen++] = SPACEGLYPH;
     }
 
@@ -1356,13 +1659,34 @@ update_line (frame, vpos)
     {
       int i,j;
 
+#if 0
+      if (FRAME_X_P (frame))
+       {
+         /* Under X, erase everything we are going to rewrite,
+            and rewrite everything from the first char that's changed.
+            This is part of supporting fonts like Courier
+            whose chars can overlap outside the char width.  */
+         for (i = 0; i < nlen; i++)
+           if (i >= olen || nbody[i] != obody[i])
+             break;
+
+         cursor_to (vpos, i);
+         if (i != olen)
+           clear_end_of_line (olen);
+         write_glyphs (nbody + i, nlen - i);
+       }
+      else
+       {}
+#endif /* 0 */
       for (i = 0; i < nlen; i++)
        {
          if (i >= olen || nbody[i] != obody[i])    /* A non-matching char. */
            {
              cursor_to (vpos, i);
-             for (j = 1; (i + j < nlen &&
-                          (i + j >= olen || nbody[i+j] != obody[i+j]));
+             for (j = 1;
+                  (i + j < nlen
+                   && (i + j >= olen || nbody[i + j] != obody[i + j]
+                       || (nbody[i + j] & GLYPH_MASK_PADDING)));
                   j++);
 
              /* Output this run of non-matching chars.  */ 
@@ -1385,6 +1709,11 @@ update_line (frame, vpos)
       desired_frame->glyphs[vpos] = current_frame->glyphs[vpos];
       current_frame->glyphs[vpos] = temp;
 
+      /* Exchange charstarts between current_frame and new_frame.  */
+      temp1 = desired_frame->charstarts[vpos];
+      desired_frame->charstarts[vpos] = current_frame->charstarts[vpos];
+      current_frame->charstarts[vpos] = temp1;
+
       return;
     }
 
@@ -1403,6 +1732,11 @@ update_line (frame, vpos)
       desired_frame->glyphs[vpos] = current_frame->glyphs[vpos];
       current_frame->glyphs[vpos] = temp;
 
+      /* Exchange charstarts between current_frame and new_frame.  */
+      temp1 = desired_frame->charstarts[vpos];
+      desired_frame->charstarts[vpos] = current_frame->charstarts[vpos];
+      current_frame->charstarts[vpos] = temp1;
+
       return;
     }
 
@@ -1510,7 +1844,7 @@ update_line (frame, vpos)
             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_WIDTH (frame))
+         if (nlen == FRAME_WINDOW_WIDTH (frame))
            olen = 0;
          write_glyphs (nbody + nsp + begmatch, nlen - tem);
 
@@ -1524,7 +1858,7 @@ update_line (frame, vpos)
             it will lose one way or another (depending on AutoWrap)
             to clear to end of line after outputting all the text.
             So pause with one character to go and clear the line then.  */
-         if (nlen == FRAME_WIDTH (frame) && fast_clear_end_of_line && olen > nlen)
+         if (nlen == FRAME_WINDOW_WIDTH (frame) && fast_clear_end_of_line && olen > nlen)
            {
              /* endmatch must be zero, and tem must equal nsp + begmatch */
              write_glyphs (nbody + tem, nlen - tem - 1);
@@ -1539,8 +1873,24 @@ update_line (frame, vpos)
        }
       else if (nlen > olen)
        {
-         write_glyphs (nbody + nsp + begmatch, olen - tem);
-         insert_glyphs (nbody + nsp + begmatch + olen - tem, nlen - olen);
+         /* Here, we used to have the following simple code:
+            ----------------------------------------
+            write_glyphs (nbody + nsp + begmatch, olen - tem);
+            insert_glyphs (nbody + nsp + begmatch + olen - tem, nlen - olen);
+            ----------------------------------------
+            but it doesn't work if nbody[nsp + begmatch + olen - tem]
+            is a padding glyph.  */
+         int out = olen - tem; /* Columns to be overwritten originally.  */
+         int del;
+
+         /* Calculate columns we can actually overwrite.  */
+         while (nbody[nsp + begmatch + out] & GLYPH_MASK_PADDING) out--;
+         write_glyphs (nbody + nsp + begmatch, out);
+         /* If we left columns to be overwritten. we must delete them.  */
+         del = olen - tem - out;
+         if (del > 0) delete_glyphs (del);
+         /* At last, we insert columns not yet written out.  */
+         insert_glyphs (nbody + nsp + begmatch + out, nlen - olen + del);
          olen = nlen;
        }
       else if (olen > nlen)
@@ -1563,6 +1913,100 @@ update_line (frame, vpos)
   temp = desired_frame->glyphs[vpos];
   desired_frame->glyphs[vpos] = current_frame->glyphs[vpos];
   current_frame->glyphs[vpos] = temp;
+
+  /* Exchange charstarts between current_frame and new_frame.  */
+  temp1 = desired_frame->charstarts[vpos];
+  desired_frame->charstarts[vpos] = current_frame->charstarts[vpos];
+  current_frame->charstarts[vpos] = temp1;
+}
+\f
+/* A vector of size >= 2 * NFRAMES + 3 * NBUFFERS + 1, containing the
+   session's frames, frame names, buffers, buffer-read-only flags, and
+   buffer-modified-flags, and a trailing sentinel (so we don't need to
+   add length checks).  */
+static Lisp_Object frame_and_buffer_state;
+
+DEFUN ("frame-or-buffer-changed-p", Fframe_or_buffer_changed_p,
+  Sframe_or_buffer_changed_p, 0, 0, 0,
+  "Return non-nil if the frame and buffer state appears to have changed.\n\
+The state variable is an internal vector containing all frames and buffers,\n\
+aside from buffers whose names start with space,\n\
+along with the buffers' read-only and modified flags, which allows a fast\n\
+check to see whether the menu bars might need to be recomputed.\n\
+If this function returns non-nil, it updates the internal vector to reflect\n\
+the current state.\n")
+  ()
+{
+  Lisp_Object tail, frame, buf;
+  Lisp_Object *vecp;
+  int n;
+
+  vecp = XVECTOR (frame_and_buffer_state)->contents;
+  FOR_EACH_FRAME (tail, frame)
+    {
+      if (!EQ (*vecp++, frame))
+       goto changed;
+      if (!EQ (*vecp++, XFRAME (frame)->name))
+       goto changed;
+    }
+  /* Check that the buffer info matches.
+     No need to test for the end of the vector
+     because the last element of the vector is lambda
+     and that will always cause a mismatch.  */
+  for (tail = Vbuffer_alist; CONSP (tail); tail = XCONS (tail)->cdr)
+    {
+      buf = XCONS (XCONS (tail)->car)->cdr;
+      /* Ignore buffers that aren't included in buffer lists.  */
+      if (XSTRING (XBUFFER (buf)->name)->data[0] == ' ')
+       continue;
+      if (!EQ (*vecp++, buf))
+       goto changed;
+      if (!EQ (*vecp++, XBUFFER (buf)->read_only))
+       goto changed;
+      if (!EQ (*vecp++, Fbuffer_modified_p (buf)))
+       goto changed;
+    }
+  /* Detect deletion of a buffer at the end of the list.  */
+  if (EQ (*vecp, Qlambda))
+    return Qnil;
+ changed:
+  /* Start with 1 so there is room for at least one lambda at the end.  */
+  n = 1;
+  FOR_EACH_FRAME (tail, frame)
+    n += 2;
+  for (tail = Vbuffer_alist; CONSP (tail); tail = XCONS (tail)->cdr)
+    n += 3;
+  /* Reallocate the vector if it's grown, or if it's shrunk a lot.  */
+  if (n > XVECTOR (frame_and_buffer_state)->size
+      || n + 20 < XVECTOR (frame_and_buffer_state)->size / 2)
+    /* Add 20 extra so we grow it less often.  */
+    frame_and_buffer_state = Fmake_vector (make_number (n + 20), Qlambda);
+  vecp = XVECTOR (frame_and_buffer_state)->contents;
+  FOR_EACH_FRAME (tail, frame)
+    {
+      *vecp++ = frame;
+      *vecp++ = XFRAME (frame)->name;
+    }
+  for (tail = Vbuffer_alist; CONSP (tail); tail = XCONS (tail)->cdr)
+    {
+      buf = XCONS (XCONS (tail)->car)->cdr;
+      /* Ignore buffers that aren't included in buffer lists.  */
+      if (XSTRING (XBUFFER (buf)->name)->data[0] == ' ')
+       continue;
+      *vecp++ = buf;
+      *vecp++ = XBUFFER (buf)->read_only;
+      *vecp++ = Fbuffer_modified_p (buf);
+    }
+  /* Fill up the vector with lambdas (always at least one).  */
+  *vecp++ = Qlambda;
+  while  (vecp - XVECTOR (frame_and_buffer_state)->contents
+         < XVECTOR (frame_and_buffer_state)->size)
+    *vecp++ = Qlambda;
+  /* Make sure we didn't overflow the vector.  */
+  if (vecp - XVECTOR (frame_and_buffer_state)->contents
+      > XVECTOR (frame_and_buffer_state)->size)
+    abort ();
+  return Qt;
 }
 \f
 DEFUN ("open-termscript", Fopen_termscript, Sopen_termscript,
@@ -1588,7 +2032,8 @@ FILE = nil means just close any termscript file currently open.")
 
 #ifdef SIGWINCH
 SIGTYPE
-window_change_signal ()
+window_change_signal (signalnum) /* If we don't have an argument, */
+     int signalnum;            /* some compilers complain in signal calls. */
 {
   int width, height;
   extern int errno;
@@ -1639,11 +2084,8 @@ do_pending_window_change ()
 
          int height = FRAME_NEW_HEIGHT (f);
          int width = FRAME_NEW_WIDTH (f);
-           
-         FRAME_NEW_HEIGHT (f) = 0;
-         FRAME_NEW_WIDTH (f) = 0;
 
-         if (height != 0)
+         if (height != 0 || width != 0)
            change_frame_size (f, height, width, 0, 0);
        }
     }
@@ -1658,10 +2100,34 @@ do_pending_window_change ()
    redisplay.  Since this tries to resize windows, we can't call it
    from a signal handler.  */
 
-change_frame_size (frame, newheight, newwidth, pretend, delay)
-     register FRAME_PTR frame;
+change_frame_size (f, newheight, newwidth, pretend, delay)
+     register FRAME_PTR f;
      int newheight, newwidth, pretend;
 {
+  Lisp_Object tail, frame;
+
+  if (! FRAME_WINDOW_P (f))
+    {
+      /* When using termcap, or on MS-DOS, all frames use
+        the same screen, so a change in size affects all frames.  */
+      FOR_EACH_FRAME (tail, frame)
+       if (! FRAME_WINDOW_P (XFRAME (frame)))
+         change_frame_size_1 (XFRAME (frame), newheight, newwidth,
+                              pretend, delay);
+    }
+  else
+    change_frame_size_1 (f, newheight, newwidth, pretend, delay);
+}
+
+static void
+change_frame_size_1 (frame, newheight, newwidth, pretend, delay)
+     register FRAME_PTR frame;
+     int newheight, newwidth, pretend, delay;
+{
+  int new_frame_window_width;
+  unsigned int total_glyphs;
+  int count = specpdl_ptr - specpdl;
+
   /* If we can't deal with the change now, queue it for later.  */
   if (delay)
     {
@@ -1675,18 +2141,37 @@ change_frame_size (frame, newheight, newwidth, pretend, delay)
   FRAME_NEW_HEIGHT (frame) = 0;
   FRAME_NEW_WIDTH  (frame) = 0;
 
-  /* If an arguments is zero, set it to the current value.  */
-  newheight || (newheight = FRAME_HEIGHT (frame));
-  newwidth  || (newwidth  = FRAME_WIDTH  (frame));
+  /* If an argument is zero, set it to the current value.  */
+  if (newheight == 0)
+    newheight = FRAME_HEIGHT (frame);
+  if (newwidth == 0)
+    newwidth  = FRAME_WIDTH  (frame);
+  new_frame_window_width = FRAME_WINDOW_WIDTH_ARG (frame, newwidth);
+
+  total_glyphs = newheight * (newwidth + 2) * sizeof (GLYPH);
+
+  /* If these sizes are so big they cause overflow,
+     just ignore the change.  It's not clear what better we could do.  */
+  if (total_glyphs / sizeof (GLYPH) / newheight != newwidth + 2)
+    return;
 
   /* Round up to the smallest acceptable size.  */
   check_frame_size (frame, &newheight, &newwidth);
 
   /* If we're not changing the frame size, quit now.  */
   if (newheight == FRAME_HEIGHT (frame)
-      && newwidth == FRAME_WIDTH (frame))
+      && new_frame_window_width == FRAME_WINDOW_WIDTH (frame))
     return;
 
+  BLOCK_INPUT;
+
+#ifdef MSDOS
+  /* We only can set screen dimensions to certain values supported
+     by our video hardware.  Try to find the smallest size greater
+     or equal to the requested dimensions.  */
+  dos_set_window_size (&newheight, &newwidth);
+#endif
+
   if (newheight != FRAME_HEIGHT (frame))
     {
       if (FRAME_HAS_MINIBUF_P (frame)
@@ -1695,8 +2180,8 @@ change_frame_size (frame, newheight, newwidth, pretend, delay)
          /* Frame has both root and minibuffer.  */
          set_window_height (FRAME_ROOT_WINDOW (frame),
                             newheight - 1 - FRAME_MENU_BAR_LINES (frame), 0);
-         XFASTINT (XWINDOW (FRAME_MINIBUF_WINDOW (frame))->top)
-           = newheight - 1;
+         XSETFASTINT (XWINDOW (FRAME_MINIBUF_WINDOW (frame))->top,
+                      newheight - 1);
          set_window_height (FRAME_MINIBUF_WINDOW (frame), 1, 0);
        }
       else
@@ -1717,11 +2202,11 @@ change_frame_size (frame, newheight, newwidth, pretend, delay)
 #endif
     }
 
-  if (newwidth != FRAME_WIDTH (frame))
+  if (new_frame_window_width  != FRAME_WINDOW_WIDTH (frame))
     {
-      set_window_width (FRAME_ROOT_WINDOW (frame), newwidth, 0);
+      set_window_width (FRAME_ROOT_WINDOW (frame), new_frame_window_width, 0);
       if (FRAME_HAS_MINIBUF_P (frame))
-       set_window_width (FRAME_MINIBUF_WINDOW (frame), newwidth, 0);
+       set_window_width (FRAME_MINIBUF_WINDOW (frame), new_frame_window_width, 0);
 
       if (FRAME_TERMCAP_P (frame) && !pretend)
        FrameCols = newwidth;
@@ -1736,25 +2221,40 @@ change_frame_size (frame, newheight, newwidth, pretend, delay)
     }
 
   FRAME_HEIGHT (frame) = newheight;
-  FRAME_WIDTH (frame)  = newwidth;
-       
+  SET_FRAME_WIDTH (frame, newwidth);
+
+  if (FRAME_CURSOR_X (frame) >= FRAME_WINDOW_WIDTH (frame))
+    FRAME_CURSOR_X (frame) = FRAME_WINDOW_WIDTH (frame) - 1;
+  if (FRAME_CURSOR_Y (frame) >= FRAME_HEIGHT (frame))
+    FRAME_CURSOR_Y (frame) = FRAME_HEIGHT (frame) - 1;
+
   remake_frame_glyphs (frame);
   calculate_costs (frame);
+
+  UNBLOCK_INPUT;
+
+  record_unwind_protect (Fset_buffer, Fcurrent_buffer ());
+
+  /* This isn't quite a no-op: it runs window-configuration-change-hook.  */
+  Fset_window_buffer (FRAME_SELECTED_WINDOW (frame),
+                     XWINDOW (FRAME_SELECTED_WINDOW (frame))->buffer);
+
+  unbind_to (count, Qnil);
 }
 \f
 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.")
-  (str)
-     Lisp_Object str;
+  (string)
+     Lisp_Object string;
 {
-  CHECK_STRING (str, 0);
-  fwrite (XSTRING (str)->data, 1, XSTRING (str)->size, stdout);
+  CHECK_STRING (string, 0);
+  fwrite (XSTRING (string)->data, 1, XSTRING (string)->size, stdout);
   fflush (stdout);
   if (termscript)
     {
-      fwrite (XSTRING (str)->data, 1, XSTRING (str)->size, termscript);
+      fwrite (XSTRING (string)->data, 1, XSTRING (string)->size, termscript);
       fflush (termscript);
     }
   return Qnil;
@@ -1794,22 +2294,32 @@ bitch_at_user ()
 
 DEFUN ("sleep-for", Fsleep_for, Ssleep_for, 1, 2, 0,
   "Pause, without updating display, for SECONDS seconds.\n\
-Optional second arg MILLISECONDS specifies an additional wait period,\n\
-in milliseconds.\n\
-\(Not all operating systems support milliseconds.)")
+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)
      Lisp_Object seconds, milliseconds;
 {
   int sec, usec;
 
-  CHECK_NUMBER (seconds, 0);
-  sec = XINT (seconds);
-  
   if (NILP (milliseconds))
-    XSET (milliseconds, Lisp_Int, 0);
+    XSETINT (milliseconds, 0);
   else
     CHECK_NUMBER (milliseconds, 1);
-  usec = XINT (milliseconds);
+  usec = XINT (milliseconds) * 1000;
+
+#ifdef LISP_FLOAT_TYPE
+  {
+    double duration = extract_float (seconds);
+    sec = (int) duration;
+    usec += (duration - sec) * 1000000;
+  }
+#else
+  CHECK_NUMBER (seconds, 0);
+  sec = XINT (seconds);
+#endif
 
 #ifndef EMACS_HAS_USECS
   if (sec == 0 && usec != 0)
@@ -1828,13 +2338,13 @@ in milliseconds.\n\
   else
     sec += usec / 1000000, usec %= 1000000;
 
-  if (sec <= 0)
+  if (sec < 0 || (sec == 0 && usec == 0))
     return Qnil;
 
   {
     Lisp_Object zero;
 
-    XFASTINT (zero) = 0;
+    XSETFASTINT (zero, 0);
     wait_reading_process_input (sec, usec, zero, 0);
   }
 
@@ -1878,19 +2388,21 @@ in milliseconds.\n\
 /* This is just like wait_reading_process_input, except that
    it does the redisplay.
 
-   It's also just like Fsit_for, except that it can be used for
+   It's also much like Fsit_for, except that it can be used for
    waiting for input as well.  */
 
 Lisp_Object
-sit_for (sec, usec, reading, display)
-     int sec, usec, reading, display;
+sit_for (sec, usec, reading, display, initial_display)
+     int sec, usec, reading, display, initial_display;
 {
   Lisp_Object read_kbd;
 
-  if (detect_input_pending ())
+  swallow_events (display);
+
+  if (detect_input_pending_run_timers (display))
     return Qnil;
 
-  if (display)
+  if (initial_display)
     redisplay_preserve_echo_area ();
 
   if (sec == 0 && usec == 0)
@@ -1900,43 +2412,20 @@ sit_for (sec, usec, reading, display)
   gobble_input (0);
 #endif
 
-  XSET (read_kbd, Lisp_Int, reading ? -1 : 1);
+  XSETINT (read_kbd, reading ? -1 : 1);
   wait_reading_process_input (sec, usec, read_kbd, display);
 
-
-  /* wait_reading_process_input should always be available now; it is
-     simulated in a simple way on systems that don't support
-     subprocesses.  */
-#if 0
-  /* No wait_reading_process_input available.  */
-  immediate_quit = 1;
-  QUIT;
-
-  waitchannels = 1;
-#ifdef VMS
-  input_wait_timeout (XINT (arg));
-#else                          /* not VMS */
-#ifndef HAVE_TIMEVAL
-  timeout_sec = sec;
-  select (1, &waitchannels, 0, 0, &timeout_sec);
-#else /* HAVE_TIMEVAL */
-  timeout.tv_sec = sec;  
-  timeout.tv_usec = usec;
-  select (1, &waitchannels, 0, 0, &timeout);
-#endif /* HAVE_TIMEVAL */
-#endif /* not VMS */
-
-  immediate_quit = 0;
-#endif 
-
   return detect_input_pending () ? Qnil : Qt;
 }
 
 DEFUN ("sit-for", Fsit_for, Ssit_for, 1, 3, 0,
   "Perform redisplay, then wait for SECONDS seconds or until input is available.\n\
-Optional second arg MILLISECONDS specifies an additional wait period, in\n\
-milliseconds.\n\
-Optional third arg non-nil means don't redisplay, just wait for input.\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.")
@@ -1945,21 +2434,29 @@ Value is t if waited the full time with no input arriving.")
 {
   int sec, usec;
 
-  CHECK_NUMBER (seconds, 0);
-  sec = XINT (seconds);
-
   if (NILP (milliseconds))
-    XSET (milliseconds, Lisp_Int, 0);
+    XSETINT (milliseconds, 0);
   else
     CHECK_NUMBER (milliseconds, 1);
-  usec = XINT (milliseconds);
+  usec = XINT (milliseconds) * 1000;
+
+#ifdef LISP_FLOAT_TYPE
+  {
+    double duration = extract_float (seconds);
+    sec = (int) duration;
+    usec += (duration - sec) * 1000000;
+  }
+#else
+  CHECK_NUMBER (seconds, 0);
+  sec = XINT (seconds);
+#endif
 
 #ifndef EMACS_HAS_USECS
   if (usec != 0 && sec == 0)
     error ("millisecond `sit-for' not supported on %s", SYSTEM_TYPE);
 #endif
 
-  return sit_for (sec, usec, 0, NILP (nodisp));
+  return sit_for (sec, usec, 0, NILP (nodisp), NILP (nodisp));
 }
 \f
 char *terminal_type;
@@ -1980,35 +2477,66 @@ init_display ()
   cursor_in_echo_area = 0;
   terminal_type = (char *) 0;
 
-  /* If the DISPLAY environment variable is set, try to use X, and
-     die with an error message if that doesn't work.  */
+  /* Now is the time to initialize this; it's used by init_sys_modes
+     during startup.  */
+  Vwindow_system = Qnil;
 
-  /* Check if we're using a window system here before trying to
-     initialize the terminal.  If we check the terminal first,
+  /* If the user wants to use a window system, we shouldn't bother
+     initializing the terminal.  This is especially important when the
+     terminal is so dumb that emacs gives up before and doesn't bother
+     using the window system.
 
-     If someone has indicated that they want
-     to use a window system, we shouldn't bother initializing the
-     terminal.  This is especially important when the terminal is so
-     dumb that emacs gives up before  and doesn't bother using the window
-     system.  */
+     If the DISPLAY environment variable is set and nonempty,
+     try to use X, and die with an error message if that doesn't work.  */
 
 #ifdef HAVE_X_WINDOWS
-  if (!inhibit_window_system && (display_arg || getenv ("DISPLAY")))
+  if (! display_arg)
+    {
+      char *display;
+#ifdef VMS
+      display = getenv ("DECW$DISPLAY");
+#else
+      display = getenv ("DISPLAY");
+#endif
+
+      display_arg = (display != 0 && *display != 0);
+    }
+
+  if (!inhibit_window_system && display_arg 
+#ifndef CANNOT_DUMP
+     && initialized
+#endif
+     )
     {
       Vwindow_system = intern ("x");
 #ifdef HAVE_X11
       Vwindow_system_version = make_number (11);
 #else
       Vwindow_system_version = make_number (10);
+#endif
+#if defined (LINUX) && defined (HAVE_LIBNCURSES)
+      /* In some versions of ncurses,
+        tputs crashes if we have not called tgetent.
+        So call tgetent.  */
+      { char b[2044]; tgetent (b, "xterm");}
 #endif
       return;
     }
 #endif /* HAVE_X_WINDOWS */
 
+#ifdef HAVE_NTGUI
+  if (!inhibit_window_system) 
+    {
+      Vwindow_system = intern ("w32");
+      Vwindow_system_version = make_number (1);
+      return;
+    }
+#endif /* HAVE_NTGUI */
+
   /* If no window system has been specified, try to use the terminal.  */
   if (! isatty (0))
     {
-      fprintf (stderr, "emacs: standard input is not a tty\n");
+      fatal ("standard input is not a tty");
       exit (1);
     }
 
@@ -2046,6 +2574,18 @@ For types not defined in VMS, use  define emacs_term \"TYPE\".\n\
 
   term_init (terminal_type);
 
+  {
+    int width = FRAME_WINDOW_WIDTH (selected_frame);
+    int height = FRAME_HEIGHT (selected_frame);
+
+    unsigned int total_glyphs = height * (width + 2) * sizeof (GLYPH);
+
+    /* If these sizes are so big they cause overflow,
+       just ignore the change.  It's not clear what better we could do.  */
+    if (total_glyphs / sizeof (GLYPH) / height != width + 2)
+      fatal ("screen size %dx%d too big", width, height);
+  }
+
   remake_frame_glyphs (selected_frame);
   calculate_costs (selected_frame);
 
@@ -2063,18 +2603,23 @@ For types not defined in VMS, use  define emacs_term \"TYPE\".\n\
 \f
 syms_of_display ()
 {
-#ifdef MULTI_FRAME
   defsubr (&Sredraw_frame);
-#endif
   defsubr (&Sredraw_display);
+  defsubr (&Sframe_or_buffer_changed_p);
   defsubr (&Sopen_termscript);
   defsubr (&Sding);
   defsubr (&Ssit_for);
   defsubr (&Ssleep_for);
   defsubr (&Ssend_string_to_terminal);
 
+  frame_and_buffer_state = Fmake_vector (make_number (20), Qlambda);
+  staticpro (&frame_and_buffer_state);
+
+  Qdisplay_table = intern ("display-table");
+  staticpro (&Qdisplay_table);
+
   DEFVAR_INT ("baud-rate", &baud_rate,
-    "The output baud rate of the terminal.\n\
+    "*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.");
   DEFVAR_BOOL ("inverse-video", &inverse_video,
@@ -2102,7 +2647,7 @@ 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 `x-set-face').");
+    and this glyph / 256 is face code for X windows (see `face-id').");
   Vglyph_table = Qnil;
 
   DEFVAR_LISP ("standard-display-table", &Vstandard_display_table,
@@ -2119,4 +2664,3 @@ See `buffer-display-table' for more information.");
       Vwindow_system_version = Qnil;
     }
 }
-