aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorRichard M. Stallman1995-09-12 17:37:32 +0000
committerRichard M. Stallman1995-09-12 17:37:32 +0000
commit318d2fa869105827f75e615fcf04605283ba8b14 (patch)
tree62fe22647724bb76c6588313767c76e52be7bc59 /src
parentc5ca07864e26c10e538a810888f3c74dde1ebec3 (diff)
downloademacs-318d2fa869105827f75e615fcf04605283ba8b14.tar.gz
emacs-318d2fa869105827f75e615fcf04605283ba8b14.zip
(call_mod_hooks): Moved from intevals.c
(verify_interval_modification): Moved from intervals.c. (interval_insert_behind_hooks, interval_insert_in_front_hooks): New variables. (report_interval_modification): New function.
Diffstat (limited to 'src')
-rw-r--r--src/textprop.c226
1 files changed, 226 insertions, 0 deletions
diff --git a/src/textprop.c b/src/textprop.c
index c41757388c7..ad41534c3ef 100644
--- a/src/textprop.c
+++ b/src/textprop.c
@@ -26,6 +26,11 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
26#ifndef NULL 26#ifndef NULL
27#define NULL (void *)0 27#define NULL (void *)0
28#endif 28#endif
29
30/* Test for membership, allowing for t (actually any non-cons) to mean the
31 universal set. */
32
33#define TMEM(sym, set) (CONSP (set) ? ! NILP (Fmemq (sym, set)) : ! NILP (set))
29 34
30 35
31/* NOTES: previous- and next- property change will have to skip 36/* NOTES: previous- and next- property change will have to skip
@@ -66,6 +71,10 @@ Lisp_Object Qfront_sticky, Qrear_nonsticky;
66Lisp_Object Vinhibit_point_motion_hooks; 71Lisp_Object Vinhibit_point_motion_hooks;
67Lisp_Object Vdefault_text_properties; 72Lisp_Object Vdefault_text_properties;
68 73
74/* verify_interval_modification saves insertion hooks here
75 to be run later by report_interval_modification. */
76Lisp_Object interval_insert_behind_hooks;
77Lisp_Object interval_insert_in_front_hooks;
69 78
70/* Extract the interval at the position pointed to by BEGIN from 79/* Extract the interval at the position pointed to by BEGIN from
71 OBJECT, a string or buffer. Additionally, check that the positions 80 OBJECT, a string or buffer. Additionally, check that the positions
@@ -1394,8 +1403,219 @@ copy_text_properties (start, end, src, pos, dest, prop)
1394 1403
1395 return modified ? Qt : Qnil; 1404 return modified ? Qt : Qnil;
1396} 1405}
1406
1407/* Call the modification hook functions in LIST, each with START and END. */
1408
1409static void
1410call_mod_hooks (list, start, end)
1411 Lisp_Object list, start, end;
1412{
1413 struct gcpro gcpro1;
1414 GCPRO1 (list);
1415 while (!NILP (list))
1416 {
1417 call2 (Fcar (list), start, end);
1418 list = Fcdr (list);
1419 }
1420 UNGCPRO;
1421}
1422
1423/* Check for read-only intervals and signal an error if we find one.
1424 Then check for any modification hooks in the range START up to
1425 (but not including) END. Create a list of all these hooks in
1426 lexicographic order, eliminating consecutive extra copies of the
1427 same hook. Then call those hooks in order, with START and END - 1
1428 as arguments. */
1397 1429
1398void 1430void
1431verify_interval_modification (buf, start, end)
1432 struct buffer *buf;
1433 int start, end;
1434{
1435 register INTERVAL intervals = BUF_INTERVALS (buf);
1436 register INTERVAL i, prev;
1437 Lisp_Object hooks;
1438 register Lisp_Object prev_mod_hooks;
1439 Lisp_Object mod_hooks;
1440 struct gcpro gcpro1;
1441
1442 hooks = Qnil;
1443 prev_mod_hooks = Qnil;
1444 mod_hooks = Qnil;
1445
1446 interval_insert_behind_hooks = Qnil;
1447 interval_insert_in_front_hooks = Qnil;
1448
1449 if (NULL_INTERVAL_P (intervals))
1450 return;
1451
1452 if (start > end)
1453 {
1454 int temp = start;
1455 start = end;
1456 end = temp;
1457 }
1458
1459 /* For an insert operation, check the two chars around the position. */
1460 if (start == end)
1461 {
1462 INTERVAL prev;
1463 Lisp_Object before, after;
1464
1465 /* Set I to the interval containing the char after START,
1466 and PREV to the interval containing the char before START.
1467 Either one may be null. They may be equal. */
1468 i = find_interval (intervals, start);
1469
1470 if (start == BUF_BEGV (buf))
1471 prev = 0;
1472 else if (i->position == start)
1473 prev = previous_interval (i);
1474 else if (i->position < start)
1475 prev = i;
1476 if (start == BUF_ZV (buf))
1477 i = 0;
1478
1479 /* If Vinhibit_read_only is set and is not a list, we can
1480 skip the read_only checks. */
1481 if (NILP (Vinhibit_read_only) || CONSP (Vinhibit_read_only))
1482 {
1483 /* If I and PREV differ we need to check for the read-only
1484 property together with its stickyness. If either I or
1485 PREV are 0, this check is all we need.
1486 We have to take special care, since read-only may be
1487 indirectly defined via the category property. */
1488 if (i != prev)
1489 {
1490 if (! NULL_INTERVAL_P (i))
1491 {
1492 after = textget (i->plist, Qread_only);
1493
1494 /* If interval I is read-only and read-only is
1495 front-sticky, inhibit insertion.
1496 Check for read-only as well as category. */
1497 if (! NILP (after)
1498 && NILP (Fmemq (after, Vinhibit_read_only)))
1499 {
1500 Lisp_Object tem;
1501
1502 tem = textget (i->plist, Qfront_sticky);
1503 if (TMEM (Qread_only, tem)
1504 || (NILP (Fplist_get (i->plist, Qread_only))
1505 && TMEM (Qcategory, tem)))
1506 error ("Attempt to insert within read-only text");
1507 }
1508 }
1509
1510 if (! NULL_INTERVAL_P (prev))
1511 {
1512 before = textget (prev->plist, Qread_only);
1513
1514 /* If interval PREV is read-only and read-only isn't
1515 rear-nonsticky, inhibit insertion.
1516 Check for read-only as well as category. */
1517 if (! NILP (before)
1518 && NILP (Fmemq (before, Vinhibit_read_only)))
1519 {
1520 Lisp_Object tem;
1521
1522 tem = textget (prev->plist, Qrear_nonsticky);
1523 if (! TMEM (Qread_only, tem)
1524 && (! NILP (Fplist_get (prev->plist,Qread_only))
1525 || ! TMEM (Qcategory, tem)))
1526 error ("Attempt to insert within read-only text");
1527 }
1528 }
1529 }
1530 else if (! NULL_INTERVAL_P (i))
1531 {
1532 after = textget (i->plist, Qread_only);
1533
1534 /* If interval I is read-only and read-only is
1535 front-sticky, inhibit insertion.
1536 Check for read-only as well as category. */
1537 if (! NILP (after) && NILP (Fmemq (after, Vinhibit_read_only)))
1538 {
1539 Lisp_Object tem;
1540
1541 tem = textget (i->plist, Qfront_sticky);
1542 if (TMEM (Qread_only, tem)
1543 || (NILP (Fplist_get (i->plist, Qread_only))
1544 && TMEM (Qcategory, tem)))
1545 error ("Attempt to insert within read-only text");
1546
1547 tem = textget (prev->plist, Qrear_nonsticky);
1548 if (! TMEM (Qread_only, tem)
1549 && (! NILP (Fplist_get (prev->plist, Qread_only))
1550 || ! TMEM (Qcategory, tem)))
1551 error ("Attempt to insert within read-only text");
1552 }
1553 }
1554 }
1555
1556 /* Run both insert hooks (just once if they're the same). */
1557 if (!NULL_INTERVAL_P (prev))
1558 interval_insert_behind_hooks
1559 = textget (prev->plist, Qinsert_behind_hooks);
1560 if (!NULL_INTERVAL_P (i))
1561 interval_insert_in_front_hooks
1562 = textget (i->plist, Qinsert_in_front_hooks);
1563 }
1564 else
1565 {
1566 /* Loop over intervals on or next to START...END,
1567 collecting their hooks. */
1568
1569 i = find_interval (intervals, start);
1570 do
1571 {
1572 if (! INTERVAL_WRITABLE_P (i))
1573 error ("Attempt to modify read-only text");
1574
1575 mod_hooks = textget (i->plist, Qmodification_hooks);
1576 if (! NILP (mod_hooks) && ! EQ (mod_hooks, prev_mod_hooks))
1577 {
1578 hooks = Fcons (mod_hooks, hooks);
1579 prev_mod_hooks = mod_hooks;
1580 }
1581
1582 i = next_interval (i);
1583 }
1584 /* Keep going thru the interval containing the char before END. */
1585 while (! NULL_INTERVAL_P (i) && i->position < end);
1586
1587 GCPRO1 (hooks);
1588 hooks = Fnreverse (hooks);
1589 while (! EQ (hooks, Qnil))
1590 {
1591 call_mod_hooks (Fcar (hooks), make_number (start),
1592 make_number (end));
1593 hooks = Fcdr (hooks);
1594 }
1595 UNGCPRO;
1596 }
1597}
1598
1599/* Run the interval hooks for an insertion.
1600 verify_interval_modification chose which hooks to run;
1601 this function is called after the insertion happens
1602 so it can indicate the range of inserted text. */
1603
1604void
1605report_interval_modification (start, end)
1606 Lisp_Object start, end;
1607{
1608 if (! NILP (interval_insert_behind_hooks))
1609 call_mod_hooks (interval_insert_behind_hooks,
1610 make_number (start), make_number (end));
1611 if (! NILP (interval_insert_in_front_hooks)
1612 && ! EQ (interval_insert_in_front_hooks,
1613 interval_insert_behind_hooks))
1614 call_mod_hooks (interval_insert_in_front_hooks,
1615 make_number (start), make_number (end));
1616}
1617
1618void
1399syms_of_textprop () 1619syms_of_textprop ()
1400{ 1620{
1401 DEFVAR_LISP ("default-text-properties", &Vdefault_text_properties, 1621 DEFVAR_LISP ("default-text-properties", &Vdefault_text_properties,
@@ -1408,6 +1628,12 @@ character that does not have its own value for that property.");
1408 "If non-nil, don't run `point-left' and `point-entered' text properties.\n\ 1628 "If non-nil, don't run `point-left' and `point-entered' text properties.\n\
1409This also inhibits the use of the `intangible' text property."); 1629This also inhibits the use of the `intangible' text property.");
1410 Vinhibit_point_motion_hooks = Qnil; 1630 Vinhibit_point_motion_hooks = Qnil;
1631
1632 staticpro (&interval_insert_behind_hooks);
1633 staticpro (&interval_insert_in_front_hooks);
1634 interval_insert_behind_hooks = Qnil;
1635 interval_insert_in_front_hooks = Qnil;
1636
1411 1637
1412 /* Common attributes one might give text */ 1638 /* Common attributes one might give text */
1413 1639