]> code.delx.au - gnu-emacs/blobdiff - src/dispnew.c
(Fdocumentation, Fdocumentation_property, Fsubstitute_command_keys):
[gnu-emacs] / src / dispnew.c
index 887fbc81cbbacdfe6470d7806d53b2bc5cd07831..19f6c33c1cfaef073c6674af9a0001ef0b594f13 100644 (file)
@@ -1,5 +1,5 @@
 /* Updating of data structures for redisplay.
-   Copyright (C) 1985, 86, 87, 88, 93, 94 Free Software Foundation, Inc.
+   Copyright (C) 1985, 86, 87, 88, 93, 94, 95 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -19,17 +19,19 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 
 
 #include <signal.h>
-#include <stdio.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"
+/* cm.h must come after dispextern.h on Windows.  */
 #include "dispextern.h"
+#include "cm.h"
 #include "buffer.h"
 #include "frame.h"
 #include "window.h"
@@ -39,26 +41,45 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 #include "intervals.h"
 
 #include "systty.h"
-#include "systime.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__
-#define        PENDING_OUTPUT_COUNT(FILE) ((FILE)->__bufp - (FILE)->__buffer)
+/* 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.  */
 
@@ -106,15 +127,19 @@ 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
@@ -173,14 +198,16 @@ 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, 0,
-  "Clear frame FRAME and output again what is supposed to appear on it.")
+  /* Don't confuse make-docfile by having two doc strings for this function.
+     make-docfile does not pay attention to #if, for good reason!  */
+  0)
   (frame)
      Lisp_Object frame;
 {
@@ -249,8 +276,8 @@ make_frame_glyphs (frame, empty)
   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));
@@ -258,16 +285,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_glyphs);
     }
   else
     {
@@ -301,7 +332,7 @@ make_frame_glyphs (frame, empty)
   return new;
 }
 
-static void
+void
 free_frame_glyphs (frame, glyphs)
      FRAME_PTR frame;
      struct frame_glyphs *glyphs;
@@ -319,8 +350,8 @@ free_frame_glyphs (frame, glyphs)
   if (glyphs->charstarts)
     xfree (glyphs->charstarts);
 
-#ifdef HAVE_X_WINDOWS
-  if (FRAME_X_P (frame))
+#ifdef HAVE_WINDOW_SYSTEM
+  if (FRAME_WINDOW_P (frame))
     {
       xfree (glyphs->top_left_x);
       xfree (glyphs->top_left_y);
@@ -328,12 +359,12 @@ free_frame_glyphs (frame, glyphs)
       xfree (glyphs->pix_height);
       xfree (glyphs->max_ascent);
     }
-#endif
+#endif /* HAVE_WINDOW_SYSTEM */
 
   xfree (glyphs);
 }
 
-static void
+void
 remake_frame_glyphs (frame)
      FRAME_PTR frame;
 {
@@ -366,7 +397,8 @@ remake_frame_glyphs (frame)
   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_TERMCAP_P (frame) || frame == selected_frame)
+    SET_FRAME_GARBAGED (frame);
 }
 \f
 /* Return the hash code of contents of line VPOS in frame-matrix M.  */
@@ -480,6 +512,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
@@ -495,9 +541,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;
@@ -595,13 +638,15 @@ rotate_vector (vector, size, distance)
    Returns nonzero if done, zero if terminal cannot scroll them.  */
 
 int
-scroll_frame_lines (frame, from, end, amount, pos_adjust)
+scroll_frame_lines (frame, from, end, amount, newpos)
      register FRAME_PTR frame;
-     int from, end, amount, pos_adjust;
+     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;
@@ -623,26 +668,8 @@ scroll_frame_lines (frame, from, end, amount, pos_adjust)
                     amount * sizeof (GLYPH *));
 
       rotate_vector (current_frame->charstarts + from,
-                    sizeof (GLYPH *) * (end + amount - from),
-                    amount * sizeof (GLYPH *));
-
-      /* Offset each char position in the charstarts lines we moved
-        by pos_adjust.  */
-      for (i = from + amount; i < end; i++)
-       {
-         int *line = current_frame->charstarts[from];
-         int col;
-         for (col = 0; col < current_frame->used[from]; col++)
-           line[col] += pos_adjust;
-       }
-      for (i = from; i <= from + amount; i++)
-       {
-         int *line = current_frame->charstarts[from];
-         int col;
-         line[0] = -1;
-         for (col = 0; col < current_frame->used[from]; col++)
-           line[col] = 0;
-       }
+                    sizeof (int *) * (end + amount - from),
+                    amount * sizeof (int *));
 
       safe_bcopy (current_frame->used + from,
                  current_frame->used + from + amount,
@@ -656,6 +683,29 @@ scroll_frame_lines (frame, from, end, amount, pos_adjust)
                  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,
@@ -673,8 +723,8 @@ scroll_frame_lines (frame, from, end, amount, pos_adjust)
                  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,
@@ -696,7 +746,7 @@ scroll_frame_lines (frame, from, end, amount, pos_adjust)
                      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);
     }
