Mercurial > emacs
comparison src/textprop.c @ 44673:01f74663f76e
(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.
author | Richard M. Stallman <rms@gnu.org> |
---|---|
date | Fri, 19 Apr 2002 00:14:14 +0000 |
parents | fccc867cca64 |
children | e137c1849517 |
comparison
equal
deleted
inserted
replaced
44672:1eb32d9cb2a6 | 44673:01f74663f76e |
---|---|
261 sym = Fcar (tail1); | 261 sym = Fcar (tail1); |
262 | 262 |
263 /* Go through i's plist, looking for tail1 */ | 263 /* Go through i's plist, looking for tail1 */ |
264 for (tail2 = i->plist; ! NILP (tail2); tail2 = Fcdr (Fcdr (tail2))) | 264 for (tail2 = i->plist; ! NILP (tail2); tail2 = Fcdr (Fcdr (tail2))) |
265 if (EQ (sym, Fcar (tail2))) | 265 if (EQ (sym, Fcar (tail2))) |
266 return 1; | |
267 } | |
268 | |
269 return 0; | |
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))) | |
266 return 1; | 290 return 1; |
267 } | 291 } |
268 | 292 |
269 return 0; | 293 return 0; |
270 } | 294 } |
412 UNGCPRO; | 436 UNGCPRO; |
413 | 437 |
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)) |
433 { | 461 tail1 = plist, use_list = 0; |
434 sym = Fcar (tail1); | 462 else |
435 | 463 tail1 = list, use_list = 1; |
436 /* First, remove the symbol if its at the head of the list */ | 464 |
437 while (! NILP (current_plist) && EQ (sym, Fcar (current_plist))) | 465 /* Go through each element of LIST or PLIST. */ |
466 while (! NILP (tail1)) | |
467 { | |
468 sym = XCAR (tail1); | |
469 | |
470 /* First, remove the symbol if it's at the head of the list */ | |
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); | 477 |
444 } | 478 current_plist = XCDR (XCDR (current_plist)); |
445 | |
446 current_plist = Fcdr (Fcdr (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); | 493 |
462 } | 494 Fsetcdr (XCDR (tail2), XCDR (XCDR (this))); |
463 | |
464 Fsetcdr (Fcdr (tail2), Fcdr (Fcdr (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) |
472 i->plist = current_plist; | 508 i->plist = current_plist; |
473 return changed; | 509 return changed; |
1457 if (! interval_has_some_properties (properties, i)) | 1493 if (! interval_has_some_properties (properties, i)) |
1458 return modified ? Qt : Qnil; | 1494 return modified ? Qt : Qnil; |
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); |
1463 if (BUFFERP (object)) | 1499 if (BUFFERP (object)) |
1464 signal_after_change (XINT (start), XINT (end) - XINT (start), | 1500 signal_after_change (XINT (start), XINT (end) - XINT (start), |
1465 XINT (end) - XINT (start)); | 1501 XINT (end) - XINT (start)); |
1466 return Qt; | 1502 return Qt; |
1467 } | 1503 } |
1468 | 1504 |
1469 /* i has the properties, and goes past the change limit */ | 1505 /* i has the properties, and goes past the change limit */ |
1470 unchanged = i; | 1506 unchanged = i; |
1471 i = split_interval_left (i, len); | 1507 i = split_interval_left (i, len); |
1472 copy_properties (unchanged, i); | 1508 copy_properties (unchanged, i); |
1473 remove_properties (properties, i, object); | 1509 remove_properties (properties, Qnil, i, object); |
1474 if (BUFFERP (object)) | 1510 if (BUFFERP (object)) |
1475 signal_after_change (XINT (start), XINT (end) - XINT (start), | 1511 signal_after_change (XINT (start), XINT (end) - XINT (start), |
1476 XINT (end) - XINT (start)); | 1512 XINT (end) - XINT (start)); |
1477 return Qt; | 1513 return Qt; |
1478 } | 1514 } |
1479 | 1515 |
1480 len -= LENGTH (i); | 1516 len -= LENGTH (i); |
1481 modified += remove_properties (properties, i, object); | 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); | |
1586 if (BUFFERP (object)) | |
1587 signal_after_change (XINT (start), XINT (end) - XINT (start), | |
1588 XINT (end) - XINT (start)); | |
1589 return Qt; | |
1590 } | |
1591 | |
1592 /* i has the properties, and goes past the change limit */ | |
1593 unchanged = i; | |
1594 i = split_interval_left (i, len); | |
1595 copy_properties (unchanged, i); | |
1596 remove_properties (Qnil, properties, i, object); | |
1597 if (BUFFERP (object)) | |
1598 signal_after_change (XINT (start), XINT (end) - XINT (start), | |
1599 XINT (end) - XINT (start)); | |
1600 return Qt; | |
1601 } | |
1602 | |
1603 len -= LENGTH (i); | |
1604 modified += remove_properties (Qnil, properties, i, object); | |
1482 i = next_interval (i); | 1605 i = next_interval (i); |
1483 } | 1606 } |
1484 } | 1607 } |
1485 | 1608 |
1486 DEFUN ("text-property-any", Ftext_property_any, | 1609 DEFUN ("text-property-any", Ftext_property_any, |
2130 defsubr (&Sprevious_single_property_change); | 2253 defsubr (&Sprevious_single_property_change); |
2131 defsubr (&Sadd_text_properties); | 2254 defsubr (&Sadd_text_properties); |
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); */ |
2138 /* defsubr (&Scopy_text_properties); */ | 2262 /* defsubr (&Scopy_text_properties); */ |
2139 } | 2263 } |