+ modified += remove_properties (properties, Qnil, i, object);
+ i = next_interval (i);
+ }
+}
+
+DEFUN ("remove-list-of-text-properties", Fremove_list_of_text_properties,
+ Sremove_list_of_text_properties, 3, 4, 0,
+ doc: /* Remove some properties from text from START to END.
+The third argument LIST-OF-PROPERTIES is a list of property names to remove.
+If the optional fourth argument OBJECT is a buffer (or nil, which means
+the current buffer), START and END are buffer positions (integers or
+markers). If OBJECT is a string, START and END are 0-based indices into it.
+Return t if any property was actually removed, nil otherwise. */)
+ (start, end, list_of_properties, object)
+ Lisp_Object start, end, list_of_properties, object;
+{
+ register INTERVAL i, unchanged;
+ register int s, len, modified = 0;
+ Lisp_Object properties;
+ properties = list_of_properties;
+
+ if (NILP (object))
+ XSETBUFFER (object, current_buffer);
+
+ i = validate_interval_range (object, &start, &end, soft);
+ if (NULL_INTERVAL_P (i))
+ return Qnil;
+
+ s = XINT (start);
+ len = XINT (end) - s;
+
+ if (i->position != s)
+ {
+ /* No properties on this first interval -- return if
+ it covers the entire region. */
+ if (! interval_has_some_properties_list (properties, i))
+ {
+ int 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);
+ }
+ }
+
+ /* We are at the beginning of an interval, with len to scan.
+ The flag `modified' records if changes have been made.
+ When object is a buffer, we must call modify_region before changes are
+ made and signal_after_change when we are done.
+ We call modify_region before calling remove_properties iff modified == 0,
+ and we call signal_after_change before returning iff modified != 0. */
+ for (;;)
+ {
+ if (i == 0)
+ abort ();
+
+ if (LENGTH (i) >= len)
+ {
+ if (! interval_has_some_properties_list (properties, i))
+ if (modified)
+ {
+ if (BUFFERP (object))
+ signal_after_change (XINT (start), XINT (end) - XINT (start),
+ XINT (end) - XINT (start));
+ return Qt;
+ }
+ else
+ return Qnil;
+
+ if (LENGTH (i) == len)
+ {
+ if (!modified && BUFFERP (object))
+ modify_region (XBUFFER (object), XINT (start), XINT (end), 1);
+ remove_properties (Qnil, properties, i, object);
+ if (BUFFERP (object))
+ signal_after_change (XINT (start), XINT (end) - XINT (start),
+ XINT (end) - XINT (start));
+ return Qt;
+ }
+
+ /* i has the properties, and goes past the change limit */
+ unchanged = i;
+ i = split_interval_left (i, len);
+ copy_properties (unchanged, i);
+ if (!modified && BUFFERP (object))
+ modify_region (XBUFFER (object), XINT (start), XINT (end), 1);
+ remove_properties (Qnil, properties, i, object);
+ if (BUFFERP (object))
+ signal_after_change (XINT (start), XINT (end) - XINT (start),
+ XINT (end) - XINT (start));
+ return Qt;
+ }
+
+ if (interval_has_some_properties_list (properties, i))
+ {
+ if (!modified && BUFFERP (object))
+ modify_region (XBUFFER (object), XINT (start), XINT (end), 1);
+ remove_properties (Qnil, properties, i, object);
+ modified = 1;
+ }
+ len -= LENGTH (i);