Avoid infinite loop in display of invisible text in strings
* src/xdisp.c (handle_invisible_prop): If the next change of invisibility spec does not mean the beginning of a visible text, update the string position from which to start the search for the next invisibility change. This avoids an infinite loop when we have more than one invisibility spec that are made inactive by buffer-invisibility-spec. Simplify code. (Bug#21200) * test/redisplay-testsuite.el (test-redisplay-4): Add a test case for the situation that caused bug #21200.
This commit is contained in:
parent
0aec2aaccd
commit
701484d524
2 changed files with 25 additions and 6 deletions
18
src/xdisp.c
18
src/xdisp.c
|
@ -4187,13 +4187,13 @@ handle_invisible_prop (struct it *it)
|
|||
|
||||
if (STRINGP (it->string))
|
||||
{
|
||||
Lisp_Object end_charpos, limit, charpos;
|
||||
Lisp_Object end_charpos, limit;
|
||||
|
||||
/* Get the value of the invisible text property at the
|
||||
current position. Value will be nil if there is no such
|
||||
property. */
|
||||
charpos = make_number (IT_STRING_CHARPOS (*it));
|
||||
prop = Fget_text_property (charpos, Qinvisible, it->string);
|
||||
end_charpos = make_number (IT_STRING_CHARPOS (*it));
|
||||
prop = Fget_text_property (end_charpos, Qinvisible, it->string);
|
||||
invis = TEXT_PROP_MEANS_INVISIBLE (prop);
|
||||
|
||||
if (invis != 0 && IT_STRING_CHARPOS (*it) < it->end_charpos)
|
||||
|
@ -4211,8 +4211,12 @@ handle_invisible_prop (struct it *it)
|
|||
XSETINT (limit, len);
|
||||
do
|
||||
{
|
||||
end_charpos = Fnext_single_property_change (charpos, Qinvisible,
|
||||
it->string, limit);
|
||||
end_charpos
|
||||
= Fnext_single_property_change (end_charpos, Qinvisible,
|
||||
it->string, limit);
|
||||
/* Since LIMIT is always an integer, so should be the
|
||||
value returned by Fnext_single_property_change. */
|
||||
eassert (INTEGERP (end_charpos));
|
||||
if (INTEGERP (end_charpos))
|
||||
{
|
||||
endpos = XFASTINT (end_charpos);
|
||||
|
@ -4221,6 +4225,8 @@ handle_invisible_prop (struct it *it)
|
|||
if (invis == 2)
|
||||
display_ellipsis_p = true;
|
||||
}
|
||||
else /* Should never happen; but if it does, exit the loop. */
|
||||
endpos = len;
|
||||
}
|
||||
while (invis != 0 && endpos < len);
|
||||
|
||||
|
@ -4256,7 +4262,7 @@ handle_invisible_prop (struct it *it)
|
|||
}
|
||||
else
|
||||
{
|
||||
IT_STRING_CHARPOS (*it) = XFASTINT (end_charpos);
|
||||
IT_STRING_CHARPOS (*it) = endpos;
|
||||
compute_string_pos (&it->current.string_pos, old, it->string);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -251,6 +251,18 @@ static unsigned char x_bits[] = {0xff, 0x81, 0xbd, 0xa5, 0xa5, 0xbd, 0x81, 0xff
|
|||
(str "ABC"))
|
||||
(put-text-property 1 2 'invisible 'test-redisplay--ellipsis-invis str)
|
||||
(overlay-put ov 'display str)))
|
||||
;; Overlay string with 2 adjacent and different invisible
|
||||
;; properties. This caused an infloop before Emacs 25.
|
||||
(insert "\n Expected: ABC")
|
||||
(insert "\n Result: ")
|
||||
(let ((opoint (point)))
|
||||
(insert "ABC\n")
|
||||
(let ((ov (make-overlay (1+ opoint) (+ 2 opoint)))
|
||||
(str (concat (propertize "X"
|
||||
'invisible 'test-redisplay--simple-invis)
|
||||
(propertize "Y"
|
||||
'invisible 'test-redisplay--simple-invis2))))
|
||||
(overlay-put ov 'after-string str)))
|
||||
|
||||
(insert "\n"))
|
||||
|
||||
|
@ -264,6 +276,7 @@ static unsigned char x_bits[] = {0xff, 0x81, 0xbd, 0xa5, 0xa5, 0xbd, 0x81, 0xff
|
|||
(erase-buffer)
|
||||
(setq buffer-invisibility-spec
|
||||
'(test-redisplay--simple-invis
|
||||
test-redisplay--simple-invis2
|
||||
(test-redisplay--ellipsis-invis . t)))
|
||||
(test-redisplay-1)
|
||||
(test-redisplay-2)
|
||||
|
|
Loading…
Add table
Reference in a new issue