@@ -714,26 +764,8 @@ scroll_frame_lines (frame, from, end, amount, pos_adjust)
                     amount * sizeof (GLYPH *));
 
       rotate_vector (current_frame->charstarts + from + amount,
-                    sizeof (GLYPH *) * (end - from - amount),
-                    amount * sizeof (GLYPH *));
-
-      /* 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[from];
-         int col;
-         for (col = 0; col < current_frame->used[from]; col++)
-           line[col] += pos_adjust;
-       }
-      for (i = end + amount; i <= end; i++)
-       {
-         int *line = current_frame->charstarts[from];
-         int col;
-         line[0] = -1;
-         for (col = 0; col < current_frame->used[from]; col++)
-           line[col] = 0;
-       }
+                    sizeof (int *) * (end - from - amount),
+                    amount * sizeof (int *));
 
       safe_bcopy (current_frame->used + from,
                  current_frame->used + from + amount,
@@ -747,6 +779,29 @@ scroll_frame_lines (frame, from, end, amount, pos_adjust)
                  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,
@@ -764,8 +819,8 @@ scroll_frame_lines (frame, from, end, amount, pos_adjust)
                  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,
@@ -787,7 +842,7 @@ scroll_frame_lines (frame, from, end, amount, pos_adjust)
                      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);
     }
@@ -822,10 +877,10 @@ preserve_other_columns (w)
 
              bcopy (current_frame->glyphs[vpos],
                     desired_frame->glyphs[vpos],
-                    start * sizeof (current_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]));
+                    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;
@@ -842,11 +897,11 @@ preserve_other_columns (w)
              bcopy (current_frame->glyphs[vpos] + end,
                     desired_frame->glyphs[vpos] + end,
                     ((current_frame->used[vpos] - end)
-                     * sizeof (current_frame->glyphs[vpos])));
+                     * 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])));
+                     * sizeof (current_frame->charstarts[vpos][0])));
              desired_frame->used[vpos] = current_frame->used[vpos];
            }
        }
@@ -893,7 +948,7 @@ preserve_my_columns (w)
 #endif
 \f
 /* Adjust by ADJUST the charstart values in window W
-   before vpos VPOS, which counts relative to the frame
+   after vpos VPOS, which counts relative to the frame
    (not relative to W itself).  */
 
 void
@@ -904,11 +959,11 @@ adjust_window_charstarts (w, vpos, adjust)
 {
   int left = XFASTINT (w->left);
   int top = XFASTINT (w->top);
-  int right = left + window_internal_height (w);
-  int height = window_internal_height (w);
+  int right = left + window_internal_width (w);
+  int bottom = top + window_internal_height (w);
   int i;
 
-  for (i = vpos + 1; i < top + height; i++)
+  for (i = vpos + 1; i < bottom; i++)
     {
       int *charstart
        = FRAME_CURRENT_GLYPHS (XFRAME (WINDOW_FRAME (w)))->charstarts[i];
@@ -918,6 +973,62 @@ adjust_window_charstarts (w, vpos, adjust)
          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
@@ -992,7 +1103,7 @@ direct_output_for_insert (g)
      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))
+      || ! NILP (Ftext_properties_at (make_number (point - 1), Qnil))
 #endif
 
   /* Give up if w is minibuffer and a message is being displayed there */
