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 }