268 |
|
|
269 |
return 0; |
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))) |
290 |
|
return 1; |
291 |
|
} |
292 |
|
|
293 |
|
return 0; |
294 |
|
} |
295 |
|
|
296 |
/* Changing the plists of individual intervals. */ |
/* Changing the plists of individual intervals. */ |
297 |
|
|
438 |
return changed; |
return changed; |
439 |
} |
} |
440 |
|
|
441 |
/* For any members of PLIST which are properties of I, remove them |
/* For any members of PLIST, or LIST, |
442 |
from I's plist. |
which are properties of I, remove them from I's plist. |
443 |
|
(If PLIST is non-nil, use that, otherwise use LIST.) |
444 |
OBJECT is the string or buffer containing I. */ |
OBJECT is the string or buffer containing I. */ |
445 |
|
|
446 |
static int |
static int |
447 |
remove_properties (plist, i, object) |
remove_properties (plist, list, i, object) |
448 |
Lisp_Object plist; |
Lisp_Object plist, list; |
449 |
INTERVAL i; |
INTERVAL i; |
450 |
Lisp_Object object; |
Lisp_Object object; |
451 |
{ |
{ |
452 |
register Lisp_Object tail1, tail2, sym, current_plist; |
register Lisp_Object tail1, tail2, sym, current_plist; |
453 |
register int changed = 0; |
register int changed = 0; |
454 |
|
|
455 |
|
/* Nonzero means tail1 is a list, otherwise it is a plist. */ |
456 |
|
int use_list; |
457 |
|
|
458 |
current_plist = i->plist; |
current_plist = i->plist; |
459 |
/* Go through each element of plist. */ |
|
460 |
for (tail1 = plist; ! NILP (tail1); tail1 = Fcdr (Fcdr (tail1))) |
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)) |
467 |
{ |
{ |
468 |
sym = Fcar (tail1); |
sym = XCAR (tail1); |
469 |
|
|
470 |
/* First, remove the symbol if its at the head of the list */ |
/* First, remove the symbol if it's at the head of the list */ |
471 |
while (! NILP (current_plist) && EQ (sym, Fcar (current_plist))) |
while (! NILP (current_plist) && EQ (sym, XCAR (current_plist))) |
472 |
{ |
{ |
473 |
if (BUFFERP (object)) |
if (BUFFERP (object)) |
474 |
{ |
record_property_change (i->position, LENGTH (i), |
475 |
record_property_change (i->position, LENGTH (i), |
sym, XCAR (XCDR (current_plist)), |
476 |
sym, Fcar (Fcdr (current_plist)), |
object); |
|
object); |
|
|
} |
|
477 |
|
|
478 |
current_plist = Fcdr (Fcdr (current_plist)); |
current_plist = XCDR (XCDR (current_plist)); |
479 |
changed++; |
changed++; |
480 |
} |
} |
481 |
|
|
482 |
/* Go through i's plist, looking for sym */ |
/* Go through I's plist, looking for SYM. */ |
483 |
tail2 = current_plist; |
tail2 = current_plist; |
484 |
while (! NILP (tail2)) |
while (! NILP (tail2)) |
485 |
{ |
{ |
486 |
register Lisp_Object this; |
register Lisp_Object this; |
487 |
this = Fcdr (Fcdr (tail2)); |
this = XCDR (XCDR (tail2)); |
488 |
if (EQ (sym, Fcar (this))) |
if (EQ (sym, XCAR (this))) |
489 |
{ |
{ |
490 |
if (BUFFERP (object)) |
if (BUFFERP (object)) |
491 |
{ |
record_property_change (i->position, LENGTH (i), |
492 |
record_property_change (i->position, LENGTH (i), |
sym, XCAR (XCDR (this)), object); |
|
sym, Fcar (Fcdr (this)), object); |
|
|
} |
|
493 |
|
|
494 |
Fsetcdr (Fcdr (tail2), Fcdr (Fcdr (this))); |
Fsetcdr (XCDR (tail2), XCDR (XCDR (this))); |
495 |
changed++; |
changed++; |
496 |
} |
} |
497 |
tail2 = this; |
tail2 = this; |
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)); |
505 |
} |
} |
506 |
|
|
507 |
if (changed) |
if (changed) |
1495 |
|
|
1496 |
if (LENGTH (i) == len) |
if (LENGTH (i) == len) |
1497 |
{ |
{ |
1498 |
remove_properties (properties, i, object); |
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); |
1586 |
if (BUFFERP (object)) |
if (BUFFERP (object)) |
1587 |
signal_after_change (XINT (start), XINT (end) - XINT (start), |
signal_after_change (XINT (start), XINT (end) - XINT (start), |
1588 |
XINT (end) - XINT (start)); |
XINT (end) - XINT (start)); |
1593 |
unchanged = i; |
unchanged = i; |
1594 |
i = split_interval_left (i, len); |
i = split_interval_left (i, len); |
1595 |
copy_properties (unchanged, i); |
copy_properties (unchanged, i); |
1596 |
remove_properties (properties, i, object); |
remove_properties (Qnil, properties, i, object); |
1597 |
if (BUFFERP (object)) |
if (BUFFERP (object)) |
1598 |
signal_after_change (XINT (start), XINT (end) - XINT (start), |
signal_after_change (XINT (start), XINT (end) - XINT (start), |
1599 |
XINT (end) - XINT (start)); |
XINT (end) - XINT (start)); |
1601 |
} |
} |
1602 |
|
|
1603 |
len -= LENGTH (i); |
len -= LENGTH (i); |
1604 |
modified += remove_properties (properties, i, object); |
modified += remove_properties (Qnil, properties, i, object); |
1605 |
i = next_interval (i); |
i = next_interval (i); |
1606 |
} |
} |
1607 |
} |
} |
2255 |
defsubr (&Sput_text_property); |
defsubr (&Sput_text_property); |
2256 |
defsubr (&Sset_text_properties); |
defsubr (&Sset_text_properties); |
2257 |
defsubr (&Sremove_text_properties); |
defsubr (&Sremove_text_properties); |
2258 |
|
defsubr (&Sremove_list_of_text_properties); |
2259 |
defsubr (&Stext_property_any); |
defsubr (&Stext_property_any); |
2260 |
defsubr (&Stext_property_not_all); |
defsubr (&Stext_property_not_all); |
2261 |
/* defsubr (&Serase_text_properties); */ |
/* defsubr (&Serase_text_properties); */ |