use dynwind_begin and dynwind_end
[bpt/emacs.git] / src / dispnew.c
index f9fed7d..5c6a43c 100644 (file)
@@ -1,6 +1,6 @@
 /* Updating of data structures for redisplay.
 
-Copyright (C) 1985-1988, 1993-1995, 1997-2013 Free Software Foundation,
+Copyright (C) 1985-1988, 1993-1995, 1997-2014 Free Software Foundation,
 Inc.
 
 This file is part of GNU Emacs.
@@ -20,9 +20,7 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 
 #include <config.h>
 
-#define DISPEXTERN_INLINE EXTERN_INLINE
-
-#include <stdio.h>
+#include "sysstdio.h"
 #include <unistd.h>
 
 #include "lisp.h"
@@ -44,21 +42,16 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 #include "process.h"
 
 #include "syssignal.h"
+#include "tparam.h"
 
 #ifdef HAVE_WINDOW_SYSTEM
 #include TERM_HEADER
 #endif /* HAVE_WINDOW_SYSTEM */
 
-/* Include systime.h after xterm.h to avoid double inclusion of time.h.  */
-
-#include "systime.h"
 #include <errno.h>
 
 #include <fpending.h>
-
-#if defined (HAVE_TERM_H) && defined (GNU_LINUX)
-#include <term.h>              /* for tgetent */
-#endif
+#include <timespec.h>
 
 #ifdef WINDOWSNT
 #include "w32.h"
@@ -79,10 +72,8 @@ struct dim
 static void update_frame_line (struct frame *, int);
 static int required_matrix_height (struct window *);
 static int required_matrix_width (struct window *);
-static void adjust_frame_glyphs (struct frame *);
-static void change_frame_size_1 (struct frame *, int, int, bool, bool, bool);
+static void change_frame_size_1 (struct frame *, int, int, bool, bool, bool, bool);
 static void increment_row_positions (struct glyph_row *, ptrdiff_t, ptrdiff_t);
