aboutsummaryrefslogtreecommitdiffstats
path: root/src/textprop.c
diff options
context:
space:
mode:
authorRichard M. Stallman2002-04-19 00:14:14 +0000
committerRichard M. Stallman2002-04-19 00:14:14 +0000
commit11713b6dafb4f63fa246c6de77133ed8ec80243a (patch)
treec330d2440dd2b8f6d7caf0df5f1e6c53f2c766c4 /src/textprop.c
parent0cf5c1e712ca58e2d3edc8d238038efb6f5beb5d (diff)
downloademacs-11713b6dafb4f63fa246c6de77133ed8ec80243a.tar.gz
emacs-11713b6dafb4f63fa246c6de77133ed8ec80243a.zip
(remove_properties): New arg LIST allows scanning
either a list or a plist. (interval_has_some_properties_list): New function, like interval_has_some_properties using list instead of plist. All callers changed. (Fremove_list_of_text_properties): New function. (syms_of_textprop): Defsubr it.
Diffstat (limited to 'src/textprop.c')
-rw-r--r--src/textprop.c176
1 files changed, 150 insertions, 26 deletions
diff --git a/src/textprop.c b/src/textprop.c
index 48791c68843..928c9f9b8b3 100644
--- a/src/textprop.c
+++ b/src/textprop.c
@@ -268,6 +268,30 @@ interval_has_some_properties (plist, i)
268 268
269 return 0; 269 return 0;
270} 270}
271
272/* Return nonzero if the plist of interval I has any of the
273 property names in LIST, regardless of their values. */
274
275static INLINE int
276interval_has_some_properties_list (list, i)
277 Lisp_Object list;
278 INTERVAL i;
279{
280 register Lisp_Object tail1, tail2, sym;
281
282 /* Go through each element of LIST. */
283 for (tail1 = list; ! NILP (tail1); tail1 = XCDR (tail1))
284 {
285 sym = Fcar (tail1);
286
287 /* Go through i's plist, looking for tail1 */
288 for (tail2 = i->plist; ! NILP (tail2); tail2 = XCDR (XCDR (tail2)))
289 if (EQ (sym, XCAR (tail2)))
290 return 1;
291 }
292
293 return 0;
294}
271 295
272/* Changing the plists of individual intervals. */ 296/* Changing the plists of individual intervals. */
273 297
@@ -414,58 +438,70 @@ add_properties (plist, i, object)
414 return changed; 438 return changed;
415} 439}
416 440
417/* For any members of PLIST which are properties of I, remove them 441/* For any members of PLIST, or LIST,
418 from I's plist. 442 which are properties of I, remove them from I's plist.
443 (If PLIST is non-nil, use that, otherwise use LIST.)
419 OBJECT is the string or buffer containing I. */ 444 OBJECT is the string or buffer containing I. */
420 445
421static int 446static int
422remove_properties (plist, i, object) 447remove_properties (plist, list, i, object)
423 Lisp_Object plist; 448 Lisp_Object plist, list;
424 INTERVAL i; 449 INTERVAL i;
425 Lisp_Object object; 450 Lisp_Object object;
426{ 451{
427 register Lisp_Object tail1, tail2, sym, current_plist; 452 register Lisp_Object tail1, tail2, sym, current_plist;
428 register int changed = 0; 453 register int changed = 0;
429 454
455 /* Nonzero means tail1 is a list, otherwise it is a plist. */
456 int use_list;
457
430 current_plist = i->plist; 458 current_plist = i->plist;
431 /* Go through each element of plist. */ 459
432 for (tail1 = plist; ! NILP (tail1); tail1 = Fcdr (Fcdr (tail1))) 460 if (! NILP (plist))
461 tail1 = plist, use_list = 0;
462 else
463 tail1 = list, use_list = 1;
464
465 /* Go through each element of LIST or PLIST. */
466 while (! NILP (tail1))
433 { 467 {
434 sym = Fcar (tail1); 468 sym = XCAR (tail1);
435 469
436 /* First, remove the symbol if its at the head of the list */ 470 /* First, remove the symbol if it's at the head of the list */
437 while (! NILP (current_plist) && EQ (sym, Fcar (current_plist))) 471 while (! NILP (current_plist) && EQ (sym, XCAR (current_plist)))
438 { 472 {
439 if (BUFFERP (object)) 473 if (BUFFERP (object))
440 { 474 record_property_change (i->position, LENGTH (i),
441 record_property_change (i->position, LENGTH (i), 475 sym, XCAR (XCDR (current_plist)),
442 sym, Fcar (Fcdr (current_plist)), 476 object);
443 object);
444 }
445 477
446 current_plist = Fcdr (Fcdr (current_plist)); 478 current_plist = XCDR (XCDR (current_plist));
447 changed++; 479 changed++;
448 } 480 }
449 481
450 /* Go through i's plist, looking for sym */ 482 /* Go through I's plist, looking for SYM. */
451 tail2 = current_plist; 483 tail2 = current_plist;
452 while (! NILP (tail2)) 484 while (! NILP (tail2))
453 { 485 {
454 register Lisp_Object this; 486 register Lisp_Object this;
455 this = Fcdr (Fcdr (tail2)); 487 this = XCDR (XCDR (tail2));
456 if (EQ (sym, Fcar (this))) 488 if (EQ (sym, XCAR (this)))
457 { 489 {
458 if (BUFFERP (object)) 490 if (BUFFERP (object))
459 { 491 record_property_change (i->position, LENGTH (i),
460 record_property_change (i->position, LENGTH (i), 492 sym, XCAR (XCDR (this)), object);
461 sym, Fcar (Fcdr (this)), object);
462 }
463 493
464 Fsetcdr (Fcdr (tail2), Fcdr (Fcdr (this))); 494 Fsetcdr (XCDR (tail2), XCDR (XCDR (this)));
465 changed++; 495 changed++;
466 } 496 }
467 tail2 = this; 497 tail2 = this;
468 } 498 }
499
500 /* Advance thru TAIL1 one way or the other. */
501 if (use_list)
502 tail1 = XCDR (tail1);
503 else
504 tail1 = XCDR (XCDR (tail1));
469 } 505 }
470 506
471 if (changed) 507 if (changed)
@@ -1459,7 +1495,94 @@ Return t if any property was actually removed, nil otherwise. */)
1459 1495
1460 if (LENGTH (i) == len) 1496 if (LENGTH (i) == len)
1461 { 1497 {
1462 remove_properties (properties, i, object); 1498 remove_properties (properties, Qnil, i, object);
1499 if (BUFFERP (object))
1500 signal_after_change (XINT (start), XINT (end) - XINT (start),
1501 XINT (end) - XINT (start));
1502 return Qt;
1503 }
1504
1505 /* i has the properties, and goes past the change limit */
1506 unchanged = i;
1507 i = split_interval_left (i, len);
1508 copy_properties (unchanged, i);
1509 remove_properties (properties, Qnil, i, object);
1510 if (BUFFERP (object))
1511 signal_after_change (XINT (start), XINT (end) - XINT (start),
1512 XINT (end) - XINT (start));
1513 return Qt;
1514 }
1515
1516 len -= LENGTH (i);
1517 modified += remove_properties (properties, Qnil, i, object);
1518 i = next_interval (i);
1519 }
1520}
1521
1522DEFUN ("remove-list-of-text-properties", Fremove_list_of_text_properties,
1523 Sremove_list_of_text_properties, 3, 4, 0,
1524 doc: /* Remove some properties from text from START to END.
1525The third argument LIST-OF-PROPERTIES is a list of property names to remove.
1526The optional fourth argument, OBJECT,
1527is the string or buffer containing the text, defaulting to the current buffer.
1528Return t if any property was actually removed, nil otherwise. */)
1529 (start, end, list_of_properties, object)
1530 Lisp_Object start, end, list_of_properties, object;
1531{
1532 register INTERVAL i, unchanged;
1533 register int s, len, modified = 0;
1534 Lisp_Object properties;
1535 properties = list_of_properties;
1536
1537 if (NILP (object))
1538 XSETBUFFER (object, current_buffer);
1539
1540 i = validate_interval_range (object, &start, &end, soft);
1541 if (NULL_INTERVAL_P (i))
1542 return Qnil;
1543
1544 s = XINT (start);
1545 len = XINT (end) - s;
1546
1547 if (i->position != s)
1548 {
1549 /* No properties on this first interval -- return if
1550 it covers the entire region. */
1551 if (! interval_has_some_properties_list (properties, i))
1552 {
1553 int got = (LENGTH (i) - (s - i->position));
1554 if (got >= len)
1555 return Qnil;
1556 len -= got;
1557 i = next_interval (i);
1558 }
1559 /* Split away the beginning of this interval; what we don't
1560 want to modify. */
1561 else
1562 {
1563 unchanged = i;
1564 i = split_interval_right (unchanged, s - unchanged->position);
1565 copy_properties (unchanged, i);
1566 }
1567 }
1568
1569 if (BUFFERP (object))
1570 modify_region (XBUFFER (object), XINT (start), XINT (end));
1571
1572 /* We are at the beginning of an interval, with len to scan */
1573 for (;;)
1574 {
1575 if (i == 0)
1576 abort ();
1577
1578 if (LENGTH (i) >= len)
1579 {
1580 if (! interval_has_some_properties_list (properties, i))
1581 return modified ? Qt : Qnil;
1582
1583 if (LENGTH (i) == len)
1584 {
1585 remove_properties (Qnil, properties, i, object);
1463 if (BUFFERP (object)) 1586 if (BUFFERP (object))
1464 signal_after_change (XINT (start), XINT (end) - XINT (start), 1587 signal_after_change (XINT (start), XINT (end) - XINT (start),
1465 XINT (end) - XINT (start)); 1588 XINT (end) - XINT (start));
@@ -1470,7 +1593,7 @@ Return t if any property was actually removed, nil otherwise. */)
1470 unchanged = i; 1593 unchanged = i;
1471 i = split_interval_left (i, len); 1594 i = split_interval_left (i, len);
1472 copy_properties (unchanged, i); 1595 copy_properties (unchanged, i);
1473 remove_properties (properties, i, object); 1596 remove_properties (Qnil, properties, i, object);
1474 if (BUFFERP (object)) 1597 if (BUFFERP (object))
1475 signal_after_change (XINT (start), XINT (end) - XINT (start), 1598 signal_after_change (XINT (start), XINT (end) - XINT (start),
1476 XINT (end) - XINT (start)); 1599 XINT (end) - XINT (start));
@@ -1478,7 +1601,7 @@ Return t if any property was actually removed, nil otherwise. */)
1478 } 1601 }
1479 1602
1480 len -= LENGTH (i); 1603 len -= LENGTH (i);
1481 modified += remove_properties (properties, i, object); 1604 modified += remove_properties (Qnil, properties, i, object);
1482 i = next_interval (i); 1605 i = next_interval (i);
1483 } 1606 }
1484} 1607}
@@ -2132,6 +2255,7 @@ rear-nonsticky properties of the character overrides NONSTICKINESS. */);
2132 defsubr (&Sput_text_property); 2255 defsubr (&Sput_text_property);
2133 defsubr (&Sset_text_properties); 2256 defsubr (&Sset_text_properties);
2134 defsubr (&Sremove_text_properties); 2257 defsubr (&Sremove_text_properties);
2258 defsubr (&Sremove_list_of_text_properties);
2135 defsubr (&Stext_property_any); 2259 defsubr (&Stext_property_any);
2136 defsubr (&Stext_property_not_all); 2260 defsubr (&Stext_property_not_all);
2137/* defsubr (&Serase_text_properties); */ 2261/* defsubr (&Serase_text_properties); */