use dynwind_begin and dynwind_end
[bpt/emacs.git] / src / dispnew.c
index 519659a..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,8 +20,6 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 
 #include <config.h>
 
-#define DISPEXTERN_INLINE EXTERN_INLINE
-
 #include "sysstdio.h"
 #include <unistd.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,28 +105,10 @@ 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;
 
-/* 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;
@@ -159,16 +128,6 @@ static int glyph_pool_count;
 
 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.  */
 
@@ -359,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 = w->total_cols;
-      double d = max (0, XFLOATINT (margin));
+      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.
@@ -426,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;
@@ -446,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)
@@ -590,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.  */
@@ -604,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)
@@ -624,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;
        }
     }
 
@@ -639,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;
@@ -732,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;
 }
 
 
@@ -808,9 +760,11 @@ clear_current_matrices (register struct frame *f)
     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)));
@@ -831,8 +785,10 @@ clear_desired_matrices (register struct frame *f)
     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)));
@@ -873,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);
 }
 
 
@@ -933,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;
 }
 
 
@@ -1046,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);
 }
 
 
@@ -1143,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;
 
@@ -1165,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;
@@ -1180,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];
@@ -1195,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)))
@@ -1740,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
@@ -1764,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
@@ -1813,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
@@ -1853,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
@@ -1867,7 +1770,7 @@ showing_window_margins_p (struct window *w)
          if (showing_window_margins_p (XWINDOW (w->contents)))
            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);
@@ -1940,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;
@@ -1962,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);
@@ -2035,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));
 
@@ -2084,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;
@@ -2105,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.  */
-    w->top_line = 0;
+    w->pixel_left = 0;
     w->left_col = 0;
-    w->total_lines = FRAME_MENU_BAR_LINES (f);
+    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.  */
@@ -2131,10 +2081,15 @@ adjust_frame_glyphs_for_window_redisplay (struct frame *f)
     else
       w = XWINDOW (f->tool_bar_window);
 
-    w->top_line = FRAME_MENU_BAR_LINES (f);
+    w->pixel_left = 0;
     w->left_col = 0;
-    w->total_lines = FRAME_TOOL_BAR_LINES (f);
+    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
@@ -2188,6 +2143,7 @@ free_glyphs (struct frame *f)
        }
 #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))
        {
@@ -2197,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.  */
@@ -2460,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.  */
@@ -2559,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];
@@ -2608,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
@@ -2650,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
@@ -2705,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.  */
@@ -2840,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)
                {
@@ -2865,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;
                }
@@ -2993,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,
@@ -3079,6 +3032,7 @@ update_frame (struct frame *f, bool force_p, bool inhibit_hairy_id_p)
        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))
        {
@@ -3090,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.  */
@@ -3099,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
     {
@@ -3126,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))
@@ -3146,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
 /************************************************************************
@@ -3202,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;
     }
 }
 
@@ -3237,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 (w, 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 (w, row->glyphs[area],
-                                             row->used[area]);
-             FRAME_RIF (f)->clear_end_of_line (w, -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;
@@ -3448,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?  */
@@ -3497,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
@@ -3518,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 (w, vpos, 0, desired_row->y, 0);
+  output_cursor_to (w, vpos, 0, desired_row->y, 0);
   if (desired_row->used[area])
-    rif->write_glyphs (w, desired_row->glyphs[area], desired_row->used[area]);
-  rif->clear_end_of_line (w, -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);
 }
 
 
@@ -3541,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
@@ -3571,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 (w, 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 (w, 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 (w, -1);
+      rif->clear_end_of_line (w, updated_row, TEXT_AREA, -1);
       changed_p = 1;
 
       /* This erases the cursor.  We do this here because
@@ -3714,8 +3702,9 @@ update_text_area (struct window *w, int vpos)
                  break;
                }
 
-             rif->cursor_to (w, vpos, start_hpos, desired_row->y, start_x);
-             rif->write_glyphs (w, 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;
            }
        }
@@ -3723,8 +3712,9 @@ update_text_area (struct window *w, int vpos)
       /* Write the rest.  */
       if (i < desired_row->used[TEXT_AREA])
        {
-         rif->cursor_to (w, vpos, i, desired_row->y, x);
-         rif->write_glyphs (w, 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;
        }
 
@@ -3744,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 (w, vpos, i, desired_row->y,
-                           desired_row->pixel_width);
-         rif->clear_end_of_line (w, -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)
@@ -3756,8 +3746,8 @@ update_text_area (struct window *w, int vpos)
          int xlim;
 
          if (i >= desired_row->used[TEXT_AREA])
-           rif->cursor_to (w, 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
@@ -3774,7 +3764,7 @@ update_text_area (struct window *w, int vpos)
            }
          else
            xlim = current_row->pixel_width;
-         rif->clear_end_of_line (w, xlim);
+         rif->clear_end_of_line (w, updated_row, TEXT_AREA, xlim);
          changed_p = 1;
        }
     }
@@ -3793,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
@@ -3807,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
@@ -3820,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)
@@ -3828,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.  */
@@ -3851,7 +3835,6 @@ update_window_line (struct window *w, int vpos, bool *mouse_face_overwritten_p)
 
   /* Update current_row from desired_row.  */
   make_current (w->desired_matrix, w->current_matrix, vpos);
-  updated_row = NULL;
   return changed_p;
 }
 
@@ -3863,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.  */
@@ -3935,14 +3917,14 @@ 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 (w, 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)
@@ -4097,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;
@@ -4117,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)
@@ -4149,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
@@ -4226,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;
@@ -4419,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;
          }
       }
@@ -4441,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;
@@ -4515,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,
@@ -4606,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);
            }
        }
@@ -4639,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
@@ -4653,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.  */
@@ -4663,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])
@@ -4674,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.  */
@@ -4794,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.  */
@@ -5097,9 +5076,7 @@ buffer_posn_from_coords (struct window *w, int *x, int *y, struct display_pos *p
      wrong thing with `face-remapping-alist' (bug#2044).  */
   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
@@ -5323,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
@@ -5415,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);
     }
   }
 }
@@ -5449,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
@@ -5469,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;
 
@@ -5481,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 ();
 
@@ -5538,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))
-       XWINDOW (f->tool_bar_window)->total_cols = 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));
@@ -5579,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;
@@ -5590,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
@@ -5736,9 +5750,9 @@ additional wait period, in milliseconds; this is for backwards compatibility.
 
   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;
@@ -5785,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))
@@ -5829,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;
 }
 
@@ -6122,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
@@ -6205,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
@@ -6226,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);