summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEli Zaretskii <eliz@gnu.org>2012-05-13 18:35:13 +0300
committerEli Zaretskii <eliz@gnu.org>2012-05-13 18:35:13 +0300
commitac268e6786fbbb4eeb5b069b462bfb9c29272c67 (patch)
tree38ae18eff258ef77d01f70c00d6e97f0e58054f0
parent6cb820bab5c5ed552baa4deebee870ceda3738db (diff)
downloademacs-ac268e6786fbbb4eeb5b069b462bfb9c29272c67.tar.gz
Fix bug #11417 with infloop when left-fringe/right-fringe spec is used on TTY.
src/xdisp.c (handle_stop): Don't call get_overlay_strings_1 if we already have overlays loaded. (handle_single_display_spec): Before returning without displaying fringe bitmap, synchronize the bidi iterator with the main display iterator, by calling iterate_out_of_display_property. (iterate_out_of_display_property): Detect buffer iteration by testing that it->string is a Lisp string. (get_next_display_element): When the current object is exhausted, and there's something on it->stack, call set_iterator_to_next to proceed with what's on the stack, instead of returning zero. (set_iterator_to_next): If called at the end of a Lisp string, proceed to consider_string_end without incrementing string position. Don't increment display vector index past the end of the display vector.
-rw-r--r--src/ChangeLog17
-rw-r--r--src/xdisp.c69
2 files changed, 81 insertions, 5 deletions
diff --git a/src/ChangeLog b/src/ChangeLog
index 9245e81a536..7352d8e0081 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,20 @@
+2012-05-13 Eli Zaretskii <eliz@gnu.org>
+
+ * xdisp.c (handle_stop): Don't call get_overlay_strings_1 if we
+ already have overlays loaded.
+ (handle_single_display_spec): Before returning without displaying
+ fringe bitmap, synchronize the bidi iterator with the main display
+ iterator, by calling iterate_out_of_display_property.
+ (iterate_out_of_display_property): Detect buffer iteration by
+ testing that it->string is a Lisp string.
+ (get_next_display_element): When the current object is exhausted,
+ and there's something on it->stack, call set_iterator_to_next to
+ proceed with what's on the stack, instead of returning zero.
+ (set_iterator_to_next): If called at the end of a Lisp string,
+ proceed to consider_string_end without incrementing string
+ position. Don't increment display vector index past the end of
+ the display vector. (Bug#11417)
+
2012-05-11 Eli Zaretskii <eliz@gnu.org>
* xdisp.c (handle_single_display_spec): Return 1 for left-margin
diff --git a/src/xdisp.c b/src/xdisp.c
index fd26853e09b..b1e2a925bce 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -839,6 +839,7 @@ static int try_cursor_movement (Lisp_Object, struct text_pos, int *);
static int trailing_whitespace_p (EMACS_INT);
static intmax_t message_log_check_duplicate (EMACS_INT, EMACS_INT);
static void push_it (struct it *, struct text_pos *);
+static void iterate_out_of_display_property (struct it *);
static void pop_it (struct it *);
static void sync_frame_with_window_matrix_rows (struct window *);
static void select_frame_for_redisplay (Lisp_Object);
@@ -3125,7 +3126,15 @@ handle_stop (struct it *it)
overlays even if the actual buffer text is replaced. */
if (!handle_overlay_change_p
|| it->sp > 1
- || !get_overlay_strings_1 (it, 0, 0))
+ /* Don't call get_overlay_strings_1 if we already
+ have overlay strings loaded, because doing so
+ will load them again and push the iterator state
+ onto the stack one more time, which is not
+ expected by the rest of the code that processes
+ overlay strings. */
+ || (it->n_overlay_strings <= 0
+ ? !get_overlay_strings_1 (it, 0, 0)
+ : 0))
{
if (it->ellipsis_p)
setup_for_ellipsis (it, 0);
@@ -4681,7 +4690,19 @@ handle_single_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object,
if (!FRAME_WINDOW_P (it->f))
/* If we return here, POSITION has been advanced
across the text with this property. */
- return 1;
+ {
+ /* Synchronize the bidi iterator with POSITION. This is
+ needed because we are not going to push the iterator
+ on behalf of this display property, so there will be
+ no pop_it call to do this synchronization for us. */
+ if (it->bidi_p)
+ {
+ it->position = *position;
+ iterate_out_of_display_property (it);
+ *position = it->position;
+ }
+ return 1;
+ }
}
else if (!frame_window_p)
return 1;
@@ -4692,7 +4713,15 @@ handle_single_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object,
|| !(fringe_bitmap = lookup_fringe_bitmap (value)))
/* If we return here, POSITION has been advanced
across the text with this property. */
- return 1;
+ {
+ if (it && it->bidi_p)
+ {
+ it->position = *position;
+ iterate_out_of_display_property (it);
+ *position = it->position;
+ }
+ return 1;
+ }
if (it)
{
@@ -5611,7 +5640,7 @@ push_it (struct it *it, struct text_pos *position)
static void
iterate_out_of_display_property (struct it *it)
{
- int buffer_p = BUFFERP (it->object);
+ int buffer_p = !STRINGP (it->string);
EMACS_INT eob = (buffer_p ? ZV : it->end_charpos);
EMACS_INT bob = (buffer_p ? BEGV : 0);
@@ -6780,6 +6809,16 @@ get_next_display_element (struct it *it)
&& FACE_FROM_ID (it->f, face_id)->box == FACE_NO_BOX);
}
}
+ /* If we reached the end of the object we've been iterating (e.g., a
+ display string or an overlay string), and there's something on
+ IT->stack, proceed with what's on the stack. It doesn't make
+ sense to return zero if there's unprocessed stuff on the stack,
+ because otherwise that stuff will never be displayed. */
+ if (!success_p && it->sp > 0)
+ {
+ set_iterator_to_next (it, 0);
+ success_p = get_next_display_element (it);
+ }
/* Value is 0 if end of buffer or string reached. */
return success_p;
@@ -6961,7 +7000,7 @@ set_iterator_to_next (struct it *it, int reseat_p)
display vector entry (these entries may contain faces). */
it->face_id = it->saved_face_id;
- if (it->dpvec + it->current.dpvec_index == it->dpend)
+ if (it->dpvec + it->current.dpvec_index >= it->dpend)
{
int recheck_faces = it->ellipsis_p;
@@ -6999,6 +7038,26 @@ set_iterator_to_next (struct it *it, int reseat_p)
case GET_FROM_STRING:
/* Current display element is a character from a Lisp string. */
xassert (it->s == NULL && STRINGP (it->string));
+ /* Don't advance past string end. These conditions are true
+ when set_iterator_to_next is called at the end of
+ get_next_display_element, in which case the Lisp string is
+ already exhausted, and all we want is pop the iterator
+ stack. */
+ if (it->current.overlay_string_index >= 0)
+ {
+ /* This is an overlay string, so there's no padding with
+ spaces, and the number of characters in the string is
+ where the string ends. */
+ if (IT_STRING_CHARPOS (*it) >= SCHARS (it->string))
+ goto consider_string_end;
+ }
+ else
+ {
+ /* Not an overlay string. There could be padding, so test
+ against it->end_charpos . */
+ if (IT_STRING_CHARPOS (*it) >= it->end_charpos)
+ goto consider_string_end;
+ }
if (it->cmp_it.id >= 0)
{
int i;