]> code.delx.au - gnu-emacs/blobdiff - src/textprop.c
(archive-l-e): New optional argument `float' means generate a float value.
[gnu-emacs] / src / textprop.c
index bf23f6a34aaaf52ef3d8dfbf9f3368a7cd38ec49..e2f9c5317356d20433a3a749e3e47bfeb3f0baed 100644 (file)
@@ -1,6 +1,6 @@
 /* Interface code for dealing with text properties.
-   Copyright (C) 1993, 1994, 1995, 1997, 1999, 2000, 2001, 2002
-   Free Software Foundation, Inc.
+   Copyright (C) 1993, 1994, 1995, 1997, 1999, 2000, 2001, 2002, 2003,
+                 2004, 2005, 2006 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -16,8 +16,8 @@ GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
 along with GNU Emacs; see the file COPYING.  If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA.  */
+the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA.  */
 
 #include <config.h>
 #include "lisp.h"
@@ -83,9 +83,10 @@ Lisp_Object interval_insert_in_front_hooks;
    to capture that error in GDB by putting a breakpoint on it.  */
 
 static void
-text_read_only ()
+text_read_only (propval)
+     Lisp_Object propval;
 {
-  Fsignal (Qtext_read_only, Qnil);
+  Fsignal (Qtext_read_only, STRINGP (propval) ? Fcons (propval, Qnil) : Qnil);
 }
 
 
@@ -158,17 +159,17 @@ validate_interval_range (object, begin, end, force)
     }
   else
     {
-      register struct Lisp_String *s = XSTRING (object);
+      int len = SCHARS (object);
 
       if (! (0 <= XINT (*begin) && XINT (*begin) <= XINT (*end)
-            && XINT (*end) <= s->size))
+            && XINT (*end) <= len))
        args_out_of_range (*begin, *end);
       XSETFASTINT (*begin, XFASTINT (*begin));
       if (begin != end)
        XSETFASTINT (*end, XFASTINT (*end));
-      i = s->intervals;
+      i = STRING_INTERVALS (object);
 
-      if (s->size == 0)
+      if (len == 0)
        return NULL_INTERVAL;
 
       searchpos = XINT (*begin);
@@ -176,7 +177,7 @@ validate_interval_range (object, begin, end, force)
 
   if (NULL_INTERVAL_P (i))
     return (force ? create_root_interval (object) : i);
-    
+
   return find_interval (i, searchpos);
 }
 
@@ -525,7 +526,7 @@ erase_properties (i)
 }
 #endif
 \f
-/* Returns the interval of POSITION in OBJECT. 
+/* Returns the interval of POSITION in OBJECT.
    POSITION is BEG-based.  */
 
 INTERVAL
@@ -553,26 +554,25 @@ interval_of (position, object)
     }
   else
     {
-      register struct Lisp_String *s = XSTRING (object);
-
       beg = 0;
-      end = s->size;
-      i = s->intervals;
+      end = SCHARS (object);
+      i = STRING_INTERVALS (object);
     }
 
   if (!(beg <= position && position <= end))
     args_out_of_range (make_number (position), make_number (position));
   if (beg == end || NULL_INTERVAL_P (i))
     return NULL_INTERVAL;
-    
+
   return find_interval (i, position);
 }
 \f
 DEFUN ("text-properties-at", Ftext_properties_at,
        Stext_properties_at, 1, 2, 0,
        doc: /* Return the list of properties of the character at POSITION in OBJECT.
-OBJECT is the string or buffer to look for the properties in;
-nil means the current buffer.
+If the optional second 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.
 If POSITION is at the end of OBJECT, the value is nil.  */)
      (position, object)
      Lisp_Object position, object;
@@ -606,7 +606,7 @@ If POSITION is at the end of OBJECT, the value is nil.  */)
   return textget (Ftext_properties_at (position, object), prop);
 }
 
-/* Return the value of POSITION's property PROP, in OBJECT.
+/* Return the value of char's property PROP, in OBJECT at POSITION.
    OBJECT is optional and defaults to the current buffer.
    If OVERLAY is non-0, then in the case that the returned property is from
    an overlay, the overlay found is returned in *OVERLAY, otherwise nil is
@@ -637,31 +637,13 @@ get_char_property_and_overlay (position, prop, object, overlay)
     }
   if (BUFFERP (object))
     {
-      int posn = XINT (position);
       int noverlays;
-      Lisp_Object *overlay_vec, tem;
-      int next_overlay;
-      int len;
+      Lisp_Object *overlay_vec;
       struct buffer *obuf = current_buffer;
 
       set_buffer_temp (XBUFFER (object));
 
-      /* First try with room for 40 overlays.  */
-      len = 40;
-      overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
-
-      noverlays = overlays_at (posn, 0, &overlay_vec, &len,
-                              &next_overlay, NULL, 0);
-
-      /* If there are more than 40,
-        make enough space for all, and try again.  */
-      if (noverlays > len)
-       {
-         len = noverlays;
-         overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
-         noverlays = overlays_at (posn, 0, &overlay_vec, &len,
-                                  &next_overlay, NULL, 0);
-       }
+      GET_OVERLAYS_AT (XINT (position), overlay_vec, noverlays, NULL, 0);
       noverlays = sort_overlays (overlay_vec, noverlays, w);
 
       set_buffer_temp (obuf);
@@ -669,7 +651,7 @@ get_char_property_and_overlay (position, prop, object, overlay)
       /* Now check the overlays in order of decreasing priority.  */
       while (--noverlays >= 0)
        {
-         tem = Foverlay_get (overlay_vec[noverlays], prop);
+         Lisp_Object tem = Foverlay_get (overlay_vec[noverlays], prop);
          if (!NILP (tem))
            {
              if (overlay)
@@ -704,16 +686,40 @@ overlays are considered only if they are associated with OBJECT.  */)
 {
   return get_char_property_and_overlay (position, prop, object, 0);
 }
+
+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
+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
+a window, then that window's buffer is used, but window-specific
+overlays are considered only if they are associated with OBJECT.  If
+POSITION is at the end of OBJECT, both car and cdr are nil.  */)
+     (position, prop, object)
+     Lisp_Object position, object;
+     register Lisp_Object prop;
+{
+  Lisp_Object overlay;
+  Lisp_Object val
+    = get_char_property_and_overlay (position, prop, object, &overlay);
+  return Fcons(val, overlay);
+}
+
 \f
 DEFUN ("next-char-property-change", Fnext_char_property_change,
        Snext_char_property_change, 1, 2, 0,
        doc: /* Return the position of next text property or overlay change.
-This scans characters forward 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.
+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 the optional third argument LIMIT is non-nil, don't search
+If the optional second argument LIMIT is non-nil, don't search
 past position LIMIT; return LIMIT if nothing is found before LIMIT.  */)
      (position, limit)
      Lisp_Object position, limit;
@@ -723,7 +729,7 @@ past position LIMIT; return LIMIT if nothing is found before LIMIT.  */)
   temp = Fnext_overlay_change (position);
   if (! NILP (limit))
     {
-      CHECK_NUMBER (limit);
+      CHECK_NUMBER_COERCE_MARKER (limit);
       if (XINT (limit) < XINT (temp))
        temp = limit;
     }
@@ -733,12 +739,12 @@ past position LIMIT; return LIMIT if nothing is found before LIMIT.  */)
 DEFUN ("previous-char-property-change", Fprevious_char_property_change,
        Sprevious_char_property_change, 1, 2, 0,
        doc: /* Return the position of previous text property or overlay change.
-Scans characters backward 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.
+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 the optional third argument LIMIT is non-nil, don't search
+If the optional second argument LIMIT is non-nil, don't search
 past position LIMIT; return LIMIT if nothing is found before LIMIT.  */)
      (position, limit)
      Lisp_Object position, limit;
@@ -748,7 +754,7 @@ past position LIMIT; return LIMIT if nothing is found before LIMIT.  */)
   temp = Fprevious_overlay_change (position);
   if (! NILP (limit))
     {
-      CHECK_NUMBER (limit);
+      CHECK_NUMBER_COERCE_MARKER (limit);
       if (XINT (limit) > XINT (temp))
        temp = limit;
     }
@@ -761,7 +767,10 @@ DEFUN ("next-single-char-property-change", Fnext_single_char_property_change,
        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.
+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.
+
 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.
@@ -778,7 +787,10 @@ past position LIMIT; return LIMIT if nothing is found before LIMIT.  */)
          if (NILP (limit))
            position = make_number (SCHARS (object));
          else
-           position = limit;
+           {
+             CHECK_NUMBER (limit);
+             position = limit;
+           }
        }
     }
   else
@@ -788,15 +800,17 @@ past position LIMIT; return LIMIT if nothing is found before LIMIT.  */)
 
       if (! NILP (object))
        CHECK_BUFFER (object);
-      
+
       if (BUFFERP (object) && current_buffer != XBUFFER (object))
        {
          record_unwind_protect (Fset_buffer, Fcurrent_buffer ());
          Fset_buffer (object);
        }
 
+      CHECK_NUMBER_COERCE_MARKER (position);
+
       initial_value = Fget_char_property (position, prop, object);
-      
+
       if (NILP (limit))
        XSETFASTINT (limit, BUF_ZV (current_buffer));
       else
@@ -827,7 +841,10 @@ DEFUN ("previous-single-char-property-change",
        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.
+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.
+
 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.
@@ -844,7 +861,10 @@ back past position LIMIT; return LIMIT if nothing is found before LIMIT.  */)
          if (NILP (limit))
            position = make_number (SCHARS (object));
          else
-           position = limit;
+           {
+             CHECK_NUMBER (limit);
+             position = limit;
+           }
        }
     }
   else
@@ -853,13 +873,15 @@ back past position LIMIT; return LIMIT if nothing is found before LIMIT.  */)
 
       if (! NILP (object))
        CHECK_BUFFER (object);
-      
+
       if (BUFFERP (object) && current_buffer != XBUFFER (object))
        {
          record_unwind_protect (Fset_buffer, Fcurrent_buffer ());
          Fset_buffer (object);
        }
-      
+
+      CHECK_NUMBER_COERCE_MARKER (position);
+
       if (NILP (limit))
        XSETFASTINT (limit, BUF_BEGV (current_buffer));
       else
@@ -872,7 +894,7 @@ back past position LIMIT; return LIMIT if nothing is found before LIMIT.  */)
          Lisp_Object initial_value =
            Fget_char_property (make_number (XFASTINT (position) - 1),
                                prop, object);
-      
+
          for (;;)
            {
              position = Fprevious_char_property_change (position, limit);
@@ -905,7 +927,9 @@ DEFUN ("next-property-change", Fnext_property_change,
        doc: /* Return the position of next property change.
 Scans characters forward from POSITION in OBJECT till it finds
 a change in some text property, then returns the position of the change.
-The optional second argument OBJECT is the string or buffer to scan.
+If the optional second 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.
 Return nil if the property is constant all the way to the end of OBJECT.
 If the value is non-nil, it is a position greater than POSITION, never equal.
 
@@ -932,7 +956,7 @@ past position LIMIT; return LIMIT if nothing is found before LIMIT.  */)
        next = i;
       else
        next = next_interval (i);
-       
+
       if (NULL_INTERVAL_P (next))
        XSETFASTINT (position, (STRINGP (object)
                                ? SCHARS (object)
@@ -1001,7 +1025,9 @@ DEFUN ("next-single-property-change", Fnext_single_property_change,
        doc: /* Return the position of next property 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.
+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.
 The property values are compared with `eq'.
 Return nil if the property is constant all the way to the end of OBJECT.
 If the value is non-nil, it is a position greater than POSITION, never equal.
