(create_process): Set input_wait_mask before forking.
[bpt/emacs.git] / src / dispnew.c
index 3aec0bd..81470fb 100644 (file)
@@ -1,12 +1,11 @@
 /* Updating of data structures for redisplay.
-   Copyright (C) 1985, 1986, 1987, 1988, 1990,
-   1992 Free Software Foundation, Inc.
+   Copyright (C) 1985, 86, 87, 88, 93, 94 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
 GNU Emacs is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 1, or (at your option)
+the Free Software Foundation; either version 2, or (at your option)
 any later version.
 
 GNU Emacs is distributed in the hope that it will be useful,
@@ -20,15 +19,16 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 
 
 #include <signal.h>
-
-#include "config.h"
 #include <stdio.h>
+
+#include <config.h>
 #include <ctype.h>
 
+#include "lisp.h"
 #include "termchar.h"
 #include "termopts.h"
+#include "termhooks.h"
 #include "cm.h"
-#include "lisp.h"
 #include "dispextern.h"
 #include "buffer.h"
 #include "frame.h"
@@ -36,23 +36,40 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 #include "commands.h"
 #include "disptab.h"
 #include "indent.h"
+#include "intervals.h"
 
 #include "systty.h"
-#include "systime.h"
 
 #ifdef HAVE_X_WINDOWS
 #include "xterm.h"
 #endif /* HAVE_X_WINDOWS */
 
+/* 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
 
 /* Nonzero upon entry to redisplay means do not assume anything about
    current contents of actual terminal frame; clear and redraw it.  */
@@ -116,7 +133,7 @@ FRAME_PTR last_nonminibuf_frame;
    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!
+   store collectible objects in any of its fields!
 
    You're not/The only frame in town/...  */
 
@@ -164,21 +181,6 @@ DEFUN ("redraw-frame", Fredraw_frame, Sredraw_frame, 1, 1, 0,
   return Qnil;
 }
 
-DEFUN ("redraw-display", Fredraw_display, Sredraw_display, 0, 0, "",
-  "Redraw all frames marked as having their images garbled.")
-  ()
-{
-  Lisp_Object frame, tail;
-
-  for (tail = Vframe_list; CONSP (tail); tail = XCONS (tail)->cdr)
-    {
-      frame = XCONS (tail)->car;
-      if (XFRAME (frame)->garbaged && XFRAME (frame)->visible)
-       Fredraw_frame (frame);
-    }
-  return Qnil;
-}
-
 redraw_frame (f)
      FRAME_PTR f;
 {
@@ -187,11 +189,12 @@ redraw_frame (f)
   Fredraw_frame (frame);
 }
 
-#else /* not MULTI_FRAME */
+#else
 
-DEFUN ("redraw-display", Fredraw_display, Sredraw_display, 0, 0, 0,
-  "Clear screen and output again what is supposed to appear on it.")
-  ()
+DEFUN ("redraw-frame", Fredraw_frame, Sredraw_frame, 1, 1, 0,
+  "Clear frame FRAME and output again what is supposed to appear on it.")
+  (frame)
+     Lisp_Object frame;
 {
   update_begin (0);
   set_terminal_modes ();
@@ -202,11 +205,39 @@ DEFUN ("redraw-display", Fredraw_display, Sredraw_display, 0, 0, 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));
+  mark_window_display_accurate (FRAME_ROOT_WINDOW (0), 0);
   return Qnil;
 }
 
-#endif /* not MULTI_FRAME */
+#endif
+
+DEFUN ("redraw-display", Fredraw_display, Sredraw_display, 0, 0, "",
+  "Clear and redisplay all visible frames.")
+  ()
+{
+  Lisp_Object tail, frame;
+
+  FOR_EACH_FRAME (tail, frame)
+    if (FRAME_VISIBLE_P (XFRAME (frame)))
+      Fredraw_frame (frame);
+
+  return Qnil;
+}
+
+/* This is used when frame_garbaged is set.
+   Redraw the individual frames marked as garbaged.  */
+
+void
+redraw_garbaged_frames ()
+{
+  Lisp_Object tail, frame;
+
+  FOR_EACH_FRAME (tail, frame)
+    if (FRAME_VISIBLE_P (XFRAME (frame))
+       && FRAME_GARBAGED_P (XFRAME (frame)))
+      Fredraw_frame (frame);
+}
+
 \f
 static struct frame_glyphs *
 make_frame_glyphs (frame, empty)
