changeset 3960:7be89f84a882

* textprop.c (set_properties): Add undo records to remove entirely new properties. Only record old property values for those properties whose values have changed. * textprop.c (set_properties): Don't try to make undo records if OBJECT is a string.
author Jim Blandy <jimb@redhat.com>
date Fri, 02 Jul 1993 22:50:40 +0000
parents 103a29fa86b7
children e828d5f28ca2
files src/textprop.c
diffstat 1 files changed, 46 insertions(+), 11 deletions(-) [+]
line wrap: on
line diff
--- a/src/textprop.c	Fri Jul 02 21:46:42 1993 +0000
+++ b/src/textprop.c	Fri Jul 02 22:50:40 1993 +0000
@@ -50,6 +50,12 @@
 /* Visual properties text (including strings) may have. */
 Lisp_Object Qforeground, Qbackground, Qfont, Qunderline, Qstipple;
 Lisp_Object Qinvisible, Qread_only;
+
+/* If o1 is a cons whose cdr is a cons, return non-zero and set o2 to
+   the o1's cdr.  Otherwise, return zero.  This is handy for
+   traversing plists.  */
+#define PLIST_ELT_P(o1, o2) (CONSP (o1) && CONSP ((o2) = XCONS (o1)->cdr))
+
 
 /* Extract the interval at the position pointed to by BEGIN from
    OBJECT, a string or buffer.  Additionally, check that the positions
@@ -239,6 +245,24 @@
   return 0;
 }
 
+/* Changing the plists of individual intervals.  */
+
+/* Return the value of PROP in property-list PLIST, or Qunbound if it
+   has none.  */
+static int
+property_value (plist, prop)
+{
+  Lisp_Object value;
+
+  while (PLIST_ELT_P (plist, value))
+    if (EQ (XCONS (plist)->car, prop))
+      return XCONS (value)->car;
+    else
+      plist = XCONS (value)->cdr;
+
+  return Qunbound;
+}
+
 /* Set the properties of INTERVAL to PROPERTIES,
    and record undo info for the previous values.
    OBJECT is the string or buffer that INTERVAL belongs to.  */
@@ -248,19 +272,30 @@
      Lisp_Object properties, object;
      INTERVAL interval;
 {
-  Lisp_Object oldprops;
-  oldprops = interval->plist;
+  Lisp_Object sym, value;
 
-  /* Record undo for old properties.  */
-  while (XTYPE (oldprops) == Lisp_Cons)
+  if (BUFFERP (object))
     {
-      Lisp_Object sym;
-      sym = Fcar (oldprops);
-      record_property_change (interval->position, LENGTH (interval),
-			      sym, Fcar_safe (Fcdr (oldprops)),
-			      object);
-      
-      oldprops = Fcdr_safe (Fcdr (oldprops));
+      /* For each property in the old plist which is missing from PROPERTIES,
+	 or has a different value in PROPERTIES, make an undo record.  */
+      for (sym = interval->plist;
+	   PLIST_ELT_P (sym, value);
+	   sym = XCONS (value)->cdr)
+	if (! EQ (property_value (properties, XCONS (sym)->car),
+		  XCONS (value)->car))
+	  record_property_change (interval->position, LENGTH (interval),
+				  XCONS (sym)->car, XCONS (value)->car,
+				  object);
+
+      /* For each new property that has no value at all in the old plist,
+	 make an undo record binding it to nil, so it will be removed.  */
+      for (sym = properties;
+	   PLIST_ELT_P (sym, value);
+	   sym = XCONS (value)->cdr)
+	if (EQ (property_value (interval->plist, XCONS (sym)->car), Qunbound))
+	  record_property_change (interval->position, LENGTH (interval),
+				  XCONS (sym)->car, Qnil,
+				  object);
     }
 
   /* Store new properties.  */