#define CLEAR_FACE_CACHE_COUNT 500
static int clear_face_cache_count;
+/* Similarly for the image cache. */
+
+#ifdef HAVE_WINDOW_SYSTEM
+#define CLEAR_IMAGE_CACHE_COUNT 101
+static int clear_image_cache_count;
+#endif
+
/* Record the previous terminal frame we displayed. */
static struct frame *previous_terminal_frame;
static int invisible_text_between_p P_ ((struct it *, int, int));
#endif
-static int next_element_from_ellipsis P_ ((struct it *));
static void pint2str P_ ((char *, int, int));
static void pint2hrstr P_ ((char *, int, int));
static struct text_pos run_window_scroll_functions P_ ((Lisp_Object,
Lisp_Object));
static void extend_face_to_end_of_line P_ ((struct it *));
static int append_space_for_newline P_ ((struct it *, int));
-static int make_cursor_line_fully_visible P_ ((struct window *, int));
+static int cursor_row_fully_visible_p P_ ((struct window *, int, int));
static int try_scrolling P_ ((Lisp_Object, int, EMACS_INT, EMACS_INT, int, int));
static int try_cursor_movement P_ ((Lisp_Object, struct text_pos, int *));
static int trailing_whitespace_p P_ ((int));
static void back_to_previous_visible_line_start P_ ((struct it *));
void reseat_at_previous_visible_line_start P_ ((struct it *));
static void reseat_at_next_visible_line_start P_ ((struct it *, int));
+static int next_element_from_ellipsis P_ ((struct it *));
static int next_element_from_display_vector P_ ((struct it *));
static int next_element_from_string P_ ((struct it *));
static int next_element_from_c_string P_ ((struct it *));
}
start_display (&it, w, top);
- move_it_to (&it, charpos, 0, it.last_visible_y, -1,
- MOVE_TO_POS | MOVE_TO_X | MOVE_TO_Y);
+ move_it_to (&it, charpos, -1, it.last_visible_y, -1,
+ MOVE_TO_POS | MOVE_TO_Y);
/* Note that we may overshoot because of invisible text. */
if (IT_CHARPOS (it) >= charpos)
}
}
}
- else if (it.current_y + it.max_ascent + it.max_descent > it.last_visible_y)
+ else
{
struct it it2;
it2 = it;
- move_it_by_lines (&it, 1, 0);
+ if (IT_CHARPOS (it) < ZV && FETCH_BYTE (IT_BYTEPOS (it)) != '\n')
+ move_it_by_lines (&it, 1, 0);
if (charpos < IT_CHARPOS (it))
{
visible_p = 1;
*y = it2.current_y + it2.max_ascent - it2.ascent;
if (rtop)
{
- *rtop = 0;
- *rbot = max (0, (it2.current_y + it2.max_ascent + it2.max_descent) - it.last_visible_y);
+ *rtop = max (0, -it2.current_y);
+ *rbot = max (0, ((it2.current_y + it2.max_ascent + it2.max_descent)
+ - it.last_visible_y));
}
}
}
check_it (it)
struct it *it;
{
- if (it->method == next_element_from_string)
+ if (it->method == GET_FROM_STRING)
{
xassert (STRINGP (it->string));
xassert (IT_STRING_CHARPOS (*it) >= 0);
else
{
xassert (IT_STRING_CHARPOS (*it) < 0);
- if (it->method == next_element_from_buffer)
+ if (it->method == GET_FROM_BUFFER)
{
/* Check that character and byte positions agree. */
xassert (IT_CHARPOS (*it) == BYTE_TO_CHAR (IT_BYTEPOS (*it)));
after-string. */
init_iterator (it, w, charpos, bytepos, NULL, DEFAULT_FACE_ID);
- for (i = 0; i < it->n_overlay_strings; ++i)
+ /* This only scans the current chunk -- it should scan all chunks.
+ However, OVERLAY_STRING_CHUNK_SIZE has been increased from 3 in 21.1
+ to 16 in 22.1 to make this a lesser problem. */
+ for (i = 0; i < it->n_overlay_strings && i < OVERLAY_STRING_CHUNK_SIZE; ++i)
{
const char *s = SDATA (it->overlay_strings[i]);
const char *e = s + SBYTES (it->overlay_strings[i]);
property for an image, the iterator will be set up for that
image, and we have to undo that setup first before we can
correct the overlay string index. */
- if (it->method == next_element_from_image)
+ if (it->method == GET_FROM_IMAGE)
pop_it (it);
/* We already have the first chunk of overlay strings in
it->string = it->overlay_strings[relative_index];
xassert (STRINGP (it->string));
it->current.string_pos = pos->string_pos;
- it->method = next_element_from_string;
+ it->method = GET_FROM_STRING;
}
#if 0 /* This is bogus because POS not having an overlay string
while (it->sp)
pop_it (it);
it->current.overlay_string_index = -1;
- it->method = next_element_from_buffer;
+ it->method = GET_FROM_BUFFER;
if (CHARPOS (pos->pos) == ZV)
it->overlay_strings_at_end_processed_p = 1;
}
{
/* Don't check for overlay strings below when set to deliver
characters from a display vector. */
- if (it->method == next_element_from_display_vector)
+ if (it->method == GET_FROM_DISPLAY_VECTOR)
handle_overlay_change_p = 0;
/* Handle overlay changes. */
/* Remember the current face id in case glyphs specify faces.
IT's face is restored in set_iterator_to_next. */
it->saved_face_id = it->face_id;
- it->method = next_element_from_display_vector;
+ it->method = GET_FROM_DISPLAY_VECTOR;
it->ellipsis_p = 1;
}
it->image_id = -1; /* no image */
it->position = start_pos;
it->object = NILP (object) ? it->w->buffer : object;
- it->method = next_element_from_image;
+ it->method = GET_FROM_IMAGE;
it->face_id = face_id;
/* Say that we haven't consumed the characters with
it->current.overlay_string_index = -1;
IT_STRING_CHARPOS (*it) = IT_STRING_BYTEPOS (*it) = 0;
it->end_charpos = it->string_nchars = SCHARS (it->string);
- it->method = next_element_from_string;
+ it->method = GET_FROM_STRING;
it->stop_charpos = 0;
it->string_from_display_prop_p = 1;
/* Say that we haven't consumed the characters with
}
else if (CONSP (value) && EQ (XCAR (value), Qspace))
{
- it->method = next_element_from_stretch;
+ it->method = GET_FROM_STRETCH;
it->object = value;
it->current.pos = it->position = start_pos;
}
it->image_id = lookup_image (it->f, value);
it->position = start_pos;
it->object = NILP (object) ? it->w->buffer : object;
- it->method = next_element_from_image;
+ it->method = GET_FROM_IMAGE;
/* Say that we haven't consumed the characters with
`display' property yet. The call to pop_it in
if (id >= 0)
{
- it->method = next_element_from_composition;
+ it->method = GET_FROM_COMPOSITION;
it->cmp_id = id;
it->cmp_len = COMPOSITION_LENGTH (prop);
/* For a terminal, draw only the first character of the
it->current.overlay_string_index = -1;
SET_TEXT_POS (it->current.string_pos, -1, -1);
it->n_overlay_strings = 0;
- it->method = next_element_from_buffer;
+ it->method = GET_FROM_BUFFER;
/* If we're at the end of the buffer, record that we have
processed the overlay strings there already, so that
it->string = it->overlay_strings[i];
it->multibyte_p = STRING_MULTIBYTE (it->string);
SET_TEXT_POS (it->current.string_pos, 0, 0);
- it->method = next_element_from_string;
+ it->method = GET_FROM_STRING;
it->stop_charpos = 0;
}
xassert (STRINGP (it->string));
it->end_charpos = SCHARS (it->string);
it->multibyte_p = STRING_MULTIBYTE (it->string);
- it->method = next_element_from_string;
+ it->method = GET_FROM_STRING;
}
else
{
it->string = Qnil;
it->current.overlay_string_index = -1;
- it->method = next_element_from_buffer;
+ it->method = GET_FROM_BUFFER;
}
CHECK_IT (it);
/* If newline has a display property that replaces the newline with something
else (image or text), find start of overlay or interval and continue search
from that point. */
- {
- struct it it2 = *it;
- int pos = IT_CHARPOS (*it);
- int beg, end;
- Lisp_Object val, overlay;
-
- it2.sp = 0;
- if (handle_display_prop (&it2) == HANDLED_RETURN
- && !NILP (val = get_char_property_and_overlay
- (make_number (pos), Qdisplay, Qnil, &overlay))
- && (OVERLAYP (overlay)
- ? (beg = OVERLAY_POSITION (OVERLAY_START (overlay)))
- : get_property_and_range (pos, Qdisplay, &val, &beg, &end, Qnil)))
- {
- if (beg < BEGV)
- beg = BEGV;
- IT_CHARPOS (*it) = beg;
- IT_BYTEPOS (*it) = buf_charpos_to_bytepos (current_buffer, beg);
- continue;
- }
- }
+ if (IT_CHARPOS (*it) > BEGV)
+ {
+ struct it it2 = *it;
+ int pos;
+ int beg, end;
+ Lisp_Object val, overlay;
+
+ pos = --IT_CHARPOS (it2);
+ --IT_BYTEPOS (it2);
+ it2.sp = 0;
+ if (handle_display_prop (&it2) == HANDLED_RETURN
+ && !NILP (val = get_char_property_and_overlay
+ (make_number (pos), Qdisplay, Qnil, &overlay))
+ && (OVERLAYP (overlay)
+ ? (beg = OVERLAY_POSITION (OVERLAY_START (overlay)))
+ : get_property_and_range (pos, Qdisplay, &val, &beg, &end, Qnil)))
+ {
+ if (beg < BEGV)
+ beg = BEGV;
+ IT_CHARPOS (*it) = beg;
+ IT_BYTEPOS (*it) = buf_charpos_to_bytepos (current_buffer, beg);
+ continue;
+ }
+ }
+
break;
}
IT_STRING_CHARPOS (*it) = -1;
IT_STRING_BYTEPOS (*it) = -1;
it->string = Qnil;
- it->method = next_element_from_buffer;
+ it->method = GET_FROM_BUFFER;
/* RMS: I added this to fix a bug in move_it_vertically_backward
where it->area continued to relate to the starting point
for the backward motion. Bug report from
it->string = string;
it->s = NULL;
it->end_charpos = it->string_nchars = SCHARS (string);
- it->method = next_element_from_string;
+ it->method = GET_FROM_STRING;
it->current.string_pos = string_pos (charpos, string);
}
else
it->end_charpos = it->string_nchars = strlen (s);
}
- it->method = next_element_from_c_string;
+ it->method = GET_FROM_C_STRING;
}
/* PRECISION > 0 means don't return more than PRECISION characters
Iteration
***********************************************************************/
+/* Map enum it_method value to corresponding next_element_from_* function. */
+
+static int (* get_next_element[NUM_IT_METHODS]) P_ ((struct it *it)) =
+{
+ next_element_from_buffer,
+ next_element_from_display_vector,
+ next_element_from_composition,
+ next_element_from_string,
+ next_element_from_c_string,
+ next_element_from_image,
+ next_element_from_stretch
+};
+
+
/* Load IT's display element fields with information about the next
display element from the current position of IT. Value is zero if
end of buffer (or C string) is reached. */
int success_p;
get_next:
- success_p = (*it->method) (it);
+ success_p = (*get_next_element[it->method]) (it);
if (it->what == IT_CHARACTER)
{
it->current.dpvec_index = 0;
it->dpvec_face_id = -1;
it->saved_face_id = it->face_id;
- it->method = next_element_from_display_vector;
+ it->method = GET_FROM_DISPLAY_VECTOR;
it->ellipsis_p = 0;
}
else
else if ((it->c < ' '
&& (it->area != TEXT_AREA
/* In mode line, treat \n like other crl chars. */
- || (it->c != '\n'
+ || (it->c != '\t'
&& it->glyph_row && it->glyph_row->mode_line_p)
|| (it->c != '\n' && it->c != '\t')))
|| (it->multibyte_p
display. Then, set IT->dpvec to these glyphs. */
GLYPH g;
int ctl_len;
- int face_id, lface_id;
+ int face_id, lface_id = 0 ;
GLYPH escape_glyph;
if (it->c < 128 && it->ctl_arrow_p)
{
+ g = '^'; /* default glyph for Control */
/* Set IT->ctl_chars[0] to the glyph for `^'. */
if (it->dp
&& INTEGERP (DISP_CTRL_GLYPH (it->dp))
{
g = XINT (DISP_CTRL_GLYPH (it->dp));
lface_id = FAST_GLYPH_FACE (g);
- if (lface_id)
- {
- g = FAST_GLYPH_CHAR (g);
- face_id = merge_faces (it->f, Qt, lface_id,
- it->face_id);
- }
+ }
+ if (lface_id)
+ {
+ g = FAST_GLYPH_CHAR (g);
+ face_id = merge_faces (it->f, Qt, lface_id,
+ it->face_id);
}
else
{
/* Merge the escape-glyph face into the current face. */
face_id = merge_faces (it->f, Qescape_glyph, 0,
it->face_id);
- g = '^';
}
XSETINT (it->ctl_chars[0], g);
goto display_control;
}
+ escape_glyph = '\\'; /* default for Octal display */
if (it->dp
&& INTEGERP (DISP_ESCAPE_GLYPH (it->dp))
&& GLYPH_CHAR_VALID_P (XFASTINT (DISP_ESCAPE_GLYPH (it->dp))))
{
escape_glyph = XFASTINT (DISP_ESCAPE_GLYPH (it->dp));
lface_id = FAST_GLYPH_FACE (escape_glyph);
- if (lface_id)
- {
- escape_glyph = FAST_GLYPH_CHAR (escape_glyph);
- face_id = merge_faces (it->f, Qt, lface_id,
- it->face_id);
- }
+ }
+ if (lface_id)
+ {
+ escape_glyph = FAST_GLYPH_CHAR (escape_glyph);
+ face_id = merge_faces (it->f, Qt, lface_id,
+ it->face_id);
}
else
{
/* Merge the escape-glyph face into the current face. */
face_id = merge_faces (it->f, Qescape_glyph, 0,
it->face_id);
- escape_glyph = '\\';
}
if (it->c == 0x8a0 || it->c == 0x8ad)
it->current.dpvec_index = 0;
it->dpvec_face_id = face_id;
it->saved_face_id = it->face_id;
- it->method = next_element_from_display_vector;
+ it->method = GET_FROM_DISPLAY_VECTOR;
it->ellipsis_p = 0;
goto get_next;
}
moving the iterator to a new position might set them. */
it->start_of_box_run_p = it->end_of_box_run_p = 0;
- if (it->method == next_element_from_buffer)
+ switch (it->method)
{
+ case GET_FROM_BUFFER:
/* The current display element of IT is a character from
current_buffer. Advance in the buffer, and maybe skip over
invisible lines that are so because of selective display. */
IT_CHARPOS (*it) += 1;
xassert (IT_BYTEPOS (*it) == CHAR_TO_BYTE (IT_CHARPOS (*it)));
}
- }
- else if (it->method == next_element_from_composition)
- {
- xassert (it->cmp_id >= 0 && it ->cmp_id < n_compositions);
+ break;
+
+ case GET_FROM_COMPOSITION:
+ xassert (it->cmp_id >= 0 && it->cmp_id < n_compositions);
if (STRINGP (it->string))
{
IT_STRING_BYTEPOS (*it) += it->len;
IT_STRING_CHARPOS (*it) += it->cmp_len;
- it->method = next_element_from_string;
+ it->method = GET_FROM_STRING;
goto consider_string_end;
}
else
{
IT_BYTEPOS (*it) += it->len;
IT_CHARPOS (*it) += it->cmp_len;
- it->method = next_element_from_buffer;
+ it->method = GET_FROM_BUFFER;
}
- }
- else if (it->method == next_element_from_c_string)
- {
+ break;
+
+ case GET_FROM_C_STRING:
/* Current display element of IT is from a C string. */
IT_BYTEPOS (*it) += it->len;
IT_CHARPOS (*it) += 1;
- }
- else if (it->method == next_element_from_display_vector)
- {
+ break;
+
+ case GET_FROM_DISPLAY_VECTOR:
/* Current display element of IT is from a display table entry.
Advance in the display table definition. Reset it to null if
end reached, and continue with characters from buffers/
if (it->dpvec + it->current.dpvec_index == it->dpend)
{
if (it->s)
- it->method = next_element_from_c_string;
+ it->method = GET_FROM_C_STRING;
else if (STRINGP (it->string))
- it->method = next_element_from_string;
+ it->method = GET_FROM_STRING;
else
- it->method = next_element_from_buffer;
+ it->method = GET_FROM_BUFFER;
it->dpvec = NULL;
it->current.dpvec_index = -1;
/* Recheck faces after display vector */
it->stop_charpos = IT_CHARPOS (*it);
}
- }
- else if (it->method == next_element_from_string)
- {
+ break;
+
+ case GET_FROM_STRING:
/* Current display element is a character from a Lisp string. */
xassert (it->s == NULL && STRINGP (it->string));
IT_STRING_BYTEPOS (*it) += it->len;
&& it->sp > 0)
{
pop_it (it);
- if (!STRINGP (it->string))
- it->method = next_element_from_buffer;
- else
+ if (STRINGP (it->string))
goto consider_string_end;
+ it->method = GET_FROM_BUFFER;
}
}
- }
- else if (it->method == next_element_from_image
- || it->method == next_element_from_stretch)
- {
+ break;
+
+ case GET_FROM_IMAGE:
+ case GET_FROM_STRETCH:
/* The position etc with which we have to proceed are on
the stack. The position may be at the end of a string,
if the `display' property takes up the whole string. */
+ xassert (it->sp > 0);
pop_it (it);
it->image_id = 0;
if (STRINGP (it->string))
{
- it->method = next_element_from_string;
+ it->method = GET_FROM_STRING;
goto consider_string_end;
}
- else
- it->method = next_element_from_buffer;
+ it->method = GET_FROM_BUFFER;
+ break;
+
+ default:
+ /* There are no other methods defined, so this should be a bug. */
+ abort ();
}
- else
- /* There are no other methods defined, so this should be a bug. */
- abort ();
- xassert (it->method != next_element_from_string
+ xassert (it->method != GET_FROM_STRING
|| (STRINGP (it->string)
&& IT_STRING_CHARPOS (*it) >= 0));
}
was in IT->saved_face_id, and signal that it's there by
setting face_before_selective_p. */
it->saved_face_id = it->face_id;
- it->method = next_element_from_buffer;
+ it->method = GET_FROM_BUFFER;
reseat_at_next_visible_line_start (it, 1);
it->face_before_selective_p = 1;
}
saved_glyph_row = it->glyph_row;
it->glyph_row = NULL;
-#define BUFFER_POS_REACHED_P() \
- ((op & MOVE_TO_POS) != 0 \
- && BUFFERP (it->object) \
- && IT_CHARPOS (*it) >= to_charpos \
- && it->method == next_element_from_buffer)
+#define BUFFER_POS_REACHED_P() \
+ ((op & MOVE_TO_POS) != 0 \
+ && BUFFERP (it->object) \
+ && IT_CHARPOS (*it) >= to_charpos \
+ && (it->method == GET_FROM_BUFFER \
+ || (it->method == GET_FROM_DISPLAY_VECTOR \
+ && it->dpvec + it->current.dpvec_index + 1 >= it->dpend)))
+
while (1)
{
value of nlines is > 0 if continuation lines were involved. */
if (nlines > 0)
move_it_by_lines (it, nlines, 1);
+#if 0
+ /* I think this assert is bogus if buffer contains
+ invisible text or images. KFS. */
xassert (IT_CHARPOS (*it) <= start_pos);
+#endif
}
else
{
a line height of 13 pixels each, recentering with point
on the bottom line will try to move -39/2 = 19 pixels
backward. Try to avoid moving into the first line. */
- && it->current_y - target_y > line_height * 2 / 3
+ && (it->current_y - target_y
+ > min (window_box_height (it->w), line_height * 2 / 3))
&& IT_CHARPOS (*it) > BEGV)
{
TRACE_MOVE ((stderr, " not far enough -> move_vert %d\n",
while (target_y >= line_bottom_y (it) && IT_CHARPOS (*it) < ZV);
}
+#if 0
+ /* I think this assert is bogus if buffer contains
+ invisible text or images. KFS. */
xassert (IT_CHARPOS (*it) >= BEGV);
+#endif
}
}
}
in_display_vector_p (it)
struct it *it;
{
- return (it->method == next_element_from_display_vector
+ return (it->method == GET_FROM_DISPLAY_VECTOR
&& it->current.dpvec_index > 0
&& it->dpvec + it->current.dpvec_index != it->dpend);
}
CHARPOS (this_line_start_pos) = 0;
consider_all_windows_p |= buffer_shared > 1;
++clear_face_cache_count;
-
+#ifdef HAVE_WINDOW_SYSTEM
+ ++clear_image_cache_count;
+#endif
/* Build desired matrices, and update the display. If
consider_all_windows_p is non-zero, do it for all windows on all
struct frame **updated
= (struct frame **) alloca (size * sizeof *updated);
- /* Clear the face cache eventually. */
- if (clear_face_cache_count > CLEAR_FACE_CACHE_COUNT)
- {
- clear_face_cache (0);
- clear_face_cache_count = 0;
- }
-
/* Recompute # windows showing selected buffer. This will be
incremented each time such a window is displayed. */
buffer_shared = 0;
variables. */
select_frame_for_redisplay (frame);
-#ifdef HAVE_WINDOW_SYSTEM
- if (clear_face_cache_count % 50 == 0
- && FRAME_WINDOW_P (f))
- clear_image_cache (f, 0);
-#endif /* HAVE_WINDOW_SYSTEM */
-
/* Mark all the scroll bars to be removed; we'll redeem
the ones we want when we redisplay their windows. */
if (condemn_scroll_bars_hook)
if (windows_or_buffers_changed && !pause)
goto retry;
+ /* Clear the face cache eventually. */
+ if (consider_all_windows_p)
+ {
+ if (clear_face_cache_count > CLEAR_FACE_CACHE_COUNT)
+ {
+ clear_face_cache (0);
+ clear_face_cache_count = 0;
+ }
+#ifdef HAVE_WINDOW_SYSTEM
+ if (clear_image_cache_count > CLEAR_IMAGE_CACHE_COUNT)
+ {
+ Lisp_Object tail, frame;
+ FOR_EACH_FRAME (tail, frame)
+ {
+ struct frame *f = XFRAME (frame);
+ if (FRAME_WINDOW_P (f))
+ clear_image_cache (f, 0);
+ }
+ clear_image_cache_count = 0;
+ }
+#endif /* HAVE_WINDOW_SYSTEM */
+ }
+
end_of_redisplay:
unbind_to (count, Qnil);
RESUME_POLLING;
as if point had gone off the screen. */
static int
-make_cursor_line_fully_visible (w, force_p)
+cursor_row_fully_visible_p (w, force_p, current_matrix_p)
struct window *w;
int force_p;
{
if (w->cursor.vpos < 0)
return 1;
- matrix = w->desired_matrix;
+ matrix = current_matrix_p ? w->current_matrix : w->desired_matrix;
row = MATRIX_ROW (matrix, w->cursor.vpos);
/* If the cursor row is not partially visible, there's nothing to do. */
/* If cursor ends up on a partially visible line,
treat that as being off the bottom of the screen. */
- if (! make_cursor_line_fully_visible (w, extra_scroll_margin_lines <= 1))
+ if (! cursor_row_fully_visible_p (w, extra_scroll_margin_lines <= 1, 0))
{
clear_glyph_matrix (w->desired_matrix);
++extra_scroll_margin_lines;
&& CHARPOS (startp) != BEGV)
scroll_p = 1;
}
+ else
+ {
+ /* Cursor did not move. So don't scroll even if cursor line
+ is partially visible, as it was so before. */
+ rc = CURSOR_MOVEMENT_SUCCESS;
+ }
if (PT < MATRIX_ROW_START_CHARPOS (row)
|| PT > MATRIX_ROW_END_CHARPOS (row))
/* if PT is not in the glyph row, give up. */
rc = CURSOR_MOVEMENT_MUST_SCROLL;
}
- else if (MATRIX_ROW_PARTIALLY_VISIBLE_P (w, row)
+ else if (rc != CURSOR_MOVEMENT_SUCCESS
+ && MATRIX_ROW_PARTIALLY_VISIBLE_P (w, row)
&& make_cursor_line_fully_visible_p)
{
if (PT == MATRIX_ROW_END_CHARPOS (row)
else
{
set_cursor_from_row (w, row, w->current_matrix, 0, 0, 0, 0);
- if (!make_cursor_line_fully_visible (w, 0))
+ if (!cursor_row_fully_visible_p (w, 0, 1))
rc = CURSOR_MOVEMENT_MUST_SCROLL;
else
rc = CURSOR_MOVEMENT_SUCCESS;
int temp_scroll_step = 0;
int count = SPECPDL_INDEX ();
int rc;
- int centering_position;
+ int centering_position = -1;
int last_line_misfit = 0;
SET_TEXT_POS (lpoint, PT, PT_BYTE);
new_vpos = window_box_height (w) / 2;
}
- if (!make_cursor_line_fully_visible (w, 0))
+ if (!cursor_row_fully_visible_p (w, 0, 0))
{
/* Point does appear, but on a line partly visible at end of window.
Move it back to a fully-visible line. */
/* Forget any recorded base line for line number display. */
w->base_line_number = Qnil;
- if (!make_cursor_line_fully_visible (w, 1))
+ if (!cursor_row_fully_visible_p (w, 1, 0))
{
clear_glyph_matrix (w->desired_matrix);
last_line_misfit = 1;
/* Finally, just choose place to start which centers point */
recenter:
- centering_position = window_box_height (w) / 2;
-
- point_at_top:
- /* Jump here with centering_position already set to 0. */
+ if (centering_position < 0)
+ centering_position = window_box_height (w) / 2;
#if GLYPH_DEBUG
debug_method_add (w, "recenter");
{
init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID);
move_it_vertically_backward (&it, 0);
+#if 0
+ /* I think this assert is bogus if buffer contains
+ invisible text or images. KFS. */
xassert (IT_CHARPOS (it) <= PT);
+#endif
it.current_y = 0;
}
set_cursor_from_row (w, row, w->current_matrix, 0, 0, 0, 0);
}
- if (!make_cursor_line_fully_visible (w, centering_position > 0))
+ if (!cursor_row_fully_visible_p (w, 0, 0))
{
/* If vscroll is enabled, disable it and try again. */
if (w->vscroll)
visible, if it can be done. */
if (centering_position == 0)
goto done;
+
clear_glyph_matrix (w->desired_matrix);
centering_position = 0;
- goto point_at_top;
+ goto recenter;
}
done:
starts at a minimum position >= last_unchanged_pos_old. */
for (; row > first_text_row; --row)
{
+ /* This used to abort, but it can happen.
+ It is ok to just stop the search instead here. KFS. */
if (!row->enabled_p || !MATRIX_ROW_DISPLAYS_TEXT_P (row))
- abort ();
+ break;
if (MATRIX_ROW_START_CHARPOS (row) >= last_unchanged_pos_old)
row_found = row;
/* Record whether this row ends inside an ellipsis. */
row->ends_in_ellipsis_p
- = (it->method == next_element_from_display_vector
+ = (it->method == GET_FROM_DISPLAY_VECTOR
&& it->ellipsis_p);
/* Save fringe bitmaps in this row. */
if (area != TEXT_AREA)
return;
- row = w->current_matrix->rows + w->phys_cursor.vpos;
- if (!row->displays_text_p)
+ if (w->phys_cursor.vpos < 0
+ || w->phys_cursor.vpos >= w->current_matrix->nrows
+ || (row = w->current_matrix->rows + w->phys_cursor.vpos,
+ !(row->enabled_p && row->displays_text_p)))
return;
if (row->cursor_in_fringe_p)
/* If whole rows or last part of a row came from a display overlay,
row_containing_pos will skip over such rows because their end pos
- equals the start pos of the overlay or interval. Backtrack if we
- have a STOP object and previous row's end glyph came from STOP. */
+ equals the start pos of the overlay or interval.
+
+ Move back if we have a STOP object and previous row's
+ end glyph came from STOP. */
if (!NILP (stop))
{
- struct glyph_row *prev = row-1;
+ struct glyph_row *prev;
while ((prev = row - 1, prev >= first)
&& MATRIX_ROW_END_CHARPOS (prev) == charpos
&& prev->used[TEXT_AREA] > 0)
{
- end = prev->glyphs[TEXT_AREA];
- glyph = end + prev->used[TEXT_AREA];
- while (--glyph >= end
+ struct glyph *beg = prev->glyphs[TEXT_AREA];
+ glyph = beg + prev->used[TEXT_AREA];
+ while (--glyph >= beg
&& INTEGERP (glyph->object));
- if (glyph >= end
- && !EQ (stop, glyph->object))
+ if (glyph < beg
+ || !EQ (stop, glyph->object))
break;
row = prev;
}
|| (r.y >= y0 && r.y < y1)
|| (r.y + r.height > y0 && r.y + r.height < y1))
{
- if (row->overlapping_p)
+ /* A header line may be overlapping, but there is no need
+ to fix overlapping areas for them. KFS 2005-02-12 */
+ if (row->overlapping_p && !row->mode_line_p)
{
if (first_overlapping_row == NULL)
first_overlapping_row = row;
message_truncate_lines = 0;
DEFVAR_LISP ("menu-bar-update-hook", &Vmenu_bar_update_hook,
- doc: /* Normal hook run for clicks on menu bar, before displaying a submenu.
-Can be used to update submenus whose contents should vary. */);
+ doc: /* Normal hook run to update the menu bar definitions.
+Redisplay runs this hook before it redisplays the menu bar.
+This is used to update submenus such as Buffers,
+whose contents depend on various data. */);
Vmenu_bar_update_hook = Qnil;
DEFVAR_BOOL ("inhibit-menubar-update", &inhibit_menubar_update,