@@ -216,14 +247,15 @@ make_frame_glyphs (frame, empty)
   register int i;
   register width = FRAME_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));
@@ -245,9 +277,13 @@ make_frame_glyphs (frame, 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_glyphs);
     }
   else
     {
@@ -257,6 +293,25 @@ 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;
@@ -268,26 +323,30 @@ free_frame_glyphs (frame, glyphs)
      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);
+    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_X_WINDOWS
   if (FRAME_X_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
 
-  free (glyphs);
+  xfree (glyphs);
 }
 
 static void
@@ -302,9 +361,20 @@ remake_frame_glyphs (frame)
     free_frame_glyphs (frame, FRAME_TEMP_GLYPHS (frame));
 
   if (FRAME_MESSAGE_BUF (frame))
-    FRAME_MESSAGE_BUF (frame)
-      = (char *) xrealloc (FRAME_MESSAGE_BUF (frame),
-                          FRAME_WIDTH (frame) + 1);
+    {
+      /* Reallocate the frame's message buffer; remember that
+        echo_area_glyphs may be pointing here.  */
+      char *old_message_buf = FRAME_MESSAGE_BUF (frame);
+
+      FRAME_MESSAGE_BUF (frame)
+       = (char *) xrealloc (FRAME_MESSAGE_BUF (frame),
+                            FRAME_WIDTH (frame) + 1);
+
+      if (echo_area_glyphs == old_message_buf)
+       echo_area_glyphs = FRAME_MESSAGE_BUF (frame);
+      if (previous_echo_glyphs == old_message_buf)
+       previous_echo_glyphs = FRAME_MESSAGE_BUF (frame);
+    }
   else
     FRAME_MESSAGE_BUF (frame)
       = (char *) xmalloc (FRAME_WIDTH (frame) + 1);
@@ -469,25 +539,27 @@ safe_bcopy (from, to, size)
      char *from, *to;
      int size;
 {
-  register char *endf;
-  register char *endt;
-
-  if (size == 0)
+  if (size <= 0 || from == to)
     return;
 
-  /* If destination is higher in memory, and overlaps source zone,
-     copy from the end.  */
-  if (from < to && from + size > to)
+  /* If the source and destination don't overlap, then bcopy can
+     handle it.  If they do overlap, but the destination is lower in
+     memory than the source, we'll assume bcopy can handle that.  */
+  if (to < from || from + size <= to)
+    bcopy (from, to, size);
+
+  /* Otherwise, we'll copy from the end.  */
+  else
     {
-      endf = from + size;
-      endt = to + size;
+      register char *endf = from + size;
+      register char *endt = to + size;
 
       /* If TO - FROM is large, then we should break the copy into
         nonoverlapping chunks of TO - FROM bytes each.  However, if
         TO - FROM is small, then the bcopy function call overhead
         makes this not worth it.  The crossover point could be about
-        anywhere.  Since I don't think the obvious copy loop is ever
-        too bad, I'm trying to err in its favor.  */
+        anywhere.  Since I don't think the obvious copy loop is too
+        bad, I'm trying to err in its favor.  */
       if (to - from < 64)
        {
          do
@@ -496,56 +568,25 @@ safe_bcopy (from, to, size)
        }
       else
        {
-         /* Since TO - FROM >= 64, the overlap is less than SIZE,
-            so we can always safely do this loop once.  */
-         while (endt > to)
+         for (;;)
            {
              endt -= (to - from);
              endf -= (to - from);
 
+             if (endt < to)
+               break;
+
              bcopy (endf, endt, to - from);
            }
-         
-         /* If TO - FROM wasn't a multiple of SIZE, there will be a
+
+         /* If SIZE wasn't a multiple of TO - FROM, there will be a
             little left over.  The amount left over is
             (endt + (to - from)) - to, which is endt - from.  */
          bcopy (from, to, endt - from);
        }
     }
-  else
-    bcopy (from, to, size);
 }     
 
