+
+DEFUN ("next-single-char-property-change", Fnext_single_char_property_change,
+ Snext_single_char_property_change, 2, 4, 0,
+ doc: /* Return the position of next text property or overlay change for a specific property.
+Scans characters forward from POSITION till it finds
+a change in the PROP property, then returns the position of the change.
+The optional third argument OBJECT is the string or buffer to scan.
+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.
+If the optional fourth argument LIMIT is non-nil, don't search
+past position LIMIT; return LIMIT if nothing is found before LIMIT. */)
+ (position, prop, object, limit)
+ Lisp_Object prop, position, object, limit;
+{
+ if (STRINGP (object))
+ {
+ position = Fnext_single_property_change (position, prop, object, limit);
+ if (NILP (position))
+ {
+ if (NILP (limit))
+ position = make_number (XSTRING (object)->size);
+ else
+ position = limit;
+ }
+ }
+ else
+ {
+ Lisp_Object initial_value, value;
+ int count = specpdl_ptr - specpdl;
+
+ if (! NILP (object))
+ CHECK_BUFFER (object);
+
+ if (BUFFERP (object) && current_buffer != XBUFFER (object))
+ {
+ record_unwind_protect (Fset_buffer, Fcurrent_buffer ());
+ Fset_buffer (object);
+ }
+
+ initial_value = Fget_char_property (position, prop, object);
+
+ if (NILP (limit))
+ XSETFASTINT (limit, BUF_ZV (current_buffer));
+ else
+ CHECK_NUMBER_COERCE_MARKER (limit);
+
+ for (;;)
+ {
+ 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);
+ }
+
+ return position;
+}
+
+DEFUN ("previous-single-char-property-change",
+ Fprevious_single_char_property_change,
+ Sprevious_single_char_property_change, 2, 4, 0,
+ doc: /* Return the position of previous text property or overlay change for a specific property.
+Scans characters backward from POSITION till it finds
+a change in the PROP property, then returns the position of the change.
+The optional third argument OBJECT is the string or buffer to scan.
+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.
+If the optional fourth argument LIMIT is non-nil, don't search
+back past position LIMIT; return LIMIT if nothing is found before LIMIT. */)
+ (position, prop, object, limit)
+ Lisp_Object prop, position, object, limit;
+{
+ if (STRINGP (object))
+ {
+ position = Fprevious_single_property_change (position, prop, object, limit);
+ if (NILP (position))
+ {
+ if (NILP (limit))
+ position = make_number (XSTRING (object)->size);
+ else
+ position = limit;
+ }
+ }
+ else
+ {
+ int count = specpdl_ptr - specpdl;
+
+ if (! NILP (object))
+ CHECK_BUFFER (object);
+
+ if (BUFFERP (object) && current_buffer != XBUFFER (object))
+ {
+ record_unwind_protect (Fset_buffer, Fcurrent_buffer ());
+ Fset_buffer (object);
+ }
+
+ if (NILP (limit))
+ XSETFASTINT (limit, BUF_BEGV (current_buffer));
+ else
+ CHECK_NUMBER_COERCE_MARKER (limit);
+
+ if (XFASTINT (position) <= XFASTINT (limit))
+ position = limit;
+ else
+ {
+ Lisp_Object initial_value =
+ Fget_char_property (make_number (XFASTINT (position) - 1),
+ prop, object);
+
+ for (;;)
+ {
+ position = Fprevious_char_property_change (position, limit);
+
+ if (XFASTINT (position) <= XFASTINT (limit))
+ {
+ position = limit;
+ break;
+ }
+ else
+ {
+ Lisp_Object value =
+ Fget_char_property (make_number (XFASTINT (position) - 1),
+ prop, object);
+
+ if (!EQ (value, initial_value))
+ break;
+ }
+ }
+ }
+
+ unbind_to (count, Qnil);
+ }
+
+ return position;
+}
+\f