src/textprop.c (Fprevious_single_char_property_change): Doc fix (bug#8655).
[bpt/emacs.git] / src / textprop.c
index 8ce5656..132c2ff 100644 (file)
@@ -1,13 +1,13 @@
 /* Interface code for dealing with text properties.
    Copyright (C) 1993, 1994, 1995, 1997, 1999, 2000, 2001, 2002, 2003,
-                 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
+                 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
-GNU Emacs is free software; you can redistribute it and/or modify
+GNU Emacs is free software: you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 3, or (at your option)
-any later version.
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
 
 GNU Emacs is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -15,11 +15,10 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 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., 51 Franklin Street, Fifth Floor,
-Boston, MA 02110-1301, USA.  */
+along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 
 #include <config.h>
+#include <setjmp.h>
 #include "lisp.h"
 #include "intervals.h"
 #include "buffer.h"
@@ -59,6 +58,7 @@ Lisp_Object Qlocal_map;
 /* Visual properties text (including strings) may have.  */
 Lisp_Object Qforeground, Qbackground, Qfont, Qunderline, Qstipple;
 Lisp_Object Qinvisible, Qread_only, Qintangible, Qmouse_face;
+Lisp_Object Qminibuffer_prompt;
 
 /* Sticky properties */
 Lisp_Object Qfront_sticky, Qrear_nonsticky;
@@ -201,9 +201,9 @@ validate_plist (list)
     {
       register int i;
       register Lisp_Object tail;
-      for (i = 0, tail = list; !NILP (tail); i++)
+      for (i = 0, tail = list; CONSP (tail); i++)
        {
-         tail = Fcdr (tail);
+         tail = XCDR (tail);
          QUIT;
        }
       if (i & 1)
@@ -226,18 +226,18 @@ interval_has_all_properties (plist, i)
   register int found;
 
   /* Go through each element of PLIST.  */
-  for (tail1 = plist; ! NILP (tail1); tail1 = Fcdr (Fcdr (tail1)))
+  for (tail1 = plist; CONSP (tail1); tail1 = Fcdr (XCDR (tail1)))
     {
-      sym1 = Fcar (tail1);
+      sym1 = XCAR (tail1);
       found = 0;
 
       /* Go through I's plist, looking for sym1 */
-      for (tail2 = i->plist; ! NILP (tail2); tail2 = Fcdr (Fcdr (tail2)))
-       if (EQ (sym1, Fcar (tail2)))
+      for (tail2 = i->plist; CONSP (tail2); tail2 = Fcdr (XCDR (tail2)))
+       if (EQ (sym1, XCAR (tail2)))
          {
            /* Found the same property on both lists.  If the
               values are unequal, return zero.  */
-           if (! EQ (Fcar (Fcdr (tail1)), Fcar (Fcdr (tail2))))
+           if (! EQ (Fcar (XCDR (tail1)), Fcar (XCDR (tail2))))
              return 0;
 
            /* Property has same value on both lists;  go to next one.  */
@@ -263,13 +263,13 @@ interval_has_some_properties (plist, i)
   register Lisp_Object tail1, tail2, sym;
 
   /* Go through each element of PLIST.  */
-  for (tail1 = plist; ! NILP (tail1); tail1 = Fcdr (Fcdr (tail1)))
+  for (tail1 = plist; CONSP (tail1); tail1 = Fcdr (XCDR (tail1)))
     {
-      sym = Fcar (tail1);
+      sym = XCAR (tail1);
 
       /* Go through i's plist, looking for tail1 */
-      for (tail2 = i->plist; ! NILP (tail2); tail2 = Fcdr (Fcdr (tail2)))
-       if (EQ (sym, Fcar (tail2)))
+      for (tail2 = i->plist; CONSP (tail2); tail2 = Fcdr (XCDR (tail2)))
+       if (EQ (sym, XCAR (tail2)))
          return 1;
     }
 
@@ -287,12 +287,12 @@ interval_has_some_properties_list (list, i)
   register Lisp_Object tail1, tail2, sym;
 
   /* Go through each element of LIST.  */
-  for (tail1 = list; ! NILP (tail1); tail1 = XCDR (tail1))
+  for (tail1 = list; CONSP (tail1); tail1 = XCDR (tail1))
     {
       sym = Fcar (tail1);
 
       /* Go through i's plist, looking for tail1 */
-      for (tail2 = i->plist; ! NILP (tail2); tail2 = XCDR (XCDR (tail2)))
+      for (tail2 = i->plist; CONSP (tail2); tail2 = XCDR (XCDR (tail2)))
        if (EQ (sym, XCAR (tail2)))
          return 1;
     }
@@ -391,21 +391,21 @@ add_properties (plist, i, object)
   GCPRO3 (tail1, sym1, val1);
 
   /* Go through each element of PLIST.  */
-  for (tail1 = plist; ! NILP (tail1); tail1 = Fcdr (Fcdr (tail1)))
+  for (tail1 = plist; CONSP (tail1); tail1 = Fcdr (XCDR (tail1)))
     {
-      sym1 = Fcar (tail1);
-      val1 = Fcar (Fcdr (tail1));
+      sym1 = XCAR (tail1);
+      val1 = Fcar (XCDR (tail1));
       found = 0;
 
       /* Go through I's plist, looking for sym1 */
-      for (tail2 = i->plist; ! NILP (tail2); tail2 = Fcdr (Fcdr (tail2)))
-       if (EQ (sym1, Fcar (tail2)))
+      for (tail2 = i->plist; CONSP (tail2); tail2 = Fcdr (XCDR (tail2)))
+       if (EQ (sym1, XCAR (tail2)))
          {
            /* No need to gcpro, because tail2 protects this
               and it must be a cons cell (we get an error otherwise).  */
            register Lisp_Object this_cdr;
 
-           this_cdr = Fcdr (tail2);
+           this_cdr = XCDR (tail2);
            /* Found the property.  Now check its value.  */
            found = 1;
 
@@ -646,6 +646,10 @@ get_char_property_and_overlay (position, prop, object, overlay)
       Lisp_Object *overlay_vec;
       struct buffer *obuf = current_buffer;
 
+      if (XINT (position) < BUF_BEGV (XBUFFER (object))
+         || XINT (position) > BUF_ZV (XBUFFER (object)))
+       xsignal1 (Qargs_out_of_range, position);
+
       set_buffer_temp (XBUFFER (object));
 
       GET_OVERLAYS_AT (XINT (position), overlay_vec, noverlays, NULL, 0);
@@ -713,7 +717,7 @@ POSITION is at the end of OBJECT, both car and cdr are nil.  */)
   Lisp_Object overlay;
   Lisp_Object val
     = get_char_property_and_overlay (position, prop, object, &overlay);
-  return Fcons(val, overlay);
+  return Fcons (val, overlay);
 }
 
 \f
@@ -870,8 +874,8 @@ 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.
-If the optional fourth argument LIMIT is non-nil, don't search
-back past position LIMIT; return LIMIT if nothing is found before LIMIT.  */)
+If the optional fourth argument LIMIT is non-nil, don't search back past
+position LIMIT; return LIMIT if nothing is found before reaching LIMIT.  */)
      (position, prop, object, limit)
      Lisp_Object prop, position, object, limit;
 {
@@ -881,7 +885,7 @@ back past position LIMIT; return LIMIT if nothing is found before LIMIT.  */)
       if (NILP (position))
        {
          if (NILP (limit))
-           position = make_number (SCHARS (object));
+           position = make_number (0);
          else
            {
              CHECK_NUMBER (limit);
@@ -1342,13 +1346,15 @@ the designated part of OBJECT.  */)
 /* Replace properties of text from START to END with new list of
    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 nil if the function _detected_ that it did not replace any
-   properties, non-nil otherwise.  */
+   COHERENT_CHANGE_P nil means this is being called as an internal
+   subroutine, rather than as a change primitive with checking of
+   read-only, invoking change hooks, etc..  Value 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)
-     Lisp_Object start, end, properties, object, signal_after_change_p;
+set_text_properties (start, end, properties, object, coherent_change_p)
+     Lisp_Object start, end, properties, object, coherent_change_p;
 {
   register INTERVAL i;
   Lisp_Object ostart, oend;
@@ -1393,12 +1399,12 @@ set_text_properties (start, end, properties, object, signal_after_change_p)
        return Qnil;
     }
 
-  if (BUFFERP (object))
+  if (BUFFERP (object) && !NILP (coherent_change_p))
     modify_region (XBUFFER (object), XINT (start), XINT (end), 1);
 
   set_text_properties_1 (start, end, properties, object, i);
 
-  if (BUFFERP (object) && !NILP (signal_after_change_p))
+  if (BUFFERP (object) && !NILP (coherent_change_p))
     signal_after_change (XINT (start), XINT (end) - XINT (start),
                         XINT (end) - XINT (start));
   return Qt;
@@ -1502,7 +1508,7 @@ 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.  */)
+Use `set-text-properties' if you want to remove all text properties.  */)
      (start, end, properties, object)
      Lisp_Object start, end, properties, object;
 {
@@ -1965,10 +1971,10 @@ text_property_list (object, start, end, prop)
          plist = i->plist;
 
          if (!NILP (prop))
-           for (; !NILP (plist); plist = Fcdr (Fcdr (plist)))
-             if (EQ (Fcar (plist), prop))
+           for (; CONSP (plist); plist = Fcdr (XCDR (plist)))
+             if (EQ (XCAR (plist), prop))
                {
-                 plist = Fcons (prop, Fcons (Fcar (Fcdr (plist)), Qnil));
+                 plist = Fcons (prop, Fcons (Fcar (XCDR (plist)), Qnil));
                  break;
                }
 
@@ -2024,24 +2030,41 @@ add_text_properties_from_list (object, list, delta)
 
 
 
-/* Modify end-points of ranges in LIST destructively.  LIST is a list
-   as returned from text_property_list.  Change end-points equal to
-   OLD_END to NEW_END.  */
+/* Modify end-points of ranges in LIST destructively, and return the
+   new list.  LIST is a list as returned from text_property_list.
+   Discard properties that begin at or after NEW_END, and limit
+   end-points to NEW_END.  */
 
-void
-extend_property_ranges (list, old_end, new_end)
-     Lisp_Object list, old_end, new_end;
+Lisp_Object
+extend_property_ranges (list, new_end)
+     Lisp_Object list, new_end;
 {
-  for (; CONSP (list); list = XCDR (list))
+  Lisp_Object prev = Qnil, head = list;
+  int max = XINT (new_end);
+
+  for (; CONSP (list); prev = list, list = XCDR (list))
     {
-      Lisp_Object item, end;
+      Lisp_Object item, beg, end;
 
       item = XCAR (list);
+      beg = XCAR (item);
       end = XCAR (XCDR (item));
 
-      if (EQ (end, old_end))
+      if (XINT (beg) >= max)
+       {
+         /* The start-point is past the end of the new string.
+            Discard this property.  */
+         if (EQ (head, list))
+           head = XCDR (list);
+         else
+           XSETCDR (prev, XCDR (list));
+       }
+      else if (XINT (end) > max)
+       /* The end-point is past the end of the new string.  */
        XSETCAR (XCDR (item), new_end);
     }
+
+  return head;
 }
 
 
@@ -2292,11 +2315,11 @@ Each element has the form (PROPERTY . NONSTICKINESS).
 
 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.  */);
+inherits it if NONSTICKINESS is nil.  The `front-sticky' and
+`rear-nonsticky' properties of the character override NONSTICKINESS.  */);
   /* Text property `syntax-table' should be nonsticky by default.  */
   Vtext_property_default_nonsticky
-    = Fcons (Fcons (intern ("syntax-table"), Qt), Qnil);
+    = Fcons (Fcons (intern_c_string ("syntax-table"), Qt), Qnil);
 
   staticpro (&interval_insert_behind_hooks);
   staticpro (&interval_insert_in_front_hooks);
@@ -2307,42 +2330,44 @@ rear-nonsticky properties of the character overrides NONSTICKINESS.  */);
   /* Common attributes one might give text */
 
   staticpro (&Qforeground);