-#if 0
-void
-safe_bcopy (from, to, size)
-     char *from, *to;
-     int size;
-{
-  register char *endf;
-  register char *endt;
-
-  if (size == 0)
-    return;
-
-  /* If destination is higher in memory, and overlaps source zone,
-     copy from the end. */
-  if (from < to && from + size > to)
-    {
-      endf = from + size;
-      endt = to + size;
-
-      do
-       *--endt = *--endf;
-      while (endf != from);
-
-      return;
-    }
-
-  bcopy (from, to, size);
-}
-#endif
-
 /* Rotate a vector of SIZE bytes right, by DISTANCE bytes.
    DISTANCE may be negative.  */
 
@@ -570,13 +611,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_WIDTH (frame);
 
   if (!line_ins_del_ok)
     return 0;
@@ -597,6 +640,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]);
@@ -609,6 +656,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,
@@ -618,6 +688,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;
        }
 
@@ -665,6 +736,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]);
@@ -677,6 +752,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,
@@ -686,6 +784,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;
        }
 
@@ -750,7 +849,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]));
+             bcopy (current_frame->charstarts[vpos],
+                    desired_frame->charstarts[vpos],
+                    start * sizeof (current_frame->charstarts[vpos]));
              len = min (start, current_frame->used[vpos]);
              if (desired_frame->used[vpos] < len)
                desired_frame->used[vpos] = len;
@@ -759,11 +862,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])));
+             bcopy (current_frame->charstarts[vpos] + end,
+                    desired_frame->charstarts[vpos] + end,
+                    ((current_frame->used[vpos] - end)
+                     * sizeof (current_frame->charstarts[vpos])));
              desired_frame->used[vpos] = current_frame->used[vpos];
            }
        }
