\f
/* Function prototypes. */
+static void save_or_restore_current_matrix P_ ((struct frame *, int));
+static void fake_current_matrices P_ ((Lisp_Object));
static void redraw_overlapping_rows P_ ((struct window *, int));
static void redraw_overlapped_rows P_ ((struct window *, int));
static int count_blanks P_ ((struct glyph *, int));
int, int, struct dim));
static void change_frame_size_1 P_ ((struct frame *, int, int, int, int, int));
static void swap_glyph_pointers P_ ((struct glyph_row *, struct glyph_row *));
-#ifdef GLYPH_DEBUG
+#if GLYPH_DEBUG
static int glyph_row_slice_p P_ ((struct glyph_row *, struct glyph_row *));
#endif
static void fill_up_frame_row_with_spaces P_ ((struct glyph_row *, int));
static void sync_window_with_frame_matrix_rows P_ ((struct window *));
struct window *frame_row_to_window P_ ((struct window *, int));
-
\f
/* Non-zero means don't pause redisplay for pending input. (This is
for debugging and for a future implementation of EDT-like
#define WINDOW_TO_FRAME_VPOS(W, VPOS) window_to_frame_vpos ((W), (VPOS))
#define WINDOW_TO_FRAME_HPOS(W, HPOS) window_to_frame_hpos ((W), (HPOS))
+/* One element of the ring buffer containing redisplay history
+ information. */
+
+struct redisplay_history
+{
+ char trace[512 + 100];
+};
+
+/* The size of the history buffer. */
+
+#define REDISPLAY_HISTORY_SIZE 30
+
+/* The redisplay history buffer. */
+
+static struct redisplay_history redisplay_history[REDISPLAY_HISTORY_SIZE];
+
+/* Next free entry in redisplay_history. */
+
+static int history_idx;
+
+/* A tick that's incremented each time something is added to the
+ history. */
+
+static unsigned history_tick;
+
+static void add_frame_display_history P_ ((struct frame *, int));
+static void add_window_display_history P_ ((struct window *, char *, int));
+
+
+/* Add to the redisplay history how window W has been displayed.
+ MSG is a trace containing the information how W's glyph matrix
+ has been contructed. PAUSED_P non-zero means that the update
+ has been interrupted for pending input. */
+
+static void
+add_window_display_history (w, msg, paused_p)
+ struct window *w;
+ char *msg;
+ int paused_p;
+{
+ char *buf;
+
+ if (history_idx >= REDISPLAY_HISTORY_SIZE)
+ history_idx = 0;
+ buf = redisplay_history[history_idx].trace;
+ ++history_idx;
+
+ sprintf (buf, "%d: window %p (`%s')%s\n",
+ history_tick++,
+ w,
+ ((BUFFERP (w->buffer)
+ && STRINGP (XBUFFER (w->buffer)->name))
+ ? (char *) XSTRING (XBUFFER (w->buffer)->name)->data
+ : "???"),
+ paused_p ? " ***paused***" : "");
+ strcat (buf, msg);
+}
+
+
+/* Add to the redisplay history that frame F has been displayed.
+ PAUSED_P non-zero means that the update has been interrupted for
+ pending input. */
+
+static void
+add_frame_display_history (f, paused_p)
+ struct frame *f;
+ int paused_p;
+{
+ char *buf;
+
+ if (history_idx >= REDISPLAY_HISTORY_SIZE)
+ history_idx = 0;
+ buf = redisplay_history[history_idx].trace;
+ ++history_idx;
+
+ sprintf (buf, "%d: update frame %p%s",
+ history_tick++,
+ f, paused_p ? " ***paused***" : "");
+}
+
+
+DEFUN ("dump-redisplay-history", Fdump_redisplay_history,
+ Sdump_redisplay_history, 0, 0, "",
+ "Dump redisplay history to stderr.")
+ ()
+{
+ int i;
+
+ for (i = history_idx - 1; i != history_idx; --i)
+ {
+ if (i < 0)
+ i = REDISPLAY_HISTORY_SIZE - 1;
+ fprintf (stderr, "%s\n", redisplay_history[i].trace);
+ }
+
+ return Qnil;
+}
+
+
#else /* GLYPH_DEBUG == 0 */
#define WINDOW_TO_FRAME_VPOS(W, VPOS) ((VPOS) + XFASTINT ((W)->top))
is non-zero if the glyph memory of WINDOW_ROW is part of the glyph
memory of FRAME_ROW. */
-#ifdef GLYPH_DEBUG
+#if GLYPH_DEBUG
static int
glyph_row_slice_p (window_row, frame_row)
}
+/* In the window tree with root W, build current matrices of leaf
+ windows from the frame's current matrix. */
+
+static void
+fake_current_matrices (window)
+ Lisp_Object window;
+{
+ struct window *w;
+
+ for (; !NILP (window); window = w->next)
+ {
+ w = XWINDOW (window);
+
+ if (!NILP (w->hchild))
+ fake_current_matrices (w->hchild);
+ else if (!NILP (w->vchild))
+ fake_current_matrices (w->vchild);
+ else
+ {
+ int i;
+ struct frame *f = XFRAME (w->frame);
+ struct glyph_matrix *m = w->current_matrix;
+ struct glyph_matrix *fm = f->current_matrix;
+
+ xassert (m->matrix_h == XFASTINT (w->height));
+ xassert (m->matrix_w == XFASTINT (w->width));
+
+ for (i = 0; i < m->matrix_h; ++i)
+ {
+ struct glyph_row *r = m->rows + i;
+ struct glyph_row *fr = fm->rows + i + XFASTINT (w->top);
+
+ xassert (r->glyphs[TEXT_AREA] >= fr->glyphs[TEXT_AREA]
+ && r->glyphs[LAST_AREA] <= fr->glyphs[LAST_AREA]);
+
+ r->enabled_p = fr->enabled_p;
+ if (r->enabled_p)
+ {
+ r->used[LEFT_MARGIN_AREA] = m->left_margin_glyphs;
+ r->used[RIGHT_MARGIN_AREA] = m->right_margin_glyphs;
+ r->used[TEXT_AREA] = (m->matrix_w
+ - r->used[LEFT_MARGIN_AREA]
+ - r->used[RIGHT_MARGIN_AREA]);
+ r->mode_line_p = 0;
+ r->inverse_p = fr->inverse_p;
+ }
+ }
+ }
+ }
+}
+
+
+/* Save or restore the contents of frame F's current frame matrix.
+ SAVE_P non-zero means save it. */
+
+static void
+save_or_restore_current_matrix (f, save_p)
+ struct frame *f;
+ int save_p;
+{
+ struct glyph_row *from, *to, *end;
+
+ if (save_p)
+ {
+ from = f->current_matrix->rows;
+ end = from + f->current_matrix->nrows;
+ to = f->desired_matrix->rows;
+ }
+ else
+ {
+ from = f->desired_matrix->rows;
+ end = from + f->desired_matrix->nrows;
+ to = f->current_matrix->rows;
+ }
+
+ for (; from < end; ++from, ++to)
+ {
+ size_t nbytes = from->used[TEXT_AREA] * sizeof (struct glyph);
+ bcopy (from->glyphs[TEXT_AREA], to->glyphs[TEXT_AREA], nbytes);
+ to->used[TEXT_AREA] = from->used[TEXT_AREA];
+ }
+}
+
+
/* Allocate/reallocate glyph matrices of a single frame F for
frame-based redisplay. */
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
/* 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);
+ /* Pointers to glyph memory in glyph rows are exchanged during
+ the update phase of redisplay, which means in general that a
+ frame's current matrix consists of pointers into both the
+ desired and current glyph pool of the frame. Adjusting a
+ matrix sets the frame matrix up so that pointers are all into
+ the same pool. If we want to preserve glyph contents of the
+ current matrix over a call to adjust_glyph_matrix, we must
+ make a copy of the current glyphs, and restore the current
+ matrix' contents from that copy. */
+ if (display_completed
+ && !FRAME_GARBAGED_P (f)
+ && matrix_dim.width == f->current_matrix->matrix_w
+ && matrix_dim.height == f->current_matrix->matrix_h)
+ {
+ save_or_restore_current_matrix (f, 1);
+ adjust_glyph_matrix (NULL, f->current_matrix, 0, 0, matrix_dim);
+ save_or_restore_current_matrix (f, 0);
+ fake_current_matrices (FRAME_ROOT_WINDOW (f));
+ }
+ else
+ {
+ adjust_glyph_matrix (NULL, f->current_matrix, 0, 0, matrix_dim);
+ SET_FRAME_GARBAGED (f);
+ }
}
}
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 GLYPH_DEBUG
strcpy (w->current_matrix->method, w->desired_matrix->method);
+ add_window_display_history (w, w->current_matrix->method, 0);
#endif
}
return Qnil;
update_begin (f);
- if (FRAME_MSDOS_P (f))
+ if (FRAME_MSDOS_P (f) || FRAME_W32_CONSOLE_P (f))
set_terminal_modes ();
clear_frame ();
clear_current_matrices (f);
fflush (stdout);
/* Check window matrices for lost pointers. */
- IF_DEBUG (check_window_matrix_pointers (root_window));
+#if GLYPH_DEBUG
+ check_window_matrix_pointers (root_window);
+ add_frame_display_history (f, paused_p);
+#endif
}
/* Reset flags indicating that a window should be updated. */
}
+#ifdef GLYPH_DEBUG
+
+/* Check that no row in the current matrix of window W is enabled
+ which is below what's displayed in the window. */
+
+void
+check_current_matrix_flags (w)
+ struct window *w;
+{
+ int last_seen_p = 0;
+ int i, yb = window_text_bottom_y (w);
+
+ for (i = 0; i < w->current_matrix->nrows - 1; ++i)
+ {
+ struct glyph_row *row = MATRIX_ROW (w->current_matrix, i);
+ if (!last_seen_p && MATRIX_ROW_BOTTOM_Y (row) >= yb)
+ last_seen_p = 1;
+ else if (last_seen_p && row->enabled_p)
+ abort ();
+ }
+}
+
+#endif /* GLYPH_DEBUG */
+
+
/* Update display of window W. FORCE_P non-zero means that we should
not stop when detecting pending input. */
else
paused_p = 1;
+#if GLYPH_DEBUG
+ /* check_current_matrix_flags (w); */
+ add_window_display_history (w, w->current_matrix->method, paused_p);
+#endif
+
clear_glyph_matrix (desired_matrix);
return paused_p;
struct glyph *current_glyph = current_row->glyphs[TEXT_AREA];
struct glyph *desired_glyph = desired_row->glyphs[TEXT_AREA];
int overlapping_glyphs_p = current_row->contains_overlapping_glyphs_p;
+ int desired_stop_pos = desired_row->used[TEXT_AREA];
+#if 0 /* This shouldn't be necessary. Let's check it. */
/* If the desired row extends its face to the text area end,
make sure we write at least one glyph, so that the face
extension actually takes place. */
- int desired_stop_pos = (desired_row->used[TEXT_AREA]
- - (MATRIX_ROW_EXTENDS_FACE_P (desired_row)
- ? 1 : 0));
+ if (MATRIX_ROW_EXTENDS_FACE_P (desired_row))
+ --desired_stop_pos;
+#endif
stop = min (current_row->used[TEXT_AREA], desired_stop_pos);
i = 0;
/* Maybe clear to end of line. */
if (MATRIX_ROW_EXTENDS_FACE_P (desired_row))
{
+#if 0
/* If new row extends to the end of the text area, nothing
has to be cleared, if and only if we did a write_glyphs
above. This is made sure by setting desired_stop_pos
appropriately above. */
xassert (i < desired_row->used[TEXT_AREA]);
+#endif
}
else if (MATRIX_ROW_EXTENDS_FACE_P (current_row))
{
we plan to reuse part of the display even if other parts are
disabled. */
i = first_old + 1;
- while (i < current_matrix->nrows - 1
- && MATRIX_ROW_BOTTOM_Y (MATRIX_ROW (current_matrix, i)) <= yb)
- ++i;
+ while (i < current_matrix->nrows - 1)
+ {
+ int bottom = MATRIX_ROW_BOTTOM_Y (MATRIX_ROW (current_matrix, i));
+ if (bottom <= yb)
+ ++i;
+ if (bottom >= yb)
+ break;
+ }
+
last_old = i;
/* Skip over rows equal at the bottom. */
defsubr (&Sinternal_show_cursor);
defsubr (&Sinternal_show_cursor_p);
+#if GLYPH_DEBUG
+ defsubr (&Sdump_redisplay_history);
+#endif
+
frame_and_buffer_state = Fmake_vector (make_number (20), Qlambda);
staticpro (&frame_and_buffer_state);