-  Qforeground = intern ("foreground");
+  Qforeground = intern_c_string ("foreground");
   staticpro (&Qbackground);
-  Qbackground = intern ("background");
+  Qbackground = intern_c_string ("background");
   staticpro (&Qfont);
-  Qfont = intern ("font");
+  Qfont = intern_c_string ("font");
   staticpro (&Qstipple);
-  Qstipple = intern ("stipple");
+  Qstipple = intern_c_string ("stipple");
   staticpro (&Qunderline);
-  Qunderline = intern ("underline");
+  Qunderline = intern_c_string ("underline");
   staticpro (&Qread_only);
-  Qread_only = intern ("read-only");
+  Qread_only = intern_c_string ("read-only");
   staticpro (&Qinvisible);
-  Qinvisible = intern ("invisible");
+  Qinvisible = intern_c_string ("invisible");
   staticpro (&Qintangible);
-  Qintangible = intern ("intangible");
+  Qintangible = intern_c_string ("intangible");
   staticpro (&Qcategory);
-  Qcategory = intern ("category");
+  Qcategory = intern_c_string ("category");
   staticpro (&Qlocal_map);
-  Qlocal_map = intern ("local-map");
+  Qlocal_map = intern_c_string ("local-map");
   staticpro (&Qfront_sticky);