@@ -809,6 +920,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 = XFASTINT (w->left);
+  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 = XFASTINT (w->left);
+  int right = left + window_internal_width (w);
+  int next_line;
+  int truncate = (XINT (w->hscroll)
+                 || (truncate_partial_width_windows
+                     && (XFASTINT (w->width) < FRAME_WIDTH (f)))
+                 || !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.  */
@@ -817,8 +1011,8 @@ cancel_my_columns (w)
      struct window *w;
 {
   register int vpos;
-  register struct frame_glyphs *desired_glyphs =
-    FRAME_DESIRED_GLYPHS (XFRAME (w->frame));
+  register struct frame_glyphs *desired_glyphs
+    FRAME_DESIRED_GLYPHS (XFRAME (w->frame));
   register int start = XFASTINT (w->left);
   register int bot = XFASTINT (w->top) + XFASTINT (w->height);
 
@@ -857,9 +1051,9 @@ direct_output_for_insert (g)
 #endif /* COMPILER_REGISTER_BUG */
     int vpos = FRAME_CURSOR_Y (frame);
 
-  /* Give up if about to continue line */
-  if (hpos - XFASTINT (w->left) + 1 + 1 >= XFASTINT (w->width)
-
+  /* Give up if about to continue line */
+  if (hpos >= XFASTINT (w->left) + window_internal_width (w) - 1
+    
   /* Avoid losing if cursor is in invisible text off left margin */
       || (XINT (w->hscroll) && hpos == XFASTINT (w->left))
     
@@ -874,11 +1068,32 @@ 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 (XFASTINT (point - 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;
+  {
+#ifdef HAVE_X_WINDOWS
+    int dummy;
+    int face = compute_char_face (frame, w, point - 1, -1, -1, &dummy, point);
+#endif
+    current_frame->glyphs[vpos][hpos] = MAKE_GLYPH (frame, g, face);
+    current_frame->charstarts[vpos][hpos] = point - 1;
+    /* Record the entry for after the newly inserted character.  */
+    current_frame->charstarts[vpos][hpos + 1] = point;
+    adjust_window_charstarts (w, vpos, 1);
+  }
   unchanged_modified = MODIFF;
   beg_unchanged = GPT - BEG;
   XFASTINT (w->last_point) = point;
@@ -904,24 +1119,51 @@ direct_output_forward_char (n)
 {
   register FRAME_PTR frame = selected_frame;
   register struct window *w = XWINDOW (selected_window);
+  int position;
+  int hpos = FRAME_CURSOR_X (frame);
+
+  /* Give up if in truncated text at end of line.  */
+  if (hpos >= XFASTINT (w->left) + window_internal_width (w) - 1)
+    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)
        && (XINT (w->hscroll) || n < 0))
       || (n > 0
-         && (FRAME_CURSOR_X (frame) + 1
-             >= (XFASTINT (w->left) + XFASTINT (w->width)
-                 - (XFASTINT (w->width) < FRAME_WIDTH (frame))
-                 - 1)))
+         && (FRAME_CURSOR_X (frame) + 1 >= window_internal_width (w) - 1))
       || 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;
+
+#ifdef USE_TEXT_PROPERTIES
+  /* Don't use direct output next to an invisible character
+     since we might need to do something special.  */
+
+  XFASTINT (position) = point;
+  if (XFASTINT (position) < ZV
+      && ! NILP (Fget_char_property (position,
+                                    Qinvisible,
+                                    selected_window)))
+    return 0;
+
+  XFASTINT (position) = point - 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;
   cursor_to (FRAME_CURSOR_Y (frame), FRAME_CURSOR_X (frame));
   fflush (stdout);
+
   return 1;
 }
 \f
@@ -937,8 +1179,8 @@ 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;
@@ -947,6 +1189,9 @@ update_frame (f, force, inhibit_hairy_id)
   register int downto, leftmost;
 #endif
 
+  if (preempt_count <= 0)
+    preempt_count = 1;
+
   if (FRAME_HEIGHT (f) == 0) abort (); /* Some bug zeros some core */
 
   detect_input_pending ();
@@ -961,6 +1206,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++)
@@ -1017,7 +1266,8 @@ 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)
@@ -1097,7 +1347,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;
 }
 
@@ -1200,14 +1450,13 @@ buffer_posn_from_coords (window, col, line)
      struct window *window;
      int col, line;
 {
+  int hscroll = XINT (window->hscroll);
   int window_left = XFASTINT (window->left);
 
   /* 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
      window.  */
-  int window_width = (XFASTINT (window->width) - 1
-                     - (XFASTINT (window->width) + window_left
-                        != FRAME_WIDTH (XFRAME (window->frame))));
+  int window_width = window_internal_width (window) - 1;
 
   int startp = marker_position (window->start);
 
@@ -1224,9 +1473,10 @@ buffer_posn_from_coords (window, col, line)
      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);
+                         ? minibuf_prompt_width : 0)
+                        + (hscroll ? 1 - hscroll : 0),
+                        ZV, line, col,
+                        window_width, hscroll, 0, window);
 
   current_buffer = old_current_buffer;
 
@@ -1262,7 +1512,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_HEIGHT((f))])
+#define char_ins_del_cost(f) (&char_ins_del_vector[FRAME_WIDTH((f))])
 
 static void
 update_line (frame, vpos)
@@ -1270,6 +1520,7 @@ 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;
@@ -1327,7 +1578,7 @@ update_line (frame, vpos)
        = current_frame->used[vpos]
          * FONT_WIDTH (frame->display.x->font);
       current_frame->pix_height[vpos]
