diff options
-rw-r--r-- | src/ChangeLog | 9 | ||||
-rw-r--r-- | src/textprop.c | 125 |
2 files changed, 75 insertions, 59 deletions
diff --git a/src/ChangeLog b/src/ChangeLog index 4f2fb4c1d53..dc9b97c3c03 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,12 @@ +2013-02-25 Eli Zaretskii <eliz@gnu.org> + + * textprop.c (Fadd_text_properties, Fremove_text_properties) + (Fremove_list_of_text_properties): Skip all of the intervals in + the region between START and END that already have resp. don't + have the requested properties, not just the first one. Add + assertions that the loop afterwards always modifies the + properties. (Bug#13743) + 2013-02-25 Stefan Monnier <monnier@iro.umontreal.ca> * callint.c (Fcall_interactively): Use the right lexical environment diff --git a/src/textprop.c b/src/textprop.c index c1f6e59bf2e..49fe427913c 100644 --- a/src/textprop.c +++ b/src/textprop.c @@ -1133,6 +1133,7 @@ Return t if any property value actually changed, nil otherwise. */) register ptrdiff_t s, len; register int modified = 0; struct gcpro gcpro1; + ptrdiff_t got; properties = validate_plist (properties); if (NILP (properties)) @@ -1152,26 +1153,25 @@ Return t if any property value actually changed, nil otherwise. */) and live buffers are always protected. */ GCPRO1 (properties); - /* If we're not starting on an interval boundary, we have to - split this interval. */ - if (i->position != s) + /* If this interval already has the properties, we can skip it. */ + if (interval_has_all_properties (properties, i)) { - /* If this interval already has the properties, we can - skip it. */ - if (interval_has_all_properties (properties, i)) - { - ptrdiff_t got = (LENGTH (i) - (s - i->position)); - if (got >= len) - RETURN_UNGCPRO (Qnil); - len -= got; - i = next_interval (i); - } - else - { - unchanged = i; - i = split_interval_right (unchanged, s - unchanged->position); - copy_properties (unchanged, i); - } + got = LENGTH (i) - (s - i->position); + do { + if (got >= len) + RETURN_UNGCPRO (Qnil); + len -= got; + i = next_interval (i); + got = LENGTH (i); + } while (interval_has_all_properties (properties, i)); + } + else if (i->position != s) + { + /* If we're not starting on an interval boundary, we have to + split this interval. */ + unchanged = i; + i = split_interval_right (unchanged, s - unchanged->position); + copy_properties (unchanged, i); } if (BUFFERP (object)) @@ -1195,7 +1195,8 @@ Return t if any property value actually changed, nil otherwise. */) signal_after_change (XINT (start), XINT (end) - XINT (start), XINT (end) - XINT (start)); - return modified ? Qt : Qnil; + eassert (modified); + return Qt; } if (LENGTH (i) == len) @@ -1426,6 +1427,7 @@ Use `set-text-properties' if you want to remove all text properties. */) register INTERVAL i, unchanged; register ptrdiff_t s, len; register int modified = 0; + ptrdiff_t got; if (NILP (object)) XSETBUFFER (object, current_buffer); @@ -1437,26 +1439,25 @@ Use `set-text-properties' if you want to remove all text properties. */) s = XINT (start); len = XINT (end) - s; - if (i->position != s) + /* If there are no properties on this entire interval, return. */ + if (! interval_has_some_properties (properties, i)) { - /* No properties on this first interval -- return if - it covers the entire region. */ - if (! interval_has_some_properties (properties, i)) - { - ptrdiff_t got = (LENGTH (i) - (s - i->position)); - if (got >= len) - return Qnil; - len -= got; - i = next_interval (i); - } - /* Split away the beginning of this interval; what we don't - want to modify. */ - else - { - unchanged = i; - i = split_interval_right (unchanged, s - unchanged->position); - copy_properties (unchanged, i); - } + got = (LENGTH (i) - (s - i->position)); + do { + if (got >= len) + return Qnil; + len -= got; + i = next_interval (i); + got = LENGTH (i); + } while (! interval_has_some_properties (properties, i)); + } + /* Split away the beginning of this interval; what we don't + want to modify. */ + else if (i->position != s) + { + unchanged = i; + i = split_interval_right (unchanged, s - unchanged->position); + copy_properties (unchanged, i); } if (BUFFERP (object)) @@ -1470,7 +1471,13 @@ Use `set-text-properties' if you want to remove all text properties. */) if (LENGTH (i) >= len) { if (! interval_has_some_properties (properties, i)) - return modified ? Qt : Qnil; + { + eassert (modified); + if (BUFFERP (object)) + signal_after_change (XINT (start), XINT (end) - XINT (start), + XINT (end) - XINT (start)); + return Qt; + } if (LENGTH (i) == len) { @@ -1512,6 +1519,7 @@ Return t if any property was actually removed, nil otherwise. */) register ptrdiff_t s, len; register int modified = 0; Lisp_Object properties; + ptrdiff_t got; properties = list_of_properties; if (NILP (object)) @@ -1524,26 +1532,25 @@ Return t if any property was actually removed, nil otherwise. */) s = XINT (start); len = XINT (end) - s; - if (i->position != s) + /* If there are no properties on the interval, return. */ + if (! interval_has_some_properties_list (properties, i)) { - /* No properties on this first interval -- return if - it covers the entire region. */ - if (! interval_has_some_properties_list (properties, i)) - { - ptrdiff_t got = (LENGTH (i) - (s - i->position)); - if (got >= len) - return Qnil; - len -= got; - i = next_interval (i); - } - /* Split away the beginning of this interval; what we don't - want to modify. */ - else - { - unchanged = i; - i = split_interval_right (unchanged, s - unchanged->position); - copy_properties (unchanged, i); - } + got = (LENGTH (i) - (s - i->position)); + do { + if (got >= len) + return Qnil; + len -= got; + i = next_interval (i); + got = LENGTH (i); + } while (! interval_has_some_properties_list (properties, i)); + } + /* Split away the beginning of this interval; what we don't + want to modify. */ + else if (i->position != s) + { + unchanged = i; + i = split_interval_right (unchanged, s - unchanged->position); + copy_properties (unchanged, i); } /* We are at the beginning of an interval, with len to scan. |