@@ -1026,7 +1052,7 @@ past position LIMIT; return LIMIT if nothing is found before LIMIT.  */)
 
   here_val = textget (i->plist, prop);
   next = next_interval (i);
-  while (! NULL_INTERVAL_P (next) 
+  while (! NULL_INTERVAL_P (next)
         && EQ (here_val, textget (next->plist, prop))
         && (NILP (limit) || next->position < XFASTINT (limit)))
     next = next_interval (next);
@@ -1048,7 +1074,9 @@ DEFUN ("previous-property-change", Fprevious_property_change,
        doc: /* Return the position of previous property change.
 Scans characters backwards from POSITION in OBJECT till it finds
 a change in some text property, then returns the position of the change.
-The optional second argument OBJECT is the string or buffer to scan.
+If the optional second 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.
 Return nil if the property is constant all the way to the start of OBJECT.
 If the value is non-nil, it is a position less than POSITION, never equal.
 
@@ -1093,7 +1121,9 @@ DEFUN ("previous-single-property-change", Fprevious_single_property_change,
        doc: /* Return the position of previous property 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.
+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.
 The property values are compared with `eq'.
 Return nil if the property is constant all the way to the start of OBJECT.
 If the value is non-nil, it is a position less than POSITION, never equal.
@@ -1144,9 +1174,10 @@ DEFUN ("add-text-properties", Fadd_text_properties,
        Sadd_text_properties, 3, 4, 0,
        doc: /* Add properties to the text from START to END.
 The third argument PROPERTIES is a property list
-specifying the property values to add.
-The optional fourth argument, OBJECT,
-is the string or buffer containing the text.
+specifying the property values to add.  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 value actually changed, nil otherwise.  */)
      (start, end, properties, object)
      Lisp_Object start, end, properties, object;
@@ -1253,8 +1284,9 @@ DEFUN ("put-text-property", Fput_text_property,
        doc: /* Set one property of the text from START to END.
 The third and fourth arguments PROPERTY and VALUE
 specify the property to add.
-The optional fifth argument, OBJECT,
-is the string or buffer containing the text.  */)
+If the optional fifth 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.  */)
      (start, end, property, value, object)
      Lisp_Object start, end, property, value, object;
 {
@@ -1268,9 +1300,9 @@ DEFUN ("set-text-properties", Fset_text_properties,
        Sset_text_properties, 3, 4, 0,
        doc: /* Completely replace properties of text from START to END.
 The third argument PROPERTIES is the new property list.
-The optional fourth argument, OBJECT,
-is the string or buffer containing the text.
-If OBJECT is omitted or nil, it defaults to the current buffer.
+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.
 If PROPERTIES is nil, the effect is to remove all properties from
 the designated part of OBJECT.  */)
      (start, end, properties, object)
@@ -1284,8 +1316,8 @@ the designated part of OBJECT.  */)
    properties PROPERTIES.  OBJECT is the buffer or string containing
    the text.  OBJECT nil means use the current buffer.
    SIGNAL_AFTER_CHANGE_P nil means don't signal after changes.  Value