-  Qfront_sticky = intern ("front-sticky");
+  Qfront_sticky = intern_c_string ("front-sticky");
   staticpro (&Qrear_nonsticky);
-  Qrear_nonsticky = intern ("rear-nonsticky");
+  Qrear_nonsticky = intern_c_string ("rear-nonsticky");
   staticpro (&Qmouse_face);
-  Qmouse_face = intern ("mouse-face");
+  Qmouse_face = intern_c_string ("mouse-face");
+  staticpro (&Qminibuffer_prompt);
+  Qminibuffer_prompt = intern_c_string ("minibuffer-prompt");
 
   /* Properties that text might use to specify certain actions */
 
   staticpro (&Qmouse_left);
-  Qmouse_left = intern ("mouse-left");
+  Qmouse_left = intern_c_string ("mouse-left");
   staticpro (&Qmouse_entered);
-  Qmouse_entered = intern ("mouse-entered");
+  Qmouse_entered = intern_c_string ("mouse-entered");
   staticpro (&Qpoint_left);
-  Qpoint_left = intern ("point-left");
+  Qpoint_left = intern_c_string ("point-left");
   staticpro (&Qpoint_entered);
-  Qpoint_entered = intern ("point-entered");
+  Qpoint_entered = intern_c_string ("point-entered");
 
   defsubr (&Stext_properties_at);
   defsubr (&Sget_text_property);