-       = FONT_HEIGHT (frame->display.x->font);
+       = frame->display.x->line_height;
     }
 #endif /* HAVE_X_WINDOWS */
 
@@ -1364,6 +1615,25 @@ 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. */
@@ -1393,6 +1663,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;
     }
 
@@ -1411,6 +1686,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;
     }
 
@@ -1571,6 +1851,70 @@ 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 >= NFRAMES + 3 * NBUFFERS + 1, containing the session's
+   frames, 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\
+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;
+  for (tail = Vbuffer_alist; CONSP (tail); tail = XCONS (tail)->cdr)
+    {
+      buf = XCONS (XCONS (tail)->car)->cdr;
+      if (!EQ (*vecp++, buf))
+       goto changed;
+      if (!EQ (*vecp++, XBUFFER (buf)->read_only))
+       goto changed;
+      if (!EQ (*vecp++, Fbuffer_modified_p (buf)))
+       goto changed;
+    }
+  return Qnil;
+ changed:
+  n = 1;
+  FOR_EACH_FRAME (tail, frame)
+    n++;
+  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 < XVECTOR (frame_and_buffer_state)->size / 2)
+    frame_and_buffer_state = Fmake_vector (make_number (n), Qlambda);
+  vecp = XVECTOR (frame_and_buffer_state)->contents;
+  FOR_EACH_FRAME (tail, frame)
+    *vecp++ = frame;
+  for (tail = Vbuffer_alist; CONSP (tail); tail = XCONS (tail)->cdr)
+    {
+      buf = XCONS (XCONS (tail)->car)->cdr;
+      *vecp++ = buf;
+      *vecp++ = XBUFFER (buf)->read_only;
+      *vecp++ = Fbuffer_modified_p (buf);
+    }
+  /* If we left any slack in the vector, fill it up now.  */
+  for (; n < XVECTOR (frame_and_buffer_state)->size; ++n)
+    *vecp++ = Qlambda;
+  return Qt;
 }
 \f
 DEFUN ("open-termscript", Fopen_termscript, Sopen_termscript,
@@ -1612,14 +1956,13 @@ window_change_signal ()
      later outside of the signal handler.  */
 
   {
-    Lisp_Object tail;
-    FRAME_PTR f;
+    Lisp_Object tail, frame;
 
-    FOR_EACH_FRAME (tail, f)
+    FOR_EACH_FRAME (tail, frame)
       {
-       if (FRAME_TERMCAP_P (f))
+       if (FRAME_TERMCAP_P (XFRAME (frame)))
          {
-           change_frame_size (f, height, width, 0, 1);
+           change_frame_size (XFRAME (frame), height, width, 0, 1);
            break;
          }
       }
@@ -1638,20 +1981,18 @@ do_pending_window_change ()
   /* If window_change_signal should have run before, run it now.  */
   while (delayed_size_change)
     {
-      Lisp_Object tail;
-      FRAME_PTR f;
+      Lisp_Object tail, frame;
 
       delayed_size_change = 0;
 
-      FOR_EACH_FRAME (tail, f)
+      FOR_EACH_FRAME (tail, frame)
        {
+         FRAME_PTR f = XFRAME (frame);
+
          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);
        }
     }
@@ -1683,7 +2024,7 @@ 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.  */
+  /* If an argument is zero, set it to the current value.  */
   newheight || (newheight = FRAME_HEIGHT (frame));
   newwidth  || (newwidth  = FRAME_WIDTH  (frame));
 
@@ -1702,14 +2043,15 @@ change_frame_size (frame, newheight, newwidth, pretend, delay)
        {
          /* Frame has both root and minibuffer.  */
          set_window_height (FRAME_ROOT_WINDOW (frame),
-                            newheight - 1, 0);
+                            newheight - 1 - FRAME_MENU_BAR_LINES (frame), 0);
          XFASTINT (XWINDOW (FRAME_MINIBUF_WINDOW (frame))->top)
            = newheight - 1;
          set_window_height (FRAME_MINIBUF_WINDOW (frame), 1, 0);
        }
       else
        /* Frame has just one top-level window.  */
