X-Git-Url: https://code.delx.au/gnu-emacs/blobdiff_plain/aaef169dc63c4b557374540756865991e1bf6305..7fdb5d54391088703953fcb22a06339531c36281:/src/textprop.c diff --git a/src/textprop.c b/src/textprop.c index 65823d9fa3..a039c17ae6 100644 --- a/src/textprop.c +++ b/src/textprop.c @@ -78,6 +78,8 @@ Lisp_Object Vtext_property_default_nonsticky; Lisp_Object interval_insert_behind_hooks; Lisp_Object interval_insert_in_front_hooks; +static void text_read_only P_ ((Lisp_Object)) NO_RETURN; + /* Signal a `text-read-only' error. This function makes it easier to capture that error in GDB by putting a breakpoint on it. */ @@ -86,7 +88,10 @@ static void text_read_only (propval) Lisp_Object propval; { - Fsignal (Qtext_read_only, STRINGP (propval) ? Fcons (propval, Qnil) : Qnil); + if (STRINGP (propval)) + xsignal1 (Qtext_read_only, propval); + + xsignal0 (Qtext_read_only); } @@ -690,10 +695,11 @@ overlays are considered only if they are associated with OBJECT. */) DEFUN ("get-char-property-and-overlay", Fget_char_property_and_overlay, Sget_char_property_and_overlay, 2, 3, 0, doc: /* Like `get-char-property', but with extra overlay information. -Return a cons whose car is the return value of `get-char-property' -with the same arguments, that is, the value of POSITION's property -PROP in OBJECT, and whose cdr is the overlay in which the property was +The value is a cons cell. Its car is the return value of `get-char-property' +with the same arguments--that is, the value of POSITION's property +PROP in OBJECT. Its cdr is the overlay in which the property was found, or nil, if it was found as a text property or not found at all. + OBJECT is optional and defaults to the current buffer. OBJECT may be a string, a buffer or a window. For strings, the cdr of the return value is always nil, since strings do not have overlays. If OBJECT is @@ -717,10 +723,11 @@ DEFUN ("next-char-property-change", Fnext_char_property_change, This scans characters forward in the current buffer from POSITION till it finds a change in some text property, or the beginning or end of an overlay, and returns the position of that. -If none is found, the function returns (point-max). +If none is found up to (point-max), the function returns (point-max). If the optional second argument LIMIT is non-nil, don't search -past position LIMIT; return LIMIT if nothing is found before LIMIT. */) +past position LIMIT; return LIMIT if nothing is found before LIMIT. +LIMIT is a no-op if it is greater than (point-max). */) (position, limit) Lisp_Object position, limit; { @@ -742,10 +749,11 @@ DEFUN ("previous-char-property-change", Fprevious_char_property_change, Scans characters backward in the current buffer from POSITION till it finds a change in some text property, or the beginning or end of an overlay, and returns the position of that. -If none is found, the function returns (point-max). +If none is found since (point-min), the function returns (point-min). If the optional second argument LIMIT is non-nil, don't search -past position LIMIT; return LIMIT if nothing is found before LIMIT. */) +past position LIMIT; return LIMIT if nothing is found before LIMIT. +LIMIT is a no-op if it is less than (point-min). */) (position, limit) Lisp_Object position, limit; { @@ -771,6 +779,9 @@ If the optional third argument OBJECT is a buffer (or nil, which means the current buffer), POSITION is a buffer position (integer or marker). If OBJECT is a string, POSITION is a 0-based index into it. +In a string, scan runs to the end of the string. +In a buffer, it runs to (point-max), and the value cannot exceed that. + The property values are compared with `eq'. If the property is constant all the way to the end of OBJECT, return the last valid position in OBJECT. @@ -812,22 +823,30 @@ past position LIMIT; return LIMIT if nothing is found before LIMIT. */) initial_value = Fget_char_property (position, prop, object); if (NILP (limit)) - XSETFASTINT (limit, BUF_ZV (current_buffer)); + XSETFASTINT (limit, ZV); else CHECK_NUMBER_COERCE_MARKER (limit); - for (;;) + if (XFASTINT (position) >= XFASTINT (limit)) { - position = Fnext_char_property_change (position, limit); - if (XFASTINT (position) >= XFASTINT (limit)) { - position = limit; - break; - } - - value = Fget_char_property (position, prop, object); - if (!EQ (value, initial_value)) - break; + position = limit; + if (XFASTINT (position) > ZV) + XSETFASTINT (position, ZV); } + else + while (1) + { + position = Fnext_char_property_change (position, limit); + if (XFASTINT (position) >= XFASTINT (limit)) + { + position = limit; + break; + } + + value = Fget_char_property (position, prop, object); + if (!EQ (value, initial_value)) + break; + } unbind_to (count, Qnil); } @@ -845,6 +864,9 @@ If the optional third argument OBJECT is a buffer (or nil, which means the current buffer), POSITION is a buffer position (integer or marker). If OBJECT is a string, POSITION is a 0-based index into it. +In a string, scan runs to the start of the string. +In a buffer, it runs to (point-min), and the value cannot be less than that. + The property values are compared with `eq'. If the property is constant all the way to the start of OBJECT, return the first valid position in OBJECT. @@ -883,19 +905,23 @@ back past position LIMIT; return LIMIT if nothing is found before LIMIT. */) CHECK_NUMBER_COERCE_MARKER (position); if (NILP (limit)) - XSETFASTINT (limit, BUF_BEGV (current_buffer)); + XSETFASTINT (limit, BEGV); else CHECK_NUMBER_COERCE_MARKER (limit); if (XFASTINT (position) <= XFASTINT (limit)) - position = limit; + { + position = limit; + if (XFASTINT (position) < BEGV) + XSETFASTINT (position, BEGV); + } else { - Lisp_Object initial_value = - Fget_char_property (make_number (XFASTINT (position) - 1), - prop, object); + Lisp_Object initial_value + = Fget_char_property (make_number (XFASTINT (position) - 1), + prop, object); - for (;;) + while (1) { position = Fprevious_char_property_change (position, limit); @@ -906,9 +932,9 @@ back past position LIMIT; return LIMIT if nothing is found before LIMIT. */) } else { - Lisp_Object value = - Fget_char_property (make_number (XFASTINT (position) - 1), - prop, object); + Lisp_Object value + = Fget_char_property (make_number (XFASTINT (position) - 1), + prop, object); if (!EQ (value, initial_value)) break; @@ -975,17 +1001,16 @@ past position LIMIT; return LIMIT if nothing is found before LIMIT. */) && (NILP (limit) || next->position < XFASTINT (limit))) next = next_interval (next); - if (NULL_INTERVAL_P (next)) + if (NULL_INTERVAL_P (next) + || (next->position + >= (INTEGERP (limit) + ? XFASTINT (limit) + : (STRINGP (object) + ? SCHARS (object) + : BUF_ZV (XBUFFER (object)))))) return limit; - if (NILP (limit)) - XSETFASTINT (limit, (STRINGP (object) - ? SCHARS (object) - : BUF_ZV (XBUFFER (object)))); - if (!(next->position < XFASTINT (limit))) - return limit; - - XSETFASTINT (position, next->position); - return position; + else + return make_number (next->position); } /* Return 1 if there's a change in some property between BEG and END. */ @@ -1057,16 +1082,16 @@ past position LIMIT; return LIMIT if nothing is found before LIMIT. */) && (NILP (limit) || next->position < XFASTINT (limit))) next = next_interval (next); - if (NULL_INTERVAL_P (next)) - return limit; - if (NILP (limit)) - XSETFASTINT (limit, (STRINGP (object) - ? SCHARS (object) - : BUF_ZV (XBUFFER (object)))); - if (!(next->position < XFASTINT (limit))) + if (NULL_INTERVAL_P (next) + || (next->position + >= (INTEGERP (limit) + ? XFASTINT (limit) + : (STRINGP (object) + ? SCHARS (object) + : BUF_ZV (XBUFFER (object)))))) return limit; - - return make_number (next->position); + else + return make_number (next->position); } DEFUN ("previous-property-change", Fprevious_property_change, @@ -1106,14 +1131,15 @@ back past position LIMIT; return LIMIT if nothing is found until LIMIT. */) && (NILP (limit) || (previous->position + LENGTH (previous) > XFASTINT (limit)))) previous = previous_interval (previous); - if (NULL_INTERVAL_P (previous)) - return limit; - if (NILP (limit)) - XSETFASTINT (limit, (STRINGP (object) ? 0 : BUF_BEGV (XBUFFER (object)))); - if (!(previous->position + LENGTH (previous) > XFASTINT (limit))) - return limit; - return make_number (previous->position + LENGTH (previous)); + if (NULL_INTERVAL_P (previous) + || (previous->position + LENGTH (previous) + <= (INTEGERP (limit) + ? XFASTINT (limit) + : (STRINGP (object) ? 0 : BUF_BEGV (XBUFFER (object)))))) + return limit; + else + return make_number (previous->position + LENGTH (previous)); } DEFUN ("previous-single-property-change", Fprevious_single_property_change, @@ -1158,14 +1184,15 @@ back past position LIMIT; return LIMIT if nothing is found until LIMIT. */) && (NILP (limit) || (previous->position + LENGTH (previous) > XFASTINT (limit)))) previous = previous_interval (previous); - if (NULL_INTERVAL_P (previous)) - return limit; - if (NILP (limit)) - XSETFASTINT (limit, (STRINGP (object) ? 0 : BUF_BEGV (XBUFFER (object)))); - if (!(previous->position + LENGTH (previous) > XFASTINT (limit))) - return limit; - return make_number (previous->position + LENGTH (previous)); + if (NULL_INTERVAL_P (previous) + || (previous->position + LENGTH (previous) + <= (INTEGERP (limit) + ? XFASTINT (limit) + : (STRINGP (object) ? 0 : BUF_BEGV (XBUFFER (object)))))) + return limit; + else + return make_number (previous->position + LENGTH (previous)); } /* Callers note, this can GC when OBJECT is a buffer (or nil). */ @@ -1227,7 +1254,7 @@ Return t if any property value actually changed, nil otherwise. */) } if (BUFFERP (object)) - modify_region (XBUFFER (object), XINT (start), XINT (end)); + modify_region (XBUFFER (object), XINT (start), XINT (end), 1); /* We are at the beginning of interval I, with LEN chars to scan. */ for (;;) @@ -1367,7 +1394,7 @@ set_text_properties (start, end, properties, object, signal_after_change_p) } if (BUFFERP (object)) - modify_region (XBUFFER (object), XINT (start), XINT (end)); + modify_region (XBUFFER (object), XINT (start), XINT (end), 1); set_text_properties_1 (start, end, properties, object, i); @@ -1515,7 +1542,7 @@ Use set-text-properties if you want to remove all text properties. */) } if (BUFFERP (object)) - modify_region (XBUFFER (object), XINT (start), XINT (end)); + modify_region (XBUFFER (object), XINT (start), XINT (end), 1); /* We are at the beginning of an interval, with len to scan */ for (;;) @@ -1602,10 +1629,12 @@ Return t if any property was actually removed, nil otherwise. */) } } - if (BUFFERP (object)) - modify_region (XBUFFER (object), XINT (start), XINT (end)); - - /* We are at the beginning of an interval, with len to scan */ + /* 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) @@ -1614,10 +1643,20 @@ Return t if any property was actually removed, nil otherwise. */) if (LENGTH (i) >= len) { if (! interval_has_some_properties_list (properties, i)) - return modified ? Qt : Qnil; + 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), @@ -1629,6 +1668,8 @@ Return t if any property was actually removed, nil otherwise. */) 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), @@ -1636,8 +1677,14 @@ Return t if any property was actually removed, nil otherwise. */) 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); - modified += remove_properties (Qnil, properties, i, object); i = next_interval (i); } } @@ -1747,8 +1794,12 @@ text_property_stickiness (prop, pos, buffer) /* PROP is rear-non-sticky. */ is_rear_sticky = 0; } + else + return 0; /* Consider following character. */ + /* This signals an arg-out-of-range error if pos is outside the + buffer's accessible range. */ front_sticky = Fget_text_property (pos, Qfront_sticky, buffer); if (EQ (front_sticky, Qt)