aboutsummaryrefslogtreecommitdiffstats
path: root/src/intervals.c
diff options
context:
space:
mode:
authorRichard M. Stallman1993-03-07 09:34:39 +0000
committerRichard M. Stallman1993-03-07 09:34:39 +0000
commit294efdbeb87b67c641e2eb6188aa120543c15953 (patch)
tree99c45abf0e9774377c3e32f31c35acd8d826b983 /src/intervals.c
parent83ec8b67da4885ccc1c7f7d9236091e603f039dd (diff)
downloademacs-294efdbeb87b67c641e2eb6188aa120543c15953.tar.gz
emacs-294efdbeb87b67c641e2eb6188aa120543c15953.zip
(verify_interval_modification): Handle insertions
specially. For non-insertions, check only the chars being changed. `modification-hooks' property is now a list of functions. (set_point): Ignore chars outside current restriction.
Diffstat (limited to 'src/intervals.c')
-rw-r--r--src/intervals.c152
1 files changed, 113 insertions, 39 deletions
diff --git a/src/intervals.c b/src/intervals.c
index b9b4c5f838e..ce682b9adbf 100644
--- a/src/intervals.c
+++ b/src/intervals.c
@@ -1,5 +1,5 @@
1/* Code for doing intervals. 1/* Code for doing intervals.
2 Copyright (C) 1991, 1992 Free Software Foundation, Inc. 2 Copyright (C) 1993 Free Software Foundation, Inc.
3 3
4This file is part of GNU Emacs. 4This file is part of GNU Emacs.
5 5
@@ -1071,7 +1071,7 @@ make_new_interval (intervals, start, length)
1071 split_interval_right (slot, length + 1); 1071 split_interval_right (slot, length + 1);
1072 return slot; 1072 return slot;
1073} 1073}
1074 1074
1075/* Insert the intervals of SOURCE into BUFFER at POSITION. 1075/* Insert the intervals of SOURCE into BUFFER at POSITION.
1076 1076
1077 This is used in insdel.c when inserting Lisp_Strings into 1077 This is used in insdel.c when inserting Lisp_Strings into
@@ -1225,7 +1225,7 @@ textget (plist, prop)
1225 } 1225 }
1226 return Qnil; 1226 return Qnil;
1227} 1227}
1228 1228
1229/* Set point in BUFFER to POSITION. If the target position is in 1229/* Set point in BUFFER to POSITION. If the target position is in
1230 after an invisible character which is not displayed with a special glyph, 1230 after an invisible character which is not displayed with a special glyph,
1231 move back to an ok place to display. */ 1231 move back to an ok place to display. */
@@ -1256,22 +1256,24 @@ set_point (position, buffer)
1256 abort (); 1256 abort ();
1257 1257
1258 /* Position Z is really one past the last char in the buffer. */ 1258 /* Position Z is really one past the last char in the buffer. */
1259 if (position == BUF_Z (buffer)) 1259 if (position == BUF_ZV (buffer))
1260 iposition = position - 1; 1260 iposition = position - 1;
1261 1261
1262 /* Set TO to the interval containing the char after POSITION, 1262 /* Set TO to the interval containing the char after POSITION,
1263 and TOPREV to the interval containing the char before POSITION. 1263 and TOPREV to the interval containing the char before POSITION.
1264 Either one may be null. They may be equal. */ 1264 Either one may be null. They may be equal. */
1265 to = find_interval (buffer->intervals, iposition); 1265 to = find_interval (buffer->intervals, iposition);
1266 if (to->position == position) 1266 if (position == BUF_BEGV (buffer))
1267 toprev = 0;
1268 else if (to->position == position)
1267 toprev = previous_interval (to); 1269 toprev = previous_interval (to);
1268 else if (iposition != position) 1270 else if (iposition != position)
1269 toprev = to, to = 0; 1271 toprev = to, to = 0;
1270 else 1272 else
1271 toprev = to; 1273 toprev = to;
1272 1274
1273 buffer_point = (BUF_PT (buffer) == BUF_Z (buffer) 1275 buffer_point = (BUF_PT (buffer) == BUF_ZV (buffer)
1274 ? BUF_Z (buffer) - 1 1276 ? BUF_ZV (buffer) - 1
1275 : BUF_PT (buffer)); 1277 : BUF_PT (buffer));
1276 1278
1277 /* Set FROM to the interval containing the char after PT, 1279 /* Set FROM to the interval containing the char after PT,
@@ -1279,7 +1281,9 @@ set_point (position, buffer)
1279 Either one may be null. They may be equal. */ 1281 Either one may be null. They may be equal. */
1280 /* We could cache this and save time. */ 1282 /* We could cache this and save time. */
1281 from = find_interval (buffer->intervals, buffer_point); 1283 from = find_interval (buffer->intervals, buffer_point);
1282 if (from->position == BUF_PT (buffer)) 1284 if (from->position == BUF_BEGV (buffer))
1285 fromprev = 0;
1286 else if (from->position == BUF_PT (buffer))
1283 fromprev = previous_interval (from); 1287 fromprev = previous_interval (from);
1284 else if (buffer_point != BUF_PT (buffer)) 1288 else if (buffer_point != BUF_PT (buffer))
1285 fromprev = from, from = 0; 1289 fromprev = from, from = 0;
@@ -1353,6 +1357,22 @@ temp_set_point (position, buffer)
1353{ 1357{
1354 buffer->text.pt = position; 1358 buffer->text.pt = position;
1355} 1359}
1360
1361/* Call the modification hook functions in LIST, each with START and END. */
1362
1363static void
1364call_mod_hooks (list, start, end)
1365 Lisp_Object list, start, end;
1366{
1367 struct gcpro gcpro1;
1368 GCPRO1 (list);
1369 while (!NILP (list))
1370 {
1371 call2 (Fcar (list), start, end);
1372 list = Fcdr (list);
1373 }
1374 UNGCPRO;
1375}
1356 1376
1357/* Check for read-only intervals and signal an error if we find one. 1377/* Check for read-only intervals and signal an error if we find one.
1358 Then check for any modification hooks in the range START up to 1378 Then check for any modification hooks in the range START up to
@@ -1367,12 +1387,16 @@ verify_interval_modification (buf, start, end)
1367 int start, end; 1387 int start, end;
1368{ 1388{
1369 register INTERVAL intervals = buf->intervals; 1389 register INTERVAL intervals = buf->intervals;
1370 register INTERVAL i; 1390 register INTERVAL i, prev;
1371 Lisp_Object hooks = Qnil; 1391 Lisp_Object hooks;
1372 register prev_mod_hook = Qnil; 1392 register Lisp_Object prev_mod_hooks;
1373 register Lisp_Object mod_hook; 1393 Lisp_Object mod_hooks;
1374 struct gcpro gcpro1; 1394 struct gcpro gcpro1;
1375 1395
1396 hooks = Qnil;
1397 prev_mod_hooks = Qnil;
1398 mod_hooks = Qnil;
1399
1376 if (NULL_INTERVAL_P (intervals)) 1400 if (NULL_INTERVAL_P (intervals))
1377 return; 1401 return;
1378 1402
@@ -1383,43 +1407,93 @@ verify_interval_modification (buf, start, end)
1383 end = temp; 1407 end = temp;
1384 } 1408 }
1385 1409
1386 if (start == BUF_Z (buf)) 1410 /* For an insert operation, check the two chars around the position. */
1411 if (start == end)
1387 { 1412 {
1388 /* This should not be getting called on empty buffers. */ 1413 INTERVAL prev;
1389 if (BUF_Z (buf) == 1) 1414 Lisp_Object before, after;
1390 abort ();
1391 1415
1392 i = find_interval (intervals, start - 1); 1416 /* Set I to the interval containing the char after START,
1393 if (! END_STICKY_P (i)) 1417 and PREV to the interval containing the char before START.
1394 return; 1418 Either one may be null. They may be equal. */
1419 i = find_interval (intervals,
1420 (start == BUF_ZV (buf) ? start - 1 : start));
1421
1422 if (start == BUF_BEGV (buf))
1423 prev = 0;
1424 if (i->position == start)
1425 prev = previous_interval (i);
1426 else if (i->position < start)
1427 prev = i;
1428 if (start == BUF_ZV (buf))
1429 i = 0;
1430
1431 if (NULL_INTERVAL_P (prev))
1432 {
1433 after = textget (i, Qread_only);
1434 if (! NILP (after))
1435 error ("Attempt to insert within read-only text");
1436 }
1437 else if (NULL_INTERVAL_P (i))
1438 {
1439 before = textget (prev, Qread_only);
1440 if (! NILP (before))
1441 error ("Attempt to insert within read-only text");
1442 }
1443 else
1444 {
1445 before = textget (prev, Qread_only);
1446 after = textget (i, Qread_only);
1447 if (! NILP (before) && EQ (before, after))
1448 error ("Attempt to insert within read-only text");
1449 }
1450
1451 /* Run both mod hooks (just once if they're the same). */
1452 if (!NULL_INTERVAL_P (prev))
1453 prev_mod_hooks = textget (prev->plist, Qmodification_hooks);
1454 if (!NULL_INTERVAL_P (i))
1455 mod_hooks = textget (i->plist, Qmodification_hooks);
1456 GCPRO1 (mod_hooks);
1457 if (! NILP (prev_mod_hooks))
1458 call_mod_hooks (prev_mod_hooks, make_number (start),
1459 make_number (end));
1460 UNGCPRO;
1461 if (! NILP (mod_hooks) && ! EQ (mod_hooks, prev_mod_hooks))
1462 call_mod_hooks (mod_hooks, make_number (start), make_number (end));
1395 } 1463 }
1396 else 1464 else
1397 i = find_interval (intervals, start);
1398
1399 do
1400 { 1465 {
1401 if (! INTERVAL_WRITABLE_P (i)) 1466 /* Loop over intervals on or next to START...END,
1402 error ("Attempt to modify read-only text"); 1467 collecting their hooks. */
1403 1468
1404 mod_hook = Fget (Qmodification, i->plist); 1469 i = find_interval (intervals, start);
1405 if (! NILP (mod_hook) && ! EQ (mod_hook, prev_mod_hook)) 1470 do
1406 { 1471 {
1407 hooks = Fcons (mod_hook, hooks); 1472 if (! INTERVAL_WRITABLE_P (i))
1408 prev_mod_hook = mod_hook; 1473 error ("Attempt to modify read-only text");
1409 }
1410 1474
1411 i = next_interval (i); 1475 mod_hooks = textget (i->plist, Qmodification_hooks);
1412 } 1476 if (! NILP (mod_hooks) && ! EQ (mod_hooks, prev_mod_hooks))
1413 while (! NULL_INTERVAL_P (i) && i->position <= end); 1477 {
1478 hooks = Fcons (mod_hooks, hooks);
1479 prev_mod_hooks = mod_hooks;
1480 }
1414 1481
1415 GCPRO1 (hooks); 1482 i = next_interval (i);
1416 hooks = Fnreverse (hooks); 1483 }
1417 while (! EQ (hooks, Qnil)) 1484 /* Keep going thru the interval containing the char before END. */
1418 { 1485 while (! NULL_INTERVAL_P (i) && i->position < end);
1419 call2 (Fcar (hooks), start, end - 1); 1486
1420 hooks = Fcdr (hooks); 1487 GCPRO1 (hooks);
1488 hooks = Fnreverse (hooks);
1489 while (! EQ (hooks, Qnil))
1490 {
1491 call_mod_hooks (Fcar (hooks), make_number (start),
1492 make_number (end));
1493 hooks = Fcdr (hooks);
1494 }
1495 UNGCPRO;
1421 } 1496 }
1422 UNGCPRO;
1423} 1497}
1424 1498
1425/* Balance an interval node if the amount of text in its left and right 1499/* Balance an interval node if the amount of text in its left and right