diff options
| author | Richard M. Stallman | 2002-04-19 00:14:14 +0000 |
|---|---|---|
| committer | Richard M. Stallman | 2002-04-19 00:14:14 +0000 |
| commit | 11713b6dafb4f63fa246c6de77133ed8ec80243a (patch) | |
| tree | c330d2440dd2b8f6d7caf0df5f1e6c53f2c766c4 /src/textprop.c | |
| parent | 0cf5c1e712ca58e2d3edc8d238038efb6f5beb5d (diff) | |
| download | emacs-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.c | 176 |
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 | |||
| 275 | static INLINE int | ||
| 276 | interval_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 | ||
| 421 | static int | 446 | static int |
| 422 | remove_properties (plist, i, object) | 447 | remove_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 | |||
| 1522 | DEFUN ("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. | ||
| 1525 | The third argument LIST-OF-PROPERTIES is a list of property names to remove. | ||
| 1526 | The optional fourth argument, OBJECT, | ||
| 1527 | is the string or buffer containing the text, defaulting to the current buffer. | ||
| 1528 | Return 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); */ |