-   is non-nil if properties were replaced; it is nil if there weren't
-   any properties to replace.  */
+   is nil if the function _detected_ that it did not replace any
+   properties, non-nil otherwise.  */
 
 Lisp_Object
 set_text_properties (start, end, properties, object, signal_after_change_p)
@@ -1309,9 +1341,9 @@ set_text_properties (start, end, properties, object, signal_after_change_p)
       && XFASTINT (end) == SCHARS (object))
     {
       if (! STRING_INTERVALS (object))
-       return Qt;
+       return Qnil;
 
-      STRING_INTERVALS (object) = 0;
+      STRING_SET_INTERVALS (object, NULL_INTERVAL);
       return Qt;
     }
 
@@ -1438,9 +1470,12 @@ DEFUN ("remove-text-properties", Fremove_text_properties,
 The third argument PROPERTIES is a property list
 whose property names specify the properties to remove.
 \(The values stored in PROPERTIES are ignored.)
-The optional fourth argument, OBJECT,
-is the string or buffer containing the text.
-Return t if any property was actually removed, nil otherwise.  */)
+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.
+
+Use set-text-properties if you want to remove all text properties.  */)
      (start, end, properties, object)
      Lisp_Object start, end, properties, object;
 {
@@ -1523,8 +1558,9 @@ 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.
-The optional fourth argument, OBJECT,
-is the string or buffer containing the text, defaulting to the current buffer.
+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;
@@ -1566,10 +1602,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)
@@ -1578,10 +1616,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));
              remove_properties (Qnil, properties, i, object);
              if (BUFFERP (object))
                signal_after_change (XINT (start), XINT (end) - XINT (start),
@@ -1593,6 +1641,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));
          remove_properties (Qnil, properties, i, object);
          if (BUFFERP (object))
            signal_after_change (XINT (start), XINT (end) - XINT (start),
@@ -1600,8 +1650,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));
+         remove_properties (Qnil, properties, i, object);
+         modified = 1;
+       }
       len -= LENGTH (i);