-       set_window_height (FRAME_ROOT_WINDOW (frame), newheight, 0);
+       set_window_height (FRAME_ROOT_WINDOW (frame),
+                          newheight - FRAME_MENU_BAR_LINES (frame), 0);
 
       if (FRAME_TERMCAP_P (frame) && !pretend)
        FrameRows = newheight;
@@ -1744,7 +2086,12 @@ change_frame_size (frame, newheight, newwidth, pretend, delay)
 
   FRAME_HEIGHT (frame) = newheight;
   FRAME_WIDTH (frame)  = newwidth;
-       
+
+  if (FRAME_CURSOR_X (frame) >= FRAME_WIDTH (frame))
+    FRAME_CURSOR_X (frame) = FRAME_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);
 }
@@ -1800,29 +2147,53 @@ bitch_at_user ()
 }
 
 DEFUN ("sleep-for", Fsleep_for, Ssleep_for, 1, 2, 0,
-  "Pause, without updating display, for ARG seconds.\n\
-Optional second arg non-nil means ARG is measured in milliseconds.\n\
-\(Not all operating systems support milliseconds.)")
-  (arg, millisec)
-     Lisp_Object arg, millisec;
+  "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)
+     Lisp_Object seconds, milliseconds;
 {
-  int usec = 0;
-  int sec;
+  int sec, usec;
 
-  CHECK_NUMBER (arg, 0);
-  sec = XINT (arg);
-  if (sec <= 0)
-    return Qnil;
+  if (NILP (milliseconds))
+    XSET (milliseconds, Lisp_Int, 0);
+  else
+    CHECK_NUMBER (milliseconds, 1);
+  usec = XINT (milliseconds) * 1000;
 
-  if (!NILP (millisec))
-    {
-#ifndef EMACS_HAS_USECS
-      error ("millisecond `sleep-for' not supported on %s", SYSTEM_TYPE);
+#ifdef LISP_FLOAT_TYPE
+  {
+    double duration = extract_float (seconds);
+    sec = (int) duration;
+    usec += (duration - sec) * 1000000;
+  }
 #else
-      usec = sec % 1000 * 1000;
-      sec /= 1000;
+  CHECK_NUMBER (seconds, 0);
+  sec = XINT (seconds);
 #endif
+
+#ifndef EMACS_HAS_USECS
+  if (sec == 0 && usec != 0)
+    error ("millisecond `sleep-for' not supported on %s", SYSTEM_TYPE);
+#endif
+
+  /* Assure that 0 <= usec < 1000000.  */
+  if (usec < 0)
+    {
+      /* We can't rely on the rounding being correct if user is negative.  */
+      if (-1000000 < usec)
+       sec--, usec += 1000000;
+      else
+       sec -= -usec / 1000000, usec = 1000000 - (-usec % 1000000);
     }
+  else
+    sec += usec / 1000000, usec %= 1000000;
+
+  if (sec <= 0)
+    return Qnil;
 
   {
     Lisp_Object zero;
@@ -1831,7 +2202,10 @@ Optional second arg non-nil means ARG is measured in milliseconds.\n\
     wait_reading_process_input (sec, usec, zero, 0);
   }
 
-#if 0 /* No wait_reading_process_input */
+  /* We should always have wait_reading_process_input; we have a dummy
+     implementation for systems which don't support subprocesses.  */
+#if 0
+  /* No wait_reading_process_input */
   immediate_quit = 1;
   QUIT;
 
@@ -1868,8 +2242,9 @@ Optional second arg non-nil means ARG is measured 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
-   waiting for input as well.  */
+   It's also much like Fsit_for, except that it can be used for
+   waiting for input as well.  One differnce is that sit_for
+   does not call prepare_menu_bars; Fsit_for does call that.  */
 
 Lisp_Object
 sit_for (sec, usec, reading, display)
@@ -1887,14 +2262,18 @@ sit_for (sec, usec, reading, display)
     return Qt;
 
 #ifdef SIGIO
-  gobble_input ();
+  gobble_input (0);
 #endif
 
   XSET (read_kbd, Lisp_Int, reading ? -1 : 1);
   wait_reading_process_input (sec, usec, read_kbd, display);
 
 
-#if 0 /* No wait_reading_process_input available.  */
+  /* 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;
 
@@ -1919,52 +2298,46 @@ sit_for (sec, usec, reading, display)
 }
 
 DEFUN ("sit-for", Fsit_for, Ssit_for, 1, 3, 0,
-  "Perform redisplay, then wait for ARG seconds or until input is available.\n\
-Optional second arg non-nil means ARG counts in milliseconds.\n\
+  "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 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.")
-  (arg, millisec, nodisp)
-     Lisp_Object arg, millisec, nodisp;
+  (seconds, milliseconds, nodisp)
+     Lisp_Object seconds, milliseconds, nodisp;
 {
-  int usec = 0;
-  int sec;
+  int sec, usec;
 
-  CHECK_NUMBER (arg, 0);
-  sec = XINT (arg);
+  if (NILP (milliseconds))
+    XSET (milliseconds, Lisp_Int, 0);
+  else
+    CHECK_NUMBER (milliseconds, 1);
+  usec = XINT (milliseconds) * 1000;
 
-  if (!NILP (millisec))
-    {
-#ifndef EMACS_HAS_USECS
-      error ("millisecond `sit-for' not supported on %s", SYSTEM_TYPE);
+#ifdef LISP_FLOAT_TYPE
+  {
+    double duration = extract_float (seconds);
+    sec = (int) duration;
+    usec += (duration - sec) * 1000000;
+  }
 #else
-      usec = (sec % 1000) * 1000;
-      sec /= 1000;
+  CHECK_NUMBER (seconds, 0);
+  sec = XINT (seconds);
 #endif
-    }
-
-  return sit_for (sec, usec, 0, NILP (nodisp));
-}
-
-DEFUN ("sleep-for-millisecs", Fsleep_for_millisecs, Ssleep_for_millisecs,
-  1, 1, 0,
-  "Pause, without updating display, for ARG milliseconds.")
-  (arg)
-     Lisp_Object arg;
-{
-  Lisp_Object zero;
 
 #ifndef EMACS_HAS_USECS
-  error ("sleep-for-millisecs not supported on %s", SYSTEM_TYPE);
-#else
-  CHECK_NUMBER (arg, 0);
+  if (usec != 0 && sec == 0)
+    error ("millisecond `sit-for' not supported on %s", SYSTEM_TYPE);
+#endif
 
-  XFASTINT (zero) = 0;
-  wait_reading_process_input (XINT (arg) / 1000, XINT (arg) % 1000 * 1000,
-                             zero, 0);
-  return Qnil;
-#endif /* EMACS_HAS_USECS */
+  if (NILP (nodisp))
+    prepare_menu_bars ();
+  return sit_for (sec, usec, 0, NILP (nodisp));
 }
 \f
 char *terminal_type;
@@ -1985,20 +2358,29 @@ 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, 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)
+    {
+#ifdef VMS
+      display_arg = (getenv ("DECW$DISPLAY") != 0);
+#else
+      display_arg = (getenv ("DISPLAY") != 0);
+#endif
+    }
+
+  if (!inhibit_window_system && display_arg)
     {
       Vwindow_system = intern ("x");
 #ifdef HAVE_X11
@@ -2072,12 +2454,16 @@ syms_of_display ()
   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 (1), Qlambda);
+  staticpro (&frame_and_buffer_state);
+
   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\
@@ -2107,7 +2493,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,
@@ -2124,4 +2510,3 @@ See `buffer-display-table' for more information.");
       Vwindow_system_version = Qnil;
     }
 }
-