aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorRichard M. Stallman1993-03-01 08:57:31 +0000
committerRichard M. Stallman1993-03-01 08:57:31 +0000
commitd4b530ad2db1e26f7c6e6635ecdf3b66b74f3585 (patch)
treec40dd5ba50c0fff9ef4a1a698e1053fdbfff14d3 /src
parent323a7ad4fd811dd71425e2fed7ebafb9daaaed72 (diff)
downloademacs-d4b530ad2db1e26f7c6e6635ecdf3b66b74f3585.tar.gz
emacs-d4b530ad2db1e26f7c6e6635ecdf3b66b74f3585.zip
(Fadd_text_properties, Fremove_text_properties):
Add len>0 as condition for main loop. Abort if reach a null interval. (Fset_text_properties): Abort if reach a null interval. (Ftext_properties_at, Fget_text_property): Return nil if POS is end of OBJECT. (add_properties): Use NILP to test result of Fequal. No longer inline. (remove_properties): No longer inline. (set_properties): Total rewrite as function. (validate_interval_range): Don't alter *begin at end of buffer. But do search for a position just before the end. Return null for an empty string. (validate_interval_range): Allow 0 as position in string. Add 1 to specified string positions. (Fprevious_single_property_change): Subtract 1 if object is string. (Fnext_single_property_change): Likewise. (Fprevious_property_change, Fnext_property_change): Likewise. (remove_properties): Call modify_buffer. (add_properties): Likewise. (Fadd_text_properties): Pass new arg to add_properties. (Fremove_text_properties): Likewise. (add_properties, remove_properties): New arg OBJECT. Record undo info. (Fput_text_property): New function.
Diffstat (limited to 'src')
-rw-r--r--src/textprop.c213
1 files changed, 172 insertions, 41 deletions
diff --git a/src/textprop.c b/src/textprop.c
index d8a674a1e70..97951ca1846 100644
--- a/src/textprop.c
+++ b/src/textprop.c
@@ -30,7 +30,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
30 set_properties needs to deal with the interval property cache. 30 set_properties needs to deal with the interval property cache.
31 31
32 It is assumed that for any interval plist, a property appears 32 It is assumed that for any interval plist, a property appears
33 only once on the list. Although some code i.e., remove_properties (), 33 only once on the list. Although some code i.e., remove_properties,
34 handles the more general case, the uniqueness of properties is 34 handles the more general case, the uniqueness of properties is
35 neccessary for the system to remain consistent. This requirement 35 neccessary for the system to remain consistent. This requirement
36 is enforced by the subrs installing properties onto the intervals. */ 36 is enforced by the subrs installing properties onto the intervals. */
@@ -56,6 +56,9 @@ Lisp_Object Qinvisible, Qread_only;
56 to by BEGIN and END may be integers or markers; if the latter, they 56 to by BEGIN and END may be integers or markers; if the latter, they
57 are coerced to integers. 57 are coerced to integers.
58 58
59 When OBJECT is a string, we increment *BEGIN and *END
60 to make them origin-one.
61
59 Note that buffer points don't correspond to interval indices. 62 Note that buffer points don't correspond to interval indices.
60 For example, point-max is 1 greater than the index of the last 63 For example, point-max is 1 greater than the index of the last
61 character. This difference is handled in the caller, which uses 64 character. This difference is handled in the caller, which uses
@@ -67,7 +70,7 @@ Lisp_Object Qinvisible, Qread_only;
67 If FORCE is soft (0), it's OK to return NULL_INTERVAL. Otherwise, 70 If FORCE is soft (0), it's OK to return NULL_INTERVAL. Otherwise,
68 create an interval tree for OBJECT if one doesn't exist, provided 71 create an interval tree for OBJECT if one doesn't exist, provided
69 the object actually contains text. In the current design, if there 72 the object actually contains text. In the current design, if there
70 is no text, there can be no text properties. */ 73 is no text, there can be no text properties. */
71 74
72#define soft 0 75#define soft 0
73#define hard 1 76#define hard 1
@@ -78,6 +81,8 @@ validate_interval_range (object, begin, end, force)
78 int force; 81 int force;
79{ 82{
80 register INTERVAL i; 83 register INTERVAL i;
84 int searchpos;
85
81 CHECK_STRING_OR_BUFFER (object, 0); 86 CHECK_STRING_OR_BUFFER (object, 0);
82 CHECK_NUMBER_COERCE_MARKER (*begin, 0); 87 CHECK_NUMBER_COERCE_MARKER (*begin, 0);
83 CHECK_NUMBER_COERCE_MARKER (*end, 0); 88 CHECK_NUMBER_COERCE_MARKER (*end, 0);
@@ -89,44 +94,60 @@ validate_interval_range (object, begin, end, force)
89 94
90 if (XINT (*begin) > XINT (*end)) 95 if (XINT (*begin) > XINT (*end))
91 { 96 {
92 register int n; 97 Lisp_Object n;
93 n = XFASTINT (*begin); /* This is legit even if *begin is < 0 */ 98 n = *begin;
94 *begin = *end; 99 *begin = *end;
95 XFASTINT (*end) = n; /* because this is all we do with n. */ 100 *end = n;
96 } 101 }
97 102
98 if (XTYPE (object) == Lisp_Buffer) 103 if (XTYPE (object) == Lisp_Buffer)
99 { 104 {
100 register struct buffer *b = XBUFFER (object); 105 register struct buffer *b = XBUFFER (object);
101 106
102 /* If there's no text, there are no properties. */
103 if (BUF_BEGV (b) == BUF_ZV (b))
104 return NULL_INTERVAL;
105
106 if (!(BUF_BEGV (b) <= XINT (*begin) && XINT (*begin) <= XINT (*end) 107 if (!(BUF_BEGV (b) <= XINT (*begin) && XINT (*begin) <= XINT (*end)
107 && XINT (*end) <= BUF_ZV (b))) 108 && XINT (*end) <= BUF_ZV (b)))
108 args_out_of_range (*begin, *end); 109 args_out_of_range (*begin, *end);
109 i = b->intervals; 110 i = b->intervals;
110 111
112 /* If there's no text, there are no properties. */
113 if (BUF_BEGV (b) == BUF_ZV (b))
114 return NULL_INTERVAL;
115
116 searchpos = XINT (*begin);
117 if (searchpos == BUF_Z (b))
118 searchpos--;
119#if 0
111 /* Special case for point-max: return the interval for the 120 /* Special case for point-max: return the interval for the
112 last character. */ 121 last character. */
113 if (*begin == *end && *begin == BUF_Z (b)) 122 if (*begin == *end && *begin == BUF_Z (b))
114 *begin -= 1; 123 *begin -= 1;
124#endif
115 } 125 }
116 else 126 else
117 { 127 {
118 register struct Lisp_String *s = XSTRING (object); 128 register struct Lisp_String *s = XSTRING (object);
119 129
120 if (! (1 <= XINT (*begin) && XINT (*begin) <= XINT (*end) 130 if (! (0 <= XINT (*begin) && XINT (*begin) <= XINT (*end)
121 && XINT (*end) <= s->size)) 131 && XINT (*end) <= s->size))
122 args_out_of_range (*begin, *end); 132 args_out_of_range (*begin, *end);
133 /* User-level Positions in strings start with 0,
134 but the interval code always wants positions starting with 1. */
135 XFASTINT (*begin) += 1;
136 XFASTINT (*end) += 1;
123 i = s->intervals; 137 i = s->intervals;
138
139 if (s->size == 0)
140 return NULL_INTERVAL;
141
142 searchpos = XINT (*begin);
143 if (searchpos > s->size)
144 searchpos--;
124 } 145 }
125 146
126 if (NULL_INTERVAL_P (i)) 147 if (NULL_INTERVAL_P (i))
127 return (force ? create_root_interval (object) : i); 148 return (force ? create_root_interval (object) : i);
128 149
129 return find_interval (i, XINT (*begin)); 150 return find_interval (i, searchpos);
130} 151}
131 152
132/* Validate LIST as a property list. If LIST is not a list, then 153/* Validate LIST as a property list. If LIST is not a list, then
@@ -153,8 +174,6 @@ validate_plist (list)
153 return Fcons (list, Fcons (Qnil, Qnil)); 174 return Fcons (list, Fcons (Qnil, Qnil));
154} 175}
155 176
156#define set_properties(list,i) (i->plist = Fcopy_sequence (list))
157
158/* Return nonzero if interval I has all the properties, 177/* Return nonzero if interval I has all the properties,
159 with the same values, of list PLIST. */ 178 with the same values, of list PLIST. */
160 179
@@ -217,18 +236,49 @@ interval_has_some_properties (plist, i)
217 236
218 return 0; 237 return 0;
219} 238}
239
240/* Set the properties of INTERVAL to PROPERTIES,
241 and record undo info for the previous values.
242 OBJECT is the string or buffer that INTERVAL belongs to. */
243
244static void
245set_properties (properties, interval, object)
246 Lisp_Object properties, object;
247 INTERVAL interval;
248{
249 Lisp_Object oldprops;
250 oldprops = interval->plist;
251
252 /* Record undo for old properties. */
253 while (XTYPE (oldprops) == Lisp_Cons)
254 {
255 Lisp_Object sym;
256 sym = Fcar (oldprops);
257 record_property_change (interval->position, LENGTH (interval),
258 sym, Fcar_safe (Fcdr (oldprops)),
259 object);
260
261 oldprops = Fcdr_safe (Fcdr (oldprops));
262 }
263
264 /* Store new properties. */
265 interval->plist = Fcopy_sequence (properties);
266}
220 267
221/* Add the properties of PLIST to the interval I, or set 268/* Add the properties of PLIST to the interval I, or set
222 the value of I's property to the value of the property on PLIST 269 the value of I's property to the value of the property on PLIST
223 if they are different. 270 if they are different.
224 271
272 OBJECT should be the string or buffer the interval is in.
273
225 Return nonzero if this changes I (i.e., if any members of PLIST 274 Return nonzero if this changes I (i.e., if any members of PLIST
226 are actually added to I's plist) */ 275 are actually added to I's plist) */
227 276
228static INLINE int 277static int
229add_properties (plist, i) 278add_properties (plist, i, object)
230 Lisp_Object plist; 279 Lisp_Object plist;
231 INTERVAL i; 280 INTERVAL i;
281 Lisp_Object object;
232{ 282{
233 register Lisp_Object tail1, tail2, sym1, val1; 283 register Lisp_Object tail1, tail2, sym1, val1;
234 register int changed = 0; 284 register int changed = 0;
@@ -252,9 +302,18 @@ add_properties (plist, i)
252 302
253 /* The properties have the same value on both lists. 303 /* The properties have the same value on both lists.
254 Continue to the next property. */ 304 Continue to the next property. */
255 if (Fequal (val1, Fcar (this_cdr))) 305 if (!NILP (Fequal (val1, Fcar (this_cdr))))
256 break; 306 break;
257 307
308 /* Record this change in the buffer, for undo purposes. */
309 if (XTYPE (object) == Lisp_Buffer)
310 {
311 record_property_change (i->position, LENGTH (i),
312 sym1, Fcar (this_cdr), object);
313 modify_region (make_number (i->position),
314 make_number (i->position + LENGTH (i)));
315 }
316
258 /* I's property has a different value -- change it */ 317 /* I's property has a different value -- change it */
259 Fsetcar (this_cdr, val1); 318 Fsetcar (this_cdr, val1);
260 changed++; 319 changed++;
@@ -263,6 +322,14 @@ add_properties (plist, i)
263 322
264 if (! found) 323 if (! found)
265 { 324 {
325 /* Record this change in the buffer, for undo purposes. */
326 if (XTYPE (object) == Lisp_Buffer)
327 {
328 record_property_change (i->position, LENGTH (i),
329 sym1, Qnil, object);
330 modify_region (make_number (i->position),
331 make_number (i->position + LENGTH (i)));
332 }
266 i->plist = Fcons (sym1, Fcons (val1, i->plist)); 333 i->plist = Fcons (sym1, Fcons (val1, i->plist));
267 changed++; 334 changed++;
268 } 335 }
@@ -272,12 +339,14 @@ add_properties (plist, i)
272} 339}
273 340
274/* For any members of PLIST which are properties of I, remove them 341/* For any members of PLIST which are properties of I, remove them
275 from I's plist. */ 342 from I's plist.
343 OBJECT is the string or buffer containing I. */
276 344
277static INLINE int 345static int
278remove_properties (plist, i) 346remove_properties (plist, i, object)
279 Lisp_Object plist; 347 Lisp_Object plist;
280 INTERVAL i; 348 INTERVAL i;
349 Lisp_Object object;
281{ 350{
282 register Lisp_Object tail1, tail2, sym; 351 register Lisp_Object tail1, tail2, sym;
283 register Lisp_Object current_plist = i->plist; 352 register Lisp_Object current_plist = i->plist;
@@ -291,6 +360,15 @@ remove_properties (plist, i)
291 /* First, remove the symbol if its at the head of the list */ 360 /* First, remove the symbol if its at the head of the list */
292 while (! NILP (current_plist) && EQ (sym, Fcar (current_plist))) 361 while (! NILP (current_plist) && EQ (sym, Fcar (current_plist)))
293 { 362 {
363 if (XTYPE (object) == Lisp_Buffer)
364 {
365 record_property_change (i->position, LENGTH (i),
366 sym, Fcar (Fcdr (current_plist)),
367 object);
368 modify_region (make_number (i->position),
369 make_number (i->position + LENGTH (i)));
370 }
371
294 current_plist = Fcdr (Fcdr (current_plist)); 372 current_plist = Fcdr (Fcdr (current_plist));
295 changed++; 373 changed++;
296 } 374 }
@@ -302,6 +380,14 @@ remove_properties (plist, i)
302 register Lisp_Object this = Fcdr (Fcdr (tail2)); 380 register Lisp_Object this = Fcdr (Fcdr (tail2));
303 if (EQ (sym, Fcar (this))) 381 if (EQ (sym, Fcar (this)))
304 { 382 {
383 if (XTYPE (object) == Lisp_Buffer)
384 {
385 record_property_change (i->position, LENGTH (i),
386 sym, Fcar (Fcdr (this)), object);
387 modify_region (make_number (i->position),
388 make_number (i->position + LENGTH (i)));
389 }
390
305 Fsetcdr (Fcdr (tail2), Fcdr (Fcdr (this))); 391 Fsetcdr (Fcdr (tail2), Fcdr (Fcdr (this)));
306 changed++; 392 changed++;
307 } 393 }
@@ -314,6 +400,7 @@ remove_properties (plist, i)
314 return changed; 400 return changed;
315} 401}
316 402
403#if 0
317/* Remove all properties from interval I. Return non-zero 404/* Remove all properties from interval I. Return non-zero
318 if this changes the interval. */ 405 if this changes the interval. */
319 406
@@ -327,12 +414,14 @@ erase_properties (i)
327 i->plist = Qnil; 414 i->plist = Qnil;
328 return 1; 415 return 1;
329} 416}
417#endif
330 418
331DEFUN ("text-properties-at", Ftext_properties_at, 419DEFUN ("text-properties-at", Ftext_properties_at,
332 Stext_properties_at, 1, 2, 0, 420 Stext_properties_at, 1, 2, 0,
333 "Return the list of properties held by the character at POSITION\n\ 421 "Return the list of properties held by the character at POSITION\n\
334in optional argument OBJECT, a string or buffer. If nil, OBJECT\n\ 422in optional argument OBJECT, a string or buffer. If nil, OBJECT\n\
335defaults to the current buffer.") 423defaults to the current buffer.\n\
424If POSITION is at the end of OBJECT, the value is nil.")
336 (pos, object) 425 (pos, object)
337 Lisp_Object pos, object; 426 Lisp_Object pos, object;
338{ 427{
@@ -344,13 +433,20 @@ defaults to the current buffer.")
344 i = validate_interval_range (object, &pos, &pos, soft); 433 i = validate_interval_range (object, &pos, &pos, soft);
345 if (NULL_INTERVAL_P (i)) 434 if (NULL_INTERVAL_P (i))
346 return Qnil; 435 return Qnil;
436 /* If POS is at the end of the interval,
437 it means it's the end of OBJECT.
438 There are no properties at the very end,
439 since no character follows. */
440 if (XINT (pos) == LENGTH (i) + i->position)
441 return Qnil;
347 442
348 return i->plist; 443 return i->plist;
349} 444}
350 445
351DEFUN ("get-text-property", Fget_text_property, Sget_text_property, 2, 3, 0, 446DEFUN ("get-text-property", Fget_text_property, Sget_text_property, 2, 3, 0,
352 "Return the value of position POS's property PROP, in OBJECT.\n\ 447 "Return the value of position POS's property PROP, in OBJECT.\n\
353OBJECT is optional and defaults to the current buffer.") 448OBJECT is optional and defaults to the current buffer.\n\
449If POSITION is at the end of OBJECT, the value is nil.")
354 (pos, prop, object) 450 (pos, prop, object)
355 Lisp_Object pos, object; 451 Lisp_Object pos, object;
356 register Lisp_Object prop; 452 register Lisp_Object prop;
@@ -360,11 +456,17 @@ OBJECT is optional and defaults to the current buffer.")
360 456
361 if (NILP (object)) 457 if (NILP (object))
362 XSET (object, Lisp_Buffer, current_buffer); 458 XSET (object, Lisp_Buffer, current_buffer);
363
364 i = validate_interval_range (object, &pos, &pos, soft); 459 i = validate_interval_range (object, &pos, &pos, soft);
365 if (NULL_INTERVAL_P (i)) 460 if (NULL_INTERVAL_P (i))
366 return Qnil; 461 return Qnil;
367 462
463 /* If POS is at the end of the interval,
464 it means it's the end of OBJECT.
465 There are no properties at the very end,
466 since no character follows. */
467 if (XINT (pos) == LENGTH (i) + i->position)
468 return Qnil;
469
368 for (tail = i->plist; !NILP (tail); tail = Fcdr (Fcdr (tail))) 470 for (tail = i->plist; !NILP (tail); tail = Fcdr (Fcdr (tail)))
369 { 471 {
370 register Lisp_Object tem; 472 register Lisp_Object tem;
@@ -402,7 +504,8 @@ If the value is non-nil, it is a position greater than POS, never equal.")
402 if (NULL_INTERVAL_P (next)) 504 if (NULL_INTERVAL_P (next))
403 return Qnil; 505 return Qnil;
404 506
405 return next->position; 507 return next->position - (XTYPE (object) == Lisp_String);
508;
406} 509}
407 510
408DEFUN ("next-single-property-change", Fnext_single_property_change, 511DEFUN ("next-single-property-change", Fnext_single_property_change,
@@ -434,7 +537,7 @@ If the value is non-nil, it is a position greater than POS, never equal.")
434 if (NULL_INTERVAL_P (next)) 537 if (NULL_INTERVAL_P (next))
435 return Qnil; 538 return Qnil;
436 539
437 return next->position; 540 return next->position - (XTYPE (object) == Lisp_String);
438} 541}
439 542
440DEFUN ("previous-property-change", Fprevious_property_change, 543DEFUN ("previous-property-change", Fprevious_property_change,
@@ -463,7 +566,8 @@ If the value is non-nil, it is a position less than POS, never equal.")
463 if (NULL_INTERVAL_P (previous)) 566 if (NULL_INTERVAL_P (previous))
464 return Qnil; 567 return Qnil;
465 568
466 return previous->position + LENGTH (previous) - 1; 569 return (previous->position + LENGTH (previous) - 1
570 - (XTYPE (object) == Lisp_String));
467} 571}
468 572
469DEFUN ("previous-single-property-change", Fprevious_single_property_change, 573DEFUN ("previous-single-property-change", Fprevious_single_property_change,
@@ -495,7 +599,8 @@ If the value is non-nil, it is a position less than POS, never equal.")
495 if (NULL_INTERVAL_P (previous)) 599 if (NULL_INTERVAL_P (previous))
496 return Qnil; 600 return Qnil;
497 601
498 return previous->position + LENGTH (previous) - 1; 602 return (previous->position + LENGTH (previous) - 1
603 - (XTYPE (object) == Lisp_String));
499} 604}
500 605
501DEFUN ("add-text-properties", Fadd_text_properties, 606DEFUN ("add-text-properties", Fadd_text_properties,
@@ -548,11 +653,11 @@ Return t if any property value actually changed, nil otherwise.")
548 { 653 {
549 i = split_interval_left (i, len + 1); 654 i = split_interval_left (i, len + 1);
550 copy_properties (unchanged, i); 655 copy_properties (unchanged, i);
551 add_properties (properties, i); 656 add_properties (properties, i, object);
552 return Qt; 657 return Qt;
553 } 658 }
554 659
555 add_properties (properties, i); 660 add_properties (properties, i, object);
556 modified = 1; 661 modified = 1;
557 len -= LENGTH (i); 662 len -= LENGTH (i);
558 i = next_interval (i); 663 i = next_interval (i);
@@ -560,8 +665,11 @@ Return t if any property value actually changed, nil otherwise.")
560 } 665 }
561 666
562 /* We are at the beginning of an interval, with len to scan */ 667 /* We are at the beginning of an interval, with len to scan */
563 while (1) 668 while (len > 0)
564 { 669 {
670 if (i == 0)
671 abort ();
672
565 if (LENGTH (i) >= len) 673 if (LENGTH (i) >= len)
566 { 674 {
567 if (interval_has_all_properties (properties, i)) 675 if (interval_has_all_properties (properties, i))
@@ -569,7 +677,7 @@ Return t if any property value actually changed, nil otherwise.")
569 677
570 if (LENGTH (i) == len) 678 if (LENGTH (i) == len)
571 { 679 {
572 add_properties (properties, i); 680 add_properties (properties, i, object);
573 return Qt; 681 return Qt;
574 } 682 }
575 683
@@ -577,16 +685,32 @@ Return t if any property value actually changed, nil otherwise.")
577 unchanged = i; 685 unchanged = i;
578 i = split_interval_left (unchanged, len + 1); 686 i = split_interval_left (unchanged, len + 1);
579 copy_properties (unchanged, i); 687 copy_properties (unchanged, i);
580 add_properties (properties, i); 688 add_properties (properties, i, object);
581 return Qt; 689 return Qt;
582 } 690 }
583 691
584 len -= LENGTH (i); 692 len -= LENGTH (i);
585 modified += add_properties (properties, i); 693 modified += add_properties (properties, i, object);
586 i = next_interval (i); 694 i = next_interval (i);
587 } 695 }
588} 696}
589 697
698DEFUN ("put-text-property", Fput_text_property,
699 Sput_text_property, 4, 5, 0,
700 "Set one property of the text from START to END.\n\
701The third and fourth arguments PROP and VALUE\n\
702specify the property to add.\n\
703The optional fifth argument, OBJECT,\n\
704is the string or buffer containing the text.")
705 (start, end, prop, value, object)
706 Lisp_Object start, end, prop, value, object;
707{
708 Fadd_text_properties (start, end,
709 Fcons (prop, Fcons (value, Qnil)),
710 object);
711 return Qnil;
712}
713
590DEFUN ("set-text-properties", Fset_text_properties, 714DEFUN ("set-text-properties", Fset_text_properties,
591 Sset_text_properties, 3, 4, 0, 715 Sset_text_properties, 3, 4, 0,
592 "Completely replace properties of text from START to END.\n\ 716 "Completely replace properties of text from START to END.\n\
@@ -618,7 +742,7 @@ is the string or buffer containing the text.")
618 { 742 {
619 unchanged = i; 743 unchanged = i;
620 i = split_interval_right (unchanged, s - unchanged->position + 1); 744 i = split_interval_right (unchanged, s - unchanged->position + 1);
621 set_properties (props, i); 745 set_properties (props, i, object);
622 746
623 if (LENGTH (i) > len) 747 if (LENGTH (i) > len)
624 { 748 {
@@ -638,13 +762,16 @@ is the string or buffer containing the text.")
638 /* We are starting at the beginning of an interval, I */ 762 /* We are starting at the beginning of an interval, I */
639 while (len > 0) 763 while (len > 0)
640 { 764 {
765 if (i == 0)
766 abort ();
767
641 if (LENGTH (i) >= len) 768 if (LENGTH (i) >= len)
642 { 769 {
643 if (LENGTH (i) > len) 770 if (LENGTH (i) > len)
644 i = split_interval_left (i, len + 1); 771 i = split_interval_left (i, len + 1);
645 772
646 if (NULL_INTERVAL_P (prev_changed)) 773 if (NULL_INTERVAL_P (prev_changed))
647 set_properties (props, i); 774 set_properties (props, i, object);
648 else 775 else
649 merge_interval_left (i); 776 merge_interval_left (i);
650 return Qt; 777 return Qt;
@@ -653,7 +780,7 @@ is the string or buffer containing the text.")
653 len -= LENGTH (i); 780 len -= LENGTH (i);
654 if (NULL_INTERVAL_P (prev_changed)) 781 if (NULL_INTERVAL_P (prev_changed))
655 { 782 {
656 set_properties (props, i); 783 set_properties (props, i, object);
657 prev_changed = i; 784 prev_changed = i;
658 } 785 }
659 else 786 else
@@ -712,11 +839,11 @@ Return t if any property was actually removed, nil otherwise.")
712 { 839 {
713 i = split_interval_left (i, len + 1); 840 i = split_interval_left (i, len + 1);
714 copy_properties (unchanged, i); 841 copy_properties (unchanged, i);
715 remove_properties (props, i); 842 remove_properties (props, i, object);
716 return Qt; 843 return Qt;
717 } 844 }
718 845
719 remove_properties (props, i); 846 remove_properties (props, i, object);
720 modified = 1; 847 modified = 1;
721 len -= LENGTH (i); 848 len -= LENGTH (i);
722 i = next_interval (i); 849 i = next_interval (i);
@@ -724,8 +851,11 @@ Return t if any property was actually removed, nil otherwise.")
724 } 851 }
725 852
726 /* We are at the beginning of an interval, with len to scan */ 853 /* We are at the beginning of an interval, with len to scan */
727 while (1) 854 while (len > 0)
728 { 855 {
856 if (i == 0)
857 abort ();
858
729 if (LENGTH (i) >= len) 859 if (LENGTH (i) >= len)
730 { 860 {
731 if (! interval_has_some_properties (props, i)) 861 if (! interval_has_some_properties (props, i))
@@ -733,19 +863,19 @@ Return t if any property was actually removed, nil otherwise.")
733 863
734 if (LENGTH (i) == len) 864 if (LENGTH (i) == len)
735 { 865 {
736 remove_properties (props, i); 866 remove_properties (props, i, object);
737 return Qt; 867 return Qt;
738 } 868 }
739 869
740 /* i has the properties, and goes past the change limit */ 870 /* i has the properties, and goes past the change limit */
741 unchanged = split_interval_right (i, len + 1); 871 unchanged = split_interval_right (i, len + 1);
742 copy_properties (unchanged, i); 872 copy_properties (unchanged, i);
743 remove_properties (props, i); 873 remove_properties (props, i, object);
744 return Qt; 874 return Qt;
745 } 875 }
746 876
747 len -= LENGTH (i); 877 len -= LENGTH (i);
748 modified += remove_properties (props, i); 878 modified += remove_properties (props, i, object);
749 i = next_interval (i); 879 i = next_interval (i);
750 } 880 }
751} 881}
@@ -903,6 +1033,7 @@ percentage by which the left interval tree should not differ from the right.");
903 defsubr (&Sprevious_property_change); 1033 defsubr (&Sprevious_property_change);
904 defsubr (&Sprevious_single_property_change); 1034 defsubr (&Sprevious_single_property_change);
905 defsubr (&Sadd_text_properties); 1035 defsubr (&Sadd_text_properties);
1036 defsubr (&Sput_text_property);
906 defsubr (&Sset_text_properties); 1037 defsubr (&Sset_text_properties);
907 defsubr (&Sremove_text_properties); 1038 defsubr (&Sremove_text_properties);
908/* defsubr (&Serase_text_properties); */ 1039/* defsubr (&Serase_text_properties); */