-      modified += remove_properties (Qnil, properties, i, object);
       i = next_interval (i);
     }
 }
@@ -1611,8 +1667,9 @@ DEFUN ("text-property-any", Ftext_property_any,
        doc: /* Check text from START to END for property PROPERTY equalling VALUE.
 If so, return the position of the first character whose property PROPERTY
 is `eq' to VALUE.  Otherwise return nil.
-The optional fifth argument, OBJECT, is the string or buffer
-containing the text.  */)
+If the optional fifth 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.  */)
      (start, end, property, value, object)
      Lisp_Object start, end, property, value, object;
 {
@@ -1647,8 +1704,9 @@ DEFUN ("text-property-not-all", Ftext_property_not_all,
        doc: /* Check text from START to END for property PROPERTY not equalling VALUE.
 If so, return the position of the first character whose property PROPERTY
 is not `eq' to VALUE.  Otherwise, return nil.
-The optional fifth argument, OBJECT, is the string or buffer
-containing the text.  */)
+If the optional fifth 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.  */)
      (start, end, property, value, object)
      Lisp_Object start, end, property, value, object;
 {
@@ -1682,23 +1740,26 @@ containing the text.  */)
 /* Return the direction from which the text-property PROP would be
    inherited by any new text inserted at POS: 1 if it would be
    inherited from the char after POS, -1 if it would be inherited from
-   the char before POS, and 0 if from neither.  */
+   the char before POS, and 0 if from neither.
+   BUFFER can be either a buffer or nil (meaning current buffer).  */
 
 int
