(struct x_display_info): Struct renamed from x_screen.
[bpt/emacs.git] / src / textprop.c
index fa0817c..2e76f0c 100644 (file)
@@ -1,5 +1,5 @@
 /* Interface code for dealing with text properties.
-   Copyright (C) 1993 Free Software Foundation, Inc.
+   Copyright (C) 1993, 1994 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -22,6 +22,10 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 #include "intervals.h"
 #include "buffer.h"
 #include "window.h"
+
+#ifndef NULL
+#define NULL (void *)0
+#endif
 \f
 
 /* NOTES:  previous- and next- property change will have to skip
@@ -49,7 +53,7 @@ Lisp_Object Qlocal_map;
 
 /* Visual properties text (including strings) may have. */
 Lisp_Object Qforeground, Qbackground, Qfont, Qunderline, Qstipple;
-Lisp_Object Qinvisible, Qread_only, Qhidden;
+Lisp_Object Qinvisible, Qread_only, Qintangible;
 
 /* Sticky properties */
 Lisp_Object Qfront_sticky, Qrear_nonsticky;
@@ -102,7 +106,7 @@ validate_interval_range (object, begin, end, force)
 
   /* If we are asked for a point, but from a subr which operates
      on a range, then return nothing. */
-  if (*begin == *end && begin != end)
+  if (EQ (*begin, *end) && begin != end)
     return NULL_INTERVAL;
 
   if (XINT (*begin) > XINT (*end))
@@ -113,7 +117,7 @@ validate_interval_range (object, begin, end, force)
       *end = n;
     }
 
