Make display strings obey buffer-invisibility-spec.

* src/xdisp.c (handle_invisible_prop): Obey TEXT_PROP_MEANS_INVISIBLE
for the string case.

* redisplay-testsuite.el (test-redisplay-4): New test.

Fixes: debbugs:3874
This commit is contained in:
Chong Yidong 2012-08-18 15:23:30 +08:00
parent 39eb03f1b0
commit a999ce26e9
4 changed files with 135 additions and 16 deletions

View file

@ -1,3 +1,8 @@
2012-08-18 Chong Yidong <cyd@gnu.org>
* xdisp.c (handle_invisible_prop): Obey TEXT_PROP_MEANS_INVISIBLE
for the string case (Bug#3874).
2012-08-18 Paul Eggert <eggert@cs.ucla.edu>
* buffer.h (BSET): Remove (Bug#12215).

View file

@ -4069,38 +4069,56 @@ static enum prop_handled
handle_invisible_prop (struct it *it)
{
enum prop_handled handled = HANDLED_NORMALLY;
int invis_p;
Lisp_Object prop;
if (STRINGP (it->string))
{
Lisp_Object prop, end_charpos, limit, charpos;
Lisp_Object end_charpos, limit, charpos;
/* 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);
invis_p = TEXT_PROP_MEANS_INVISIBLE (prop);
if (!NILP (prop)
&& IT_STRING_CHARPOS (*it) < it->end_charpos)
if (invis_p && IT_STRING_CHARPOS (*it) < it->end_charpos)
{
/* Record whether we have to display an ellipsis for the
invisible text. */
int display_ellipsis_p = (invis_p == 2);
ptrdiff_t endpos;
handled = HANDLED_RECOMPUTE_PROPS;
/* Get the position at which the next change of the
invisible text property can be found in IT->string.
Value will be nil if the property value is the same for
all the rest of IT->string. */
/* Get the position at which the next visible text can be
found in IT->string, if any. */
XSETINT (limit, SCHARS (it->string));
end_charpos = Fnext_single_property_change (charpos, Qinvisible,
it->string, limit);
do
{
end_charpos = Fnext_single_property_change (charpos, Qinvisible,
it->string, limit);
if (!NILP (end_charpos))
{
prop = Fget_text_property (end_charpos, Qinvisible, it->string);
invis_p = TEXT_PROP_MEANS_INVISIBLE (prop);
if (invis_p == 2)
display_ellipsis_p = 1;
}
}
while (!NILP (end_charpos) && invis_p);
if (display_ellipsis_p)
{
it->ellipsis_p = 1;
handled = HANDLED_RETURN;
}
/* Text at current position is invisible. The next
change in the property is at position end_charpos.
Move IT's current position to that position. */
if (INTEGERP (end_charpos)
&& (endpos = XFASTINT (end_charpos)) < XFASTINT (limit))
{
/* Text at END_CHARPOS is visible. Move IT there. */
struct text_pos old;
ptrdiff_t oldpos;
@ -4153,9 +4171,8 @@ handle_invisible_prop (struct it *it)
}
else
{
int invis_p;
ptrdiff_t newpos, next_stop, start_charpos, tem;
Lisp_Object pos, prop, overlay;
Lisp_Object pos, overlay;
/* First of all, is there invisible text at this position? */
tem = start_charpos = IT_CHARPOS (*it);
@ -6032,7 +6049,7 @@ back_to_previous_visible_line_start (struct it *it)
{
Lisp_Object prop;
prop = Fget_char_property (make_number (IT_CHARPOS (*it) - 1),
Qinvisible, it->window);
Qinvisible, it->window);
if (TEXT_PROP_MEANS_INVISIBLE (prop))
continue;
}

View file

@ -1,3 +1,7 @@
2012-08-18 Chong Yidong <cyd@gnu.org>
* redisplay-testsuite.el (test-redisplay-4): New test (Bug#3874).
2012-08-14 Dmitry Gutov <dgutov@yandex.ru>
* indent/ruby.rb: Rearrange examples, add new ones.

View file

@ -113,7 +113,7 @@
(insert "\n\n"))
(defun test-redisplay-3 ()
(insert "Test 3: Overlay with before/after strings and images:\n\n")
(insert "Test 3: Overlay with strings and images:\n\n")
(let ((img-data "#define x_width 8
#define x_height 8
static unsigned char x_bits[] = {0xff, 0x81, 0xbd, 0xa5, 0xa5, 0xbd, 0x81, 0xff };"))
@ -165,6 +165,95 @@ static unsigned char x_bits[] = {0xff, 0x81, 0xbd, 0xa5, 0xa5, 0xbd, 0x81, 0xff
(overlay-put ov2 'before-string "C")
(overlay-put ov3 'display `(image :data ,img-data :type xbm))))))
(defun test-redisplay-4 ()
(insert "Test 4: Overlay strings and invisibility:\n\n")
;; Before and after strings with non-nil `invisibility'.
(insert " Expected: ABC\n")
(insert " Result: ")
(let ((opoint (point)))
(insert "ABC\n")
(let ((ov (make-overlay (1+ opoint) (+ 2 opoint))))
(overlay-put ov 'before-string
(propertize "XX" 'invisible
'test-redisplay--simple-invis))
(overlay-put ov 'after-string
(propertize "XX" 'invisible
'test-redisplay--simple-invis))))
;; Before and after strings bogus `invisibility' property (value is
;; not listed in `buffer-invisibility-spec').
(insert "\n Expected: ABC")
(insert "\n Result: ")
(let ((opoint (point)))
(insert "B\n")
(let ((ov (make-overlay opoint (1+ opoint))))
(overlay-put ov 'before-string
(propertize "A" 'invisible 'bogus-invis-spec))
(overlay-put ov 'after-string
(propertize "C" 'invisible 'bogus-invis-spec))))
;; Before/after string with ellipsis `invisibility' property.
(insert "\n Expected: ...B...")
(insert "\n Result: ")
(let ((opoint (point)))
(insert "B\n")
(let ((ov (make-overlay opoint (1+ opoint))))
(overlay-put ov 'before-string
(propertize "A" 'invisible 'test-redisplay--ellipsis-invis))
(overlay-put ov 'after-string
(propertize "C" 'invisible 'test-redisplay--ellipsis-invis))))
;; Before/after string with partial ellipsis `invisibility' property.
(insert "\n Expected: A...ABC...C")
(insert "\n Result: ")
(let ((opoint (point)))
(insert "B\n")
(let ((ov (make-overlay opoint (1+ opoint)))
(a "AAA")
(c "CCC"))
(put-text-property 1 2 'invisible 'test-redisplay--ellipsis-invis a)
(put-text-property 1 2 'invisible 'test-redisplay--ellipsis-invis c)
(overlay-put ov 'before-string a)
(overlay-put ov 'after-string c)))
;; Display string with `invisibility' property.
(insert "\n Expected: ABC")
(insert "\n Result: ")
(let ((opoint (point)))
(insert "AYBC\n")
(let ((ov (make-overlay (1+ opoint) (+ 2 opoint))))
(overlay-put ov 'display
(propertize "XX" 'invisible
'test-redisplay--simple-invis))))
;; Display string with bogus `invisibility' property.
(insert "\n Expected: ABC")
(insert "\n Result: ")
(let ((opoint (point)))
(insert "AXC\n")
(let ((ov (make-overlay (1+ opoint) (+ 2 opoint))))
(overlay-put ov 'display
(propertize "B" 'invisible 'bogus-invis-spec))))
;; Display string with ellipsis `invisibility' property.
(insert "\n Expected: A...C")
(insert "\n Result: ")
(let ((opoint (point)))
(insert "AXC\n")
(let ((ov (make-overlay (1+ opoint) (+ 2 opoint))))
(overlay-put ov 'display
(propertize "B" 'invisible
'test-redisplay--ellipsis-invis))))
;; Display string with partial `invisibility' property.
(insert "\n Expected: A...C")
(insert "\n Result: ")
(let ((opoint (point)))
(insert "X\n")
(let ((ov (make-overlay opoint (1+ opoint)))
(str "ABC"))
(put-text-property 1 2 'invisible 'test-redisplay--ellipsis-invis str)
(overlay-put ov 'display str)))
(insert "\n"))
(defun test-redisplay ()
(interactive)
@ -173,8 +262,12 @@ static unsigned char x_bits[] = {0xff, 0x81, 0xbd, 0xa5, 0xa5, 0xbd, 0x81, 0xff
(kill-buffer buf))
(pop-to-buffer (get-buffer-create "*Redisplay Test*"))
(erase-buffer)
(setq buffer-invisibility-spec
'(test-redisplay--simple-invis
(test-redisplay--ellipsis-invis . t)))
(test-redisplay-1)
(test-redisplay-2)
(test-redisplay-3)
(test-redisplay-4)
(goto-char (point-min))))