+ The algorithm used for rotating the vector was, I believe, first
+ described by Kernighan. See the vector R as consisting of two
+ sub-vectors AB, where A has length BY for BY >= 0. The result
+ after rotating is then BA. Reverse both sub-vectors to get ArBr
+ and reverse the result to get (ArBr)r which is BA. Similar for
+ rotating right. */
+
+void
+rotate_matrix (matrix, first, last, by)
+ struct glyph_matrix *matrix;
+ int first, last, by;
+{
+ if (by < 0)
+ {
+ /* Up (rotate left, i.e. towards lower indices). */
+ by = -by;
+ reverse_rows (matrix, first, first + by);
+ reverse_rows (matrix, first + by, last);
+ reverse_rows (matrix, first, last);
+ }
+ else if (by > 0)
+ {
+ /* Down (rotate right, i.e. towards higher indices). */
+ reverse_rows (matrix, last - by, last);
+ reverse_rows (matrix, first, last - by);
+ reverse_rows (matrix, first, last);
+ }
+}
+
+
+/* Increment buffer positions in glyph rows of MATRIX. Do it for rows
+ with indices START <= index < END. Increment positions by DELTA/
+ DELTA_BYTES. */
+
+void
+increment_matrix_positions (matrix, start, end, delta, delta_bytes)
+ struct glyph_matrix *matrix;
+ int start, end, delta, delta_bytes;
+{
+ /* Check that START and END are reasonable values. */
+ xassert (start >= 0 && start <= matrix->nrows);
+ xassert (end >= 0 && end <= matrix->nrows);
+ xassert (start <= end);
+
+ for (; start < end; ++start)
+ increment_row_positions (matrix->rows + start, delta, delta_bytes);
+}
+
+
+/* Enable a range of rows in glyph matrix MATRIX. START and END are
+ the row indices of the first and last + 1 row to enable. If
+ ENABLED_P is non-zero, enabled_p flags in rows will be set to 1. */
+
+void
+enable_glyph_matrix_rows (matrix, start, end, enabled_p)
+ struct glyph_matrix *matrix;
+ int start, end;
+ int enabled_p;
+{
+ xassert (start <= end);
+ xassert (start >= 0 && start < matrix->nrows);
+ xassert (end >= 0 && end <= matrix->nrows);
+
+ for (; start < end; ++start)
+ matrix->rows[start].enabled_p = enabled_p != 0;
+}
+
+
+/* Clear MATRIX.
+
+ This empties all rows in MATRIX by setting the enabled_p flag for
+ all rows of the matrix to zero. The function prepare_desired_row
+ will eventually really clear a row when it sees one with a zero
+ enabled_p flag.
+
+ Resets update hints to defaults value. The only update hint
+ currently present is the flag MATRIX->no_scrolling_p. */
+
+void
+clear_glyph_matrix (matrix)
+ struct glyph_matrix *matrix;
+{
+ if (matrix)
+ {
+ enable_glyph_matrix_rows (matrix, 0, matrix->nrows, 0);
+ matrix->no_scrolling_p = 0;
+ }
+}
+
+
+/* Shift part of the glyph matrix MATRIX of window W up or down.
+ Increment y-positions in glyph rows between START and END by DY,
+ and recompute their visible height. */
+
+void
+shift_glyph_matrix (w, matrix, start, end, dy)
+ struct window *w;
+ struct glyph_matrix *matrix;
+ int start, end, dy;
+{
+ int min_y, max_y;
+
+ xassert (start <= end);
+ xassert (start >= 0 && start < matrix->nrows);
+ xassert (end >= 0 && end <= matrix->nrows);
+
+ min_y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
+ max_y = WINDOW_DISPLAY_HEIGHT_NO_MODE_LINE (w);
+
+ for (; start < end; ++start)
+ {
+ struct glyph_row *row = &matrix->rows[start];
+
+ row->y += dy;
+
+ if (row->y < min_y)
+ row->visible_height = row->height - (min_y - row->y);
+ else if (row->y + row->height > max_y)
+ row->visible_height = row->height - (row->y + row->height - max_y);
+ else
+ row->visible_height = row->height;
+ }
+}
+
+
+/* Mark all rows in current matrices of frame F as invalid. Marking
+ invalid is done by setting enabled_p to zero for all rows in a
+ current matrix. */
+
+void
+clear_current_matrices (f)
+ register struct frame *f;
+{
+ /* Clear frame current matrix, if we have one. */
+ if (f->current_matrix)
+ clear_glyph_matrix (f->current_matrix);
+
+ /* 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);
+
+ /* 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);
+
+ /* Clear current window matrices. */
+ xassert (WINDOWP (FRAME_ROOT_WINDOW (f)));
+ clear_window_matrices (XWINDOW (FRAME_ROOT_WINDOW (f)), 0);
+}
+
+
+/* Clear out all display lines of F for a coming redisplay. */
+
+void
+clear_desired_matrices (f)
+ register struct frame *f;
+{
+ if (f->desired_matrix)
+ clear_glyph_matrix (f->desired_matrix);
+
+ if (WINDOWP (f->menu_bar_window))
+ clear_glyph_matrix (XWINDOW (f->menu_bar_window)->desired_matrix);
+
+ if (WINDOWP (f->tool_bar_window))
+ clear_glyph_matrix (XWINDOW (f->tool_bar_window)->desired_matrix);
+
+ /* Do it for window matrices. */
+ xassert (WINDOWP (FRAME_ROOT_WINDOW (f)));
+ clear_window_matrices (XWINDOW (FRAME_ROOT_WINDOW (f)), 1);
+}
+
+
+/* Clear matrices in window tree rooted in W. If DESIRED_P is
+ non-zero clear desired matrices, otherwise clear current matrices. */
+
+static void
+clear_window_matrices (w, desired_p)
+ struct window *w;
+ int desired_p;
+{
+ while (w)
+ {
+ if (!NILP (w->hchild))
+ {
+ xassert (WINDOWP (w->hchild));
+ clear_window_matrices (XWINDOW (w->hchild), desired_p);
+ }
+ else if (!NILP (w->vchild))
+ {
+ xassert (WINDOWP (w->vchild));
+ clear_window_matrices (XWINDOW (w->vchild), desired_p);
+ }
+ else
+ {
+ if (desired_p)
+ clear_glyph_matrix (w->desired_matrix);
+ else
+ {
+ clear_glyph_matrix (w->current_matrix);
+ w->window_end_valid = Qnil;
+ }
+ }
+
+ w = NILP (w->next) ? 0 : XWINDOW (w->next);
+ }
+}
+
+
+\f
+/***********************************************************************
+ Glyph Rows
+
+ 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. */
+
+void
+clear_glyph_row (row)
+ struct glyph_row *row;
+{
+ struct glyph *p[1 + LAST_AREA];
+ static struct glyph_row null_row;
+
+ /* 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. */
+ bzero (p[0], (char *) p[LAST_AREA] - (char *) p[0]);
+#endif
+}
+
+
+/* Make ROW an empty, enabled row of canonical character height,
+ in window W starting at y-position Y. */
+
+void
+blank_row (w, row, y)
+ struct window *w;
+ struct glyph_row *row;
+ int y;
+{
+ int min_y, max_y;
+
+ min_y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
+ max_y = WINDOW_DISPLAY_HEIGHT_NO_MODE_LINE (w);
+
+ clear_glyph_row (row);
+ row->y = y;
+ row->ascent = row->phys_ascent = 0;
+ row->height = row->phys_height = CANON_Y_UNIT (XFRAME (w->frame));
+
+ if (row->y < min_y)
+ row->visible_height = row->height - (min_y - row->y);
+ else if (row->y + row->height > max_y)
+ row->visible_height = row->height - (row->y + row->height - max_y);
+ else
+ row->visible_height = row->height;
+
+ row->enabled_p = 1;
+}
+
+
+/* Increment buffer positions in glyph row ROW. DELTA and DELTA_BYTES
+ are the amounts by which to change positions. Note that the first
+ glyph of the text area of a row can have a buffer position even if
+ the used count of the text area is zero. Such rows display line
+ ends. */
+
+void
+increment_row_positions (row, delta, delta_bytes)
+ struct glyph_row *row;
+ int delta, delta_bytes;
+{
+ int area, i;
+
+ /* Increment start and end positions. */
+ MATRIX_ROW_START_CHARPOS (row) += delta;
+ MATRIX_ROW_START_BYTEPOS (row) += delta_bytes;
+ MATRIX_ROW_END_CHARPOS (row) += delta;
+ MATRIX_ROW_END_BYTEPOS (row) += delta_bytes;
+
+ /* Increment positions in glyphs. */
+ for (area = 0; area < LAST_AREA; ++area)
+ for (i = 0; i < row->used[area]; ++i)
+ if (BUFFERP (row->glyphs[area][i].object)
+ && row->glyphs[area][i].charpos > 0)
+ row->glyphs[area][i].charpos += delta;
+
+ /* Capture the case of rows displaying a line end. */
+ if (row->used[TEXT_AREA] == 0
+ && MATRIX_ROW_DISPLAYS_TEXT_P (row))
+ row->glyphs[TEXT_AREA]->charpos += delta;
+}
+
+
+#if 0
+/* Swap glyphs between two glyph rows A and B. This exchanges glyph
+ contents, i.e. glyph structure contents are exchanged between A and
+ B without changing glyph pointers in A and B. */
+
+static void
+swap_glyphs_in_rows (a, b)
+ struct glyph_row *a, *b;
+{
+ int area;
+
+ for (area = 0; area < LAST_AREA; ++area)
+ {
+ /* Number of glyphs to swap. */
+ int max_used = max (a->used[area], b->used[area]);
+
+ /* Start of glyphs in area of row A. */
+ struct glyph *glyph_a = a->glyphs[area];
+
+ /* End + 1 of glyphs in area of row A. */
+ struct glyph *glyph_a_end = a->glyphs[max_used];
+
+ /* Start of glyphs in area of row B. */
+ struct glyph *glyph_b = b->glyphs[area];
+
+ while (glyph_a < glyph_a_end)
+ {
+ /* Non-ISO HP/UX compiler doesn't like auto struct
+ initialization. */
+ struct glyph temp;
+ temp = *glyph_a;
+ *glyph_a = *glyph_b;
+ *glyph_b = temp;
+ ++glyph_a;
+ ++glyph_b;
+ }
+ }
+}
+
+#endif /* 0 */
+
+/* Exchange pointers to glyph memory between glyph rows A and B. */
+
+static INLINE void
+swap_glyph_pointers (a, b)
+ struct glyph_row *a, *b;
+{
+ int i;
+ for (i = 0; i < LAST_AREA + 1; ++i)
+ {
+ struct glyph *temp = a->glyphs[i];
+ a->glyphs[i] = b->glyphs[i];
+ b->glyphs[i] = temp;
+ }
+}
+
+
+/* Copy glyph row structure FROM to glyph row structure TO, except
+ that glyph pointers in the structures are left unchanged. */
+
+INLINE void
+copy_row_except_pointers (to, from)
+ struct glyph_row *to, *from;
+{
+ struct glyph *pointers[1 + LAST_AREA];
+
+ /* Save glyph pointers of TO. */
+ bcopy (to->glyphs, pointers, sizeof to->glyphs);
+
+ /* Do a structure assignment. */
+ *to = *from;
+
+ /* Restore original pointers of TO. */
+ bcopy (pointers, to->glyphs, sizeof to->glyphs);
+}
+
+
+/* Copy contents of glyph row FROM to glyph row TO. Glyph pointers in
+ TO and FROM are left unchanged. Glyph contents are copied from the
+ glyph memory of FROM to the glyph memory of TO. Increment buffer
+ positions in row TO by DELTA/ DELTA_BYTES. */
+
+void
+copy_glyph_row_contents (to, from, delta, delta_bytes)
+ struct glyph_row *to, *from;
+ int delta, delta_bytes;
+{
+ int area;
+
+ /* This is like a structure assignment TO = FROM, except that
+ glyph pointers in the rows are left unchanged. */
+ copy_row_except_pointers (to, from);
+
+ /* Copy glyphs from FROM to TO. */
+ for (area = 0; area < LAST_AREA; ++area)
+ if (from->used[area])
+ bcopy (from->glyphs[area], to->glyphs[area],
+ from->used[area] * sizeof (struct glyph));
+
+ /* Increment buffer positions in TO by DELTA. */
+ increment_row_positions (to, delta, delta_bytes);
+}
+
+
+/* Assign glyph row FROM to glyph row TO. This works like a structure
+ assignment TO = FROM, except that glyph pointers are not copied but
+ exchanged between TO and FROM. Pointers must be exchanged to avoid
+ a memory leak. */
+
+static INLINE void
+assign_row (to, from)
+ struct glyph_row *to, *from;
+{
+ swap_glyph_pointers (to, from);
+ copy_row_except_pointers (to, from);
+}
+
+
+/* Test whether the glyph memory of the glyph row WINDOW_ROW, which is
+ a row in a window matrix, is a slice of the glyph memory of the
+ glyph row FRAME_ROW which is a row in a frame glyph matrix. Value
+ is non-zero if the glyph memory of WINDOW_ROW is part of the glyph
+ memory of FRAME_ROW. */
+
+#ifdef GLYPH_DEBUG
+
+static int
+glyph_row_slice_p (window_row, frame_row)
+ struct glyph_row *window_row, *frame_row;
+{
+ struct glyph *window_glyph_start = window_row->glyphs[0];
+ struct glyph *frame_glyph_start = frame_row->glyphs[0];
+ struct glyph *frame_glyph_end = frame_row->glyphs[LAST_AREA];
+
+ return (frame_glyph_start <= window_glyph_start
+ && window_glyph_start < frame_glyph_end);
+}
+
+#endif /* GLYPH_DEBUG */
+
+#if 0
+
+/* Find the row in the window glyph matrix WINDOW_MATRIX being a slice
+ of ROW in the frame matrix FRAME_MATRIX. Value is null if no row
+ in WINDOW_MATRIX is found satisfying the condition. */
+
+static struct glyph_row *
+find_glyph_row_slice (window_matrix, frame_matrix, row)
+ struct glyph_matrix *window_matrix, *frame_matrix;
+ int row;
+{
+ int i;
+
+ xassert (row >= 0 && row < frame_matrix->nrows);
+
+ for (i = 0; i < window_matrix->nrows; ++i)
+ if (glyph_row_slice_p (window_matrix->rows + i,
+ frame_matrix->rows + row))
+ break;
+
+ return i < window_matrix->nrows ? window_matrix->rows + i : 0;
+}
+
+#endif /* 0 */
+
+/* Prepare ROW for display. Desired rows are cleared lazily,
+ i.e. they are only marked as to be cleared by setting their
+ enabled_p flag to zero. When a row is to be displayed, a prior
+ call to this function really clears it. */
+
+void
+prepare_desired_row (row)
+ struct glyph_row *row;
+{
+ if (!row->enabled_p)
+ {
+ clear_glyph_row (row);
+ row->enabled_p = 1;
+ }
+}
+
+
+/* Return a hash code for glyph row ROW. */
+
+int
+line_hash_code (row)
+ struct glyph_row *row;
+{
+ int hash = 0;
+
+ if (row->enabled_p)
+ {
+ if (row->inverse_p)
+ {
+ /* Give all highlighted lines the same hash code
+ so as to encourage scrolling to leave them in place. */
+ hash = -1;
+ }
+ else
+ {
+ struct glyph *glyph = row->glyphs[TEXT_AREA];
+ struct glyph *end = glyph + row->used[TEXT_AREA];
+
+ while (glyph < end)
+ {
+ int c = glyph->u.ch;
+ int face_id = glyph->face_id;
+ if (must_write_spaces)
+ c -= SPACEGLYPH;
+ hash = (((hash << 4) + (hash >> 24)) & 0x0fffffff) + c;
+ hash = (((hash << 4) + (hash >> 24)) & 0x0fffffff) + face_id;
+ ++glyph;
+ }
+
+ if (hash == 0)
+ hash = 1;
+ }
+ }
+
+ return hash;
+}
+
+
+/* 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. */
+
+static unsigned int
+line_draw_cost (matrix, vpos)
+ struct glyph_matrix *matrix;
+ int vpos;
+{
+ struct glyph_row *row = matrix->rows + vpos;
+ struct glyph *beg = row->glyphs[TEXT_AREA];
+ struct glyph *end = beg + row->used[TEXT_AREA];
+ int len;
+ Lisp_Object *glyph_table_base = GLYPH_TABLE_BASE;
+ int glyph_table_len = GLYPH_TABLE_LENGTH;
+
+ /* Ignore trailing and leading spaces if we can. */
+ if (!must_write_spaces)
+ {
+ /* Skip from the end over trailing spaces. */
+ while (end != beg && CHAR_GLYPH_SPACE_P (*end))
+ --end;
+
+ /* All blank line. */
+ if (end == beg)
+ return 0;
+
+ /* Skip over leading spaces. */
+ while (CHAR_GLYPH_SPACE_P (*beg))
+ ++beg;
+ }
+
+ /* If we don't have a glyph-table, each glyph is one character,
+ so return the number of glyphs. */
+ if (glyph_table_base == 0)
+ len = end - beg;
+ else
+ {
+ /* Otherwise, scan the glyphs and accumulate their total length
+ in LEN. */
+ len = 0;
+ while (beg < end)
+ {
+ GLYPH g = GLYPH_FROM_CHAR_GLYPH (*beg);
+
+ if (g < 0
+ || GLYPH_SIMPLE_P (glyph_table_base, glyph_table_len, g))
+ len += 1;
+ else
+ len += GLYPH_LENGTH (glyph_table_base, g);
+
+ ++beg;
+ }
+ }
+
+ return len;
+}
+
+
+/* Test two glyph rows A and B for equality. Value is non-zero if A
+ and B have equal contents. W is the window to which the glyphs
+ rows A and B belong. It is needed here to test for partial row
+ visibility. MOUSE_FACE_P non-zero means compare the mouse_face_p
+ flags of A and B, too. */
+
+static INLINE int
+row_equal_p (w, a, b, mouse_face_p)
+ struct window *w;
+ struct glyph_row *a, *b;
+ int mouse_face_p;
+{
+ if (a == b)
+ return 1;
+ else if (a->hash != b->hash)
+ return 0;
+ else
+ {
+ struct glyph *a_glyph, *b_glyph, *a_end;
+ int area;
+
+ if (mouse_face_p && a->mouse_face_p != b->mouse_face_p)
+ return 0;
+
+ /* Compare glyphs. */
+ for (area = LEFT_MARGIN_AREA; area < LAST_AREA; ++area)
+ {
+ if (a->used[area] != b->used[area])
+ return 0;
+
+ a_glyph = a->glyphs[area];
+ a_end = a_glyph + a->used[area];
+ b_glyph = b->glyphs[area];
+
+ while (a_glyph < a_end
+ && GLYPH_EQUAL_P (a_glyph, b_glyph))
+ ++a_glyph, ++b_glyph;
+
+ if (a_glyph != a_end)
+ return 0;
+ }
+
+ if (a->truncated_on_left_p != b->truncated_on_left_p
+ || a->inverse_p != b->inverse_p
+ || a->fill_line_p != b->fill_line_p
+ || a->truncated_on_right_p != b->truncated_on_right_p
+ || a->overlay_arrow_p != b->overlay_arrow_p
+ || a->continued_p != b->continued_p
+ || a->indicate_empty_line_p != b->indicate_empty_line_p
+ || a->overlapped_p != b->overlapped_p
+ || (MATRIX_ROW_CONTINUATION_LINE_P (a)
+ != MATRIX_ROW_CONTINUATION_LINE_P (b))
+ /* Different partially visible characters on left margin. */
+ || a->x != b->x
+ /* Different height. */
+ || a->ascent != b->ascent
+ || a->phys_ascent != b->phys_ascent
+ || a->phys_height != b->phys_height
+ || a->visible_height != b->visible_height)
+ return 0;
+ }
+
+ return 1;
+}
+
+
+\f
+/***********************************************************************
+ Glyph Pool
+
+ 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. */
+
+static struct glyph_pool *
+new_glyph_pool ()
+{
+ struct glyph_pool *result;
+
+ /* Allocate a new glyph_pool and clear it. */
+ result = (struct glyph_pool *) xmalloc (sizeof *result);
+ bzero (result, sizeof *result);
+
+ /* For memory leak and double deletion checking. */
+ ++glyph_pool_count;
+
+ 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. */
+
+static void
+free_glyph_pool (pool)
+ struct glyph_pool *pool;
+{
+ if (pool)
+ {
+ /* More freed than allocated? */
+ --glyph_pool_count;
+ xassert (glyph_pool_count >= 0);
+
+ xfree (pool->glyphs);
+ xfree (pool);
+ }
+}
+
+
+/* Enlarge a glyph pool POOL. MATRIX_DIM gives the number of rows and
+ columns we need. This function never shrinks a pool. The only
+ case in which this would make sense, would be when a frame's size
+ is changed from a large value to a smaller one. But, if someone
+ does it once, we can expect that he will do it again.
+
+ Value is non-zero if the pool changed in a way which makes
+ re-adjusting window glyph matrices necessary. */
+
+static int
+realloc_glyph_pool (pool, matrix_dim)
+ struct glyph_pool *pool;
+ struct dim matrix_dim;
+{
+ int needed;
+ int changed_p;
+
+ changed_p = (pool->glyphs == 0
+ || matrix_dim.height != pool->nrows
+ || matrix_dim.width != pool->ncolumns);
+
+ /* Enlarge the glyph pool. */
+ needed = matrix_dim.width * matrix_dim.height;
+ if (needed > pool->nglyphs)
+ {
+ int size = needed * sizeof (struct glyph);
+
+ if (pool->glyphs)
+ pool->glyphs = (struct glyph *) xrealloc (pool->glyphs, size);
+ else
+ {
+ pool->glyphs = (struct glyph *) xmalloc (size);
+ bzero (pool->glyphs, size);
+ }
+
+ pool->nglyphs = needed;
+ }
+
+ /* Remember the number of rows and columns because (a) we use then
+ to do sanity checks, and (b) the number of columns determines
+ where rows in the frame matrix start---this must be available to
+ determine pointers to rows of window sub-matrices. */
+ pool->nrows = matrix_dim.height;
+ pool->ncolumns = matrix_dim.width;
+
+ return changed_p;
+}
+
+
+\f
+/***********************************************************************
+ Debug Code
+ ***********************************************************************/
+
+#if GLYPH_DEBUG
+
+
+/* Flush standard output. This is sometimes useful to call from
+ the debugger. */
+
+void
+flush_stdout ()
+{
+ fflush (stdout);
+}
+
+
+/* Check that no glyph pointers have been lost in MATRIX. If a
+ pointer has been lost, e.g. by using a structure assignment between
+ rows, at least one pointer must occur more than once in the rows of
+ MATRIX. */
+
+void
+check_matrix_pointer_lossage (matrix)
+ struct glyph_matrix *matrix;
+{
+ int i, j;
+
+ for (i = 0; i < matrix->nrows; ++i)
+ for (j = 0; j < matrix->nrows; ++j)
+ xassert (i == j
+ || (matrix->rows[i].glyphs[TEXT_AREA]
+ != matrix->rows[j].glyphs[TEXT_AREA]));
+}
+
+
+/* Get a pointer to glyph row ROW in MATRIX, with bounds checks. */
+
+struct glyph_row *
+matrix_row (matrix, row)
+ struct glyph_matrix *matrix;
+ int row;
+{
+ xassert (matrix && matrix->rows);
+ xassert (row >= 0 && row < matrix->nrows);
+
+ /* That's really too slow for normal testing because this function
+ is called almost everywhere. Although---it's still astonishingly
+ fast, so it is valuable to have for debugging purposes. */
+#if 0
+ check_matrix_pointer_lossage (matrix);
+#endif
+
+ return matrix->rows + row;
+}
+
+
+#if 0 /* This function makes invalid assumptions when text is
+ partially invisible. But it might come handy for debugging
+ nevertheless. */
+
+/* Check invariants that must hold for an up to date current matrix of
+ window W. */
+
+static void
+check_matrix_invariants (w)
+ struct window *w;
+{
+ struct glyph_matrix *matrix = w->current_matrix;
+ int yb = window_text_bottom_y (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);
+ int c;
+
+ /* This can sometimes happen for a fresh window. */
+ if (matrix->nrows < 2)
+ return;
+
+ set_buffer_temp (buffer);
+
+ /* Note: last row is always reserved for the mode line. */
+ while (MATRIX_ROW_DISPLAYS_TEXT_P (row)
+ && MATRIX_ROW_BOTTOM_Y (row) < yb)
+ {
+ struct glyph_row *next = row + 1;
+
+ if (MATRIX_ROW_DISPLAYS_TEXT_P (row))
+ last_text_row = row;
+
+ /* Check that character and byte positions are in sync. */
+ xassert (MATRIX_ROW_START_BYTEPOS (row)
+ == CHAR_TO_BYTE (MATRIX_ROW_START_CHARPOS (row)));
+
+ /* CHAR_TO_BYTE aborts when invoked for a position > Z. We can
+ have such a position temporarily in case of a minibuffer
+ displaying something like `[Sole completion]' at its end. */
+ if (MATRIX_ROW_END_CHARPOS (row) < BUF_ZV (current_buffer))
+ xassert (MATRIX_ROW_END_BYTEPOS (row)
+ == CHAR_TO_BYTE (MATRIX_ROW_END_CHARPOS (row)));
+
+ /* Check that end position of `row' is equal to start position
+ of next row. */
+ if (next->enabled_p && MATRIX_ROW_DISPLAYS_TEXT_P (next))
+ {
+ xassert (MATRIX_ROW_END_CHARPOS (row)
+ == MATRIX_ROW_START_CHARPOS (next));
+ xassert (MATRIX_ROW_END_BYTEPOS (row)
+ == MATRIX_ROW_START_BYTEPOS (next));
+ }
+ row = next;
+ }
+
+ xassert (w->current_matrix->nrows == w->desired_matrix->nrows);
+ xassert (w->desired_matrix->rows != NULL);
+ set_buffer_temp (saved);
+}
+
+#endif /* 0 */
+
+#endif /* GLYPH_DEBUG != 0 */
+
+
+\f
+/**********************************************************************
+ Allocating/ Adjusting Glyph Matrices
+ **********************************************************************/
+
+/* Allocate glyph matrices over a window tree for a frame-based
+ redisplay
+
+ X and Y are column/row within the frame glyph matrix where
+ sub-matrices for the window tree rooted at WINDOW must be
+ allocated. CH_DIM contains the dimensions of the smallest
+ character that could be used during display. DIM_ONLY_P non-zero
+ means that the caller of this function is only interested in the
+ result matrix dimension, and matrix adjustments should not be
+ performed.
+
+ The function returns the total width/height of the sub-matrices of
+ the window tree. If called on a frame root window, the computation
+ will take the mini-buffer window into account.
+
+ *WINDOW_CHANGE_FLAGS is set to a bit mask with bits
+
+ NEW_LEAF_MATRIX set if any window in the tree did not have a
+ glyph matrices yet, and
+
+ CHANGED_LEAF_MATRIX set if the dimension or location of a matrix of
+ any window in the tree will be changed or have been changed (see
+ DIM_ONLY_P).
+
+ *WINDOW_CHANGE_FLAGS must be initialized by the caller of this
+ function.
+
+ Windows are arranged into chains of windows on the same level
+ through the next fields of window structures. Such a level can be
+ either a sequence of horizontally adjacent windows from left to
+ right, or a sequence of vertically adjacent windows from top to
+ bottom. Each window in a horizontal sequence can be either a leaf
+ window or a vertical sequence; a window in a vertical sequence can
+ be either a leaf or a horizontal sequence. All windows in a
+ horizontal sequence have the same height, and all windows in a
+ vertical sequence have the same width.
+
+ This function uses, for historical reasons, a more general
+ algorithm to determine glyph matrix dimensions that would be
+ necessary.
+
+ The matrix height of a horizontal sequence is determined by the
+ maximum height of any matrix in the sequence. The matrix width of
+ a horizontal sequence is computed by adding up matrix widths of
+ windows in the sequence.
+
+ |<------- result width ------->|
+ +---------+----------+---------+ ---
+ | | | | |
+ | | | |
+ +---------+ | | result height
+ | +---------+
+ | | |
+ +----------+ ---
+
+ The matrix width of a vertical sequence is the maximum matrix width
+ of any window in the sequence. Its height is computed by adding up
+ matrix heights of windows in the sequence.
+
+ |<---- result width -->|
+ +---------+ ---
+ | | |
+ | | |
+ +---------+--+ |
+ | | |
+ | | result height
+ | |
+ +------------+---------+ |
+ | | |
+ | | |
+ +------------+---------+ --- */
+
+/* Bit indicating that a new matrix will be allocated or has been
+ allocated. */
+
+#define NEW_LEAF_MATRIX (1 << 0)
+
+/* Bit indicating that a matrix will or has changed its location or
+ size. */
+
+#define CHANGED_LEAF_MATRIX (1 << 1)
+
+static struct dim
+allocate_matrices_for_frame_redisplay (window, x, y, ch_dim,
+ dim_only_p, window_change_flags)
+ Lisp_Object window;
+ int x, y;
+ struct dim ch_dim;
+ int dim_only_p;
+ int *window_change_flags;
+{
+ struct frame *f = XFRAME (WINDOW_FRAME (XWINDOW (window)));
+ int x0 = x, y0 = y;
+ int wmax = 0, hmax = 0;
+ struct dim total;
+ struct dim dim;
+ struct window *w;
+ int in_horz_combination_p;
+
+ /* What combination is WINDOW part of? Compute this once since the
+ result is the same for all windows in the `next' chain. The
+ special case of a root window (parent equal to nil) is treated
+ like a vertical combination because a root window's `next'
+ points to the mini-buffer window, if any, which is arranged
+ vertically below other windows. */
+ in_horz_combination_p
+ = (!NILP (XWINDOW (window)->parent)
+ && !NILP (XWINDOW (XWINDOW (window)->parent)->hchild));
+
+ /* For WINDOW and all windows on the same level. */
+ do
+ {
+ w = XWINDOW (window);
+
+ /* Get the dimension of the window sub-matrix for W, depending
+ on whether this a combination or a leaf window. */
+ if (!NILP (w->hchild))
+ dim = allocate_matrices_for_frame_redisplay (w->hchild, x, y, ch_dim,
+ dim_only_p,
+ window_change_flags);
+ else if (!NILP (w->vchild))
+ dim = allocate_matrices_for_frame_redisplay (w->vchild, x, y, ch_dim,
+ dim_only_p,
+ window_change_flags);
+ else
+ {
+ /* If not already done, allocate sub-matrix structures. */
+ if (w->desired_matrix == NULL)
+ {
+ w->desired_matrix = new_glyph_matrix (f->desired_pool);
+ w->current_matrix = new_glyph_matrix (f->current_pool);
+ *window_change_flags |= NEW_LEAF_MATRIX;
+ }
+
+ /* Width and height MUST be chosen so that there are no
+ holes in the frame matrix. */
+ dim.width = XINT (w->width);
+ dim.height = XINT (w->height);
+
+ /* Will matrix be re-allocated? */
+ if (x != w->desired_matrix->matrix_x
+ || y != w->desired_matrix->matrix_y
+ || dim.width != w->desired_matrix->matrix_w
+ || dim.height != w->desired_matrix->matrix_h
+ || (margin_glyphs_to_reserve (w, dim.width,
+ w->right_margin_width)
+ != w->desired_matrix->left_margin_glyphs)
+ || (margin_glyphs_to_reserve (w, dim.width,
+ w->left_margin_width)
+ != w->desired_matrix->right_margin_glyphs))
+ *window_change_flags |= CHANGED_LEAF_MATRIX;
+
+ /* Actually change matrices, if allowed. Do not consider
+ CHANGED_LEAF_MATRIX computed above here because the pool
+ may have been changed which we don't now here. We trust
+ that we only will be called with DIM_ONLY_P != 0 when
+ necessary. */
+ if (!dim_only_p)
+ {
+ adjust_glyph_matrix (w, w->desired_matrix, x, y, dim);
+ adjust_glyph_matrix (w, w->current_matrix, x, y, dim);
+ }
+ }
+
+ /* If we are part of a horizontal combination, advance x for
+ windows to the right of W; otherwise advance y for windows
+ below W. */
+ if (in_horz_combination_p)
+ x += dim.width;
+ else
+ y += dim.height;
+
+ /* Remember maximum glyph matrix dimensions. */
+ wmax = max (wmax, dim.width);
+ hmax = max (hmax, dim.height);
+
+ /* Next window on same level. */
+ window = w->next;
+ }
+ while (!NILP (window));
+
+ /* Set `total' to the total glyph matrix dimension of this window
+ level. In a vertical combination, the width is the width of the
+ widest window; the height is the y we finally reached, corrected
+ by the y we started with. In a horizontal combination, the total
+ height is the height of the tallest window, and the width is the
+ x we finally reached, corrected by the x we started with. */
+ if (in_horz_combination_p)
+ {
+ total.width = x - x0;
+ total.height = hmax;
+ }
+ else
+ {
+ total.width = wmax;
+ total.height = y - y0;
+ }
+
+ return total;
+}
+
+
+/* Allocate window matrices for window-based redisplay. W is the
+ window whose matrices must be allocated/reallocated. CH_DIM is the
+ size of the smallest character that could potentially be used on W. */
+
+static void
+allocate_matrices_for_window_redisplay (w, ch_dim)
+ struct window *w;
+ struct dim ch_dim;
+{
+ struct frame *f = XFRAME (w->frame);
+
+ while (w)
+ {
+ if (!NILP (w->vchild))
+ allocate_matrices_for_window_redisplay (XWINDOW (w->vchild), ch_dim);
+ else if (!NILP (w->hchild))
+ allocate_matrices_for_window_redisplay (XWINDOW (w->hchild), ch_dim);
+ else
+ {
+ /* W is a leaf window. */
+ int window_pixel_width = XFLOATINT (w->width) * CANON_X_UNIT (f);
+ int window_pixel_height = window_box_height (w) + abs (w->vscroll);
+ struct dim dim;
+
+ /* If matrices are not yet allocated, allocate them now. */
+ if (w->desired_matrix == NULL)
+ {
+ w->desired_matrix = new_glyph_matrix (NULL);
+ w->current_matrix = new_glyph_matrix (NULL);
+ }
+
+ /* Compute number of glyphs needed in a glyph row. */
+ dim.width = (((window_pixel_width + ch_dim.width - 1)
+ / ch_dim.width)
+ /* 2 partially visible columns in the text area. */
+ + 2
+ /* One partially visible column at the right
+ edge of each marginal area. */
+ + 1 + 1);
+
+ /* Compute number of glyph rows needed. */
+ dim.height = (((window_pixel_height + ch_dim.height - 1)
+ / ch_dim.height)
+ /* One partially visible line at the top and
+ bottom of the window. */
+ + 2
+ /* 2 for top and mode line. */
+ + 2);
+
+ /* Change matrices. */
+ adjust_glyph_matrix (w, w->desired_matrix, 0, 0, dim);
+ adjust_glyph_matrix (w, w->current_matrix, 0, 0, dim);
+ }
+
+ w = NILP (w->next) ? NULL : XWINDOW (w->next);
+ }
+}
+
+
+/* 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. */
+
+void
+adjust_glyphs (f)
+ 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;
+}
+
+
+/* Adjust frame glyphs when Emacs is initialized.
+
+ To be called from init_display.
+
+ We need a glyph matrix because redraw will happen soon.
+ Unfortunately, window sizes on selected_frame are not yet set to
+ meaningful values. I believe we can assume that there are only two
+ windows on the frame---the mini-buffer and the root window. Frame
+ height and width seem to be correct so far. So, set the sizes of
+ windows to estimated values. */
+
+static void
+adjust_frame_glyphs_initially ()
+{
+ struct frame *sf = SELECTED_FRAME ();
+ struct window *root = XWINDOW (sf->root_window);
+ struct window *mini = XWINDOW (root->next);
+ int frame_height = FRAME_HEIGHT (sf);
+ int frame_width = FRAME_WIDTH (sf);
+ int top_margin = FRAME_TOP_MARGIN (sf);
+
+ /* Do it for the root window. */
+ XSETFASTINT (root->top, top_margin);
+ XSETFASTINT (root->width, frame_width);
+ set_window_height (sf->root_window, frame_height - 1 - top_margin, 0);
+
+ /* Do it for the mini-buffer window. */
+ XSETFASTINT (mini->top, frame_height - 1);
+ XSETFASTINT (mini->width, frame_width);
+ set_window_height (root->next, 1, 0);
+
+ adjust_frame_glyphs (sf);
+ glyphs_initialized_initially_p = 1;
+}
+
+
+/* Allocate/reallocate glyph matrices of a single frame F. */
+
+static void
+adjust_frame_glyphs (f)
+ struct frame *f;
+{
+ if (FRAME_WINDOW_P (f))
+ adjust_frame_glyphs_for_window_redisplay (f);
+ else
+ adjust_frame_glyphs_for_frame_redisplay (f);
+
+ /* Don't forget the message buffer and the buffer for
+ decode_mode_spec. */
+ adjust_frame_message_buffer (f);
+ adjust_decode_mode_spec_buffer (f);
+
+ f->glyphs_initialized_p = 1;
+}
+
+
+/* Allocate/reallocate glyph matrices of a single frame F for
+ frame-based redisplay. */
+
+static void
+adjust_frame_glyphs_for_frame_redisplay (f)
+ struct frame *f;
+{
+ struct dim ch_dim;
+ struct dim matrix_dim;
+ int pool_changed_p;
+ int window_change_flags;
+ int top_window_y;
+
+ if (!FRAME_LIVE_P (f))
+ return;
+
+ /* Determine the smallest character in any font for F. On
+ console windows, all characters have dimension (1, 1). */
+ ch_dim.width = ch_dim.height = 1;
+
+ top_window_y = FRAME_TOP_MARGIN (f);
+
+ /* Allocate glyph pool structures if not already done. */
+ if (f->desired_pool == NULL)
+ {
+ f->desired_pool = new_glyph_pool ();
+ f->current_pool = new_glyph_pool ();
+ }
+
+ /* Allocate frames matrix structures if needed. */
+ if (f->desired_matrix == NULL)
+ {
+ f->desired_matrix = new_glyph_matrix (f->desired_pool);
+ f->current_matrix = new_glyph_matrix (f->current_pool);
+ }
+
+ /* Compute window glyph matrices. (This takes the mini-buffer
+ window into account). The result is the size of the frame glyph
+ matrix needed. The variable window_change_flags is set to a bit
+ mask indicating whether new matrices will be allocated or
+ existing matrices change their size or location within the frame
+ matrix. */
+ window_change_flags = 0;
+ matrix_dim
+ = allocate_matrices_for_frame_redisplay (FRAME_ROOT_WINDOW (f),
+ 0, top_window_y,
+ ch_dim, 1,
+ &window_change_flags);
+
+ /* Add in menu bar lines, if any. */
+ matrix_dim.height += top_window_y;
+
+ /* Enlarge pools as necessary. */
+ pool_changed_p = realloc_glyph_pool (f->desired_pool, matrix_dim);
+ realloc_glyph_pool (f->current_pool, matrix_dim);
+
+ /* Set up glyph pointers within window matrices. Do this only if
+ absolutely necessary since it requires a frame redraw. */
+ if (pool_changed_p || window_change_flags)
+ {
+ /* Do it for window matrices. */
+ allocate_matrices_for_frame_redisplay (FRAME_ROOT_WINDOW (f),
+ 0, top_window_y, ch_dim, 0,
+ &window_change_flags);
+
+ /* 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). */
+ xassert (matrix_dim.width == FRAME_WIDTH (f)
+ && matrix_dim.height == FRAME_HEIGHT (f));
+
+ /* Resize frame matrices. */
+ adjust_glyph_matrix (NULL, f->desired_matrix, 0, 0, matrix_dim);
+ adjust_glyph_matrix (NULL, f->current_matrix, 0, 0, matrix_dim);
+
+ /* Since location and size of sub-matrices within the pool may
+ have changed, and current matrices don't have meaningful
+ contents anymore, mark the frame garbaged. */
+ SET_FRAME_GARBAGED (f);
+ }
+}
+
+
+/* Allocate/reallocate glyph matrices of a single frame F for
+ window-based redisplay. */
+
+static void
+adjust_frame_glyphs_for_window_redisplay (f)
+ struct frame *f;
+{
+ struct dim ch_dim;
+ struct window *w;
+
+ xassert (FRAME_WINDOW_P (f) && FRAME_LIVE_P (f));
+
+ /* Get minimum sizes. */
+#ifdef HAVE_WINDOW_SYSTEM
+ ch_dim.width = FRAME_SMALLEST_CHAR_WIDTH (f);
+ ch_dim.height = FRAME_SMALLEST_FONT_HEIGHT (f);
+#else
+ ch_dim.width = ch_dim.height = 1;
+#endif
+
+ /* Allocate/reallocate window matrices. */
+ allocate_matrices_for_window_redisplay (XWINDOW (FRAME_ROOT_WINDOW (f)),
+ ch_dim);
+
+ /* Allocate/ reallocate matrices of the dummy window used to display
+ the menu bar under X when no X toolkit support is available. */
+#ifndef USE_X_TOOLKIT
+ {
+ /* Allocate a dummy window if not already done. */
+ if (NILP (f->menu_bar_window))
+ {
+ f->menu_bar_window = make_window ();
+ w = XWINDOW (f->menu_bar_window);
+ XSETFRAME (w->frame, f);
+ w->pseudo_window_p = 1;
+ }
+ else
+ w = XWINDOW (f->menu_bar_window);
+
+ /* Set window dimensions to frame dimensions and allocate or
+ adjust glyph matrices of W. */
+ XSETFASTINT (w->top, 0);
+ XSETFASTINT (w->left, 0);
+ XSETFASTINT (w->height, FRAME_MENU_BAR_LINES (f));
+ XSETFASTINT (w->width, FRAME_WINDOW_WIDTH (f));
+ allocate_matrices_for_window_redisplay (w, ch_dim);
+ }
+#endif /* not USE_X_TOOLKIT */
+
+ /* Allocate/ reallocate matrices of the tool bar window. If we
+ don't have a tool bar window yet, make one. */
+ if (NILP (f->tool_bar_window))
+ {
+ f->tool_bar_window = make_window ();
+ w = XWINDOW (f->tool_bar_window);
+ XSETFRAME (w->frame, f);
+ w->pseudo_window_p = 1;
+ }
+ else
+ w = XWINDOW (f->tool_bar_window);
+
+ XSETFASTINT (w->top, FRAME_MENU_BAR_LINES (f));
+ XSETFASTINT (w->left, 0);
+ XSETFASTINT (w->height, FRAME_TOOL_BAR_LINES (f));
+ XSETFASTINT (w->width, FRAME_WINDOW_WIDTH (f));
+ allocate_matrices_for_window_redisplay (w, ch_dim);
+}
+
+
+/* Adjust/ allocate message buffer of frame F.
+
+ Note that the message buffer is never freed. Since I could not
+ find a free in 19.34, I assume that freeing it would be
+ problematic in some way and don't do it either.
+
+ (Implementation note: It should be checked if we can free it
+ eventually without causing trouble). */
+
+static void
+adjust_frame_message_buffer (f)
+ struct frame *f;
+{
+ int size = FRAME_MESSAGE_BUF_SIZE (f) + 1;
+
+ if (FRAME_MESSAGE_BUF (f))
+ {
+ char *buffer = FRAME_MESSAGE_BUF (f);
+ char *new_buffer = (char *) xrealloc (buffer, size);
+ FRAME_MESSAGE_BUF (f) = new_buffer;
+ }
+ else
+ FRAME_MESSAGE_BUF (f) = (char *) xmalloc (size);
+}
+
+
+/* Re-allocate buffer for decode_mode_spec on frame F. */
+
+static void
+adjust_decode_mode_spec_buffer (f)
+ struct frame *f;
+{
+ f->decode_mode_spec_buffer
+ = (char *) xrealloc (f->decode_mode_spec_buffer,
+ FRAME_MESSAGE_BUF_SIZE (f) + 1);
+}
+
+
+\f
+/**********************************************************************
+ Freeing Glyph Matrices
+ **********************************************************************/
+
+/* Free glyph memory for a frame F. F may be null. This function can
+ be called for the same frame more than once. The root window of
+ F may be nil when this function is called. This is the case when
+ the function is called when F is destroyed. */
+
+void
+free_glyphs (f)
+ struct frame *f;
+{
+ if (f && f->glyphs_initialized_p)
+ {
+ /* Block interrupt input so that we don't get surprised by an X
+ event while we're in an inconsistent state. */
+ BLOCK_INPUT;
+ f->glyphs_initialized_p = 0;
+
+ /* Release window sub-matrices. */
+ if (!NILP (f->root_window))
+ free_window_matrices (XWINDOW (f->root_window));
+
+ /* Free the dummy window for menu bars without X toolkit and its
+ glyph matrices. */
+ if (!NILP (f->menu_bar_window))
+ {
+ struct window *w = XWINDOW (f->menu_bar_window);
+ free_glyph_matrix (w->desired_matrix);
+ free_glyph_matrix (w->current_matrix);
+ w->desired_matrix = w->current_matrix = NULL;
+ f->menu_bar_window = Qnil;
+ }
+
+ /* Free the tool bar window and its glyph matrices. */
+ if (!NILP (f->tool_bar_window))
+ {
+ struct window *w = XWINDOW (f->tool_bar_window);
+ free_glyph_matrix (w->desired_matrix);
+ free_glyph_matrix (w->current_matrix);
+ w->desired_matrix = w->current_matrix = NULL;
+ f->tool_bar_window = Qnil;
+ }
+
+ /* Release frame glyph matrices. Reset fields to zero in
+ case we are called a second time. */
+ if (f->desired_matrix)
+ {
+ free_glyph_matrix (f->desired_matrix);
+ free_glyph_matrix (f->current_matrix);
+ f->desired_matrix = f->current_matrix = NULL;
+ }
+
+ /* Release glyph pools. */
+ if (f->desired_pool)
+ {
+ free_glyph_pool (f->desired_pool);
+ free_glyph_pool (f->current_pool);
+ f->desired_pool = f->current_pool = NULL;
+ }
+
+ UNBLOCK_INPUT;
+ }
+}
+
+
+/* Free glyph sub-matrices in the window tree rooted at W. This
+ function may be called with a null pointer, and it may be called on
+ the same tree more than once. */
+
+void
+free_window_matrices (w)
+ 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));
+ else
+ {
+ /* This is a leaf window. Free its memory and reset fields
+ to zero in case this function is called a second time for
+ W. */
+ free_glyph_matrix (w->current_matrix);
+ free_glyph_matrix (w->desired_matrix);
+ w->current_matrix = w->desired_matrix = NULL;
+ }
+
+ /* Next window on same level. */
+ w = NILP (w->next) ? 0 : XWINDOW (w->next);
+ }
+}
+
+
+/* Check glyph memory leaks. This function is called from
+ shut_down_emacs. Note that frames are not destroyed when Emacs
+ exits. We therefore free all glyph memory for all active frames
+ explicitly and check that nothing is left allocated. */
+
+void
+check_glyph_memory ()
+{
+ Lisp_Object tail, frame;
+
+ /* Free glyph memory for all frames. */
+ FOR_EACH_FRAME (tail, frame)
+ free_glyphs (XFRAME (frame));
+
+ /* Check that nothing is left allocated. */
+ if (glyph_matrix_count)
+ abort ();
+ if (glyph_pool_count)
+ abort ();
+}
+
+
+\f
+/**********************************************************************
+ Building a Frame Matrix
+ **********************************************************************/
+
+/* Most of the redisplay code works on glyph matrices attached to
+ windows. This is a good solution most of the time, but it is not
+ suitable for terminal code. Terminal output functions cannot rely
+ on being able to set an arbitrary terminal window. Instead they
+ must be provided with a view of the whole frame, i.e. the whole
+ 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.
+ 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.
+
+ +-----------------+----------------+
+ | desired | desired |
+ | | |
+ +-----------------+----------------+
+ | current |
+ | |
+ +----------------------------------+
+
+ Desired window matrices can be made part of the frame matrix in a
+ cheap way: We exploit the fact that the desired frame matrix and
+ desired window matrices share their glyph memory. This is not
+ possible for current window matrices. Their glyphs are copied to
+ the desired frame matrix. The latter is equivalent to
+ preserve_other_columns in the old redisplay.
+
+ Used glyphs counters for frame matrix rows are the result of adding
+ up glyph lengths of the window matrices. A line in the frame
+ matrix is enabled, if a corresponding line in a window matrix is
+ enabled.
+
+ After building the desired frame matrix, it will be passed to
+ terminal code, which will manipulate both the desired and current
+ frame matrix. Changes applied to the frame's current matrix have
+ to be visible in current window matrices afterwards, of course.
+
+ This problem is solved like this:
+
+ 1. Window and frame matrices share glyphs. Window matrices are
+ constructed in a way that their glyph contents ARE the glyph
+ contents needed in a frame matrix. Thus, any modification of
+ glyphs done in terminal code will be reflected in window matrices
+ automatically.
+
+ 2. Exchanges of rows in a frame matrix done by terminal code are
+ intercepted by hook functions so that corresponding row operations
+ on window matrices can be performed. This is necessary because we
+ use pointers to glyphs in glyph row structures. To satisfy the
+ assumption of point 1 above that glyphs are updated implicitly in
+ window matrices when they are manipulated via the frame matrix,
+ window and frame matrix must of course agree where to find the
+ glyphs for their rows. Possible manipulations that must be
+ mirrored are assignments of rows of the desired frame matrix to the
+ current frame matrix and scrolling the current frame matrix. */
+
+/* Build frame F's desired matrix from window matrices. Only windows
+ which have the flag must_be_updated_p set have to be updated. Menu
+ bar lines of a frame are not covered by window matrices, so make
+ sure not to touch them in this function. */
+
+static void
+build_frame_matrix (f)
+ struct frame *f;
+{
+ int i;
+
+ /* F must have a frame matrix when this function is called. */
+ xassert (!FRAME_WINDOW_P (f));
+
+ /* Clear all rows in the frame matrix covered by window matrices.
+ Menu bar lines are not covered by windows. */
+ for (i = FRAME_TOP_MARGIN (f); i < f->desired_matrix->nrows; ++i)
+ clear_glyph_row (MATRIX_ROW (f->desired_matrix, i));
+
+ /* Build the matrix by walking the window tree. */
+ build_frame_matrix_from_window_tree (f->desired_matrix,
+ XWINDOW (FRAME_ROOT_WINDOW (f)));
+}
+
+
+/* Walk a window tree, building a frame matrix MATRIX from window
+ matrices. W is the root of a window tree. */
+
+static void
+build_frame_matrix_from_window_tree (matrix, w)
+ struct glyph_matrix *matrix;
+ struct window *w;
+{
+ 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));
+ else
+ build_frame_matrix_from_leaf_window (matrix, w);
+
+ w = NILP (w->next) ? 0 : XWINDOW (w->next);
+ }
+}
+
+
+/* Add a window's matrix to a frame matrix. FRAME_MATRIX is the
+ desired frame matrix built. W is a leaf window whose desired or
+ current matrix is to be added to FRAME_MATRIX. W's flag
+ must_be_updated_p determines which matrix it contributes to
+ FRAME_MATRIX. If must_be_updated_p is non-zero, W's desired matrix
+ is added to FRAME_MATRIX, otherwise W's current matrix is added.
+ Adding a desired matrix means setting up used counters and such in
+ frame rows, while adding a current window matrix to FRAME_MATRIX
+ means copying glyphs. The latter case corresponds to
+ preserve_other_columns in the old redisplay. */
+
+static void
+build_frame_matrix_from_leaf_window (frame_matrix, w)
+ struct glyph_matrix *frame_matrix;
+ struct window *w;
+{
+ struct glyph_matrix *window_matrix;
+ int window_y, frame_y;
+ /* If non-zero, a glyph to insert at the right border of W. */
+ GLYPH right_border_glyph = 0;
+
+ /* Set window_matrix to the matrix we have to add to FRAME_MATRIX. */
+ if (w->must_be_updated_p)
+ {
+ window_matrix = w->desired_matrix;
+
+ /* Decide whether we want to add a vertical border glyph. */
+ if (!WINDOW_RIGHTMOST_P (w))
+ {
+ struct Lisp_Char_Table *dp = window_display_table (w);
+ right_border_glyph = (dp && INTEGERP (DISP_BORDER_GLYPH (dp))
+ ? XINT (DISP_BORDER_GLYPH (dp))
+ : '|');
+ }
+ }
+ else
+ window_matrix = w->current_matrix;
+
+ /* For all rows in the window matrix and corresponding rows in the
+ frame matrix. */
+ window_y = 0;
+ frame_y = window_matrix->matrix_y;
+ while (window_y < window_matrix->nrows)
+ {
+ struct glyph_row *frame_row = frame_matrix->rows + frame_y;
+ struct glyph_row *window_row = window_matrix->rows + window_y;
+ int current_row_p = window_matrix == w->current_matrix;
+
+ /* Fill up the frame row with spaces up to the left margin of the
+ window row. */
+ fill_up_frame_row_with_spaces (frame_row, window_matrix->matrix_x);
+
+ /* Fill up areas in the window matrix row with spaces. */
+ fill_up_glyph_row_with_spaces (window_row);
+
+ /* If only part of W's desired matrix has been built, and
+ window_row wasn't displayed, use the corresponding current
+ row instead. */
+ if (window_matrix == w->desired_matrix
+ && !window_row->enabled_p)
+ {
+ window_row = w->current_matrix->rows + window_y;
+ current_row_p = 1;
+ }
+
+ if (current_row_p)
+ {
+ /* Copy window row to frame row. */
+ bcopy (window_row->glyphs[0],
+ frame_row->glyphs[TEXT_AREA] + window_matrix->matrix_x,
+ window_matrix->matrix_w * sizeof (struct glyph));
+ }
+ else
+ {
+ xassert (window_row->enabled_p);
+
+ /* Only when a desired row has been displayed, we want
+ the corresponding frame row to be updated. */
+ frame_row->enabled_p = 1;
+
+ /* Maybe insert a vertical border between horizontally adjacent
+ windows. */
+ if (right_border_glyph)
+ {
+ struct glyph *border = window_row->glyphs[LAST_AREA] - 1;
+ SET_CHAR_GLYPH_FROM_GLYPH (*border, right_border_glyph);
+ }
+
+#if 0 /* This shouldn't be necessary. Let's check it. */
+ /* Due to hooks installed, it normally doesn't happen that
+ window rows and frame rows of the same matrix are out of
+ sync, i.e. have a different understanding of where to
+ find glyphs for the row. The following is a safety-belt
+ that doesn't cost much and makes absolutely sure that
+ window and frame matrices are in sync. */
+ if (!glyph_row_slice_p (window_row, frame_row))
+ {
+ /* Find the row in the window being a slice. There
+ should exist one from program logic. */
+ struct glyph_row *slice_row
+ = find_glyph_row_slice (window_matrix, frame_matrix, frame_y);
+ xassert (slice_row != 0);
+
+ /* Exchange glyphs between both window rows. */
+ swap_glyphs_in_rows (window_row, slice_row);
+
+ /* Exchange pointers between both rows. */
+ swap_glyph_pointers (window_row, slice_row);
+ }
+#endif
+
+ /* Window row window_y must be a slice of frame row
+ frame_y. */
+ xassert (glyph_row_slice_p (window_row, frame_row));
+
+ /* If rows are in sync, we don't have to copy glyphs because
+ frame and window share glyphs. */
+
+#if GLYPH_DEBUG
+ strcpy (w->current_matrix->method, w->desired_matrix->method);
+#endif
+ }
+
+ /* Set number of used glyphs in the frame matrix. Since we fill
+ up with spaces, and visit leaf windows from left to right it
+ can be done simply. */
+ frame_row->used[TEXT_AREA]
+ = window_matrix->matrix_x + window_matrix->matrix_w;
+
+ /* Or in other flags. */
+ frame_row->inverse_p |= window_row->inverse_p;
+
+ /* Next row. */
+ ++window_y;
+ ++frame_y;
+ }
+}
+
+
+/* Add spaces to a glyph row ROW in a window matrix.
+
+ Each row has the form:
+
+ +---------+-----------------------------+------------+
+ | left | text | right |
+ +---------+-----------------------------+------------+
+
+ Left and right marginal areas are optional. This function adds
+ spaces to areas so that there are no empty holes between areas.
+ In other words: If the right area is not empty, the text area
+ is filled up with spaces up to the right area. If the text area
+ is not empty, the left area is filled up.
+
+ To be called for frame-based redisplay, only. */
+
+static void
+fill_up_glyph_row_with_spaces (row)
+ struct glyph_row *row;
+{
+ fill_up_glyph_row_area_with_spaces (row, LEFT_MARGIN_AREA);
+ fill_up_glyph_row_area_with_spaces (row, TEXT_AREA);
+ fill_up_glyph_row_area_with_spaces (row, RIGHT_MARGIN_AREA);
+}
+
+
+/* Fill area AREA of glyph row ROW with spaces. To be called for
+ frame-based redisplay only. */
+
+static void
+fill_up_glyph_row_area_with_spaces (row, area)
+ struct glyph_row *row;
+ int area;
+{
+ if (row->glyphs[area] < row->glyphs[area + 1])
+ {
+ struct glyph *end = row->glyphs[area + 1];
+ struct glyph *text = row->glyphs[area] + row->used[area];
+
+ while (text < end)
+ *text++ = space_glyph;
+ row->used[area] = text - row->glyphs[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
+fill_up_frame_row_with_spaces (row, upto)
+ struct glyph_row *row;
+ int upto;
+{
+ int i = row->used[TEXT_AREA];
+ struct glyph *glyph = row->glyphs[TEXT_AREA];
+
+ while (i < upto)
+ glyph[i++] = space_glyph;
+
+ row->used[TEXT_AREA] = i;
+}
+
+
+\f
+/**********************************************************************
+ Mirroring operations on frame matrices in window matrices
+ **********************************************************************/
+
+/* Set frame being updated via frame-based redisplay to F. This
+ function must be called before updates to make explicit that we are
+ working on frame matrices or not. */
+
+static INLINE void
+set_frame_matrix_frame (f)
+ struct frame *f;
+{
+ frame_matrix_frame = f;
+}
+
+
+/* Make sure glyph row ROW in CURRENT_MATRIX is up to date.
+ DESIRED_MATRIX is the desired matrix corresponding to
+ CURRENT_MATRIX. The update is done by exchanging glyph pointers
+ between rows in CURRENT_MATRIX and DESIRED_MATRIX. If
+ frame_matrix_frame is non-null, this indicates that the exchange is
+ done in frame matrices, and that we have to perform analogous
+ operations in window matrices of frame_matrix_frame. */
+
+static INLINE void
+make_current (desired_matrix, current_matrix, row)
+ struct glyph_matrix *desired_matrix, *current_matrix;
+ int row;
+{
+ struct glyph_row *current_row = MATRIX_ROW (current_matrix, row);
+ struct glyph_row *desired_row = MATRIX_ROW (desired_matrix, row);
+ int mouse_face_p = current_row->mouse_face_p;
+
+ /* Do current_row = desired_row. This exchanges glyph pointers
+ between both rows, and does a structure assignment otherwise. */
+ assign_row (current_row, desired_row);
+
+ /* Enable current_row to mark it as valid. */
+ current_row->enabled_p = 1;
+ current_row->mouse_face_p = mouse_face_p;
+
+ /* If we are called on frame matrices, perform analogous operations
+ for window matrices. */
+ if (frame_matrix_frame)
+ mirror_make_current (XWINDOW (frame_matrix_frame->root_window), row);
+}
+
+
+/* W is the root of a window tree. FRAME_ROW is the index of a row in
+ W's frame which has been made current (by swapping pointers between
+ current and desired matrix). Perform analogous operations in the
+ matrices of leaf windows in the window tree rooted at W. */
+
+static void
+mirror_make_current (w, frame_row)
+ 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);
+ else
+ {
+ /* Row relative to window W. Don't use FRAME_TO_WINDOW_VPOS
+ here because the checks performed in debug mode there
+ will not allow the conversion. */
+ int row = frame_row - w->desired_matrix->matrix_y;
+
+ /* If FRAME_ROW is within W, assign the desired row to the
+ current row (exchanging glyph pointers). */
+ if (row >= 0 && row < w->desired_matrix->matrix_h)
+ {
+ struct glyph_row *current_row
+ = MATRIX_ROW (w->current_matrix, row);
+ struct glyph_row *desired_row
+ = MATRIX_ROW (w->desired_matrix, row);
+
+ if (desired_row->enabled_p)
+ assign_row (current_row, desired_row);
+ else
+ swap_glyph_pointers (desired_row, current_row);
+ current_row->enabled_p = 1;
+ }
+ }
+
+ w = NILP (w->next) ? 0 : XWINDOW (w->next);
+ }
+}
+
+
+/* Perform row dance after scrolling. We are working on the range of
+ lines UNCHANGED_AT_TOP + 1 to UNCHANGED_AT_TOP + NLINES (not
+ including) in MATRIX. COPY_FROM is a vector containing, for each
+ row I in the range 0 <= I < NLINES, the index of the original line
+ to move to I. This index is relative to the row range, i.e. 0 <=
+ index < NLINES. RETAINED_P is a vector containing zero for each
+ row 0 <= I < NLINES which is empty.
+
+ This function is called from do_scrolling and do_direct_scrolling. */
+
+void
+mirrored_line_dance (matrix, unchanged_at_top, nlines, copy_from,
+ retained_p)
+ struct glyph_matrix *matrix;
+ int unchanged_at_top, nlines;
+ int *copy_from;
+ char *retained_p;
+{
+ /* A copy of original rows. */
+ struct glyph_row *old_rows;
+
+ /* Rows to assign to. */
+ struct glyph_row *new_rows = MATRIX_ROW (matrix, unchanged_at_top);
+
+ int i;
+
+ /* Make a copy of the original rows. */
+ old_rows = (struct glyph_row *) alloca (nlines * sizeof *old_rows);
+ bcopy (new_rows, old_rows, nlines * sizeof *old_rows);
+
+ /* Assign new rows, maybe clear lines. */
+ for (i = 0; i < nlines; ++i)
+ {
+ int enabled_before_p = new_rows[i].enabled_p;
+
+ xassert (i + unchanged_at_top < matrix->nrows);
+ xassert (unchanged_at_top + copy_from[i] < matrix->nrows);
+ new_rows[i] = old_rows[copy_from[i]];
+ new_rows[i].enabled_p = enabled_before_p;
+
+ /* RETAINED_P is zero for empty lines. */
+ if (!retained_p[copy_from[i]])
+ new_rows[i].enabled_p = 0;
+ }
+
+ /* Do the same for window matrices, if MATRIX Is a frame matrix. */
+ if (frame_matrix_frame)
+ mirror_line_dance (XWINDOW (frame_matrix_frame->root_window),
+ unchanged_at_top, nlines, copy_from, retained_p);
+}
+
+
+/* Synchronize glyph pointers in the current matrix of window W with
+ the current frame matrix. W must be full-width, and be on a tty
+ frame. */
+
+static void
+sync_window_with_frame_matrix_rows (w)
+ struct window *w;
+{
+ struct frame *f = XFRAME (w->frame);
+ struct glyph_row *window_row, *window_row_end, *frame_row;
+
+ /* Preconditions: W must be a leaf window and full-width. Its frame
+ must have a frame matrix. */
+ xassert (NILP (w->hchild) && NILP (w->vchild));
+ xassert (WINDOW_FULL_WIDTH_P (w));
+ xassert (!FRAME_WINDOW_P (f));
+
+ /* If W is a full-width window, glyph pointers in W's current matrix
+ have, by definition, to be the same as glyph pointers in the
+ corresponding frame matrix. */
+ window_row = w->current_matrix->rows;
+ window_row_end = window_row + w->current_matrix->nrows;
+ frame_row = f->current_matrix->rows + XFASTINT (w->top);
+ while (window_row < window_row_end)
+ {
+ int area;
+
+ for (area = LEFT_MARGIN_AREA; area <= LAST_AREA; ++area)
+ window_row->glyphs[area] = frame_row->glyphs[area];
+
+ ++window_row, ++frame_row;
+ }
+}
+
+
+/* Return the window in the window tree rooted in W containing frame
+ row ROW. Value is null if none is found. */
+
+struct window *
+frame_row_to_window (w, row)
+ struct window *w;
+ int row;
+{
+ struct window *found = NULL;
+
+ 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);
+ else if (row >= XFASTINT (w->top)
+ && row < XFASTINT (w->top) + XFASTINT (w->height))
+ found = w;
+
+ w = NILP (w->next) ? 0 : XWINDOW (w->next);
+ }
+
+ return found;
+}
+
+
+/* Perform a line dance in the window tree rooted at W, after
+ scrolling a frame matrix in mirrored_line_dance.
+
+ We are working on the range of lines UNCHANGED_AT_TOP + 1 to
+ UNCHANGED_AT_TOP + NLINES (not including) in W's frame matrix.
+ COPY_FROM is a vector containing, for each row I in the range 0 <=
+ I < NLINES, the index of the original line to move to I. This
+ index is relative to the row range, i.e. 0 <= index < NLINES.
+ RETAINED_P is a vector containing zero for each row 0 <= I < NLINES
+ which is empty. */
+
+static void
+mirror_line_dance (w, unchanged_at_top, nlines, copy_from, retained_p)
+ struct window *w;
+ int unchanged_at_top, nlines;
+ int *copy_from;
+ char *retained_p;
+{
+ 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,
+ nlines, copy_from, retained_p);
+ else
+ {
+ /* W is a leaf window, and we are working on its current
+ matrix m. */
+ struct glyph_matrix *m = w->current_matrix;
+ int i, sync_p = 0;
+ struct glyph_row *old_rows;
+
+ /* Make a copy of the original rows of matrix m. */
+ old_rows = (struct glyph_row *) alloca (m->nrows * sizeof *old_rows);
+ bcopy (m->rows, old_rows, m->nrows * sizeof *old_rows);
+
+ for (i = 0; i < nlines; ++i)
+ {
+ /* Frame relative line assigned to. */
+ int frame_to = i + unchanged_at_top;
+
+ /* Frame relative line assigned. */
+ int frame_from = copy_from[i] + unchanged_at_top;
+
+ /* Window relative line assigned to. */
+ int window_to = frame_to - m->matrix_y;
+
+ /* Window relative line assigned. */
+ int window_from = frame_from - m->matrix_y;
+
+ /* Is assigned line inside window? */
+ int from_inside_window_p
+ = window_from >= 0 && window_from < m->matrix_h;
+
+ /* Is assigned to line inside window? */
+ int to_inside_window_p
+ = window_to >= 0 && window_to < m->matrix_h;
+
+ if (from_inside_window_p && to_inside_window_p)
+ {
+ /* Enabled setting before assignment. */
+ int enabled_before_p;
+
+ /* Do the assignment. The enabled_p flag is saved
+ over the assignment because the old redisplay did
+ that. */
+ enabled_before_p = m->rows[window_to].enabled_p;
+ m->rows[window_to] = old_rows[window_from];
+ m->rows[window_to].enabled_p = enabled_before_p;
+
+ /* If frame line is empty, window line is empty, too. */
+ if (!retained_p[copy_from[i]])
+ m->rows[window_to].enabled_p = 0;
+ }
+ else if (to_inside_window_p)
+ {
+ /* A copy between windows. This is an infrequent
+ case not worth optimizing. */
+ struct frame *f = XFRAME (w->frame);
+ struct window *root = XWINDOW (FRAME_ROOT_WINDOW (f));
+ struct window *w2;
+ struct glyph_matrix *m2;
+ int m2_from;
+
+ w2 = frame_row_to_window (root, frame_to);
+ m2 = w2->current_matrix;
+ m2_from = frame_from - m2->matrix_y;
+ copy_row_except_pointers (m->rows + window_to,
+ m2->rows + m2_from);
+
+ /* If frame line is empty, window line is empty, too. */
+ if (!retained_p[copy_from[i]])
+ m->rows[window_to].enabled_p = 0;
+ sync_p = 1;
+ }
+ else if (from_inside_window_p)
+ sync_p = 1;
+ }
+
+ /* If there was a copy between windows, make sure glyph
+ pointers are in sync with the frame matrix. */
+ if (sync_p)
+ sync_window_with_frame_matrix_rows (w);
+
+ /* Check that no pointers are lost. */
+ CHECK_MATRIX (m);
+ }
+
+ /* Next window on same level. */
+ w = NILP (w->next) ? 0 : XWINDOW (w->next);
+ }
+}
+
+
+#if GLYPH_DEBUG
+
+/* Check that window and frame matrices agree about their
+ understanding where glyphs of the rows are to find. For each
+ window in the window tree rooted at W, check that rows in the
+ matrices of leaf window agree with their frame matrices about
+ glyph pointers. */
+
+void
+check_window_matrix_pointers (w)
+ 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));
+ else
+ {
+ struct frame *f = XFRAME (w->frame);
+ check_matrix_pointers (w->desired_matrix, f->desired_matrix);
+ check_matrix_pointers (w->current_matrix, f->current_matrix);