-static void fill_up_frame_row_with_spaces (struct glyph_row *, int);
 static void build_frame_matrix_from_window_tree (struct glyph_matrix *,
                                                  struct window *);
 static void build_frame_matrix_from_leaf_window (struct glyph_matrix *,
@@ -101,16 +92,12 @@ static void check_matrix_pointers (struct glyph_matrix *,
 static void mirror_line_dance (struct window *, int, int, int *, char *);
 static bool update_window_tree (struct window *, bool);
 static bool update_window (struct window *, bool);
-static bool update_frame_1 (struct frame *, bool, bool);
+static bool update_frame_1 (struct frame *, bool, bool, bool);
 static bool scrolling (struct frame *);
 static void set_window_cursor_after_update (struct window *);
 static void adjust_frame_glyphs_for_window_redisplay (struct frame *);
 static void adjust_frame_glyphs_for_frame_redisplay (struct frame *);
-
-/* True upon entry to redisplay means do not assume anything about
-   current contents of actual terminal frame; clear and redraw it.  */
-
-bool frame_garbaged;
+static void set_window_update_flags (struct window *w, bool on_p);
 
 /* True means last display completed.  False means it was preempted.  */
 
@@ -118,57 +105,29 @@ bool display_completed;
 
 Lisp_Object Qdisplay_table, Qredisplay_dont_pause;
 
-\f
-/* The currently selected frame.  In a single-frame version, this
-   variable always equals the_only_frame.  */
-
-Lisp_Object selected_frame;
-
-/* A frame which is not just a mini-buffer, 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 holds
-   the address of the_only_frame.  */
-
-struct frame *last_nonminibuf_frame;
-
 /* True means SIGWINCH happened when not safe.  */
 
 static bool delayed_size_change;
 
-/* Updated window if != 0.  Set by update_window.  */
-
-struct window *updated_window;
-
-/* Glyph row updated in update_window_line, and area that is updated.  */
-
-struct glyph_row *updated_row;
-int updated_area;
-
 /* A glyph for a space.  */
 
 struct glyph space_glyph;
 
+#if defined GLYPH_DEBUG && defined ENABLE_CHECKING
+
 /* Counts of allocated structures.  These counts serve to diagnose
    memory leaks and double frees.  */
 
 static int glyph_matrix_count;
 static int glyph_pool_count;
 
+#endif /* GLYPH_DEBUG and ENABLE_CHECKING */
+
 /* If non-null, the frame whose frame matrices are manipulated.  If
    null, window matrices are worked on.  */
 
 static struct frame *frame_matrix_frame;
 
-/* True means that fonts have been loaded since the last glyph
-   matrix adjustments.  Redisplay must stop, and glyph matrices must
-   be adjusted when this flag becomes true during display.  The
-   reason fonts can be loaded so late is that fonts of fontsets are
-   loaded on demand.  Another reason is that a line contains many
-   characters displayed by zero width or very narrow glyphs of
-   variable-width fonts.  */
-
-bool fonts_changed_p;
-
 /* Convert vpos and hpos from frame to window and vice versa.
    This may only be used for terminal frames.  */
 
@@ -213,6 +172,7 @@ static void
 add_window_display_history (struct window *w, const char *msg, bool paused_p)
 {
   char *buf;
+  void *ptr = w;
 
   if (history_idx >= REDISPLAY_HISTORY_SIZE)
     history_idx = 0;
@@ -222,10 +182,10 @@ add_window_display_history (struct window *w, const char *msg, bool paused_p)
   snprintf (buf, sizeof redisplay_history[0].trace,
            "%"pMu": window %p (`%s')%s\n%s",
            history_tick++,
-           w,
-           ((BUFFERP (w->buffer)
-             && STRINGP (BVAR (XBUFFER (w->buffer), name)))
-            ? SSDATA (BVAR (XBUFFER (w->buffer), name))
+           ptr,
+           ((BUFFERP (w->contents)
+             && STRINGP (BVAR (XBUFFER (w->contents), name)))
+            ? SSDATA (BVAR (XBUFFER (w->contents), name))
             : "???"),
            paused_p ? " ***paused***" : "",
            msg);
@@ -240,6 +200,7 @@ static void
 add_frame_display_history (struct frame *f, bool paused_p)
 {
   char *buf;
+  void *ptr = f;
 
   if (history_idx >= REDISPLAY_HISTORY_SIZE)
     history_idx = 0;
@@ -248,7 +209,7 @@ add_frame_display_history (struct frame *f, bool paused_p)
 
   sprintf (buf, "%"pMu": update frame %p%s",
           history_tick++,
-          f, paused_p ? " ***paused***" : "");
+          ptr, paused_p ? " ***paused***" : "");
 }
 
 
@@ -305,9 +266,11 @@ new_glyph_matrix (struct glyph_pool *pool)
 {
   struct glyph_matrix *result = xzalloc (sizeof *result);
 
+#if defined GLYPH_DEBUG && defined ENABLE_CHECKING
   /* Increment number of allocated matrices.  This count is used
      to detect memory leaks.  */
   ++glyph_matrix_count;
+#endif
 
   /* Set pool and return.  */
   result->pool = pool;
@@ -317,10 +280,10 @@ new_glyph_matrix (struct glyph_pool *pool)
 
 /* Free glyph matrix MATRIX.  Passing in a null MATRIX is allowed.
 
-   The global counter glyph_matrix_count is decremented when a matrix
-   is freed.  If the count gets negative, more structures were freed
-   than allocated, i.e. one matrix was freed more than once or a bogus
-   pointer was passed to this function.
+   If GLYPH_DEBUG and ENABLE_CHECKING are in effect, the global counter
+   glyph_matrix_count is decremented when a matrix is freed.  If the count
+   gets negative, more structures were freed than allocated, i.e. one matrix
+   was freed more than once or a bogus pointer was passed to this function.
 
    If MATRIX->pool is null, this means that the matrix manages its own
    glyph memory---this is done for matrices on X frames.  Freeing the
@@ -333,10 +296,12 @@ free_glyph_matrix (struct glyph_matrix *matrix)
     {
       int i;
 
+#if defined GLYPH_DEBUG && defined ENABLE_CHECKING
       /* Detect the case that more matrices are freed than were
         allocated.  */
-      if (--glyph_matrix_count < 0)
-       emacs_abort ();
+      --glyph_matrix_count;
+      eassert (glyph_matrix_count >= 0);
+#endif
 
       /* Free glyph memory if MATRIX owns it.  */
       if (matrix->pool == NULL)
@@ -353,25 +318,19 @@ free_glyph_matrix (struct glyph_matrix *matrix)
 /* Return the number of glyphs to reserve for a marginal area of
    window W.  TOTAL_GLYPHS is the number of glyphs in a complete
    display line of window W.  MARGIN gives the width of the marginal
-   area in canonical character units.  MARGIN should be an integer
-   or a float.  */
+   area in canonical character units.  */
 
 static int
-margin_glyphs_to_reserve (struct window *w, int total_glyphs, Lisp_Object margin)
+margin_glyphs_to_reserve (struct window *w, int total_glyphs, int margin)
 {
-  int n;
-
-  if (NUMBERP (margin))
+  if (margin > 0)
     {
-      int width = XFASTINT (w->total_cols);
-      double d = max (0, XFLOATINT (margin));
+      int width = w->total_cols;
+      double d = max (0, margin);
       d = min (width / 2 - 1, d);
-      n = (int) ((double) total_glyphs / width * d);
+      return (int) ((double) total_glyphs / width * d);
     }
-  else
-    n = 0;
-
-  return n;
+  return 0;
 }
 
 /* Return true if ROW's hash value is correct.
@@ -420,7 +379,7 @@ adjust_glyph_matrix (struct window *w, struct glyph_matrix *matrix, int x, int y
      Get W's size.  */
   if (w)
     {
-      window_box (w, -1, 0, 0, &window_width, &window_height);
+      window_box (w, ANY_AREA, 0, 0, &window_width, &window_height);
 
       header_line_p = WINDOW_WANTS_HEADER_LINE_P (w);
       header_line_changed_p = header_line_p != matrix->header_line_p;
@@ -440,10 +399,10 @@ adjust_glyph_matrix (struct window *w, struct glyph_matrix *matrix, int x, int y
                                  || right != matrix->right_margin_glyphs);
 
       if (!marginal_areas_changed_p
-         && !fonts_changed_p
+         && !XFRAME (w->frame)->fonts_changed
          && !header_line_changed_p
-         && matrix->window_left_col == WINDOW_LEFT_EDGE_COL (w)
-         && matrix->window_top_line == WINDOW_TOP_EDGE_LINE (w)
+         && matrix->window_pixel_left == WINDOW_LEFT_PIXEL_EDGE (w)
+         && matrix->window_pixel_top == WINDOW_TOP_PIXEL_EDGE (w)
          && matrix->window_height == window_height
          && matrix->window_vscroll == w->vscroll
          && matrix->window_width == window_width)
@@ -584,8 +543,8 @@ adjust_glyph_matrix (struct window *w, struct glyph_matrix *matrix, int x, int y
              && !header_line_changed_p
              && new_rows == 0
              && dim.width == matrix->matrix_w
-             && matrix->window_left_col == WINDOW_LEFT_EDGE_COL (w)
-             && matrix->window_top_line == WINDOW_TOP_EDGE_LINE (w)
+             && matrix->window_pixel_left == WINDOW_LEFT_PIXEL_EDGE (w)
+             && matrix->window_pixel_top == WINDOW_TOP_PIXEL_EDGE (w)
              && matrix->window_width == window_width)
            {
              /* Find the last row in the window.  */
@@ -598,17 +557,16 @@ adjust_glyph_matrix (struct window *w, struct glyph_matrix *matrix, int x, int y
 
              /* Window end is invalid, if inside of the rows that
                 are invalidated below.  */
-             if (INTEGERP (w->window_end_vpos)
-                 && XFASTINT (w->window_end_vpos) >= i)
+             if (w->window_end_vpos >= i)
                w->window_end_valid = 0;
 
              while (i < matrix->nrows)
-               matrix->rows[i++].enabled_p = 0;
+               matrix->rows[i++].enabled_p = false;
            }
          else
            {
              for (i = 0; i < matrix->nrows; ++i)
-               matrix->rows[i].enabled_p = 0;
+               matrix->rows[i].enabled_p = false;
            }
        }
       else if (matrix == w->desired_matrix)
@@ -618,7 +576,7 @@ adjust_glyph_matrix (struct window *w, struct glyph_matrix *matrix, int x, int y
             had better be the case when we adjust matrices between
             redisplays.  */
          for (i = 0; i < matrix->nrows; ++i)
-           matrix->rows[i].enabled_p = 0;
+           matrix->rows[i].enabled_p = false;
        }
     }
 
@@ -633,8 +591,8 @@ adjust_glyph_matrix (struct window *w, struct glyph_matrix *matrix, int x, int y
      was last adjusted.  This is used to optimize redisplay above.  */
   if (w)
     {
-      matrix->window_left_col = WINDOW_LEFT_EDGE_COL (w);
-      matrix->window_top_line = WINDOW_TOP_EDGE_LINE (w);
+      matrix->window_pixel_left = WINDOW_LEFT_PIXEL_EDGE (w);
+      matrix->window_pixel_top = WINDOW_TOP_PIXEL_EDGE (w);
       matrix->window_height = window_height;
       matrix->window_width = window_width;
       matrix->window_vscroll = w->vscroll;
@@ -726,7 +684,7 @@ clear_glyph_matrix_rows (struct glyph_matrix *matrix, int start, int end)
   eassert (end >= 0 && end <= matrix->nrows);
 
   for (; start < end; ++start)
-    matrix->rows[start].enabled_p = 0;
+    matrix->rows[start].enabled_p = false;
 }
 
 
@@ -794,15 +752,19 @@ clear_current_matrices (register struct frame *f)
   if (f->current_matrix)
     clear_glyph_matrix (f->current_matrix);
 
+#if defined (HAVE_X_WINDOWS) && ! defined (USE_X_TOOLKIT) && ! defined (USE_GTK)
   /* Clear the matrix of the menu bar window, if such a window exists.
      The menu bar window is currently used to display menus on X when
      no toolkit support is compiled in.  */
   if (WINDOWP (f->menu_bar_window))
     clear_glyph_matrix (XWINDOW (f->menu_bar_window)->current_matrix);
+#endif
 
+#if defined (HAVE_WINDOW_SYSTEM) && ! defined (USE_GTK) && ! defined (HAVE_NS)
   /* Clear the matrix of the tool-bar window, if any.  */
   if (WINDOWP (f->tool_bar_window))
     clear_glyph_matrix (XWINDOW (f->tool_bar_window)->current_matrix);
+#endif
 
   /* Clear current window matrices.  */
   eassert (WINDOWP (FRAME_ROOT_WINDOW (f)));
@@ -818,11 +780,15 @@ clear_desired_matrices (register struct frame *f)
   if (f->desired_matrix)
     clear_glyph_matrix (f->desired_matrix);
 
+#if defined (HAVE_X_WINDOWS) && ! defined (USE_X_TOOLKIT) && ! defined (USE_GTK)
   if (WINDOWP (f->menu_bar_window))
     clear_glyph_matrix (XWINDOW (f->menu_bar_window)->desired_matrix);
+#endif
 
+#if defined (HAVE_WINDOW_SYSTEM) && ! defined (USE_GTK) && ! defined (HAVE_NS)
   if (WINDOWP (f->tool_bar_window))
     clear_glyph_matrix (XWINDOW (f->tool_bar_window)->desired_matrix);
+#endif
 
   /* Do it for window matrices.  */
   eassert (WINDOWP (FRAME_ROOT_WINDOW (f)));
@@ -838,16 +804,8 @@ clear_window_matrices (struct window *w, bool desired_p)
 {
   while (w)
     {
-      if (!NILP (w->hchild))
-       {
-         eassert (WINDOWP (w->hchild));
-         clear_window_matrices (XWINDOW (w->hchild), desired_p);
-       }
-      else if (!NILP (w->vchild))
-       {
-         eassert (WINDOWP (w->vchild));
-         clear_window_matrices (XWINDOW (w->vchild), desired_p);
-       }
+      if (WINDOWP (w->contents))
+       clear_window_matrices (XWINDOW (w->contents), desired_p);
       else
        {
          if (desired_p)
@@ -871,41 +829,16 @@ clear_window_matrices (struct window *w, bool desired_p)
       See dispextern.h for an overall explanation of glyph rows.
  ***********************************************************************/
 
-/* Clear glyph row ROW.  Do it in a way that makes it robust against
-   changes in the glyph_row structure, i.e. addition or removal of
-   structure members.  */
-
-static struct glyph_row null_row;
+/* Clear glyph row ROW.  NOTE: this code relies on the current
+   layout of `glyphs' and `used' fields of `struct glyph_row'.  */
 
 void
 clear_glyph_row (struct glyph_row *row)
 {
-  struct glyph *p[1 + LAST_AREA];
-
-  /* Save pointers.  */
-  p[LEFT_MARGIN_AREA] = row->glyphs[LEFT_MARGIN_AREA];
-  p[TEXT_AREA] = row->glyphs[TEXT_AREA];
-  p[RIGHT_MARGIN_AREA] = row->glyphs[RIGHT_MARGIN_AREA];
-  p[LAST_AREA] = row->glyphs[LAST_AREA];
-
-  /* Clear.  */
-  *row = null_row;
-
-  /* Restore pointers.  */
-  row->glyphs[LEFT_MARGIN_AREA] = p[LEFT_MARGIN_AREA];
-  row->glyphs[TEXT_AREA] = p[TEXT_AREA];
-  row->glyphs[RIGHT_MARGIN_AREA] = p[RIGHT_MARGIN_AREA];
-  row->glyphs[LAST_AREA] = p[LAST_AREA];
-
-#if 0 /* At some point, some bit-fields of struct glyph were not set,
-        which made glyphs unequal when compared with GLYPH_EQUAL_P.
-        Redisplay outputs such glyphs, and flickering effects were
-        the result.  This also depended on the contents of memory
-        returned by xmalloc.  If flickering happens again, activate
-        the code below.  If the flickering is gone with that, chances
-        are that the flickering has the same reason as here.  */
-  memset (p[0], 0, (char *) p[LAST_AREA] - (char *) p[0]);
-#endif
+  enum { off = offsetof (struct glyph_row, used) };
+
+  /* Zero everything except pointers in `glyphs'.  */
+  memset (row->used, 0, sizeof *row - off);
 }
 
 
@@ -931,7 +864,7 @@ blank_row (struct window *w, struct glyph_row *row, int y)
   if (row->y + row->height > max_y)
     row->visible_height -= row->y + row->height - max_y;
 
-  row->enabled_p = 1;
+  row->enabled_p = true;
 }
 
 
@@ -1044,29 +977,17 @@ swap_glyph_pointers (struct glyph_row *a, struct glyph_row *b)
 }
 
 
-/* Copy glyph row structure FROM to glyph row structure TO, except
-   that glyph pointers, the `used' counts, and the hash values in the
-   structures are left unchanged.  */
+/* Copy glyph row structure FROM to glyph row structure TO, except that
+   glyph pointers, the `used' counts, and the hash values in the structures
+   are left unchanged.  NOTE: this code relies on the current layout of
+   `glyphs', `used', `hash' and `x' fields of `struct glyph_row'.  */
 
 static void
 copy_row_except_pointers (struct glyph_row *to, struct glyph_row *from)
 {
-  struct glyph *pointers[1 + LAST_AREA];
-  short used[LAST_AREA];
-  unsigned hashval;
-
-  /* Save glyph pointers of TO.  */
-  memcpy (pointers, to->glyphs, sizeof to->glyphs);
-  memcpy (used, to->used, sizeof to->used);
-  hashval = to->hash;
-
-  /* Do a structure assignment.  */
-  *to = *from;
-
-  /* Restore original pointers of TO.  */
-  memcpy (to->glyphs, pointers, sizeof to->glyphs);
-  memcpy (to->used, used, sizeof to->used);
-  to->hash = hashval;
+  enum { off = offsetof (struct glyph_row, x) };
+
+  memcpy (&to->x, &from->x, sizeof *to - off);
 }
 
 
@@ -1141,16 +1062,17 @@ prepare_desired_row (struct glyph_row *row)
       bool rp = row->reversed_p;
 
       clear_glyph_row (row);
-      row->enabled_p = 1;
+      row->enabled_p = true;
       row->reversed_p = rp;
     }
 }
 
 
-/* Return a hash code for glyph row ROW.  */
+/* Return a hash code for glyph row ROW, which may
+   be from current or desired matrix of frame F.  */
 
 static int
-line_hash_code (struct glyph_row *row)
+line_hash_code (struct frame *f, struct glyph_row *row)
 {
   int hash = 0;
 
@@ -1163,7 +1085,7 @@ line_hash_code (struct glyph_row *row)
        {
          int c = glyph->u.ch;
          int face_id = glyph->face_id;
-         if (FRAME_MUST_WRITE_SPACES (SELECTED_FRAME ())) /* XXX Is SELECTED_FRAME OK here? */
+         if (FRAME_MUST_WRITE_SPACES (f))
            c -= SPACEGLYPH;
          hash = (((hash << 4) + (hash >> 24)) & 0x0fffffff) + c;
          hash = (((hash << 4) + (hash >> 24)) & 0x0fffffff) + face_id;
@@ -1178,12 +1100,13 @@ line_hash_code (struct glyph_row *row)
 }
 
 
-/* Return the cost of drawing line VPOS in MATRIX.  The cost equals
-   the number of characters in the line.  If must_write_spaces is
-   zero, leading and trailing spaces are ignored.  */
+/* Return the cost of drawing line VPOS in MATRIX, which may
+   be current or desired matrix of frame F.  The cost equals
+   the number of characters in the line.  If must_write_spaces
+   is zero, leading and trailing spaces are ignored.  */
 
 static int
-line_draw_cost (struct glyph_matrix *matrix, int vpos)
+line_draw_cost (struct frame *f, struct glyph_matrix *matrix, int vpos)
 {
   struct glyph_row *row = matrix->rows + vpos;
   struct glyph *beg = row->glyphs[TEXT_AREA];
@@ -1193,7 +1116,7 @@ line_draw_cost (struct glyph_matrix *matrix, int vpos)
   ptrdiff_t glyph_table_len = GLYPH_TABLE_LENGTH;
 
   /* Ignore trailing and leading spaces if we can.  */
-  if (!FRAME_MUST_WRITE_SPACES (SELECTED_FRAME ())) /* XXX Is SELECTED_FRAME OK here? */
+  if (!FRAME_MUST_WRITE_SPACES (f))
     {
       /* Skip from the end over trailing spaces.  */
       while (end > beg && CHAR_GLYPH_SPACE_P (*(end - 1)))
@@ -1312,38 +1235,41 @@ row_equal_p (struct glyph_row *a, struct glyph_row *b, bool mouse_face_p)
      See dispextern.h for an overall explanation of glyph pools.
  ***********************************************************************/
 
-/* Allocate a glyph_pool structure.  The structure returned is
-   initialized with zeros.  The global variable glyph_pool_count is
-   incremented for each pool allocated.  */
+/* Allocate a glyph_pool structure.  The structure returned is initialized
+   with zeros.  If GLYPH_DEBUG and ENABLE_CHECKING are in effect, the global
+   variable glyph_pool_count is incremented for each pool allocated.  */
 
 static struct glyph_pool *
 new_glyph_pool (void)
 {
   struct glyph_pool *result = xzalloc (sizeof *result);
 
+#if defined GLYPH_DEBUG && defined ENABLE_CHECKING
   /* For memory leak and double deletion checking.  */
   ++glyph_pool_count;
+#endif
 
   return result;
 }
 
 
 /* Free a glyph_pool structure POOL.  The function may be called with
-   a null POOL pointer.  The global variable glyph_pool_count is
-   decremented with every pool structure freed.  If this count gets
-   negative, more structures were freed than allocated, i.e. one
-   structure must have been freed more than once or a bogus pointer
-   was passed to free_glyph_pool.  */
+   a null POOL pointer.  If GLYPH_DEBUG and ENABLE_CHECKING are in effect,
+   global variable glyph_pool_count is decremented with every pool structure
+   freed.  If this count gets negative, more structures were freed than
+   allocated, i.e. one structure must have been freed more than once or
+   a bogus pointer was passed to free_glyph_pool.  */
 
 static void
 free_glyph_pool (struct glyph_pool *pool)
 {
   if (pool)
     {
+#if defined GLYPH_DEBUG && defined ENABLE_CHECKING
       /* More freed than allocated?  */
       --glyph_pool_count;
       eassert (glyph_pool_count >= 0);
-
+#endif
       xfree (pool->glyphs);
       xfree (pool);
     }
@@ -1468,7 +1394,7 @@ check_matrix_invariants (struct window *w)
   struct glyph_row *row = matrix->rows;
   struct glyph_row *last_text_row = NULL;
   struct buffer *saved = current_buffer;
-  struct buffer *buffer = XBUFFER (w->buffer);
+  struct buffer *buffer = XBUFFER (w->contents);
   int c;
 
   /* This can sometimes happen for a fresh window.  */
@@ -1632,7 +1558,7 @@ allocate_matrices_for_frame_redisplay (Lisp_Object window, int x, int y,
      vertically below other windows.  */
   in_horz_combination_p
     = (!NILP (XWINDOW (window)->parent)
-       && !NILP (XWINDOW (XWINDOW (window)->parent)->hchild));
+       && WINDOW_HORIZONTAL_COMBINATION_P (XWINDOW (XWINDOW (window)->parent)));
 
   /* For WINDOW and all windows on the same level.  */
   do
@@ -1641,12 +1567,8 @@ allocate_matrices_for_frame_redisplay (Lisp_Object window, int x, int y,
 
       /* Get the dimension of the window sub-matrix for W, depending
         on whether this is a combination or a leaf window.  */
-      if (!NILP (w->hchild))
-       dim = allocate_matrices_for_frame_redisplay (w->hchild, x, y,
-                                                    dim_only_p,
-                                                    window_change_flags);
-      else if (!NILP (w->vchild))
-       dim = allocate_matrices_for_frame_redisplay (w->vchild, x, y,
+      if (WINDOWP (w->contents))
+       dim = allocate_matrices_for_frame_redisplay (w->contents, x, y,
                                                     dim_only_p,
                                                     window_change_flags);
       else
@@ -1739,6 +1661,7 @@ required_matrix_height (struct window *w)
     {
       int ch_height = FRAME_SMALLEST_FONT_HEIGHT (f);
       int window_pixel_height = window_box_height (w) + eabs (w->vscroll);
+
       return (((window_pixel_height + ch_height - 1)
               / ch_height) * w->nrows_scale_factor
              /* One partially visible line at the top and
@@ -1763,10 +1686,9 @@ required_matrix_width (struct window *w)
   if (FRAME_WINDOW_P (f))
     {
       int ch_width = FRAME_SMALLEST_CHAR_WIDTH (f);
-      int window_pixel_width = WINDOW_TOTAL_WIDTH (w);
 
       /* Compute number of glyphs needed in a glyph row.  */
-      return (((window_pixel_width + ch_width - 1)
+      return (((WINDOW_PIXEL_WIDTH (w) + ch_width - 1)
               / ch_width) * w->ncols_scale_factor
              /* 2 partially visible columns in the text area.  */
              + 2
@@ -1776,7 +1698,7 @@ required_matrix_width (struct window *w)
     }
 #endif /* HAVE_WINDOW_SYSTEM */
 
-  return XINT (w->total_cols);
+  return w->total_cols;
 }
 
 
@@ -1788,10 +1710,8 @@ allocate_matrices_for_window_redisplay (struct window *w)
 {
   while (w)
     {
-      if (!NILP (w->vchild))
-       allocate_matrices_for_window_redisplay (XWINDOW (w->vchild));
-      else if (!NILP (w->hchild))
-       allocate_matrices_for_window_redisplay (XWINDOW (w->hchild));
+      if (WINDOWP (w->contents))
+       allocate_matrices_for_window_redisplay (XWINDOW (w->contents));
       else
        {
          /* W is a leaf window.  */
@@ -1814,37 +1734,17 @@ allocate_matrices_for_window_redisplay (struct window *w)
     }
 }
 
-
-/* Re-allocate/ re-compute glyph matrices on frame F.  If F is null,
-   do it for all frames; otherwise do it just for the given frame.
-   This function must be called when a new frame is created, its size
-   changes, or its window configuration changes.  */
+/* Allocate/reallocate glyph matrices of a single frame F.
+   This function must be called when a new frame is created,
+   its size changes, or its window configuration changes.  */
 
 void
-adjust_glyphs (struct frame *f)
+adjust_frame_glyphs (struct frame *f)
 {
   /* Block input so that expose events and other events that access
      glyph matrices are not processed while we are changing them.  */
   block_input ();
 
-  if (f)
-    adjust_frame_glyphs (f);
-  else
-    {
-      Lisp_Object tail, lisp_frame;
-
-      FOR_EACH_FRAME (tail, lisp_frame)
-       adjust_frame_glyphs (XFRAME (lisp_frame));
-    }
-
-  unblock_input ();
-}
-
-/* Allocate/reallocate glyph matrices of a single frame F.  */
-
-static void
-adjust_frame_glyphs (struct frame *f)
-{
   if (FRAME_WINDOW_P (f))
     adjust_frame_glyphs_for_window_redisplay (f);
   else
@@ -1854,6 +1754,8 @@ adjust_frame_glyphs (struct frame *f)
   adjust_decode_mode_spec_buffer (f);
 
   f->glyphs_initialized_p = 1;
+
+  unblock_input ();
 }
 
 /* Return true if any window in the tree has nonzero window margins.  See
@@ -1863,18 +1765,12 @@ showing_window_margins_p (struct window *w)
 {
   while (w)
     {
-      if (!NILP (w->hchild))
+      if (WINDOWP (w->contents))
        {
-         if (showing_window_margins_p (XWINDOW (w->hchild)))
+         if (showing_window_margins_p (XWINDOW (w->contents)))
            return 1;
        }
-      else if (!NILP (w->vchild))
-       {
-         if (showing_window_margins_p (XWINDOW (w->vchild)))
-           return 1;
-       }
-      else if (!NILP (w->left_margin_cols)
-              || !NILP (w->right_margin_cols))
+      else if (w->left_margin_cols > 0 || w->right_margin_cols > 0)
        return 1;
 
       w = NILP (w->next) ? 0 : XWINDOW (w->next);
@@ -1895,10 +1791,8 @@ fake_current_matrices (Lisp_Object window)
     {
       w = XWINDOW (window);
 
-      if (!NILP (w->hchild))
-       fake_current_matrices (w->hchild);
-      else if (!NILP (w->vchild))
-       fake_current_matrices (w->vchild);
+      if (WINDOWP (w->contents))
+       fake_current_matrices (w->contents);
       else
        {
          int i;
@@ -1949,9 +1843,28 @@ save_current_matrix (struct frame *f)
       struct glyph_row *from = f->current_matrix->rows + i;
       struct glyph_row *to = saved->rows + i;
       ptrdiff_t nbytes = from->used[TEXT_AREA] * sizeof (struct glyph);
+
       to->glyphs[TEXT_AREA] = xmalloc (nbytes);
       memcpy (to->glyphs[TEXT_AREA], from->glyphs[TEXT_AREA], nbytes);
       to->used[TEXT_AREA] = from->used[TEXT_AREA];
+      to->enabled_p = from->enabled_p;
+      to->hash = from->hash;
+      if (from->used[LEFT_MARGIN_AREA])
+       {
+         nbytes = from->used[LEFT_MARGIN_AREA] * sizeof (struct glyph);
+         to->glyphs[LEFT_MARGIN_AREA] = xmalloc (nbytes);
+         memcpy (to->glyphs[LEFT_MARGIN_AREA],
+                 from->glyphs[LEFT_MARGIN_AREA], nbytes);
+         to->used[LEFT_MARGIN_AREA] = from->used[LEFT_MARGIN_AREA];
+       }
+      if (from->used[RIGHT_MARGIN_AREA])
+       {
+         nbytes = from->used[RIGHT_MARGIN_AREA] * sizeof (struct glyph);
+         to->glyphs[RIGHT_MARGIN_AREA] = xmalloc (nbytes);
+         memcpy (to->glyphs[RIGHT_MARGIN_AREA],
+                 from->glyphs[RIGHT_MARGIN_AREA], nbytes);
+         to->used[RIGHT_MARGIN_AREA] = from->used[RIGHT_MARGIN_AREA];
+       }
     }
 
   return saved;
@@ -1971,9 +1884,30 @@ restore_current_matrix (struct frame *f, struct glyph_matrix *saved)
       struct glyph_row *from = saved->rows + i;
       struct glyph_row *to = f->current_matrix->rows + i;
       ptrdiff_t nbytes = from->used[TEXT_AREA] * sizeof (struct glyph);
+
       memcpy (to->glyphs[TEXT_AREA], from->glyphs[TEXT_AREA], nbytes);
       to->used[TEXT_AREA] = from->used[TEXT_AREA];
       xfree (from->glyphs[TEXT_AREA]);
+      nbytes = from->used[LEFT_MARGIN_AREA] * sizeof (struct glyph);
+      if (nbytes)
+       {
+         memcpy (to->glyphs[LEFT_MARGIN_AREA],
+                 from->glyphs[LEFT_MARGIN_AREA], nbytes);
+         to->used[LEFT_MARGIN_AREA] = from->used[LEFT_MARGIN_AREA];
+         xfree (from->glyphs[LEFT_MARGIN_AREA]);
+       }
+      else
+       to->used[LEFT_MARGIN_AREA] = 0;
+      nbytes = from->used[RIGHT_MARGIN_AREA] * sizeof (struct glyph);
+      if (nbytes)
+       {
+         memcpy (to->glyphs[RIGHT_MARGIN_AREA],
+                 from->glyphs[RIGHT_MARGIN_AREA], nbytes);
+         to->used[RIGHT_MARGIN_AREA] = from->used[RIGHT_MARGIN_AREA];
+         xfree (from->glyphs[RIGHT_MARGIN_AREA]);
+       }
+      else
+       to->used[RIGHT_MARGIN_AREA] = 0;
     }
 
   xfree (saved->rows);
@@ -2044,6 +1978,10 @@ adjust_frame_glyphs_for_frame_redisplay (struct frame *f)
       /* Size of frame matrices must equal size of frame.  Note
         that we are called for X frames with window widths NOT equal
         to the frame width (from CHANGE_FRAME_SIZE_1).  */
+      if (matrix_dim.width != FRAME_COLS (f)
+         || matrix_dim.height != FRAME_LINES (f))
+       return;
+
       eassert (matrix_dim.width == FRAME_COLS (f)
               && matrix_dim.height == FRAME_LINES (f));
 
@@ -2093,10 +2031,9 @@ adjust_frame_glyphs_for_window_redisplay (struct frame *f)
   /* Allocate/reallocate window matrices.  */
   allocate_matrices_for_window_redisplay (XWINDOW (FRAME_ROOT_WINDOW (f)));
 
-#ifdef HAVE_X_WINDOWS
+#if defined (HAVE_X_WINDOWS) && ! defined (USE_X_TOOLKIT) && ! defined (USE_GTK)
   /* Allocate/ reallocate matrices of the dummy window used to display
      the menu bar under X when no X toolkit support is available.  */
-#if ! defined (USE_X_TOOLKIT) && ! defined (USE_GTK)
   {
     /* Allocate a dummy window if not already done.  */
     struct window *w;
@@ -2114,16 +2051,20 @@ adjust_frame_glyphs_for_window_redisplay (struct frame *f)
 
     /* Set window dimensions to frame dimensions and allocate or
        adjust glyph matrices of W.  */
-    wset_top_line (w, make_number (0));
-    wset_left_col (w, make_number (0));
-    wset_total_lines (w, make_number (FRAME_MENU_BAR_LINES (f)));
-    wset_total_cols (w, make_number (FRAME_TOTAL_COLS (f)));
+    w->pixel_left = 0;
+    w->left_col = 0;
+    w->pixel_top = 0;
+    w->top_line = 0;
+    w->pixel_width = (FRAME_PIXEL_WIDTH (f)
+                     - 2 * FRAME_INTERNAL_BORDER_WIDTH (f));
+    w->total_cols = FRAME_TOTAL_COLS (f);
+    w->pixel_height = FRAME_MENU_BAR_HEIGHT (f);
+    w->total_lines = FRAME_MENU_BAR_LINES (f);
     allocate_matrices_for_window_redisplay (w);
   }
-#endif /* not USE_X_TOOLKIT && not USE_GTK */
-#endif /* HAVE_X_WINDOWS */
+#endif
 
-#ifndef USE_GTK
+#if defined (HAVE_WINDOW_SYSTEM) && ! defined (USE_GTK) && ! defined (HAVE_NS)
   {
     /* Allocate/ reallocate matrices of the tool bar window.  If we
        don't have a tool bar window yet, make one.  */
@@ -2140,10 +2081,15 @@ adjust_frame_glyphs_for_window_redisplay (struct frame *f)
     else
       w = XWINDOW (f->tool_bar_window);
 
-    wset_top_line (w, make_number (FRAME_MENU_BAR_LINES (f)));
-    wset_left_col (w, make_number (0));
-    wset_total_lines (w, make_number (FRAME_TOOL_BAR_LINES (f)));
-    wset_total_cols (w, make_number (FRAME_TOTAL_COLS (f)));
+    w->pixel_left = 0;
+    w->left_col = 0;
+    w->pixel_top = FRAME_MENU_BAR_HEIGHT (f);
+    w->top_line = FRAME_MENU_BAR_LINES (f);
+    w->pixel_width = (FRAME_PIXEL_WIDTH (f)
+                      - 2 * FRAME_INTERNAL_BORDER_WIDTH (f));
+    w->total_cols = FRAME_TOTAL_COLS (f);
+    w->pixel_height = FRAME_TOOL_BAR_HEIGHT (f);
+    w->total_lines = FRAME_TOOL_BAR_LINES (f);
     allocate_matrices_for_window_redisplay (w);
   }
 #endif
@@ -2184,6 +2130,7 @@ free_glyphs (struct frame *f)
       if (!NILP (f->root_window))
         free_window_matrices (XWINDOW (f->root_window));
 
+#if defined (HAVE_X_WINDOWS) && ! defined (USE_X_TOOLKIT) && ! defined (USE_GTK)
       /* Free the dummy window for menu bars without X toolkit and its
         glyph matrices.  */
       if (!NILP (f->menu_bar_window))
@@ -2194,7 +2141,9 @@ free_glyphs (struct frame *f)
          w->desired_matrix = w->current_matrix = NULL;
          fset_menu_bar_window (f, Qnil);
        }
+#endif
 
+#if defined (HAVE_WINDOW_SYSTEM) && ! defined (USE_GTK) && ! defined (HAVE_NS)
       /* Free the tool bar window and its glyph matrices.  */
       if (!NILP (f->tool_bar_window))
        {
@@ -2204,6 +2153,7 @@ free_glyphs (struct frame *f)
          w->desired_matrix = w->current_matrix = NULL;
          fset_tool_bar_window (f, Qnil);
        }
+#endif
 
       /* Release frame glyph matrices.  Reset fields to zero in
         case we are called a second time.  */
@@ -2236,10 +2186,8 @@ free_window_matrices (struct window *w)
 {
   while (w)
     {
-      if (!NILP (w->hchild))
-       free_window_matrices (XWINDOW (w->hchild));
-      else if (!NILP (w->vchild))
-       free_window_matrices (XWINDOW (w->vchild));
+      if (WINDOWP (w->contents))
+       free_window_matrices (XWINDOW (w->contents));
       else
        {
          /* This is a leaf window.  Free its memory and reset fields
@@ -2270,11 +2218,11 @@ check_glyph_memory (void)
   FOR_EACH_FRAME (tail, frame)
     free_glyphs (XFRAME (frame));
 
+#if defined GLYPH_DEBUG && defined ENABLE_CHECKING
   /* Check that nothing is left allocated.  */
-  if (glyph_matrix_count)
-    emacs_abort ();
-  if (glyph_pool_count)
-    emacs_abort ();
+  eassert (glyph_matrix_count == 0);
+  eassert (glyph_pool_count == 0);
+#endif
 }
 
 
@@ -2291,7 +2239,7 @@ check_glyph_memory (void)
    screen.  We build such a view by constructing a frame matrix from
    window matrices in this section.
 
-   Windows that must be updated have their must_be_update_p flag set.
+   Windows that must be updated have their must_be_updated_p flag set.
    For all such windows, their desired matrix is made part of the
    desired frame matrix.  For other windows, their current matrix is
    made part of the desired frame matrix.
@@ -2372,10 +2320,8 @@ build_frame_matrix_from_window_tree (struct glyph_matrix *matrix, struct window
 {
   while (w)
     {
-      if (!NILP (w->hchild))
-       build_frame_matrix_from_window_tree (matrix, XWINDOW (w->hchild));
-      else if (!NILP (w->vchild))
-       build_frame_matrix_from_window_tree (matrix, XWINDOW (w->vchild));
+      if (WINDOWP (w->contents))
+       build_frame_matrix_from_window_tree (matrix, XWINDOW (w->contents));
       else
        build_frame_matrix_from_leaf_window (matrix, w);
 
@@ -2471,7 +2417,7 @@ build_frame_matrix_from_leaf_window (struct glyph_matrix *frame_matrix, struct w
 
          /* Only when a desired row has been displayed, we want
             the corresponding frame row to be updated.  */
-         frame_row->enabled_p = 1;
+         frame_row->enabled_p = true;
 
           /* Maybe insert a vertical border between horizontally adjacent
             windows.  */
@@ -2570,7 +2516,7 @@ fill_up_glyph_row_area_with_spaces (struct glyph_row *row, int area)
 /* Add spaces to the end of ROW in a frame matrix until index UPTO is
    reached.  In frame matrices only one area, TEXT_AREA, is used.  */
 
-static void
+void
 fill_up_frame_row_with_spaces (struct glyph_row *row, int upto)
 {
   int i = row->used[TEXT_AREA];
@@ -2619,7 +2565,7 @@ make_current (struct glyph_matrix *desired_matrix, struct glyph_matrix *current_
   assign_row (current_row, desired_row);
 
   /* Enable current_row to mark it as valid.  */
-  current_row->enabled_p = 1;
+  current_row->enabled_p = true;
   current_row->mouse_face_p = mouse_face_p;
 
   /* If we are called on frame matrices, perform analogous operations
@@ -2639,10 +2585,8 @@ mirror_make_current (struct window *w, int frame_row)
 {
   while (w)
     {
-      if (!NILP (w->hchild))
-       mirror_make_current (XWINDOW (w->hchild), frame_row);
-      else if (!NILP (w->vchild))
-       mirror_make_current (XWINDOW (w->vchild), frame_row);
+      if (WINDOWP (w->contents))
+       mirror_make_current (XWINDOW (w->contents), frame_row);
       else
        {
          /* Row relative to window W.  Don't use FRAME_TO_WINDOW_VPOS
@@ -2663,7 +2607,7 @@ mirror_make_current (struct window *w, int frame_row)
                assign_row (current_row, desired_row);
              else
                swap_glyph_pointers (desired_row, current_row);
-             current_row->enabled_p = 1;
+             current_row->enabled_p = true;
 
              /* Set the Y coordinate of the mode/header line's row.
                 It is needed in draw_row_with_mouse_face to find the
@@ -2718,7 +2662,7 @@ mirrored_line_dance (struct glyph_matrix *matrix, int unchanged_at_top, int nlin
 
       /* RETAINED_P is zero for empty lines.  */
       if (!retained_p[copy_from[i]])
-       new_rows[i].enabled_p = 0;
+       new_rows[i].enabled_p = false;
     }
 
   /* Do the same for window matrices, if MATRIX is a frame matrix.  */
@@ -2738,8 +2682,8 @@ sync_window_with_frame_matrix_rows (struct window *w)
   struct glyph_row *window_row, *window_row_end, *frame_row;
   int left, right, x, width;
 
-  /* Preconditions: W must be a leaf window on a tty frame.  */
-  eassert (NILP (w->hchild) && NILP (w->vchild));
+  /* Preconditions: W must be a live window on a tty frame.  */
+  eassert (BUFFERP (w->contents));
   eassert (!FRAME_WINDOW_P (f));
 
   left = margin_glyphs_to_reserve (w, 1, w->left_margin_cols);
@@ -2775,10 +2719,8 @@ frame_row_to_window (struct window *w, int row)
 
   while (w && !found)
     {
-      if (!NILP (w->hchild))
-       found = frame_row_to_window (XWINDOW (w->hchild), row);
-      else if (!NILP (w->vchild))
-       found = frame_row_to_window (XWINDOW (w->vchild), row);
+      if (WINDOWP (w->contents))
+       found = frame_row_to_window (XWINDOW (w->contents), row);
       else if (row >= WINDOW_TOP_EDGE_LINE (w)
               && row < WINDOW_BOTTOM_EDGE_LINE (w))
        found = w;
@@ -2806,11 +2748,8 @@ mirror_line_dance (struct window *w, int unchanged_at_top, int nlines, int *copy
 {
   while (w)
     {
-      if (!NILP (w->hchild))
-       mirror_line_dance (XWINDOW (w->hchild), unchanged_at_top,
-                          nlines, copy_from, retained_p);
-      else if (!NILP (w->vchild))
-       mirror_line_dance (XWINDOW (w->vchild), unchanged_at_top,
+      if (WINDOWP (w->contents))
+       mirror_line_dance (XWINDOW (w->contents), unchanged_at_top,
                           nlines, copy_from, retained_p);
       else
        {
@@ -2858,7 +2797,7 @@ mirror_line_dance (struct window *w, int unchanged_at_top, int nlines, int *copy
 
                  /* If frame line is empty, window line is empty, too.  */
                  if (!retained_p[copy_from[i]])
-                   m->rows[window_to].enabled_p = 0;
+                   m->rows[window_to].enabled_p = false;
                }
              else if (to_inside_window_p)
                {
@@ -2883,7 +2822,7 @@ mirror_line_dance (struct window *w, int unchanged_at_top, int nlines, int *copy
 
                      /* If frame line is empty, window line is empty, too.  */
                      if (!retained_p[copy_from[i]])
-                       m->rows[window_to].enabled_p = 0;
+                       m->rows[window_to].enabled_p = false;
                    }
                  sync_p = 1;
                }
@@ -2919,10 +2858,8 @@ check_window_matrix_pointers (struct window *w)
 {
   while (w)
     {
-      if (!NILP (w->hchild))
-       check_window_matrix_pointers (XWINDOW (w->hchild));
-      else if (!NILP (w->vchild))
-       check_window_matrix_pointers (XWINDOW (w->vchild));
+      if (WINDOWP (w->contents))
+       check_window_matrix_pointers (XWINDOW (w->contents));
       else
        {
          struct frame *f = XFRAME (w->frame);
@@ -3013,21 +2950,17 @@ redraw_frame (struct frame *f)
   /* Error if F has no glyphs.  */
   eassert (f->glyphs_initialized_p);
   update_begin (f);
-#ifdef MSDOS
   if (FRAME_MSDOS_P (f))
     FRAME_TERMINAL (f)->set_terminal_modes_hook (FRAME_TERMINAL (f));
-#endif
   clear_frame (f);
   clear_current_matrices (f);
   update_end (f);
-  if (FRAME_TERMCAP_P (f))
-    fflush (FRAME_TTY (f)->output);
-  windows_or_buffers_changed++;
+  windows_or_buffers_changed = 13;
   /* Mark all windows as inaccurate, so that every window will have
      its redisplay done.  */
   mark_window_display_accurate (FRAME_ROOT_WINDOW (f), 0);
-  set_window_update_flags (XWINDOW (FRAME_ROOT_WINDOW (f)), 1);
-  f->garbaged = 0;
+  set_window_update_flags (XWINDOW (FRAME_ROOT_WINDOW (f)), true);
+  f->garbaged = false;
 }
 
 DEFUN ("redraw-frame", Fredraw_frame, Sredraw_frame, 0, 1, 0,
@@ -3092,11 +3025,14 @@ update_frame (struct frame *f, bool force_p, bool inhibit_hairy_id_p)
         when pending input is detected.  */
       update_begin (f);
 
+#if defined (HAVE_X_WINDOWS) && ! defined (USE_X_TOOLKIT) && ! defined (USE_GTK)
       /* Update the menu bar on X frames that don't have toolkit
         support.  */
       if (WINDOWP (f->menu_bar_window))
        update_window (XWINDOW (f->menu_bar_window), 1);
+#endif
 
+#if defined (HAVE_WINDOW_SYSTEM) && ! defined (USE_GTK) && ! defined (HAVE_NS)
       /* Update the tool-bar window, if present.  */
       if (WINDOWP (f->tool_bar_window))
        {
@@ -3108,7 +3044,7 @@ update_frame (struct frame *f, bool force_p, bool inhibit_hairy_id_p)
              Lisp_Object tem;
 
              update_window (w, 1);
-             w->must_be_updated_p = 0;
+             w->must_be_updated_p = false;
 
              /* Swap tool-bar strings.  We swap because we want to
                 reuse strings.  */
@@ -3117,21 +3053,11 @@ update_frame (struct frame *f, bool force_p, bool inhibit_hairy_id_p)
              fset_desired_tool_bar_string (f, tem);
            }
        }
-
+#endif
 
       /* Update windows.  */
       paused_p = update_window_tree (root_window, force_p);
       update_end (f);
-
-      /* This flush is a performance bottleneck under X,
-        and it doesn't seem to be necessary anyway (in general).
-         It is necessary when resizing the window with the mouse, or
-        at least the fringes are not redrawn in a timely manner.  ++kfs */
-      if (f->force_flush_display_p)
-       {
-         FRAME_RIF (f)->flush_display (f);
-         f->force_flush_display_p = 0;
-       }
     }
   else
     {
@@ -3144,7 +3070,7 @@ update_frame (struct frame *f, bool force_p, bool inhibit_hairy_id_p)
 
       /* Update the display  */
       update_begin (f);
-      paused_p = update_frame_1 (f, force_p, inhibit_hairy_id_p);
+      paused_p = update_frame_1 (f, force_p, inhibit_hairy_id_p, 1);
       update_end (f);
 
       if (FRAME_TERMCAP_P (f) || FRAME_MSDOS_P (f))
@@ -3164,12 +3090,64 @@ update_frame (struct frame *f, bool force_p, bool inhibit_hairy_id_p)
 
  do_pause:
   /* Reset flags indicating that a window should be updated.  */
-  set_window_update_flags (root_window, 0);
+  set_window_update_flags (root_window, false);
 
   display_completed = !paused_p;
   return paused_p;
 }
 
+/* Update a TTY frame F that has a menu dropped down over some of its
+   glyphs.  This is like the second part of update_frame, but it
+   doesn't call build_frame_matrix, because we already have the
+   desired matrix prepared, and don't want it to be overwritten by the
+   text of the normal display.
+
+   ROW and COL, if non-negative, are the row and column of the TTY
+   frame where to position the cursor after the frame update is
+   complete.  Negative values mean ask update_frame_1 to position the
+   cursor "normally", i.e. at point in the selected window.  */
+void
+update_frame_with_menu (struct frame *f, int row, int col)
+{
+  struct window *root_window = XWINDOW (f->root_window);
+  bool paused_p, cursor_at_point_p;
+
+  eassert (FRAME_TERMCAP_P (f));
+
+  /* We are working on frame matrix basis.  Set the frame on whose
+     frame matrix we operate.  */
+  set_frame_matrix_frame (f);
+
+  /* Update the display.  */
+  update_begin (f);
+  cursor_at_point_p = !(row >= 0 && col >= 0);
+  /* Force update_frame_1 not to stop due to pending input, and not
+     try scrolling.  */
+  paused_p = update_frame_1 (f, 1, 1, cursor_at_point_p);
+  /* ROW and COL tell us where in the menu to position the cursor, so
+     that screen readers know the active region on the screen.  */
+  if (!cursor_at_point_p)
+    cursor_to (f, row, col);
+  update_end (f);
+
+  if (FRAME_TTY (f)->termscript)
+    fflush (FRAME_TTY (f)->termscript);
+  fflush (FRAME_TTY (f)->output);
+  /* Check window matrices for lost pointers.  */
+#if GLYPH_DEBUG
+#if 0
+      /* We cannot possibly survive the matrix pointers check, since
+        we have overwritten parts of the frame glyph matrix without
+        making any updates to the window matrices.  */
+  check_window_matrix_pointers (root_window);
+#endif
+  add_frame_display_history (f, paused_p);
+#endif
+
+  /* Reset flags indicating that a window should be updated.  */
+  set_window_update_flags (root_window, false);
+  display_completed = !paused_p;
+}
 
 \f
 /************************************************************************
@@ -3186,10 +3164,8 @@ update_window_tree (struct window *w, bool force_p)
 
   while (w && !paused_p)
     {
-      if (!NILP (w->hchild))
-       paused_p |= update_window_tree (XWINDOW (w->hchild), force_p);
-      else if (!NILP (w->vchild))
-       paused_p |= update_window_tree (XWINDOW (w->vchild), force_p);
+      if (WINDOWP (w->contents))
+       paused_p |= update_window_tree (XWINDOW (w->contents), force_p);
       else if (w->must_be_updated_p)
        paused_p |= update_window (w, force_p);
 
@@ -3222,7 +3198,7 @@ update_single_window (struct window *w, bool force_p)
       update_end (f);
 
       /* Reset flag in W.  */
-      w->must_be_updated_p = 0;
+      w->must_be_updated_p = false;
     }
 }
 
@@ -3257,14 +3233,12 @@ redraw_overlapped_rows (struct window *w, int yb)
 
          for (area = LEFT_MARGIN_AREA; area < LAST_AREA; ++area)
            {
-             updated_row = row;
-             updated_area = area;
-             FRAME_RIF (f)->cursor_to (i, 0, row->y,
-                                        area == TEXT_AREA ? row->x : 0);
+             output_cursor_to (w, i, 0, row->y,
+                               area == TEXT_AREA ? row->x : 0);
              if (row->used[area])
-               FRAME_RIF (f)->write_glyphs (row->glyphs[area],
-                                             row->used[area]);
-             FRAME_RIF (f)->clear_end_of_line (-1);
+               FRAME_RIF (f)->write_glyphs (w, row, row->glyphs[area],
+                                             area, row->used[area]);
+             FRAME_RIF (f)->clear_end_of_line (w, row, area, -1);
            }
 
          row->overlapped_p = 0;
@@ -3392,8 +3366,8 @@ update_window (struct window *w, bool force_p)
 
       rif->update_window_begin_hook (w);
       yb = window_text_bottom_y (w);
-      row = desired_matrix->rows;
-      end = row + desired_matrix->nrows - 1;
+      row = MATRIX_ROW (desired_matrix, 0);
+      end = MATRIX_MODE_LINE_ROW (desired_matrix);
 
       /* Take note of the header line, if there is one.  We will
         update it below, after updating all of the window's lines.  */
@@ -3468,7 +3442,7 @@ update_window (struct window *w, bool force_p)
               in the first redisplay.  */
            if (MATRIX_ROW_BOTTOM_Y (row) >= yb)
              for (i = vpos + 1; i < w->current_matrix->nrows - 1; ++i)
-               MATRIX_ROW (w->current_matrix, i)->enabled_p = 0;
+               SET_MATRIX_ROW_ENABLED_P (w->current_matrix, i, false);
          }
 
       /* Was display preempted?  */
@@ -3517,7 +3491,7 @@ update_window (struct window *w, bool force_p)
       /* End the update of window W.  Don't set the cursor if we
          paused updating the display because in this case,
          set_window_cursor_after_update hasn't been called, and
-         output_cursor doesn't contain the cursor location.  */
+         W->output_cursor doesn't contain the cursor location.  */
       rif->update_window_end_hook (w, !paused_p, mouse_face_overwritten_p);
     }
   else
@@ -3538,22 +3512,20 @@ update_window (struct window *w, bool force_p)
    AREA can be either LEFT_MARGIN_AREA or RIGHT_MARGIN_AREA.  */
 
 static void
-update_marginal_area (struct window *w, int area, int vpos)
+update_marginal_area (struct window *w, struct glyph_row *updated_row,
+                     enum glyph_row_area area, int vpos)
 {
   struct glyph_row *desired_row = MATRIX_ROW (w->desired_matrix, vpos);
   struct redisplay_interface *rif = FRAME_RIF (XFRAME (WINDOW_FRAME (w)));
 
-  /* Let functions in xterm.c know what area subsequent X positions
-     will be relative to.  */
-  updated_area = area;
-
   /* Set cursor to start of glyphs, write them, and clear to the end
      of the area.  I don't think that something more sophisticated is
      necessary here, since marginal areas will not be the default.  */
-  rif->cursor_to (vpos, 0, desired_row->y, 0);
+  output_cursor_to (w, vpos, 0, desired_row->y, 0);
   if (desired_row->used[area])
-    rif->write_glyphs (desired_row->glyphs[area], desired_row->used[area]);
-  rif->clear_end_of_line (-1);
+    rif->write_glyphs (w, updated_row, desired_row->glyphs[area],
+                      area, desired_row->used[area]);
+  rif->clear_end_of_line (w, updated_row, area, -1);
 }
 
 
@@ -3561,17 +3533,13 @@ update_marginal_area (struct window *w, int area, int vpos)
    Value is true if display has changed.  */
 
 static bool
-update_text_area (struct window *w, int vpos)
+update_text_area (struct window *w, struct glyph_row *updated_row, int vpos)
 {
   struct glyph_row *current_row = MATRIX_ROW (w->current_matrix, vpos);
   struct glyph_row *desired_row = MATRIX_ROW (w->desired_matrix, vpos);
   struct redisplay_interface *rif = FRAME_RIF (XFRAME (WINDOW_FRAME (w)));
   bool changed_p = 0;
 
-  /* Let functions in xterm.c know what area subsequent X positions
-     will be relative to.  */
-  updated_area = TEXT_AREA;
-
   /* If rows are at different X or Y, or rows have different height,
      or the current row is marked invalid, write the entire line.  */
   if (!current_row->enabled_p
@@ -3591,14 +3559,14 @@ update_text_area (struct window *w, int vpos)
          && !(current_row->mode_line_p && vpos > 0))
       || current_row->x != desired_row->x)
     {
-      rif->cursor_to (vpos, 0, desired_row->y, desired_row->x);
+      output_cursor_to (w, vpos, 0, desired_row->y, desired_row->x);
 
       if (desired_row->used[TEXT_AREA])
-       rif->write_glyphs (desired_row->glyphs[TEXT_AREA],
-                          desired_row->used[TEXT_AREA]);
+       rif->write_glyphs (w, updated_row, desired_row->glyphs[TEXT_AREA],
+                          TEXT_AREA, desired_row->used[TEXT_AREA]);
 
       /* Clear to end of window.  */
-      rif->clear_end_of_line (-1);
+      rif->clear_end_of_line (w, updated_row, TEXT_AREA, -1);
       changed_p = 1;
 
       /* This erases the cursor.  We do this here because
@@ -3734,8 +3702,9 @@ update_text_area (struct window *w, int vpos)
                  break;
                }
 
-             rif->cursor_to (vpos, start_hpos, desired_row->y, start_x);
-             rif->write_glyphs (start, i - start_hpos);
+             output_cursor_to (w, vpos, start_hpos, desired_row->y, start_x);
+             rif->write_glyphs (w, updated_row, start,
+                                TEXT_AREA, i - start_hpos);
              changed_p = 1;
            }
        }
@@ -3743,8 +3712,9 @@ update_text_area (struct window *w, int vpos)
       /* Write the rest.  */
       if (i < desired_row->used[TEXT_AREA])
        {
-         rif->cursor_to (vpos, i, desired_row->y, x);
-         rif->write_glyphs (desired_glyph, desired_row->used[TEXT_AREA] - i);
+         output_cursor_to (w, vpos, i, desired_row->y, x);
+         rif->write_glyphs (w, updated_row, desired_glyph,
+                            TEXT_AREA, desired_row->used[TEXT_AREA] - i);
          changed_p = 1;
        }
 
@@ -3764,9 +3734,9 @@ update_text_area (struct window *w, int vpos)
        {
          /* If old row extends to the end of the text area, clear.  */
          if (i >= desired_row->used[TEXT_AREA])
-           rif->cursor_to (vpos, i, desired_row->y,
-                           desired_row->pixel_width);
-         rif->clear_end_of_line (-1);
+           output_cursor_to (w, vpos, i, desired_row->y,
+                             desired_row->pixel_width);
+         rif->clear_end_of_line (w, updated_row, TEXT_AREA, -1);
          changed_p = 1;
        }
       else if (desired_row->pixel_width < current_row->pixel_width)
@@ -3776,8 +3746,8 @@ update_text_area (struct window *w, int vpos)
          int xlim;
 
          if (i >= desired_row->used[TEXT_AREA])
-           rif->cursor_to (vpos, i, desired_row->y,
-                           desired_row->pixel_width);
+           output_cursor_to (w, vpos, i, desired_row->y,
+                             desired_row->pixel_width);
 
          /* If cursor is displayed at the end of the line, make sure
             it's cleared.  Nowadays we don't have a phys_cursor_glyph
@@ -3794,7 +3764,7 @@ update_text_area (struct window *w, int vpos)
            }
          else
            xlim = current_row->pixel_width;
-         rif->clear_end_of_line (xlim);
+         rif->clear_end_of_line (w, updated_row, TEXT_AREA, xlim);
          changed_p = 1;
        }
     }
@@ -3813,10 +3783,6 @@ update_window_line (struct window *w, int vpos, bool *mouse_face_overwritten_p)
   struct redisplay_interface *rif = FRAME_RIF (XFRAME (WINDOW_FRAME (w)));
   bool changed_p = 0;
 
-  /* Set the row being updated.  This is important to let xterm.c
-     know what line height values are in effect.  */
-  updated_row = desired_row;
-
   /* A row can be completely invisible in case a desired matrix was
      built with a vscroll and then make_cursor_line_fully_visible shifts
      the matrix.  Make sure to make such rows current anyway, since
@@ -3827,11 +3793,10 @@ update_window_line (struct window *w, int vpos, bool *mouse_face_overwritten_p)
       eassert (desired_row->enabled_p);
 
       /* Update display of the left margin area, if there is one.  */
-      if (!desired_row->full_width_p
-         && !NILP (w->left_margin_cols))
+      if (!desired_row->full_width_p && w->left_margin_cols > 0)
        {
          changed_p = 1;
-         update_marginal_area (w, LEFT_MARGIN_AREA, vpos);
+         update_marginal_area (w, desired_row, LEFT_MARGIN_AREA, vpos);
          /* Setting this flag will ensure the vertical border, if
             any, between this window and the one on its left will be
             redrawn.  This is necessary because updating the left
@@ -3840,7 +3805,7 @@ update_window_line (struct window *w, int vpos, bool *mouse_face_overwritten_p)
        }
 
       /* Update the display of the text area.  */
-      if (update_text_area (w, vpos))
+      if (update_text_area (w, desired_row, vpos))
        {
          changed_p = 1;
          if (current_row->mouse_face_p)
@@ -3848,11 +3813,10 @@ update_window_line (struct window *w, int vpos, bool *mouse_face_overwritten_p)
        }
 
       /* Update display of the right margin area, if there is one.  */
-      if (!desired_row->full_width_p
-         && !NILP (w->right_margin_cols))
+      if (!desired_row->full_width_p && w->right_margin_cols > 0)
        {
          changed_p = 1;
-         update_marginal_area (w, RIGHT_MARGIN_AREA, vpos);
+         update_marginal_area (w, desired_row, RIGHT_MARGIN_AREA, vpos);
        }
 
       /* Draw truncation marks etc.  */
@@ -3866,12 +3830,11 @@ update_window_line (struct window *w, int vpos, bool *mouse_face_overwritten_p)
          || desired_row->exact_window_width_line_p != current_row->exact_window_width_line_p
          || (MATRIX_ROW_CONTINUATION_LINE_P (desired_row)
              != MATRIX_ROW_CONTINUATION_LINE_P (current_row)))
-       rif->after_update_window_line_hook (desired_row);
+       rif->after_update_window_line_hook (w, desired_row);
     }
 
   /* Update current_row from desired_row.  */
   make_current (w->desired_matrix, w->current_matrix, vpos);
-  updated_row = NULL;
   return changed_p;
 }
 
@@ -3883,7 +3846,6 @@ static void
 set_window_cursor_after_update (struct window *w)
 {
   struct frame *f = XFRAME (w->frame);
-  struct redisplay_interface *rif = FRAME_RIF (f);
   int cx, cy, vpos, hpos;
 
   /* Not intended for frame matrix updates.  */
@@ -3955,22 +3917,20 @@ set_window_cursor_after_update (struct window *w)
      Horizontal position is -1 when cursor is on the left fringe.   */
   hpos = clip_to_bounds (-1, hpos, w->current_matrix->matrix_w - 1);
   vpos = clip_to_bounds (0, vpos, w->current_matrix->nrows - 1);
-  rif->cursor_to (vpos, hpos, cy, cx);
+  output_cursor_to (w, vpos, hpos, cy, cx);
 }
 
 
-/* Set WINDOW->must_be_updated_p to ON_P for all windows in the window
-   tree rooted at W.  */
+/* Set WINDOW->must_be_updated_p to ON_P for all windows in
+   the window tree rooted at W.  */
 
-void
+static void
 set_window_update_flags (struct window *w, bool on_p)
 {
   while (w)
     {
-      if (!NILP (w->hchild))
-       set_window_update_flags (XWINDOW (w->hchild), on_p);
-      else if (!NILP (w->vchild))
-       set_window_update_flags (XWINDOW (w->vchild), on_p);
+      if (WINDOWP (w->contents))
+       set_window_update_flags (XWINDOW (w->contents), on_p);
       else
        w->must_be_updated_p = on_p;
 
@@ -4119,14 +4079,14 @@ scrolling_window (struct window *w, bool header_line_p)
          && row_equal_p (c, d, 1))
        {
          assign_row (c, d);
-         d->enabled_p = 0;
+         d->enabled_p = false;
        }
       else
        break;
     }
 
   /* Give up if some rows in the desired matrix are not enabled.  */
-  if (!MATRIX_ROW (desired_matrix, i)->enabled_p)
+  if (! MATRIX_ROW_ENABLED_P (desired_matrix, i))
     return -1;
 
   first_old = first_new = i;
@@ -4139,7 +4099,7 @@ scrolling_window (struct window *w, bool header_line_p)
     {
       int bottom;
 
-      if (!MATRIX_ROW (desired_matrix, i)->enabled_p)
+      if (! MATRIX_ROW_ENABLED_P (desired_matrix, i))
        return 0;
       bottom = MATRIX_ROW_BOTTOM_Y (MATRIX_ROW (desired_matrix, i));
       if (bottom <= yb)
@@ -4171,7 +4131,7 @@ scrolling_window (struct window *w, bool header_line_p)
   j = last_old;
   while (i - 1 > first_new
          && j - 1 > first_old
-         && MATRIX_ROW (current_matrix, j - 1)->enabled_p
+         && MATRIX_ROW_ENABLED_P (current_matrix, j - 1)
         && (MATRIX_ROW (current_matrix, j - 1)->y
             == MATRIX_ROW (desired_matrix, i - 1)->y)
         && !MATRIX_ROW (desired_matrix, i - 1)->redraw_fringe_bitmaps_p
@@ -4248,7 +4208,7 @@ scrolling_window (struct window *w, bool header_line_p)
 
   for (i = first_old; i < last_old; ++i)
     {
-      if (MATRIX_ROW (current_matrix, i)->enabled_p)
+      if (MATRIX_ROW_ENABLED_P (current_matrix, i))
        {
          entry = add_row_entry (MATRIX_ROW (current_matrix, i));
          old_lines[i] = entry;
@@ -4441,7 +4401,7 @@ scrolling_window (struct window *w, bool header_line_p)
               preceding for-loop, we no longer have such an overlap,
               and thus the assigned row should always be enabled.  */
            eassert (to->enabled_p);
-           from->enabled_p = 0;
+           from->enabled_p = false;
            to->overlapped_p = to_overlapped_p;
          }
       }
@@ -4451,7 +4411,7 @@ scrolling_window (struct window *w, bool header_line_p)
     row_table[row_entry_pool[i].bucket] = NULL;
 
   /* Value is 1 to indicate that we scrolled the display.  */
-  return 0 < nruns;
+  return nruns > 0;
 }
 
 
@@ -4463,12 +4423,14 @@ scrolling_window (struct window *w, bool header_line_p)
 /* Update the desired frame matrix of frame F.
 
    FORCE_P means that the update should not be stopped by pending input.
-   INHIBIT_HAIRY_ID_P means that scrolling should not be tried.
+   INHIBIT_ID_P means that scrolling by insert/delete should not be tried.
+   SET_CURSOR_P false means do not set cursor at point in selected window.
 
    Value is true if update was stopped due to pending input.  */
 
 static bool
-update_frame_1 (struct frame *f, bool force_p, bool inhibit_id_p)
+update_frame_1 (struct frame *f, bool force_p, bool inhibit_id_p,
+               bool set_cursor_p)
 {
   /* Frame matrices to work on.  */
   struct glyph_matrix *current_matrix = f->current_matrix;
@@ -4537,11 +4499,10 @@ update_frame_1 (struct frame *f, bool force_p, bool inhibit_id_p)
        }
     }
 
-  lint_assume (0 <= FRAME_LINES (f));
   pause_p = 0 < i && i < FRAME_LINES (f) - 1;
 
   /* Now just clean up termcap drivers and set cursor, etc.  */
-  if (!pause_p)
+  if (!pause_p && set_cursor_p)
     {
       if ((cursor_in_echo_area
           /* If we are showing a message instead of the mini-buffer,
@@ -4628,10 +4589,7 @@ update_frame_1 (struct frame *f, bool force_p, bool inhibit_id_p)
              int x = WINDOW_TO_FRAME_HPOS (w, w->cursor.hpos);
              int y = WINDOW_TO_FRAME_VPOS (w, w->cursor.vpos);
 
-             if (INTEGERP (w->left_margin_cols))
-               x += XFASTINT (w->left_margin_cols);
-
-             /* x = max (min (x, FRAME_TOTAL_COLS (f) - 1), 0); */
+             x += max (0, w->left_margin_cols);
              cursor_to (f, y, x);
            }
        }
@@ -4661,8 +4619,7 @@ scrolling (struct frame *frame)
   struct glyph_matrix *current_matrix = frame->current_matrix;
   struct glyph_matrix *desired_matrix = frame->desired_matrix;
 
-  if (!current_matrix)
-    emacs_abort ();
+  eassert (current_matrix);
 
   /* Compute hash codes of all the lines.  Also calculate number of
      changed lines, number of unchanged lines at the beginning, and
@@ -4675,7 +4632,7 @@ scrolling (struct frame *frame)
       /* Give up on this scrolling if some old lines are not enabled.  */
       if (!MATRIX_ROW_ENABLED_P (current_matrix, i))
        return 0;
-      old_hash[i] = line_hash_code (MATRIX_ROW (current_matrix, i));
+      old_hash[i] = line_hash_code (frame, MATRIX_ROW (current_matrix, i));
       if (! MATRIX_ROW_ENABLED_P (desired_matrix, i))
        {
          /* This line cannot be redrawn, so don't let scrolling mess it.  */
@@ -4685,8 +4642,8 @@ scrolling (struct frame *frame)
        }
       else
        {
-         new_hash[i] = line_hash_code (MATRIX_ROW (desired_matrix, i));
-         draw_cost[i] = line_draw_cost (desired_matrix, i);
+         new_hash[i] = line_hash_code (frame, MATRIX_ROW (desired_matrix, i));
+         draw_cost[i] = line_draw_cost (frame, desired_matrix, i);
        }
 
       if (old_hash[i] != new_hash[i])
@@ -4696,7 +4653,7 @@ scrolling (struct frame *frame)
        }
       else if (i == unchanged_at_top)
        unchanged_at_top++;
-      old_draw_cost[i] = line_draw_cost (current_matrix, i);
+      old_draw_cost[i] = line_draw_cost (frame, current_matrix, i);
     }
 
   /* If changed lines are few, don't allow preemption, don't scroll.  */
@@ -4816,7 +4773,7 @@ update_frame_line (struct frame *f, int vpos)
          olen--;
     }
 
-  current_row->enabled_p = 1;
+  current_row->enabled_p = true;
   current_row->used[TEXT_AREA] = desired_row->used[TEXT_AREA];
 
   /* If desired line is empty, just clear the line.  */
@@ -5117,11 +5074,9 @@ buffer_posn_from_coords (struct window *w, int *x, int *y, struct display_pos *p
 
   /* We used to set current_buffer directly here, but that does the
      wrong thing with `face-remapping-alist' (bug#2044).  */
-  Fset_buffer (w->buffer);
+  Fset_buffer (w->contents);
   itdata = bidi_shelve_cache ();
-  SET_TEXT_POS_FROM_MARKER (startp, w->start);
-  CHARPOS (startp) = min (ZV, max (BEGV, CHARPOS (startp)));
-  BYTEPOS (startp) = min (ZV_BYTE, max (BEGV_BYTE, BYTEPOS (startp)));
+  CLIP_TEXT_POS_FROM_MARKER (startp, w->start);
   start_display (&it, w, startp);
   /* start_display takes into account the header-line row, but IT's
      vpos still counts from the glyph row that includes the window's
@@ -5163,7 +5118,7 @@ buffer_posn_from_coords (struct window *w, int *x, int *y, struct display_pos *p
   *dx = x0 + it.first_visible_x - it.current_x;
   *dy = *y - it.current_y;
 
-  string =  w->buffer;
+  string = w->contents;
   if (STRINGP (it.string))
     string = it.string;
   *pos = it.current;
@@ -5181,7 +5136,7 @@ buffer_posn_from_coords (struct window *w, int *x, int *y, struct display_pos *p
       if (STRINGP (it.string))
        BYTEPOS (pos->pos) = string_char_to_byte (string, CHARPOS (pos->pos));
       else
-       BYTEPOS (pos->pos) = buf_charpos_to_bytepos (XBUFFER (w->buffer),
+       BYTEPOS (pos->pos) = buf_charpos_to_bytepos (XBUFFER (w->contents),
                                                     CHARPOS (pos->pos));
     }
 
@@ -5345,7 +5300,7 @@ marginal_area_string (struct window *w, enum window_part part,
       if (area == RIGHT_MARGIN_AREA)
        x0 = ((WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
               ? WINDOW_LEFT_FRINGE_WIDTH (w)
-              : WINDOW_TOTAL_FRINGE_WIDTH (w))
+              : WINDOW_FRINGES_WIDTH (w))
              + window_box_width (w, LEFT_MARGIN_AREA)
              + window_box_width (w, TEXT_AREA));
       else
@@ -5437,7 +5392,7 @@ handle_window_change_signal (int sig)
           /* Record the new sizes, but don't reallocate the data
              structures now.  Let that be done later outside of the
              signal handler.  */
-          change_frame_size (XFRAME (frame), height, width, 0, 1, 0);
+          change_frame_size (XFRAME (frame), width, height, 0, 1, 0, 0);
     }
   }
 }
@@ -5471,17 +5426,21 @@ do_pending_window_change (bool safe)
        {
          struct frame *f = XFRAME (frame);
 
-         if (f->new_text_lines != 0 || f->new_text_cols != 0)
-           change_frame_size (f, f->new_text_lines, f->new_text_cols,
-                              0, 0, safe);
+         if (f->new_height != 0 || f->new_width != 0)
+           change_frame_size (f, f->new_width, f->new_height,
+                              0, 0, safe, f->new_pixelwise);
        }
     }
 }
 
-
 /* Change the frame height and/or width.  Values may be given as zero to
    indicate no change is to take place.
 
+   new_height and new_width refer to the text portion of the frame.  It
+   doesn't matter for new_height, since text and total portion are the
+   same in that case.  But new_width must be enlarged to get the total
+   width of the frame.
+
    If DELAY, assume we're being called from a signal handler, and
    queue the change for later - perhaps the next redisplay.
    Since this tries to resize windows, we can't call it
@@ -5491,8 +5450,8 @@ do_pending_window_change (bool safe)
    safe to change frame sizes while a redisplay is in progress.  */
 
 void
-change_frame_size (struct frame *f, int newheight, int newwidth,
-                  bool pretend, bool delay, bool safe)
+change_frame_size (struct frame *f, int new_width, int new_height,
+                  bool pretend, bool delay, bool safe, bool pixelwise)
 {
   Lisp_Object tail, frame;
 
@@ -5503,56 +5462,81 @@ change_frame_size (struct frame *f, int newheight, int newwidth,
          ttys. */
       FOR_EACH_FRAME (tail, frame)
        if (! FRAME_WINDOW_P (XFRAME (frame)))
-         change_frame_size_1 (XFRAME (frame), newheight, newwidth,
-                              pretend, delay, safe);
+         change_frame_size_1 (XFRAME (frame), new_width, new_height,
+                              pretend, delay, safe, pixelwise);
     }
   else
-    change_frame_size_1 (f, newheight, newwidth, pretend, delay, safe);
+    change_frame_size_1 (f, new_width, new_height, pretend, delay, safe,
+                        pixelwise);
 }
 
 static void
-change_frame_size_1 (struct frame *f, int newheight, int newwidth,
-                    bool pretend, bool delay, bool safe)
+change_frame_size_1 (struct frame *f, int new_width, int new_height,
+                    bool pretend, bool delay, bool safe, bool pixelwise)
 {
-  int new_frame_total_cols;
-  ptrdiff_t count = SPECPDL_INDEX ();
+  int new_text_width, new_text_height, new_root_width;
+  int old_root_width = WINDOW_PIXEL_WIDTH (XWINDOW (FRAME_ROOT_WINDOW (f)));
+  int new_cols, new_lines;
+  dynwind_begin ();
 
   /* If we can't deal with the change now, queue it for later.  */
   if (delay || (redisplaying_p && !safe))
     {
-      f->new_text_lines = newheight;
-      f->new_text_cols = newwidth;
+      f->new_width = new_width;
+      f->new_height = new_height;
+      f->new_pixelwise = pixelwise;
       delayed_size_change = 1;
+      dynwind_end ();
       return;
     }
 
   /* This size-change overrides any pending one for this frame.  */
-  f->new_text_lines = 0;
-  f->new_text_cols = 0;
+  f->new_height = 0;
+  f->new_width = 0;
+  f->new_pixelwise = 0;
 
   /* If an argument is zero, set it to the current value.  */
-  if (newheight == 0)
-    newheight = FRAME_LINES (f);
-  if (newwidth == 0)
-    newwidth  = FRAME_COLS  (f);
+  if (pixelwise)
+    {
+      new_text_width = (new_width == 0) ? FRAME_TEXT_WIDTH (f) : new_width;
+      new_text_height = (new_height == 0) ? FRAME_TEXT_HEIGHT (f) : new_height;
+      /* Consider rounding here: Currently, the root window can be
+        larger than the frame in terms of columns/lines.  */
+      new_cols = new_text_width / FRAME_COLUMN_WIDTH (f);
+      new_lines = new_text_height / FRAME_LINE_HEIGHT (f);
+    }
+  else
+    {
+      new_cols = (new_width == 0) ? FRAME_COLS (f) : new_width;
+      new_lines = (new_height == 0) ? FRAME_LINES (f) : new_height;
+      new_text_width = new_cols * FRAME_COLUMN_WIDTH (f);
+      new_text_height = new_lines * FRAME_LINE_HEIGHT (f);
+    }
 
   /* Compute width of windows in F.  */
   /* Round up to the smallest acceptable size.  */
-  check_frame_size (f, &newheight, &newwidth);
-
-  /* This is the width of the frame with vertical scroll bars and fringe
-     columns.  Do this after rounding - see discussion of bug#9723.  */
-  new_frame_total_cols = FRAME_TOTAL_COLS_ARG (f, newwidth);
-
+  check_frame_size (f, &new_text_width, &new_text_height, 1);
+
+  /* This is the width of the frame without vertical scroll bars and
+     fringe columns.  Do this after rounding - see discussion of
+     bug#9723.  */
+  new_root_width = (new_text_width
+                   + FRAME_SCROLL_BAR_AREA_WIDTH (f)
+                   + FRAME_TOTAL_FRINGE_WIDTH (f));
   /* If we're not changing the frame size, quit now.  */
   /* Frame width may be unchanged but the text portion may change, for
      example, fullscreen and remove/add scroll bar.  */
-  if (newheight == FRAME_LINES (f)
-      /* Text portion unchanged?  */
-      && newwidth == FRAME_COLS  (f)
-      /* Frame width unchanged?  */
-      && new_frame_total_cols == FRAME_TOTAL_COLS (f))
-    return;
+  if (new_text_height == FRAME_TEXT_HEIGHT (f)
+      && new_text_width == FRAME_TEXT_WIDTH (f)
+      && new_root_width == old_root_width
+      && (FRAME_PIXEL_HEIGHT (f) ==
+         FRAME_TEXT_TO_PIXEL_HEIGHT (f, new_text_height))
+      && (FRAME_PIXEL_WIDTH (f) ==
+         FRAME_TEXT_TO_PIXEL_WIDTH (f, new_text_width)))
+    {
+      dynwind_end ();
+      return;
+    }
 
   block_input ();
 
@@ -5560,34 +5544,44 @@ change_frame_size_1 (struct frame *f, int newheight, int newwidth,
   /* 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);
+  dos_set_window_size (&new_lines, &new_cols);
 #endif
 
-  if (newheight != FRAME_LINES (f))
+  if (new_text_height != FRAME_TEXT_HEIGHT (f))
     {
-      resize_frame_windows (f, newheight, 0);
+      resize_frame_windows (f, new_text_height, 0, 1);
 
       /* MSDOS frames cannot PRETEND, as they change frame size by
         manipulating video hardware.  */
       if ((FRAME_TERMCAP_P (f) && !pretend) || FRAME_MSDOS_P (f))
-       FrameRows (FRAME_TTY (f)) = newheight;
+       FrameRows (FRAME_TTY (f)) = new_lines;
     }
 
-  if (new_frame_total_cols != FRAME_TOTAL_COLS (f))
+  if (new_text_width != FRAME_TEXT_WIDTH (f)
+      || new_root_width != old_root_width)
     {
-      resize_frame_windows (f, new_frame_total_cols, 1);
+      resize_frame_windows (f, new_root_width, 1, 1);
 
       /* MSDOS frames cannot PRETEND, as they change frame size by
         manipulating video hardware.  */
       if ((FRAME_TERMCAP_P (f) && !pretend) || FRAME_MSDOS_P (f))
-       FrameCols (FRAME_TTY (f)) = newwidth;
+       FrameCols (FRAME_TTY (f)) = new_cols;
 
+#if defined (HAVE_WINDOW_SYSTEM) && ! defined (USE_GTK) && ! defined (HAVE_NS)
       if (WINDOWP (f->tool_bar_window))
-       wset_total_cols (XWINDOW (f->tool_bar_window), make_number (newwidth));
+       {
+         XWINDOW (f->tool_bar_window)->total_cols = new_cols;
+         XWINDOW (f->tool_bar_window)->pixel_width = new_root_width;
+       }
+#endif
     }
 
-  FRAME_LINES (f) = newheight;
-  SET_FRAME_COLS (f, newwidth);
+  SET_FRAME_COLS (f, new_cols);
+  FRAME_LINES (f) = new_lines;
+  FRAME_TEXT_WIDTH (f) = new_text_width;
+  FRAME_TEXT_HEIGHT (f) = new_text_height;
+  FRAME_PIXEL_WIDTH (f) = FRAME_TEXT_TO_PIXEL_WIDTH (f, new_text_width);
+  FRAME_PIXEL_HEIGHT (f) = FRAME_TEXT_TO_PIXEL_HEIGHT (f, new_text_height);
 
   {
     struct window *w = XWINDOW (FRAME_SELECTED_WINDOW (f));
@@ -5601,7 +5595,7 @@ change_frame_size_1 (struct frame *f, int newheight, int newwidth,
       w->cursor.vpos = w->cursor.y = 0;
   }
 
-  adjust_glyphs (f);
+  adjust_frame_glyphs (f);
   calculate_costs (f);
   SET_FRAME_GARBAGED (f);
   f->resized_p = 1;
@@ -5612,10 +5606,8 @@ change_frame_size_1 (struct frame *f, int newheight, int newwidth,
 
   run_window_configuration_change_hook (f);
 
-  unbind_to (count, Qnil);
+  dynwind_end ();
 }
-
-
 \f
 /***********************************************************************
                   Terminal Related Lisp Functions
@@ -5636,19 +5628,19 @@ FILE = nil means just close any termscript file currently open.  */)
   tty = CURTTY ();
 
   if (tty->termscript != 0)
-  {
-    block_input ();
-    fclose (tty->termscript);
-    unblock_input ();
-  }
-  tty->termscript = 0;
+    {
+      block_input ();
+      fclose (tty->termscript);
+      tty->termscript = 0;
+      unblock_input ();
+    }
 
   if (! NILP (file))
     {
       file = Fexpand_file_name (file, Qnil);
-      tty->termscript = fopen (SSDATA (file), "w");
+      tty->termscript = emacs_fopen (SSDATA (file), "w");
       if (tty->termscript == 0)
-       report_file_error ("Opening termscript", Fcons (file, Qnil));
+       report_file_error ("Opening termscript", file);
     }
   return Qnil;
 }
@@ -5725,7 +5717,11 @@ bitch_at_user (void)
   if (noninteractive)
     putchar (07);
   else if (!INTERACTIVE)  /* Stop executing a keyboard macro.  */
-    error ("Keyboard macro terminated by a command ringing the bell");
+    {
+      const char *msg
+       = "Keyboard macro terminated by a command ringing the bell";
+      Fsignal (Quser_error, list1 (build_string (msg)));
+    }
   else
     ring_bell (XFRAME (selected_frame));
 }
@@ -5752,11 +5748,11 @@ additional wait period, in milliseconds; this is for backwards compatibility.
       duration += XINT (milliseconds) / 1000.0;
     }
 
-  if (0 < duration)
+  if (duration > 0)
     {
-      EMACS_TIME t = EMACS_TIME_FROM_DOUBLE (duration);
-      wait_reading_process_output (min (EMACS_SECS (t), WAIT_READING_MAX),
-                                  EMACS_NSECS (t), 0, 0, Qnil, NULL, 0);
+      struct timespec t = dtotimespec (duration);
+      wait_reading_process_output (min (t.tv_sec, WAIT_READING_MAX),
+                                  t.tv_nsec, 0, 0, Qnil, NULL, 0);
     }
 
   return Qnil;
@@ -5792,7 +5788,7 @@ sit_for (Lisp_Object timeout, bool reading, int display_option)
   if (INTEGERP (timeout))
     {
       sec = XINT (timeout);
-      if (! (0 < sec))
+      if (sec <= 0)
        return Qt;
       nsec = 0;
     }
@@ -5803,9 +5799,9 @@ sit_for (Lisp_Object timeout, bool reading, int display_option)
        return Qt;
       else
        {
-         EMACS_TIME t = EMACS_TIME_FROM_DOUBLE (seconds);
-         sec = min (EMACS_SECS (t), WAIT_READING_MAX);
-         nsec = EMACS_NSECS (t);
+         struct timespec t = dtotimespec (seconds);
+         sec = min (t.tv_sec, WAIT_READING_MAX);
+         nsec = t.tv_nsec;
        }
     }
   else if (EQ (timeout, Qt))
@@ -5847,11 +5843,11 @@ immediately by pending input.  */)
       || !NILP (Vexecuting_kbd_macro))
     return Qnil;
 
-  count = SPECPDL_INDEX ();
+  dynwind_begin ();
   if (!NILP (force) && !redisplay_dont_pause)
     specbind (Qredisplay_dont_pause, Qt);
   redisplay_preserve_echo_area (2);
-  unbind_to (count, Qnil);
+  dynwind_end ();
   return Qt;
 }
 
@@ -5909,9 +5905,8 @@ pass nil for VARIABLE.  */)
        goto changed;
     }
   /* Check that the buffer info matches.  */
-  for (tail = Vbuffer_alist; CONSP (tail); tail = XCDR (tail))
+  FOR_EACH_LIVE_BUFFER (tail, buf)
     {
-      buf = XCDR (XCAR (tail));
       /* Ignore buffers that aren't included in buffer lists.  */
       if (SREF (BVAR (XBUFFER (buf), name), 0) == ' ')
        continue;
@@ -5941,7 +5936,7 @@ pass nil for VARIABLE.  */)
   n = 1;
   FOR_EACH_FRAME (tail, frame)
     n += 2;
-  for (tail = Vbuffer_alist; CONSP (tail); tail = XCDR (tail))
+  FOR_EACH_LIVE_BUFFER (tail, buf)
     n += 3;
   /* Reallocate the vector if data has grown to need it,
      or if it has shrunk a lot.  */
@@ -5966,9 +5961,8 @@ pass nil for VARIABLE.  */)
       ASET (state, idx, XFRAME (frame)->name);
       idx++;
     }
-  for (tail = Vbuffer_alist; CONSP (tail); tail = XCDR (tail))
+  FOR_EACH_LIVE_BUFFER (tail, buf)
     {
-      buf = XCDR (XCAR (tail));
       /* Ignore buffers that aren't included in buffer lists.  */
       if (SREF (BVAR (XBUFFER (buf), name), 0) == ' ')
        continue;
@@ -6066,7 +6060,7 @@ init_display (void)
 #ifdef HAVE_X11
       Vwindow_system_version = make_number (11);
 #endif
-#ifdef GNU_LINUX
+#ifdef USE_NCURSES
       /* In some versions of ncurses,
         tputs crashes if we have not called tgetent.
         So call tgetent.  */
@@ -6100,10 +6094,7 @@ init_display (void)
 
   /* If no window system has been specified, try to use the terminal.  */
   if (! isatty (0))
-    {
-      fatal ("standard input is not a tty");
-      exit (1);
-    }
+    fatal ("standard input is not a tty");
 
 #ifdef WINDOWSNT
   terminal_type = "w32console";
@@ -6145,8 +6136,8 @@ init_display (void)
 #endif
     t->display_info.tty->top_frame = selected_frame;
     change_frame_size (XFRAME (selected_frame),
-                       FrameRows (t->display_info.tty),
-                       FrameCols (t->display_info.tty), 0, 0, 1);
+                       FrameCols (t->display_info.tty),
+                       FrameRows (t->display_info.tty), 0, 0, 1, 0);
 
     /* Delete the initial terminal. */
     if (--initial_terminal->reference_count == 0
@@ -6155,15 +6146,14 @@ init_display (void)
 
     /* Update frame parameters to reflect the new type. */
     Fmodify_frame_parameters
-      (selected_frame, Fcons (Fcons (Qtty_type,
-                                     Ftty_type (selected_frame)), Qnil));
+      (selected_frame, list1 (Fcons (Qtty_type,
+                                     Ftty_type (selected_frame))));
     if (t->display_info.tty->name)
-      Fmodify_frame_parameters (selected_frame,
-                               Fcons (Fcons (Qtty, build_string (t->display_info.tty->name)),
-                                      Qnil));
+      Fmodify_frame_parameters
+       (selected_frame,
+        list1 (Fcons (Qtty, build_string (t->display_info.tty->name))));
     else
-      Fmodify_frame_parameters (selected_frame, Fcons (Fcons (Qtty, Qnil),
-                                                      Qnil));
+      Fmodify_frame_parameters (selected_frame, list1 (Fcons (Qtty, Qnil)));
   }
 
   {
@@ -6229,19 +6219,6 @@ WINDOW nil or omitted means report on the selected window.  */)
 {
   return decode_any_window (window)->cursor_off_p ? Qnil : Qt;
 }
-
-DEFUN ("last-nonminibuffer-frame", Flast_nonminibuf_frame,
-       Slast_nonminibuf_frame, 0, 0, 0,
-       doc: /* Value is last nonminibuffer frame. */)
-  (void)
-{
-  Lisp_Object frame = Qnil;
-
-  if (last_nonminibuf_frame)
-    XSETFRAME (frame, last_nonminibuf_frame);
-
-  return frame;
-}
 \f
 /***********************************************************************
                            Initialization
@@ -6250,21 +6227,7 @@ DEFUN ("last-nonminibuffer-frame", Flast_nonminibuf_frame,
 void
 syms_of_display (void)
 {
-  defsubr (&Sredraw_frame);
-  defsubr (&Sredraw_display);
-  defsubr (&Sframe_or_buffer_changed_p);
-  defsubr (&Sopen_termscript);
-  defsubr (&Sding);
-  defsubr (&Sredisplay);
-  defsubr (&Ssleep_for);
-  defsubr (&Ssend_string_to_terminal);
-  defsubr (&Sinternal_show_cursor);
-  defsubr (&Sinternal_show_cursor_p);
-  defsubr (&Slast_nonminibuf_frame);
-
-#ifdef GLYPH_DEBUG
-  defsubr (&Sdump_redisplay_history);
-#endif
+#include "dispnew.x"
 
   frame_and_buffer_state = Fmake_vector (make_number (20), Qlambda);
   staticpro (&frame_and_buffer_state);