-text_property_stickiness (prop, pos)
-     Lisp_Object prop;
-     Lisp_Object pos;
+text_property_stickiness (prop, pos, buffer)
+     Lisp_Object prop, pos, buffer;
 {
   Lisp_Object prev_pos, front_sticky;
   int is_rear_sticky = 1, is_front_sticky = 0; /* defaults */
 
-  if (XINT (pos) > BEGV)
+  if (NILP (buffer))
+    XSETBUFFER (buffer, current_buffer);
+
+  if (XINT (pos) > BUF_BEGV (XBUFFER (buffer)))
     /* Consider previous character.  */
     {
       Lisp_Object rear_non_sticky;
 
       prev_pos = make_number (XINT (pos) - 1);
-      rear_non_sticky = Fget_text_property (prev_pos, Qrear_nonsticky, Qnil);
+      rear_non_sticky = Fget_text_property (prev_pos, Qrear_nonsticky, buffer);
 
       if (!NILP (CONSP (rear_non_sticky)
                 ? Fmemq (prop, rear_non_sticky)
@@ -1708,7 +1769,7 @@ text_property_stickiness (prop, pos)
     }
 
   /* Consider following character.  */
-  front_sticky = Fget_text_property (pos, Qfront_sticky, Qnil);
+  front_sticky = Fget_text_property (pos, Qfront_sticky, buffer);
 
   if (EQ (front_sticky, Qt)
       || (CONSP (front_sticky)
@@ -1728,7 +1789,8 @@ text_property_stickiness (prop, pos)
      disambiguate.  Basically, rear-sticky wins, _except_ if the
      property that would be inherited has a value of nil, in which case
      front-sticky wins.  */
-  if (XINT (pos) == BEGV || NILP (Fget_text_property (prev_pos, prop, Qnil)))
+  if (XINT (pos) == BUF_BEGV (XBUFFER (buffer))
+      || NILP (Fget_text_property (prev_pos, prop, buffer)))
     return 1;
   else
     return -1;
@@ -1852,23 +1914,23 @@ text_property_list (object, start, end, prop)
   Lisp_Object result;
 
   result = Qnil;
-  
+
   i = validate_interval_range (object, &start, &end, soft);
   if (!NULL_INTERVAL_P (i))
     {
       int s = XINT (start);
       int e = XINT (end);
-      
+
       while (s < e)
        {
          int interval_end, len;
          Lisp_Object plist;
-         
+
          interval_end = i->position + LENGTH (i);
          if (interval_end > e)
            interval_end = e;
          len = interval_end - s;
-         
+
          plist = i->plist;
 
          if (!NILP (prop))
@@ -1884,14 +1946,14 @@ text_property_list (object, start, end, prop)
                                   Fcons (make_number (s + len),
                                          Fcons (plist, Qnil))),
                            result);
-         
+
          i = next_interval (i);
          if (NULL_INTERVAL_P (i))
            break;
          s = i->position;
        }
     }
-  
+
   return result;
 }
 
@@ -1908,18 +1970,18 @@ add_text_properties_from_list (object, list, delta)
 {
   struct gcpro gcpro1, gcpro2;
   int modified_p = 0;
-  
+
   GCPRO2 (list, object);
-  
+
   for (; CONSP (list); list = XCDR (list))
     {
       Lisp_Object item, start, end, plist, tem;
-      
+
       item = XCAR (list);
       start = make_number (XINT (XCAR (item)) + XINT (delta));
       end = make_number (XINT (XCAR (XCDR (item))) + XINT (delta));
       plist = XCAR (XCDR (XCDR (item)));
-      
+
       tem = Fadd_text_properties (start, end, plist, object);
       if (!NILP (tem))
        modified_p = 1;
@@ -1942,7 +2004,7 @@ extend_property_ranges (list, old_end, new_end)
   for (; CONSP (list); list = XCDR (list))
     {
       Lisp_Object item, end;
-      
+
       item = XCAR (list);
       end = XCAR (XCDR (item));
 
@@ -2040,7 +2102,7 @@ verify_interval_modification (buf, start, end)
              if (! NULL_INTERVAL_P (i))
                {
                  after = textget (i->plist, Qread_only);
-                 
+
                  /* If interval I is read-only and read-only is
                     front-sticky, inhibit insertion.
                     Check for read-only as well as category.  */
@@ -2053,14 +2115,14 @@ verify_interval_modification (buf, start, end)
                      if (TMEM (Qread_only, tem)
                          || (NILP (Fplist_get (i->plist, Qread_only))
                              && TMEM (Qcategory, tem)))
-                       text_read_only ();
+                       text_read_only (after);
                    }
                }
 
              if (! NULL_INTERVAL_P (prev))
                {
                  before = textget (prev->plist, Qread_only);
-                 
+
                  /* If interval PREV is read-only and read-only isn't
                     rear-nonsticky, inhibit insertion.
                     Check for read-only as well as category.  */
@@ -2073,14 +2135,14 @@ verify_interval_modification (buf, start, end)
                      if (! TMEM (Qread_only, tem)
                          && (! NILP (Fplist_get (prev->plist,Qread_only))
                              || ! TMEM (Qcategory, tem)))
-                       text_read_only ();
+                       text_read_only (before);
                    }
                }
            }
          else if (! NULL_INTERVAL_P (i))
            {
              after = textget (i->plist, Qread_only);
-                 
+
              /* If interval I is read-only and read-only is
                 front-sticky, inhibit insertion.
                 Check for read-only as well as category.  */
@@ -2092,13 +2154,13 @@ verify_interval_modification (buf, start, end)
                  if (TMEM (Qread_only, tem)
                      || (NILP (Fplist_get (i->plist, Qread_only))
                          && TMEM (Qcategory, tem)))
-                   text_read_only ();
+                   text_read_only (after);
 
                  tem = textget (prev->plist, Qrear_nonsticky);
                  if (! TMEM (Qread_only, tem)
                      && (! NILP (Fplist_get (prev->plist, Qread_only))
                          || ! TMEM (Qcategory, tem)))
-                   text_read_only ();
+                   text_read_only (after);
                }
            }
        }
