diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/intervals.c | 147 |
1 files changed, 61 insertions, 86 deletions
diff --git a/src/intervals.c b/src/intervals.c index 81bf0b123ad..da391d559cb 100644 --- a/src/intervals.c +++ b/src/intervals.c | |||
| @@ -432,8 +432,9 @@ split_interval_left (interval, offset) | |||
| 432 | } | 432 | } |
| 433 | 433 | ||
| 434 | /* Find the interval containing text position POSITION in the text | 434 | /* Find the interval containing text position POSITION in the text |
| 435 | represented by the interval tree TREE. POSITION is relative to | 435 | represented by the interval tree TREE. POSITION is a buffer |
| 436 | the beginning of that text. | 436 | position; the earliest position is 1. If POSITION is at the end of |
| 437 | the buffer, return the interval containing the last character. | ||
| 437 | 438 | ||
| 438 | The `position' field, which is a cache of an interval's position, | 439 | The `position' field, which is a cache of an interval's position, |
| 439 | is updated in the interval found. Other functions (e.g., next_interval) | 440 | is updated in the interval found. Other functions (e.g., next_interval) |
| @@ -444,25 +445,25 @@ find_interval (tree, position) | |||
| 444 | register INTERVAL tree; | 445 | register INTERVAL tree; |
| 445 | register int position; | 446 | register int position; |
| 446 | { | 447 | { |
| 447 | register int relative_position = position; | 448 | /* The distance from the left edge of the subtree at TREE |
| 449 | to POSITION. */ | ||
| 450 | register int relative_position = position - BEG; | ||
| 448 | 451 | ||
| 449 | if (NULL_INTERVAL_P (tree)) | 452 | if (NULL_INTERVAL_P (tree)) |
| 450 | return NULL_INTERVAL; | 453 | return NULL_INTERVAL; |
| 451 | 454 | ||
| 452 | if (position > TOTAL_LENGTH (tree)) | 455 | if (relative_position > TOTAL_LENGTH (tree)) |
| 453 | abort (); /* Paranoia */ | 456 | abort (); /* Paranoia */ |
| 454 | #if 0 | ||
| 455 | position = TOTAL_LENGTH (tree); | ||
| 456 | #endif | ||
| 457 | 457 | ||
| 458 | while (1) | 458 | while (1) |
| 459 | { | 459 | { |
| 460 | if (relative_position <= LEFT_TOTAL_LENGTH (tree)) | 460 | if (relative_position < LEFT_TOTAL_LENGTH (tree)) |
| 461 | { | 461 | { |
| 462 | tree = tree->left; | 462 | tree = tree->left; |
| 463 | } | 463 | } |
| 464 | else if (relative_position > (TOTAL_LENGTH (tree) | 464 | else if (! NULL_RIGHT_CHILD (tree) |
| 465 | - RIGHT_TOTAL_LENGTH (tree))) | 465 | && relative_position >= (TOTAL_LENGTH (tree) |
| 466 | - RIGHT_TOTAL_LENGTH (tree))) | ||
| 466 | { | 467 | { |
| 467 | relative_position -= (TOTAL_LENGTH (tree) | 468 | relative_position -= (TOTAL_LENGTH (tree) |
| 468 | - RIGHT_TOTAL_LENGTH (tree)); | 469 | - RIGHT_TOTAL_LENGTH (tree)); |
| @@ -470,8 +471,10 @@ find_interval (tree, position) | |||
| 470 | } | 471 | } |
| 471 | else | 472 | else |
| 472 | { | 473 | { |
| 473 | tree->position = LEFT_TOTAL_LENGTH (tree) | 474 | tree->position = |
| 474 | + position - relative_position + 1; | 475 | (position - relative_position /* the left edge of *tree */ |
| 476 | + LEFT_TOTAL_LENGTH (tree)); /* the left edge of this interval */ | ||
| 477 | |||
| 475 | return tree; | 478 | return tree; |
| 476 | } | 479 | } |
| 477 | } | 480 | } |
| @@ -639,16 +642,16 @@ adjust_intervals_for_insertion (tree, position, length) | |||
| 639 | if (TOTAL_LENGTH (tree) == 0) /* Paranoia */ | 642 | if (TOTAL_LENGTH (tree) == 0) /* Paranoia */ |
| 640 | abort (); | 643 | abort (); |
| 641 | 644 | ||
| 642 | /* If inserting at point-max of a buffer, that position | 645 | /* If inserting at point-max of a buffer, that position will be out |
| 643 | will be out of range. */ | 646 | of range. Remember that buffer positions are 1-based. */ |
| 644 | if (position > TOTAL_LENGTH (tree)) | 647 | if (position > BEG + TOTAL_LENGTH (tree)) |
| 645 | position = TOTAL_LENGTH (tree); | 648 | position = BEG + TOTAL_LENGTH (tree); |
| 646 | 649 | ||
| 647 | i = find_interval (tree, position); | 650 | i = find_interval (tree, position); |
| 648 | /* If we are positioned between intervals, check the stickiness of | 651 | /* If we are positioned between intervals, check the stickiness of |
| 649 | both of them. */ | 652 | both of them. */ |
| 650 | if (position == i->position | 653 | if (position == i->position |
| 651 | && position != 1) | 654 | && position != BEG) |
| 652 | { | 655 | { |
| 653 | register INTERVAL prev = previous_interval (i); | 656 | register INTERVAL prev = previous_interval (i); |
| 654 | 657 | ||
| @@ -747,11 +750,14 @@ delete_interval (i) | |||
| 747 | } | 750 | } |
| 748 | } | 751 | } |
| 749 | 752 | ||
| 750 | /* Find the interval in TREE corresponding to the character position FROM | 753 | /* Find the interval in TREE corresponding to the relative position |
| 751 | and delete as much as possible of AMOUNT from that interval, starting | 754 | FROM and delete as much as possible of AMOUNT from that interval. |
| 752 | after the relative position of FROM within it. Return the amount | 755 | Return the amount actually deleted, and if the interval was |
| 753 | actually deleted, and if the interval was zeroed-out, delete that | 756 | zeroed-out, delete that interval node from the tree. |
| 754 | interval node from the tree. | 757 | |
| 758 | Note that FROM is actually origin zero, aka relative to the | ||
| 759 | leftmost edge of tree. This is appropriate since we call ourselves | ||
| 760 | recursively on subtrees. | ||
| 755 | 761 | ||
| 756 | Do this by recursing down TREE to the interval in question, and | 762 | Do this by recursing down TREE to the interval in question, and |
| 757 | deleting the appropriate amount of text. */ | 763 | deleting the appropriate amount of text. */ |
| @@ -767,7 +773,7 @@ interval_deletion_adjustment (tree, from, amount) | |||
| 767 | return 0; | 773 | return 0; |
| 768 | 774 | ||
| 769 | /* Left branch */ | 775 | /* Left branch */ |
| 770 | if (relative_position <= LEFT_TOTAL_LENGTH (tree)) | 776 | if (relative_position < LEFT_TOTAL_LENGTH (tree)) |
| 771 | { | 777 | { |
| 772 | int subtract = interval_deletion_adjustment (tree->left, | 778 | int subtract = interval_deletion_adjustment (tree->left, |
| 773 | relative_position, | 779 | relative_position, |
| @@ -776,8 +782,8 @@ interval_deletion_adjustment (tree, from, amount) | |||
| 776 | return subtract; | 782 | return subtract; |
| 777 | } | 783 | } |
| 778 | /* Right branch */ | 784 | /* Right branch */ |
| 779 | else if (relative_position > (TOTAL_LENGTH (tree) | 785 | else if (relative_position >= (TOTAL_LENGTH (tree) |
| 780 | - RIGHT_TOTAL_LENGTH (tree))) | 786 | - RIGHT_TOTAL_LENGTH (tree))) |
| 781 | { | 787 | { |
| 782 | int subtract; | 788 | int subtract; |
| 783 | 789 | ||
| @@ -792,55 +798,28 @@ interval_deletion_adjustment (tree, from, amount) | |||
| 792 | /* Here -- this node */ | 798 | /* Here -- this node */ |
| 793 | else | 799 | else |
| 794 | { | 800 | { |
| 795 | /* If this is a zero-length, marker interval, then | 801 | /* How much can we delete from this interval? */ |
| 796 | we must skip it. */ | 802 | int my_amount = ((tree->total_length |
| 797 | 803 | - RIGHT_TOTAL_LENGTH (tree)) | |
| 798 | if (relative_position == LEFT_TOTAL_LENGTH (tree) + 1) | 804 | - relative_position); |
| 799 | { | 805 | |
| 800 | /* This means we're deleting from the beginning of this interval. */ | 806 | if (amount > my_amount) |
| 801 | register int my_amount = LENGTH (tree); | 807 | amount = my_amount; |
| 802 | 808 | ||
| 803 | if (amount < my_amount) | 809 | tree->total_length -= amount; |
| 804 | { | 810 | if (LENGTH (tree) == 0) |
| 805 | tree->total_length -= amount; | 811 | delete_interval (tree); |
| 806 | return amount; | 812 | |
| 807 | } | 813 | return amount; |
| 808 | else | ||
| 809 | { | ||
| 810 | tree->total_length -= my_amount; | ||
| 811 | if (LENGTH (tree) != 0) | ||
| 812 | abort (); /* Paranoia */ | ||
| 813 | |||
| 814 | delete_interval (tree); | ||
| 815 | return my_amount; | ||
| 816 | } | ||
| 817 | } | ||
| 818 | else /* Deleting starting in the middle. */ | ||
| 819 | { | ||
| 820 | register int my_amount = ((tree->total_length | ||
| 821 | - RIGHT_TOTAL_LENGTH (tree)) | ||
| 822 | - relative_position + 1); | ||
| 823 | |||
| 824 | if (amount <= my_amount) | ||
| 825 | { | ||
| 826 | tree->total_length -= amount; | ||
| 827 | return amount; | ||
| 828 | } | ||
| 829 | else | ||
| 830 | { | ||
| 831 | tree->total_length -= my_amount; | ||
| 832 | return my_amount; | ||
| 833 | } | ||
| 834 | } | ||
| 835 | } | 814 | } |
| 836 | 815 | ||
| 837 | /* Never reach here */ | 816 | /* Never reach here */ |
| 838 | } | 817 | } |
| 839 | 818 | ||
| 840 | /* Effect the adjustments necessary to the interval tree of BUFFER | 819 | /* Effect the adjustments necessary to the interval tree of BUFFER to |
| 841 | to correspond to the deletion of LENGTH characters from that buffer | 820 | correspond to the deletion of LENGTH characters from that buffer |
| 842 | text. The deletion is effected at position START (relative to the | 821 | text. The deletion is effected at position START (which is a |
| 843 | buffer). */ | 822 | buffer position, i.e. origin 1). */ |
| 844 | 823 | ||
| 845 | static void | 824 | static void |
| 846 | adjust_intervals_for_deletion (buffer, start, length) | 825 | adjust_intervals_for_deletion (buffer, start, length) |
| @@ -854,6 +833,10 @@ adjust_intervals_for_deletion (buffer, start, length) | |||
| 854 | if (NULL_INTERVAL_P (tree)) | 833 | if (NULL_INTERVAL_P (tree)) |
| 855 | return; | 834 | return; |
| 856 | 835 | ||
| 836 | if (start > BEG + TOTAL_LENGTH (tree) | ||
| 837 | || start + length > BEG + TOTAL_LENGTH (tree)) | ||
| 838 | abort (); | ||
| 839 | |||
| 857 | if (length == TOTAL_LENGTH (tree)) | 840 | if (length == TOTAL_LENGTH (tree)) |
| 858 | { | 841 | { |
| 859 | buffer->intervals = NULL_INTERVAL; | 842 | buffer->intervals = NULL_INTERVAL; |
| @@ -866,11 +849,11 @@ adjust_intervals_for_deletion (buffer, start, length) | |||
| 866 | return; | 849 | return; |
| 867 | } | 850 | } |
| 868 | 851 | ||
| 869 | if (start > TOTAL_LENGTH (tree)) | 852 | if (start > BEG + TOTAL_LENGTH (tree)) |
| 870 | start = TOTAL_LENGTH (tree); | 853 | start = BEG + TOTAL_LENGTH (tree); |
| 871 | while (left_to_delete > 0) | 854 | while (left_to_delete > 0) |
| 872 | { | 855 | { |
| 873 | left_to_delete -= interval_deletion_adjustment (tree, start, | 856 | left_to_delete -= interval_deletion_adjustment (tree, start - 1, |
| 874 | left_to_delete); | 857 | left_to_delete); |
| 875 | tree = buffer->intervals; | 858 | tree = buffer->intervals; |
| 876 | if (left_to_delete == tree->total_length) | 859 | if (left_to_delete == tree->total_length) |
| @@ -1030,6 +1013,9 @@ reproduce_tree (source, parent) | |||
| 1030 | return t; | 1013 | return t; |
| 1031 | } | 1014 | } |
| 1032 | 1015 | ||
| 1016 | #if 0 | ||
| 1017 | /* Nobody calls this. Perhaps it's a vestige of an earlier design. */ | ||
| 1018 | |||
| 1033 | /* Make a new interval of length LENGTH starting at START in the | 1019 | /* Make a new interval of length LENGTH starting at START in the |
| 1034 | group of intervals INTERVALS, which is actually an interval tree. | 1020 | group of intervals INTERVALS, which is actually an interval tree. |
| 1035 | Returns the new interval. | 1021 | Returns the new interval. |
| @@ -1070,6 +1056,7 @@ make_new_interval (intervals, start, length) | |||
| 1070 | split_interval_right (slot, length + 1); | 1056 | split_interval_right (slot, length + 1); |
| 1071 | return slot; | 1057 | return slot; |
| 1072 | } | 1058 | } |
| 1059 | #endif | ||
| 1073 | 1060 | ||
| 1074 | /* Insert the intervals of SOURCE into BUFFER at POSITION. | 1061 | /* Insert the intervals of SOURCE into BUFFER at POSITION. |
| 1075 | 1062 | ||
| @@ -1244,7 +1231,6 @@ set_point (position, buffer) | |||
| 1244 | register struct buffer *buffer; | 1231 | register struct buffer *buffer; |
| 1245 | { | 1232 | { |
| 1246 | register INTERVAL to, from, toprev, fromprev, target; | 1233 | register INTERVAL to, from, toprev, fromprev, target; |
| 1247 | register int iposition = position; | ||
| 1248 | int buffer_point; | 1234 | int buffer_point; |
| 1249 | register Lisp_Object obj; | 1235 | register Lisp_Object obj; |
| 1250 | int backwards = (position < BUF_PT (buffer)) ? 1 : 0; | 1236 | int backwards = (position < BUF_PT (buffer)) ? 1 : 0; |
| @@ -1265,20 +1251,14 @@ set_point (position, buffer) | |||
| 1265 | return; | 1251 | return; |
| 1266 | } | 1252 | } |
| 1267 | 1253 | ||
| 1268 | /* Position Z is really one past the last char in the buffer. */ | ||
| 1269 | if (position == BUF_ZV (buffer)) | ||
| 1270 | iposition = position - 1; | ||
| 1271 | |||
| 1272 | /* Set TO to the interval containing the char after POSITION, | 1254 | /* Set TO to the interval containing the char after POSITION, |
| 1273 | and TOPREV to the interval containing the char before POSITION. | 1255 | and TOPREV to the interval containing the char before POSITION. |
| 1274 | Either one may be null. They may be equal. */ | 1256 | Either one may be null. They may be equal. */ |
| 1275 | to = find_interval (buffer->intervals, iposition); | 1257 | to = find_interval (buffer->intervals, position); |
| 1276 | if (position == BUF_BEGV (buffer)) | 1258 | if (position == BUF_BEGV (buffer)) |
| 1277 | toprev = 0; | 1259 | toprev = 0; |
| 1278 | else if (to->position == position) | 1260 | else if (to->position == position) |
| 1279 | toprev = previous_interval (to); | 1261 | toprev = previous_interval (to); |
| 1280 | else if (iposition != position) | ||
| 1281 | toprev = to, to = 0; | ||
| 1282 | else | 1262 | else |
| 1283 | toprev = to; | 1263 | toprev = to; |
| 1284 | 1264 | ||
| @@ -1390,10 +1370,6 @@ get_local_map (position, buffer) | |||
| 1390 | if (position > BUF_Z (buffer) || position < BUF_BEG (buffer)) | 1370 | if (position > BUF_Z (buffer) || position < BUF_BEG (buffer)) |
| 1391 | abort (); | 1371 | abort (); |
| 1392 | 1372 | ||
| 1393 | /* Position Z is really one past the last char in the buffer. */ | ||
| 1394 | if (position == BUF_ZV (buffer)) | ||
| 1395 | return current_buffer->keymap; | ||
| 1396 | |||
| 1397 | interval = find_interval (buffer->intervals, position); | 1373 | interval = find_interval (buffer->intervals, position); |
| 1398 | prop = textget (interval->plist, Qlocal_map); | 1374 | prop = textget (interval->plist, Qlocal_map); |
| 1399 | if (NILP (prop)) | 1375 | if (NILP (prop)) |
| @@ -1465,8 +1441,7 @@ verify_interval_modification (buf, start, end) | |||
| 1465 | /* Set I to the interval containing the char after START, | 1441 | /* Set I to the interval containing the char after START, |
| 1466 | and PREV to the interval containing the char before START. | 1442 | and PREV to the interval containing the char before START. |
| 1467 | Either one may be null. They may be equal. */ | 1443 | Either one may be null. They may be equal. */ |
| 1468 | i = find_interval (intervals, | 1444 | i = find_interval (intervals, start); |
| 1469 | (start == BUF_ZV (buf) ? start - 1 : start)); | ||
| 1470 | 1445 | ||
| 1471 | if (start == BUF_BEGV (buf)) | 1446 | if (start == BUF_BEGV (buf)) |
| 1472 | prev = 0; | 1447 | prev = 0; |