/* Updating of data structures for redisplay.
- Copyright (C) 1985, 86, 87, 88, 93, 94, 95, 97, 98, 1999
+ Copyright (C) 1985, 86, 87, 88, 93, 94, 95, 97, 98, 1999, 2000
Free Software Foundation, Inc.
This file is part of GNU Emacs.
#include "w32term.h"
#endif /* HAVE_NTGUI */
+#ifdef macintosh
+#include "macterm.h"
+#endif /* macintosh */
+
/* Include systime.h after xterm.h to avoid double inclusion of time.h. */
#include "systime.h"
\f
/* Function prototypes. */
+static struct glyph_matrix *save_frame_matrix P_ ((struct glyph_matrix *));
+static void restore_frame_matrix P_ ((struct glyph_matrix *, struct glyph_matrix *));
+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 header_line_changed_p = 0;
int header_line_p = 0;
int left = -1, right = -1;
- int window_x, window_y, window_width, window_height;
+ int window_x, window_y, window_width = -1, window_height;
/* See if W had a top line that has disappeared now, or vice versa. */
if (w)
if (!marginal_areas_changed_p
&& !fonts_changed_p
&& !header_line_changed_p
+ && matrix->window_left_x == XFASTINT (w->left)
&& matrix->window_top_y == XFASTINT (w->top)
&& matrix->window_height == window_height
&& matrix->window_vscroll == w->vscroll
/* Number of rows to be used by MATRIX. */
matrix->nrows = dim.height;
+ xassert (matrix->nrows >= 0);
/* Mark rows in a current matrix of a window as not having valid
contents. It's important to not do this for desired matrices.
when this function runs. */
if (w && matrix == w->current_matrix)
{
+ if (window_width < 0)
+ window_width = window_box_width (w, -1);
+
/* Optimize the case that only the height has changed (C-x 2,
upper window). Invalidate all rows that are no longer part
of the window. */
if (!marginal_areas_changed_p
+ && matrix->window_left_x == XFASTINT (w->left)
&& matrix->window_top_y == XFASTINT (w->top)
- && matrix->window_width == window_width)
+ && matrix->window_width == window_box_width (w, -1))
{
i = 0;
while (matrix->rows[i].enabled_p
was last adjusted. This is used to optimize redisplay above. */
if (w)
{
+ matrix->window_left_x = XFASTINT (w->left);
matrix->window_top_y = XFASTINT (w->top);
matrix->window_height = window_height;
matrix->window_width = window_width;
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;
}
changes in the glyph_row structure, i.e. addition or removal of
structure members. */
+static struct glyph_row null_row;
+
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];
if (!must_write_spaces)
{
/* Skip from the end over trailing spaces. */
- while (end != beg && CHAR_GLYPH_SPACE_P (*end))
+ while (end > beg && CHAR_GLYPH_SPACE_P (*(end - 1)))
--end;
/* All blank line. */
}
+/* 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;
+ }
+ }
+ }
+ }
+}
+
+
+/* Return a glyph matrix that holds of copy of the glyph contents
+ of frame matrix M. */
+
+static struct glyph_matrix *
+save_frame_matrix (m)
+ struct glyph_matrix *m;
+{
+ struct glyph_matrix *copy;
+ int i;
+
+ copy = (struct glyph_matrix *) xmalloc (sizeof *copy);
+ *copy = *m;
+ copy->rows = (struct glyph_row *) xmalloc (m->nrows * sizeof (*copy->rows));
+
+ for (i = 0; i < copy->nrows; ++i)
+ {
+ struct glyph_row *from = m->rows + i;
+ struct glyph_row *to = copy->rows + i;
+ size_t nbytes = from->used[TEXT_AREA] * sizeof (struct glyph);
+ to->glyphs[TEXT_AREA] = (struct glyph *) xmalloc (nbytes);
+ bcopy (from->glyphs[TEXT_AREA], to->glyphs[TEXT_AREA], nbytes);
+ to->used[TEXT_AREA] = from->used[TEXT_AREA];
+ }
+
+ return copy;
+}
+
+
+/* Restore the glyph contents of frame matrix M from the copy COPY,
+ made by save_frame_matrix. Free memory allocated for COPY. */
+
+static void
+restore_frame_matrix (m, copy)
+ struct glyph_matrix *m, *copy;
+{
+ int i;
+
+ for (i = 0; i < copy->nrows; ++i)
+ {
+ struct glyph_row *from = copy->rows + i;
+ struct glyph_row *to = m->rows + i;
+ 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];
+ xfree (from->glyphs[TEXT_AREA]);
+ }
+
+ xfree (copy->rows);
+ xfree (copy);
+}
+
+
/* 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)
+ {
+ struct glyph_matrix *saved = save_frame_matrix (f->current_matrix);
+ adjust_glyph_matrix (NULL, f->current_matrix, 0, 0, matrix_dim);
+ restore_frame_matrix (f->current_matrix, saved);
+ fake_current_matrices (FRAME_ROOT_WINDOW (f));
+ }
+ else
+ {
+ adjust_glyph_matrix (NULL, f->current_matrix, 0, 0, matrix_dim);
+ SET_FRAME_GARBAGED (f);
+ }
}
}
|| !display_completed
/* Give up if buffer appears in two places. */
|| buffer_shared > 1
- /* Give up if w is mini-buffer and a message is being displayed there */
- || (MINI_WINDOW_P (w) && !NILP (echo_area_buffer[0]))
+ /* Give up if currently displaying a message instead of the
+ minibuffer contents. */
+ || (EQ (selected_window, minibuf_window)
+ && EQ (minibuf_window, echo_area_window))
/* Give up for hscrolled mini-buffer because display of the prompt
is handled specially there (see display_line). */
|| (MINI_WINDOW_P (w) && XFASTINT (w->hscroll))
delta += 1;
delta_bytes += it.len;
- set_iterator_to_next (&it);
+ set_iterator_to_next (&it, 1);
}
/* Give up if we hit the right edge of the window. We would have
{
if (it2.c == '\t')
return 0;
- set_iterator_to_next (&it2);
+ set_iterator_to_next (&it2, 1);
}
/* Number of new glyphs produced. */
tem = f->current_tool_bar_string;
f->current_tool_bar_string = f->desired_tool_bar_string;
f->desired_tool_bar_string = tem;
- f->n_current_tool_bar_items = f->n_desired_tool_bar_items;
-
- /* Swap tool-bar items. We swap because we want to
- reuse vectors. */
- tem = f->current_tool_bar_items;
- f->current_tool_bar_items = f->desired_tool_bar_items;
- f->desired_tool_bar_items = tem;
}
}
int paused_p;
int preempt_count = baud_rate / 2400 + 1;
extern int input_pending;
+ extern Lisp_Object do_mouse_tracking;
#if GLYPH_DEBUG
struct frame *f = XFRAME (WINDOW_FRAME (w));
extern struct frame *updating_frame;
/* If forced to complete the update, or if no input is pending, do
the update. */
- if (force_p || !input_pending)
+ if (force_p || !input_pending || !NILP (do_mouse_tracking))
{
struct glyph_row *row, *end;
struct glyph_row *mode_line_row;
struct glyph_row *header_line_row = NULL;
- int yb, changed_p = 0, mouse_face_overwritten_p = 0;
+ int yb, changed_p = 0, mouse_face_overwritten_p = 0, n_updated;
rif->update_window_begin_hook (w);
yb = window_text_bottom_y (w);
}
/* Update the rest of the lines. */
- for (; row < end && (force_p || !input_pending); ++row)
+ for (n_updated = 0; row < end && (force_p || !input_pending); ++row)
if (row->enabled_p)
{
int vpos = MATRIX_ROW_VPOS (row, desired_matrix);
detect_input_pending. If it's done too often,
scrolling large windows with repeated scroll-up
commands will too quickly pause redisplay. */
- if (!force_p && vpos % preempt_count == 0)
+ if (!force_p && ++n_updated % preempt_count == 0)
detect_input_pending ();
changed_p |= update_window_line (w, vpos,
int stop, i, x;
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;
/* If the desired row extends its face to the text area end,
make sure we write at least one glyph, so that the face
while (i < stop)
{
+ int can_skip_p = 1;
+
/* Skip over glyphs that both rows have in common. These
- don't have to be written. */
- while (i < stop
- && GLYPH_EQUAL_P (desired_glyph, current_glyph))
- {
- x += desired_glyph->pixel_width;
- ++desired_glyph, ++current_glyph, ++i;
- }
-
- /* Consider the case that the current row contains "xxx ppp
- ggg" in italic Courier font, and the desired row is "xxx
- ggg". The character `p' has lbearing, `g' has not. The
- loop above will stop in front of the first `p' in the
- current row. If we would start writing glyphs there, we
- wouldn't erase the lbearing of the `p'. The rest of the
- lbearing problem is then taken care of by x_draw_glyphs. */
- if (current_row->contains_overlapping_glyphs_p
- && i > 0
- && i < current_row->used[TEXT_AREA]
- && current_row->used[TEXT_AREA] != desired_row->used[TEXT_AREA])
+ don't have to be written. We can't skip if the last
+ current glyph overlaps the glyph to its right. For
+ example, consider a current row of `if ' with the `f' in
+ Courier bold so that it overlaps the ` ' to its right.
+ If the desired row is ` ', we would skip over the space
+ after the `if' and there would remain a pixel from the
+ `f' on the screen. */
+ if (overlapping_glyphs_p && i > 0)
{
+ struct glyph *glyph = ¤t_row->glyphs[TEXT_AREA][i - 1];
int left, right;
- rif->get_glyph_overhangs (current_glyph, XFRAME (w->frame),
+
+ rif->get_glyph_overhangs (glyph, XFRAME (w->frame),
&left, &right);
- while (left > 0 && i > 0)
+ can_skip_p = right == 0;
+ }
+
+ if (can_skip_p)
+ {
+ while (i < stop
+ && GLYPH_EQUAL_P (desired_glyph, current_glyph))
+ {
+ x += desired_glyph->pixel_width;
+ ++desired_glyph, ++current_glyph, ++i;
+ }
+
+ /* Consider the case that the current row contains "xxx
+ ppp ggg" in italic Courier font, and the desired row
+ is "xxx ggg". The character `p' has lbearing, `g'
+ has not. The loop above will stop in front of the
+ first `p' in the current row. If we would start
+ writing glyphs there, we wouldn't erase the lbearing
+ of the `p'. The rest of the lbearing problem is then
+ taken care of by x_draw_glyphs. */
+ if (overlapping_glyphs_p
+ && i > 0
+ && i < current_row->used[TEXT_AREA]
+ && (current_row->used[TEXT_AREA]
+ != desired_row->used[TEXT_AREA]))
{
- --i, --desired_glyph, --current_glyph;
- x -= desired_glyph->pixel_width;
- left -= desired_glyph->pixel_width;
+ int left, right;
+
+ rif->get_glyph_overhangs (current_glyph, XFRAME (w->frame),
+ &left, &right);
+ while (left > 0 && i > 0)
+ {
+ --i, --desired_glyph, --current_glyph;
+ x -= desired_glyph->pixel_width;
+ left -= desired_glyph->pixel_width;
+ }
}
}
int start_x = x, start_hpos = i;
struct glyph *start = desired_glyph;
int current_x = x;
-
+ int skip_first_p = !can_skip_p;
+
/* Find the next glyph that's equal again. */
while (i < stop
- && !GLYPH_EQUAL_P (desired_glyph, current_glyph)
+ && (skip_first_p
+ || !GLYPH_EQUAL_P (desired_glyph, current_glyph))
&& x == current_x)
{
x += desired_glyph->pixel_width;
current_x += current_glyph->pixel_width;
++desired_glyph, ++current_glyph, ++i;
+ skip_first_p = 0;
}
if (i == start_hpos || x != current_x)
desired_glyph = start;
break;
}
-
+
rif->cursor_to (vpos, start_hpos, desired_row->y, start_x);
rif->write_glyphs (start, i - start_hpos);
changed_p = 1;
case. */
for (j = 0; j < nruns && runs[j]->height > run->height; ++j)
;
- for (k = nruns; k >= j; --k)
+ for (k = nruns; k > j; --k)
runs[k] = runs[k - 1];
runs[j] = run;
++nruns;
int len;
{
int i;
-
+
for (i = 0; i < len; ++i)
if (!CHAR_GLYPH_SPACE_P (r[i]))
break;
struct glyph_row *current_row = MATRIX_ROW (current_matrix, vpos);
struct glyph_row *desired_row = MATRIX_ROW (desired_matrix, vpos);
int must_write_whole_line_p;
+ int write_spaces_p = must_write_spaces;
+ int colored_spaces_p = (FACE_FROM_ID (frame, DEFAULT_FACE_ID)->background
+ != FACE_TTY_DEFAULT_BG_COLOR);
+
+ if (colored_spaces_p)
+ write_spaces_p = 1;
if (desired_row->inverse_p
!= (current_row->enabled_p && current_row->inverse_p))
obody = MATRIX_ROW_GLYPH_START (current_matrix, vpos);
olen = current_row->used[TEXT_AREA];
- if (! current_row->inverse_p)
+ if (!current_row->inverse_p)
{
/* Ignore trailing spaces, if we can. */
- if (!must_write_spaces)
+ if (!write_spaces_p)
while (olen > 0 && CHAR_GLYPH_SPACE_P (obody[olen-1]))
olen--;
}
if (must_write_whole_line_p)
{
/* Ignore spaces at the end, if we can. */
- if (!must_write_spaces)
+ if (!write_spaces_p)
while (nlen > 0 && CHAR_GLYPH_SPACE_P (nbody[nlen - 1]))
--nlen;
unless for one reason or another we must write all spaces. */
if (!desired_row->inverse_p)
{
- if (!must_write_spaces)
+ if (!write_spaces_p)
while (nlen > 0 && CHAR_GLYPH_SPACE_P (nbody[nlen - 1]))
nlen--;
}
{
/* If current line is blank, skip over initial spaces, if
possible, and write the rest. */
- if (must_write_spaces || desired_row->inverse_p)
+ if (write_spaces_p || desired_row->inverse_p)
nsp = 0;
else
nsp = count_blanks (nbody, nlen);
/* Compute number of leading blanks in old and new contents. */
osp = count_blanks (obody, olen);
- nsp = desired_row->inverse_p ? 0 : count_blanks (nbody, nlen);
+ nsp = (desired_row->inverse_p || colored_spaces_p
+ ? 0
+ : count_blanks (nbody, nlen));
/* Compute number of matching chars starting with first non-blank. */
begmatch = count_match (obody + osp, obody + olen,
/* Spaces in new match implicit space past the end of old. */
/* A bug causing this to be a no-op was fixed in 18.29. */
- if (!must_write_spaces && osp + begmatch == olen)
+ if (!write_spaces_p && osp + begmatch == olen)
{
np1 = nbody + nsp;
while (np1 + begmatch < nend && CHAR_GLYPH_SPACE_P (np1[begmatch]))
}
#endif /* HAVE_NTGUI */
+#ifdef macintosh
+ if (!inhibit_window_system)
+ {
+ Vwindow_system = intern ("mac");
+ Vwindow_system_version = make_number (1);
+ adjust_frame_glyphs_initially ();
+ return;
+ }
+#endif /* macintosh */
+
/* If no window system has been specified, try to use the terminal. */
if (! isatty (0))
{