@@ -2120,7 +2182,7 @@ verify_interval_modification (buf, start, end)
       do
        {
          if (! INTERVAL_WRITABLE_P (i))
-           text_read_only ();
+           text_read_only (textget (i->plist, Qread_only));
 
          if (!inhibit_modification_hooks)
            {
@@ -2201,14 +2263,16 @@ If a character in a buffer has PROPERTY, new text inserted adjacent to
 the character doesn't inherit PROPERTY if NONSTICKINESS is non-nil,
 inherits it if NONSTICKINESS is nil.  The front-sticky and
 rear-nonsticky properties of the character overrides NONSTICKINESS.  */);
-  Vtext_property_default_nonsticky = Qnil;
+  /* Text property `syntax-table' should be nonsticky by default.  */
+  Vtext_property_default_nonsticky
+    = Fcons (Fcons (intern ("syntax-table"), Qt), Qnil);
 
   staticpro (&interval_insert_behind_hooks);
   staticpro (&interval_insert_in_front_hooks);
   interval_insert_behind_hooks = Qnil;
   interval_insert_in_front_hooks = Qnil;
 
-              
+
   /* Common attributes one might give text */
 
   staticpro (&Qforeground);
@@ -2252,6 +2316,7 @@ rear-nonsticky properties of the character overrides NONSTICKINESS.  */);
   defsubr (&Stext_properties_at);
   defsubr (&Sget_text_property);
   defsubr (&Sget_char_property);
+  defsubr (&Sget_char_property_and_overlay);
   defsubr (&Snext_char_property_change);
   defsubr (&Sprevious_char_property_change);
   defsubr (&Snext_single_char_property_change);
@@ -2271,3 +2336,5 @@ rear-nonsticky properties of the character overrides NONSTICKINESS.  */);
 /*  defsubr (&Scopy_text_properties); */
 }
 
+/* arch-tag: 454cdde8-5f86-4faa-a078-101e3625d479
+   (do not change this comment) */