-  if (XTYPE (object) == Lisp_Buffer)
+  if (BUFFERP (object))
     {
       register struct buffer *b = XBUFFER (object);
 
@@ -137,9 +141,9 @@ validate_interval_range (object, begin, end, force)
        args_out_of_range (*begin, *end);
       /* User-level Positions in strings start with 0,
         but the interval code always wants positions starting with 1.  */
-      XFASTINT (*begin) += 1;
+      XSETFASTINT (*begin, XFASTINT (*begin) + 1);
       if (begin != end)
-       XFASTINT (*end) += 1;
+       XSETFASTINT (*end, XFASTINT (*end) + 1);
       i = s->intervals;
 
       if (s->size == 0)
@@ -248,8 +252,9 @@ interval_has_some_properties (plist, i)
 
 /* Return the value of PROP in property-list PLIST, or Qunbound if it
    has none.  */
-static int
+static Lisp_Object
 property_value (plist, prop)
+     Lisp_Object plist, prop;
 {
   Lisp_Object value;
 
@@ -353,7 +358,7 @@ add_properties (plist, i, object)
              break;
 
            /* Record this change in the buffer, for undo purposes.  */
-           if (XTYPE (object) == Lisp_Buffer)
+           if (BUFFERP (object))
              {
                modify_region (XBUFFER (object),
                               make_number (i->position),
@@ -371,7 +376,7 @@ add_properties (plist, i, object)
       if (! found)
        {
          /* Record this change in the buffer, for undo purposes.  */
-         if (XTYPE (object) == Lisp_Buffer)
+         if (BUFFERP (object))
            {
              modify_region (XBUFFER (object),
                             make_number (i->position),
@@ -409,7 +414,7 @@ remove_properties (plist, i, object)
       /* First, remove the symbol if its at the head of the list */
       while (! NILP (current_plist) && EQ (sym, Fcar (current_plist)))
        {
-         if (XTYPE (object) == Lisp_Buffer)
+         if (BUFFERP (object))
            {
              modify_region (XBUFFER (object),
                             make_number (i->position),
@@ -431,7 +436,7 @@ remove_properties (plist, i, object)
          this = Fcdr (Fcdr (tail2));
          if (EQ (sym, Fcar (this)))
            {
-             if (XTYPE (object) == Lisp_Buffer)
+             if (BUFFERP (object))
                {
                  modify_region (XBUFFER (object),
                                 make_number (i->position),
@@ -480,7 +485,7 @@ If POSITION is at the end of OBJECT, the value is nil.")
   register INTERVAL i;
 
   if (NILP (object))
-    XSET (object, Lisp_Buffer, current_buffer);
+    XSETBUFFER (object, current_buffer);
 
   i = validate_interval_range (object, &pos, &pos, soft);
   if (NULL_INTERVAL_P (i))
@@ -501,25 +506,9 @@ OBJECT is optional and defaults to the current buffer.\n\
 If POSITION is at the end of OBJECT, the value is nil.")
   (pos, prop, object)
      Lisp_Object pos, object;
-     register Lisp_Object prop;
+     Lisp_Object prop;
 {
-  register INTERVAL i;
-  register Lisp_Object tail;
-
-  if (NILP (object))
-    XSET (object, Lisp_Buffer, current_buffer);
-  i = validate_interval_range (object, &pos, &pos, soft);
-  if (NULL_INTERVAL_P (i))
-    return Qnil;
-
-  /* If POS is at the end of the interval,
-     it means it's the end of OBJECT.
-     There are no properties at the very end,
-     since no character follows.  */
-  if (XINT (pos) == LENGTH (i) + i->position)
-    return Qnil;
-
-  return textget (i->plist, prop);
+  return textget (Ftext_properties_at (pos, object), prop);
 }
 
 DEFUN ("get-char-property", Fget_char_property, Sget_char_property, 2, 3, 0,
@@ -539,12 +528,12 @@ overlays are considered only if they are associated with OBJECT.")
   CHECK_NUMBER_COERCE_MARKER (pos, 0);
 
   if (NILP (object))
-    XSET (object, Lisp_Buffer, current_buffer);
+    XSETBUFFER (object, current_buffer);
 
   if (WINDOWP (object))
     {
       w = XWINDOW (object);
-      XSET (object, Lisp_Buffer, w->buffer);
+      object = w->buffer;
     }
   if (BUFFERP (object))
     {
@@ -558,7 +547,8 @@ overlays are considered only if they are associated with OBJECT.")
       len = 40;
       overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
 
-      noverlays = overlays_at (posn, 0, &overlay_vec, &len, &next_overlay);
+      noverlays = overlays_at (posn, 0, &overlay_vec, &len,
+                              &next_overlay, NULL);
 
       /* If there are more than 40,
         make enough space for all, and try again.  */
@@ -566,7 +556,8 @@ overlays are considered only if they are associated with OBJECT.")
        {
          len = noverlays;
          overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
-         noverlays = overlays_at (posn, 0, &overlay_vec, &len, &next_overlay);
+         noverlays = overlays_at (posn, 0, &overlay_vec, &len,
+                                  &next_overlay, NULL);
        }
       noverlays = sort_overlays (overlay_vec, noverlays, w);
 
@@ -599,7 +590,10 @@ past position LIMIT; return LIMIT if nothing is found before LIMIT.")
   register INTERVAL i, next;
 
   if (NILP (object))
-    XSET (object, Lisp_Buffer, current_buffer);
+    XSETBUFFER (object, current_buffer);
+
+  if (!NILP (limit))
+    CHECK_NUMBER_COERCE_MARKER (limit, 0);
 
   i = validate_interval_range (object, &pos, &pos, soft);
   if (NULL_INTERVAL_P (i))
@@ -615,7 +609,8 @@ past position LIMIT; return LIMIT if nothing is found before LIMIT.")
   if (! NILP (limit) && !(next->position < XFASTINT (limit)))
     return limit;
 
-  return next->position - (XTYPE (object) == Lisp_String);
+  XSETFASTINT (pos, next->position - (STRINGP (object)));
+  return pos;
 }
 
 /* Return 1 if there's a change in some property between BEG and END.  */
@@ -627,8 +622,8 @@ property_change_between_p (beg, end)
   register INTERVAL i, next;
   Lisp_Object object, pos;
 
-  XSET (object, Lisp_Buffer, current_buffer);
-  XFASTINT (pos) = beg;
+  XSETBUFFER (object, current_buffer);
+  XSETFASTINT (pos, beg);
 
   i = validate_interval_range (object, &pos, &pos, soft);
   if (NULL_INTERVAL_P (i))
@@ -668,7 +663,10 @@ past position LIMIT; return LIMIT if nothing is found before LIMIT.")
   register Lisp_Object here_val;
 
   if (NILP (object))
-    XSET (object, Lisp_Buffer, current_buffer);
+    XSETBUFFER (object, current_buffer);
+
+  if (!NILP (limit))
+    CHECK_NUMBER_COERCE_MARKER (limit, 0);
 
   i = validate_interval_range (object, &pos, &pos, soft);
   if (NULL_INTERVAL_P (i))
@@ -686,7 +684,8 @@ past position LIMIT; return LIMIT if nothing is found before LIMIT.")
   if (! NILP (limit) && !(next->position < XFASTINT (limit)))
     return limit;
 
-  return next->position - (XTYPE (object) == Lisp_String);
+  XSETFASTINT (pos, next->position - (STRINGP (object)));
+  return pos;
 }
 
 DEFUN ("previous-property-change", Fprevious_property_change,
@@ -705,7 +704,10 @@ back past position LIMIT; return LIMIT if nothing is found until LIMIT.")
   register INTERVAL i, previous;
 
   if (NILP (object))
-    XSET (object, Lisp_Buffer, current_buffer);
+    XSETBUFFER (object, current_buffer);
+
+  if (!NILP (limit))
+    CHECK_NUMBER_COERCE_MARKER (limit, 0);
 
   i = validate_interval_range (object, &pos, &pos, soft);
   if (NULL_INTERVAL_P (i))
@@ -726,8 +728,9 @@ back past position LIMIT; return LIMIT if nothing is found until LIMIT.")
       && !(previous->position + LENGTH (previous) > XFASTINT (limit)))
     return limit;
 
-  return (previous->position + LENGTH (previous)
-         - (XTYPE (object) == Lisp_String));
+  XSETFASTINT (pos, (previous->position + LENGTH (previous)
+                    - (STRINGP (object))));
+  return pos;
 }
 
 DEFUN ("previous-single-property-change", Fprevious_single_property_change,
@@ -748,16 +751,20 @@ back past position LIMIT; return LIMIT if nothing is found until LIMIT.")
   register Lisp_Object here_val;
 
   if (NILP (object))
-    XSET (object, Lisp_Buffer, current_buffer);
+    XSETBUFFER (object, current_buffer);
+
+  if (!NILP (limit))
+    CHECK_NUMBER_COERCE_MARKER (limit, 0);
 
   i = validate_interval_range (object, &pos, &pos, soft);
-  if (NULL_INTERVAL_P (i))
-    return limit;
 
   /* Start with the interval containing the char before point.  */
-  if (i->position == XFASTINT (pos))
+  if (! NULL_INTERVAL_P (i) && i->position == XFASTINT (pos))
     i = previous_interval (i);
 
+  if (NULL_INTERVAL_P (i))
+    return limit;
+
   here_val = textget (i->plist, prop);
   previous = previous_interval (i);
   while (! NULL_INTERVAL_P (previous)
@@ -771,8 +778,9 @@ back past position LIMIT; return LIMIT if nothing is found until LIMIT.")
       && !(previous->position + LENGTH (previous) > XFASTINT (limit)))
     return limit;
 
-  return (previous->position + LENGTH (previous)
-         - (XTYPE (object) == Lisp_String));
+  XSETFASTINT (pos, (previous->position + LENGTH (previous)
+                    - (STRINGP (object))));
+  return pos;
 }
 
 DEFUN ("add-text-properties", Fadd_text_properties,
@@ -794,7 +802,7 @@ Return t if any property value actually changed, nil otherwise.")
     return Qnil;
 
   if (NILP (object))
-    XSET (object, Lisp_Buffer, current_buffer);
+    XSETBUFFER (object, current_buffer);
 
   i = validate_interval_range (object, &start, &end, hard);
   if (NULL_INTERVAL_P (i))
@@ -884,15 +892,44 @@ is the string or buffer containing the text.")
   register INTERVAL i, unchanged;
   register INTERVAL prev_changed = NULL_INTERVAL;
   register int s, len;
+  Lisp_Object ostart, oend;
+
+  ostart = start;
+  oend = end;
 
   props = validate_plist (props);
 
   if (NILP (object))
-    XSET (object, Lisp_Buffer, current_buffer);
+    XSETBUFFER (object, current_buffer);
+
+  /* If we want no properties for a whole string,
+     get rid of its intervals.  */
+  if (NILP (props) && STRINGP (object)
+      && XFASTINT (start) == 0
+      && XFASTINT (end) == XSTRING (object)->size)
+    {
+      XSTRING (object)->intervals = 0;
+      return Qt;
+    }
+
+  i = validate_interval_range (object, &start, &end, soft);
 
-  i = validate_interval_range (object, &start, &end, hard);
   if (NULL_INTERVAL_P (i))
-    return Qnil;
+    {
+      /* If buffer has no props, and we want none, return now.  */
+      if (NILP (props))
+       return Qnil;
+
+      /* Restore the original START and END values
+        because validate_interval_range increments them for strings.  */
+      start = ostart;
+      end = oend;
+
+      i = validate_interval_range (object, &start, &end, hard);
+      /* This can return if start == end.  */
+      if (NULL_INTERVAL_P (i))
+       return Qnil;
+    }
 
   s = XINT (start);
   len = XINT (end) - s;
@@ -969,7 +1006,7 @@ Return t if any property was actually removed, nil otherwise.")
   register int s, len, modified = 0;
 
   if (NILP (object))
-    XSET (object, Lisp_Buffer, current_buffer);
+    XSETBUFFER (object, current_buffer);
 
   i = validate_interval_range (object, &start, &end, soft);
   if (NULL_INTERVAL_P (i))
@@ -1045,7 +1082,7 @@ containing the text.")
   register int e, pos;
 
   if (NILP (object))
-    XSET (object, Lisp_Buffer, current_buffer);
+    XSETBUFFER (object, current_buffer);
   i = validate_interval_range (object, &start, &end, soft);
   e = XINT (end);
 
@@ -1058,7 +1095,7 @@ containing the text.")
          pos = i->position;
          if (pos < XINT (start))
            pos = XINT (start);
-         return make_number (pos - (XTYPE (object) == Lisp_String));
+         return make_number (pos - (STRINGP (object)));
        }
       i = next_interval (i);
     }
@@ -1079,7 +1116,7 @@ containing the text.")
   register int s, e;
 
   if (NILP (object))
-    XSET (object, Lisp_Buffer, current_buffer);
+    XSETBUFFER (object, current_buffer);
   i = validate_interval_range (object, &start, &end, soft);
   if (NULL_INTERVAL_P (i))
     return (NILP (value) || EQ (start, end)) ? Qnil : start;
@@ -1094,7 +1131,7 @@ containing the text.")
        {
          if (i->position > s)
            s = i->position;
-         return make_number (s - (XTYPE (object) == Lisp_String));
+         return make_number (s - (STRINGP (object)));
        }
       i = next_interval (i);
     }
@@ -1116,7 +1153,7 @@ is the string or buffer containing the text.")
   register int s, len, modified;
 
   if (NILP (object))
-    XSET (object, Lisp_Buffer, current_buffer);
+    XSETBUFFER (object, current_buffer);
 
   i = validate_interval_range (object, &start, &end, soft);
   if (NULL_INTERVAL_P (i))
@@ -1244,7 +1281,7 @@ copy_text_properties (start, end, src, pos, dest, prop)
     Lisp_Object dest_start, dest_end;
 
     dest_start = pos;
-    XFASTINT (dest_end) = XINT (dest_start) + (XINT (end) - XINT (start));
+    XSETFASTINT (dest_end, XINT (dest_start) + (XINT (end) - XINT (start)));
     /* Apply this to a copy of pos; it will try to increment its arguments,
        which we don't want.  */
     validate_interval_range (dest, &dest_start, &dest_end, soft);
@@ -1308,14 +1345,9 @@ copy_text_properties (start, end, src, pos, dest, prop)
 void
 syms_of_textprop ()
 {
-  DEFVAR_INT ("interval-balance-threshold", &interval_balance_threshold,
-             "Threshold for rebalancing interval trees, expressed as the\n\
-percentage by which the left interval tree should not differ from the right.");
-  interval_balance_threshold = 8;
-
   DEFVAR_LISP ("inhibit-point-motion-hooks", &Vinhibit_point_motion_hooks,
-              "If non-nil, don't call the text property values of\n\
-`point-left' and `point-entered'.");
+   "If non-nil, don't run `point-left' and `point-entered' text properties.\n\
+This also inhibits the use of the `intangible' text property.");
   Vinhibit_point_motion_hooks = Qnil;
               
   /* Common attributes one might give text */
@@ -1334,8 +1366,8 @@ percentage by which the left interval tree should not differ from the right.");
   Qread_only = intern ("read-only");
   staticpro (&Qinvisible);
   Qinvisible = intern ("invisible");
-  staticpro (&Qhidden);
-  Qhidden = intern ("hidden");
+  staticpro (&Qintangible);
+  Qintangible = intern ("intangible");
   staticpro (&Qcategory);
   Qcategory = intern ("category");
   staticpro (&Qlocal_map);
@@ -1358,6 +1390,7 @@ percentage by which the left interval tree should not differ from the right.");
 
   defsubr (&Stext_properties_at);
   defsubr (&Sget_text_property);
+  defsubr (&Sget_char_property);
   defsubr (&Snext_property_change);
   defsubr (&Snext_single_property_change);
   defsubr (&Sprevious_property_change);