@@ -1000,19 +1111,24 @@ direct_output_for_insert (g)
     return 0;
 
   {
-#ifdef HAVE_X_WINDOWS
+    int face = 0;
+#ifdef HAVE_FACES
     int dummy;
-    int face = compute_char_face (frame, w, point - 1, -1, -1, &dummy, point);
+
+    if (FRAME_WINDOW_P (frame))
+      face = compute_char_face (frame, w, point - 1, -1, -1, &dummy, point, 0);
 #endif
     current_frame->glyphs[vpos][hpos] = MAKE_GLYPH (frame, g, face);
-    current_frame->charstarts[vpos][hpos] = point;
+    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;
-  XFASTINT (w->last_point_x) = hpos;
-  XFASTINT (w->last_modified) = MODIFF;
+  XSETFASTINT (w->last_point, point);
+  XSETFASTINT (w->last_point_x, hpos);
+  XSETFASTINT (w->last_modified, MODIFF);
 
   reassert_line_highlight (0, vpos);
   write_glyphs (&current_frame->glyphs[vpos][hpos], 1);
@@ -1033,7 +1149,7 @@ direct_output_forward_char (n)
 {
   register FRAME_PTR frame = selected_frame;
   register struct window *w = XWINDOW (selected_window);
-  int position;
+  Lisp_Object position;
   int hpos = FRAME_CURSOR_X (frame);
 
   /* Give up if in truncated text at end of line.  */
@@ -1048,23 +1164,28 @@ direct_output_forward_char (n)
          && (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;
 
+  /* 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.  */
 
-  XFASTINT (position) = point;
+  XSETFASTINT (position, point);
   if (XFASTINT (position) < ZV
       && ! NILP (Fget_char_property (position,
                                     Qinvisible,
                                     selected_window)))
     return 0;
 
-  XFASTINT (position) = point - 1;
+  XSETFASTINT (position, point - 1);
   if (XFASTINT (position) >= BEGV
       && ! NILP (Fget_char_property (position,
                                     Qinvisible,
@@ -1073,8 +1194,8 @@ direct_output_forward_char (n)
 #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, point);
   cursor_to (FRAME_CURSOR_Y (frame), FRAME_CURSOR_X (frame));
   fflush (stdout);
 
@@ -1093,16 +1214,19 @@ 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;
 
@@ -1120,6 +1244,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++)
@@ -1135,21 +1263,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++)
@@ -1176,7 +1304,7 @@ update_frame (f, force, inhibit_hairy_id)
                        outq = PENDING_OUTPUT_COUNT (stdout);
 #endif
                      outq *= 10;
-                     if (baud_rate >= outq)
+                     if (baud_rate <= outq && baud_rate > 0)
                        sleep (outq / baud_rate);
                    }
                }
@@ -1185,27 +1313,36 @@ update_frame (f, force, inhibit_hairy_id)
            }
 
          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), minibuf_window))
        {
          int top = XINT (XWINDOW (FRAME_MINIBUF_WINDOW (f))->top);
          int row, col;
@@ -1257,7 +1394,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;
 }
 
@@ -1267,12 +1404,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 */
@@ -1288,6 +1427,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);
@@ -1320,10 +1460,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;
 
@@ -1337,7 +1478,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,
@@ -1346,6 +1487,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);
@@ -1377,16 +1519,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)
-                        + (hscroll ? 1 - 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_width, hscroll, 0, window);
 
   current_buffer = old_current_buffer;
 
@@ -1461,7 +1609,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
@@ -1481,16 +1629,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])
     {
@@ -1768,6 +1916,95 @@ update_line (frame, 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 (*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,
   1, 1, "FOpen termscript file: ",
   "Start writing all terminal output to FILE as well as the terminal.\n\
@@ -1791,7 +2028,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;
@@ -1858,9 +2096,28 @@ 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_TERMCAP_P (f))
+    {
+      /* When using termcap, all frames use the same screen,
+        so a change in size affects all termcap frames.  */
+      FOR_EACH_FRAME (tail, frame)
+       if (FRAME_TERMCAP_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;
 {
   /* If we can't deal with the change now, queue it for later.  */
   if (delay)
@@ -1895,8 +2152,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
@@ -1937,7 +2194,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);
 }
@@ -1946,15 +2208,15 @@ 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;
@@ -2005,7 +2267,7 @@ Emacs was built without floating point support.\n\
   int sec, usec;
 
   if (NILP (milliseconds))
-    XSET (milliseconds, Lisp_Int, 0);
+    XSETINT (milliseconds, 0);
   else
     CHECK_NUMBER (milliseconds, 1);
   usec = XINT (milliseconds) * 1000;
@@ -2044,7 +2306,7 @@ Emacs was built without floating point support.\n\
   {
     Lisp_Object zero;
 
-    XFASTINT (zero) = 0;
+    XSETFASTINT (zero, 0);
     wait_reading_process_input (sec, usec, zero, 0);
   }
 
@@ -2089,8 +2351,7 @@ Emacs was built without floating point support.\n\
    it does the redisplay.
 
    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.  */
+   waiting for input as well.  */
 
 Lisp_Object
 sit_for (sec, usec, reading, display)
@@ -2111,7 +2372,7 @@ 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);
 
 
@@ -2150,7 +2411,7 @@ 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\
+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.")
@@ -2160,7 +2421,7 @@ Value is t if waited the full time with no input arriving.")
   int sec, usec;
 
   if (NILP (milliseconds))
-    XSET (milliseconds, Lisp_Int, 0);
+    XSETINT (milliseconds, 0);
   else
     CHECK_NUMBER (milliseconds, 1);
   usec = XINT (milliseconds) * 1000;
@@ -2181,8 +2442,6 @@ Value is t if waited the full time with no input arriving.")
     error ("millisecond `sit-for' not supported on %s", SYSTEM_TYPE);
 #endif
 
-  if (NILP (nodisp))
-    prepare_menu_bars ();
   return sit_for (sec, usec, 0, NILP (nodisp));
 }
 \f
@@ -2238,6 +2497,15 @@ init_display ()
     }
 #endif /* HAVE_X_WINDOWS */
 
+#ifdef HAVE_NTGUI
+  if (!inhibit_window_system) 
+    {
+      Vwindow_system = intern ("win32");
+      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))
     {
@@ -2300,14 +2568,21 @@ 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 (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,
@@ -2335,7 +2610,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,