Avoid infinite recursion while displaying box face

* src/xdisp.c (face_before_or_after_it_pos): Fix calculation of
the previous string/buffer character position under bidi
iteration.  (Bug#21428)
This commit is contained in:
Eli Zaretskii 2015-09-21 12:35:26 +03:00
parent 18028318d8
commit e2f0dd2f49

View file

@ -4014,21 +4014,23 @@ face_before_or_after_it_pos (struct it *it, bool before_p)
/* With bidi iteration, the character before the current
in the visual order cannot be found by simple
iteration, because "reverse" reordering is not
supported. Instead, we need to use the move_it_*
family of functions. */
supported. Instead, we need to start from the string
beginning and go all the way to the current string
position, remembering the previous position. */
/* Ignore face changes before the first visible
character on this display line. */
if (it->current_x <= it->first_visible_x)
return it->face_id;
SAVE_IT (it_copy, *it, it_copy_data);
/* Implementation note: Since move_it_in_display_line
works in the iterator geometry, and thinks the first
character is always the leftmost, even in R2L lines,
we don't need to distinguish between the R2L and L2R
cases here. */
move_it_in_display_line (&it_copy, SCHARS (it_copy.string),
it_copy.current_x - 1, MOVE_TO_X);
charpos = IT_STRING_CHARPOS (it_copy);
IT_STRING_CHARPOS (it_copy) = 0;
bidi_init_it (0, 0, FRAME_WINDOW_P (it_copy.f), &it_copy.bidi_it);
while (IT_STRING_CHARPOS (it_copy) != IT_STRING_CHARPOS (*it))
{
charpos = IT_STRING_CHARPOS (it_copy);
if (charpos >= SCHARS (it->string))
break;
bidi_move_to_visually_next (&it_copy.bidi_it);
}
RESTORE_IT (it, it, it_copy_data);
}
else
@ -4108,11 +4110,15 @@ face_before_or_after_it_pos (struct it *it, bool before_p)
{
if (before_p)
{
int current_x;
/* With bidi iteration, the character before the current
in the visual order cannot be found by simple
iteration, because "reverse" reordering is not
supported. Instead, we need to use the move_it_*
family of functions. */
family of functions, and move to the previous
character starting from the beginning of the visual
line. */
/* Ignore face changes before the first visible
character on this display line. */
if (it->current_x <= it->first_visible_x)
@ -4123,8 +4129,9 @@ face_before_or_after_it_pos (struct it *it, bool before_p)
character is always the leftmost, even in R2L lines,
we don't need to distinguish between the R2L and L2R
cases here. */
move_it_in_display_line (&it_copy, ZV,
it_copy.current_x - 1, MOVE_TO_X);
current_x = it_copy.current_x;
move_it_vertically_backward (&it_copy, 0);
move_it_in_display_line (&it_copy, ZV, current_x - 1, MOVE_TO_X);
pos = it_copy.current.pos;
RESTORE_IT (it, it, it_copy_data);
}