Mercurial > emacs
comparison src/intervals.c @ 4383:d4a36c1669e6
(adjust_intervals_for_insertion): Handle insertion
between two unlike intervals via merge_properties_sticky.
(merge_properties_sticky): New function.
(graft_intervals_into_buffer): Leave handling of `sticky'-ness to
adjust_intervals_for_insertion, then merge properties of the
inserted text onto the old ones.
(textget_direct): New function.
(set_point): Fix calculating of fromprev.
(verify_interval_modification): Check for `read-only' property
and take its `sticky'-ness into account.
(set_point): Ignore `invisible' property unless property value is `hidden'.
author | Richard M. Stallman <rms@gnu.org> |
---|---|
date | Sat, 31 Jul 1993 21:58:03 +0000 |
parents | 23fe7f6c9ae4 |
children | 3872f91770fc |
comparison
equal
deleted
inserted
replaced
4382:c11d710e0403 | 4383:d4a36c1669e6 |
---|---|
3 | 3 |
4 This file is part of GNU Emacs. | 4 This file is part of GNU Emacs. |
5 | 5 |
6 GNU Emacs is free software; you can redistribute it and/or modify | 6 GNU Emacs is free software; you can redistribute it and/or modify |
7 it under the terms of the GNU General Public License as published by | 7 it under the terms of the GNU General Public License as published by |
8 the Free Software Foundation; either version 1, or (at your option) | 8 the Free Software Foundation; either version 2, or (at your option) |
9 any later version. | 9 any later version. |
10 | 10 |
11 GNU Emacs is distributed in the hope that it will be useful, | 11 GNU Emacs is distributed in the hope that it will be useful, |
12 but WITHOUT ANY WARRANTY; without even the implied warranty of | 12 but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
41 #include "config.h" | 41 #include "config.h" |
42 #include "lisp.h" | 42 #include "lisp.h" |
43 #include "intervals.h" | 43 #include "intervals.h" |
44 #include "buffer.h" | 44 #include "buffer.h" |
45 | 45 |
46 /* The rest of the file is within this conditional. */ | 46 /* The rest of the file is within this conditional. */ |
47 #ifdef USE_TEXT_PROPERTIES | 47 #ifdef USE_TEXT_PROPERTIES |
48 | 48 |
49 /* Factor for weight-balancing interval trees. */ | 49 /* Factor for weight-balancing interval trees. */ |
50 Lisp_Object interval_balance_threshold; | 50 Lisp_Object interval_balance_threshold; |
51 | 51 |
52 /* Utility functions for intervals. */ | 52 /* Utility functions for intervals. */ |
53 | 53 |
54 | 54 |
55 /* Create the root interval of some object, a buffer or string. */ | 55 /* Create the root interval of some object, a buffer or string. */ |
56 | 56 |
57 INTERVAL | 57 INTERVAL |
58 create_root_interval (parent) | 58 create_root_interval (parent) |
59 Lisp_Object parent; | 59 Lisp_Object parent; |
60 { | 60 { |
123 o = Fcdr (Fcdr (o)); | 123 o = Fcdr (Fcdr (o)); |
124 } | 124 } |
125 } | 125 } |
126 | 126 |
127 /* Return 1 if the two intervals have the same properties, | 127 /* Return 1 if the two intervals have the same properties, |
128 0 otherwise. */ | 128 0 otherwise. */ |
129 | 129 |
130 int | 130 int |
131 intervals_equal (i0, i1) | 131 intervals_equal (i0, i1) |
132 INTERVAL i0, i1; | 132 INTERVAL i0, i1; |
133 { | 133 { |
145 abort (); | 145 abort (); |
146 i1_len /= 2; | 146 i1_len /= 2; |
147 i0_cdr = i0->plist; | 147 i0_cdr = i0->plist; |
148 while (!NILP (i0_cdr)) | 148 while (!NILP (i0_cdr)) |
149 { | 149 { |
150 /* Lengths of the two plists were unequal */ | 150 /* Lengths of the two plists were unequal. */ |
151 if (i1_len == 0) | 151 if (i1_len == 0) |
152 return 0; | 152 return 0; |
153 | 153 |
154 i0_sym = Fcar (i0_cdr); | 154 i0_sym = Fcar (i0_cdr); |
155 i1_val = Fmemq (i0_sym, i1->plist); | 155 i1_val = Fmemq (i0_sym, i1->plist); |
156 | 156 |
157 /* i0 has something i1 doesn't */ | 157 /* i0 has something i1 doesn't. */ |
158 if (EQ (i1_val, Qnil)) | 158 if (EQ (i1_val, Qnil)) |
159 return 0; | 159 return 0; |
160 | 160 |
161 /* i0 and i1 both have sym, but it has different values in each */ | 161 /* i0 and i1 both have sym, but it has different values in each. */ |
162 i0_cdr = Fcdr (i0_cdr); | 162 i0_cdr = Fcdr (i0_cdr); |
163 if (! EQ (i1_val, Fcar (i0_cdr))) | 163 if (! EQ (Fcar (Fcdr (i1_val)), Fcar (i0_cdr))) |
164 return 0; | 164 return 0; |
165 | 165 |
166 i0_cdr = Fcdr (i0_cdr); | 166 i0_cdr = Fcdr (i0_cdr); |
167 i1_len--; | 167 i1_len--; |
168 } | 168 } |
169 | 169 |
170 /* Lengths of the two plists were unequal */ | 170 /* Lengths of the two plists were unequal. */ |
171 if (i1_len > 0) | 171 if (i1_len > 0) |
172 return 0; | 172 return 0; |
173 | 173 |
174 return 1; | 174 return 1; |
175 } | 175 } |
198 position += LENGTH (tree); | 198 position += LENGTH (tree); |
199 traverse_intervals (tree->right, position, depth + 1, function, arg); | 199 traverse_intervals (tree->right, position, depth + 1, function, arg); |
200 } | 200 } |
201 | 201 |
202 #if 0 | 202 #if 0 |
203 /* These functions are temporary, for debugging purposes only. */ | 203 /* These functions are temporary, for debugging purposes only. */ |
204 | 204 |
205 INTERVAL search_interval, found_interval; | 205 INTERVAL search_interval, found_interval; |
206 | 206 |
207 void | 207 void |
208 check_for_interval (i) | 208 check_for_interval (i) |
277 { | 277 { |
278 INTERVAL i; | 278 INTERVAL i; |
279 INTERVAL B = interval->left; | 279 INTERVAL B = interval->left; |
280 int len = LENGTH (interval); | 280 int len = LENGTH (interval); |
281 | 281 |
282 /* Deal with any Parent of A; make it point to B. */ | 282 /* Deal with any Parent of A; make it point to B. */ |
283 if (! ROOT_INTERVAL_P (interval)) | 283 if (! ROOT_INTERVAL_P (interval)) |
284 if (AM_LEFT_CHILD (interval)) | 284 if (AM_LEFT_CHILD (interval)) |
285 interval->parent->left = interval->left; | 285 interval->parent->left = interval->left; |
286 else | 286 else |
287 interval->parent->right = interval->left; | 287 interval->parent->right = interval->left; |
288 interval->left->parent = interval->parent; | 288 interval->left->parent = interval->parent; |
289 | 289 |
290 /* B gets the same length as A, since it get A's position in the tree. */ | 290 /* B gets the same length as A, since it get A's position in the tree. */ |
291 interval->left->total_length = interval->total_length; | 291 interval->left->total_length = interval->total_length; |
292 | 292 |
293 /* B becomes the parent of A. */ | 293 /* B becomes the parent of A. */ |
294 i = interval->left->right; | 294 i = interval->left->right; |
295 interval->left->right = interval; | 295 interval->left->right = interval; |
296 interval->parent = interval->left; | 296 interval->parent = interval->left; |
297 | 297 |
298 /* A gets c as left child. */ | 298 /* A gets c as left child. */ |
299 interval->left = i; | 299 interval->left = i; |
300 if (! NULL_INTERVAL_P (i)) | 300 if (! NULL_INTERVAL_P (i)) |
301 i->parent = interval; | 301 i->parent = interval; |
302 interval->total_length = (len + LEFT_TOTAL_LENGTH (interval) | 302 interval->total_length = (len + LEFT_TOTAL_LENGTH (interval) |
303 + RIGHT_TOTAL_LENGTH (interval)); | 303 + RIGHT_TOTAL_LENGTH (interval)); |
320 { | 320 { |
321 INTERVAL i; | 321 INTERVAL i; |
322 INTERVAL B = interval->right; | 322 INTERVAL B = interval->right; |
323 int len = LENGTH (interval); | 323 int len = LENGTH (interval); |
324 | 324 |
325 /* Deal with the parent of A. */ | 325 /* Deal with the parent of A. */ |
326 if (! ROOT_INTERVAL_P (interval)) | 326 if (! ROOT_INTERVAL_P (interval)) |
327 if (AM_LEFT_CHILD (interval)) | 327 if (AM_LEFT_CHILD (interval)) |
328 interval->parent->left = interval->right; | 328 interval->parent->left = interval->right; |
329 else | 329 else |
330 interval->parent->right = interval->right; | 330 interval->parent->right = interval->right; |
331 interval->right->parent = interval->parent; | 331 interval->right->parent = interval->parent; |
332 | 332 |
333 /* B must have the same total length of A. */ | 333 /* B must have the same total length of A. */ |
334 interval->right->total_length = interval->total_length; | 334 interval->right->total_length = interval->total_length; |
335 | 335 |
336 /* Make B the parent of A */ | 336 /* Make B the parent of A */ |
337 i = interval->right->left; | 337 i = interval->right->left; |
338 interval->right->left = interval; | 338 interval->right->left = interval; |
357 those of the original interval. The property list of the new interval | 357 those of the original interval. The property list of the new interval |
358 is reset, thus it is up to the caller to do the right thing with the | 358 is reset, thus it is up to the caller to do the right thing with the |
359 result. | 359 result. |
360 | 360 |
361 Note that this does not change the position of INTERVAL; if it is a root, | 361 Note that this does not change the position of INTERVAL; if it is a root, |
362 it is still a root after this operation. */ | 362 it is still a root after this operation. */ |
363 | 363 |
364 INTERVAL | 364 INTERVAL |
365 split_interval_right (interval, offset) | 365 split_interval_right (interval, offset) |
366 INTERVAL interval; | 366 INTERVAL interval; |
367 int offset; | 367 int offset; |
379 new->total_length = new_length; | 379 new->total_length = new_length; |
380 | 380 |
381 return new; | 381 return new; |
382 } | 382 } |
383 | 383 |
384 /* Insert the new node between INTERVAL and its right child. */ | 384 /* Insert the new node between INTERVAL and its right child. */ |
385 new->right = interval->right; | 385 new->right = interval->right; |
386 interval->right->parent = new; | 386 interval->right->parent = new; |
387 interval->right = new; | 387 interval->right = new; |
388 | 388 |
389 new->total_length = new_length + new->right->total_length; | 389 new->total_length = new_length + new->right->total_length; |
400 those of the original interval. The property list of the new interval | 400 those of the original interval. The property list of the new interval |
401 is reset, thus it is up to the caller to do the right thing with the | 401 is reset, thus it is up to the caller to do the right thing with the |
402 result. | 402 result. |
403 | 403 |
404 Note that this does not change the position of INTERVAL; if it is a root, | 404 Note that this does not change the position of INTERVAL; if it is a root, |
405 it is still a root after this operation. */ | 405 it is still a root after this operation. */ |
406 | 406 |
407 INTERVAL | 407 INTERVAL |
408 split_interval_left (interval, offset) | 408 split_interval_left (interval, offset) |
409 INTERVAL interval; | 409 INTERVAL interval; |
410 int offset; | 410 int offset; |
423 new->total_length = new_length; | 423 new->total_length = new_length; |
424 | 424 |
425 return new; | 425 return new; |
426 } | 426 } |
427 | 427 |
428 /* Insert the new node between INTERVAL and its left child. */ | 428 /* Insert the new node between INTERVAL and its left child. */ |
429 new->left = interval->left; | 429 new->left = interval->left; |
430 new->left->parent = new; | 430 new->left->parent = new; |
431 interval->left = new; | 431 interval->left = new; |
432 new->total_length = new_length + LEFT_TOTAL_LENGTH (new); | 432 new->total_length = new_length + LEFT_TOTAL_LENGTH (new); |
433 | 433 |
439 position; the earliest position is 1. If POSITION is at the end of | 439 position; the earliest position is 1. If POSITION is at the end of |
440 the buffer, return the interval containing the last character. | 440 the buffer, return the interval containing the last character. |
441 | 441 |
442 The `position' field, which is a cache of an interval's position, | 442 The `position' field, which is a cache of an interval's position, |
443 is updated in the interval found. Other functions (e.g., next_interval) | 443 is updated in the interval found. Other functions (e.g., next_interval) |
444 will update this cache based on the result of find_interval. */ | 444 will update this cache based on the result of find_interval. */ |
445 | 445 |
446 INLINE INTERVAL | 446 INLINE INTERVAL |
447 find_interval (tree, position) | 447 find_interval (tree, position) |
448 register INTERVAL tree; | 448 register INTERVAL tree; |
449 register int position; | 449 register int position; |
483 } | 483 } |
484 } | 484 } |
485 | 485 |
486 /* Find the succeeding interval (lexicographically) to INTERVAL. | 486 /* Find the succeeding interval (lexicographically) to INTERVAL. |
487 Sets the `position' field based on that of INTERVAL (see | 487 Sets the `position' field based on that of INTERVAL (see |
488 find_interval). */ | 488 find_interval). */ |
489 | 489 |
490 INTERVAL | 490 INTERVAL |
491 next_interval (interval) | 491 next_interval (interval) |
492 register INTERVAL interval; | 492 register INTERVAL interval; |
493 { | 493 { |
523 return NULL_INTERVAL; | 523 return NULL_INTERVAL; |
524 } | 524 } |
525 | 525 |
526 /* Find the preceding interval (lexicographically) to INTERVAL. | 526 /* Find the preceding interval (lexicographically) to INTERVAL. |
527 Sets the `position' field based on that of INTERVAL (see | 527 Sets the `position' field based on that of INTERVAL (see |
528 find_interval). */ | 528 find_interval). */ |
529 | 529 |
530 INTERVAL | 530 INTERVAL |
531 previous_interval (interval) | 531 previous_interval (interval) |
532 register INTERVAL interval; | 532 register INTERVAL interval; |
533 { | 533 { |
572 | 572 |
573 Modifications are needed to handle the hungry bits -- after simply | 573 Modifications are needed to handle the hungry bits -- after simply |
574 finding the interval at position (don't add length going down), | 574 finding the interval at position (don't add length going down), |
575 if it's the beginning of the interval, get the previous interval | 575 if it's the beginning of the interval, get the previous interval |
576 and check the hugry bits of both. Then add the length going back up | 576 and check the hugry bits of both. Then add the length going back up |
577 to the root. */ | 577 to the root. */ |
578 | 578 |
579 static INTERVAL | 579 static INTERVAL |
580 adjust_intervals_for_insertion (tree, position, length) | 580 adjust_intervals_for_insertion (tree, position, length) |
581 INTERVAL tree; | 581 INTERVAL tree; |
582 int position, length; | 582 int position, length; |
610 this = this->right; | 610 this = this->right; |
611 } | 611 } |
612 else | 612 else |
613 { | 613 { |
614 /* If we are to use zero-length intervals as buffer pointers, | 614 /* If we are to use zero-length intervals as buffer pointers, |
615 then this code will have to change. */ | 615 then this code will have to change. */ |
616 this->total_length += length; | 616 this->total_length += length; |
617 this->position = LEFT_TOTAL_LENGTH (this) | 617 this->position = LEFT_TOTAL_LENGTH (this) |
618 + position - relative_position + 1; | 618 + position - relative_position + 1; |
619 return tree; | 619 return tree; |
620 } | 620 } |
631 is actually between the two intervals, make the new text belong to | 631 is actually between the two intervals, make the new text belong to |
632 the interval which is "sticky". | 632 the interval which is "sticky". |
633 | 633 |
634 If both intervals are "sticky", then make them belong to the left-most | 634 If both intervals are "sticky", then make them belong to the left-most |
635 interval. Another possibility would be to create a new interval for | 635 interval. Another possibility would be to create a new interval for |
636 this text, and make it have the merged properties of both ends. */ | 636 this text, and make it have the merged properties of both ends. */ |
637 | 637 |
638 static INTERVAL | 638 static INTERVAL |
639 adjust_intervals_for_insertion (tree, position, length) | 639 adjust_intervals_for_insertion (tree, position, length) |
640 INTERVAL tree; | 640 INTERVAL tree; |
641 int position, length; | 641 int position, length; |
642 { | 642 { |
643 register INTERVAL i; | 643 register INTERVAL i; |
644 | 644 register INTERVAL temp; |
645 int eobp = 0; | |
646 | |
645 if (TOTAL_LENGTH (tree) == 0) /* Paranoia */ | 647 if (TOTAL_LENGTH (tree) == 0) /* Paranoia */ |
646 abort (); | 648 abort (); |
647 | 649 |
648 /* If inserting at point-max of a buffer, that position will be out | 650 /* If inserting at point-max of a buffer, that position will be out |
649 of range. Remember that buffer positions are 1-based. */ | 651 of range. Remember that buffer positions are 1-based. */ |
650 if (position > BEG + TOTAL_LENGTH (tree)) | 652 if (position >= BEG + TOTAL_LENGTH (tree)){ |
651 position = BEG + TOTAL_LENGTH (tree); | 653 position = BEG + TOTAL_LENGTH (tree); |
654 eobp = 1; | |
655 } | |
652 | 656 |
653 i = find_interval (tree, position); | 657 i = find_interval (tree, position); |
658 | |
654 /* If we are positioned between intervals, check the stickiness of | 659 /* If we are positioned between intervals, check the stickiness of |
655 both of them. */ | 660 both of them. We have to do this too, if we are at BEG or Z. */ |
656 if (position == i->position | 661 if (position == i->position || eobp) |
657 && position != BEG) | 662 { |
658 { | 663 register INTERVAL prev; |
659 register INTERVAL prev = previous_interval (i); | 664 |
660 | 665 if (position == BEG) |
661 /* If both intervals are sticky here, then default to the | 666 prev = 0; |
662 left-most one. But perhaps we should create a new | 667 else if (eobp) |
663 interval here instead... */ | 668 { |
664 if (END_STICKY_P (prev) || ! FRONT_STICKY_P (i)) | 669 prev = i; |
665 i = prev; | 670 i = 0; |
666 } | 671 } |
667 | 672 else |
668 while (! NULL_INTERVAL_P (i)) | 673 prev = previous_interval (i); |
669 { | 674 |
670 i->total_length += length; | 675 /* Even if we are positioned between intervals, we default |
671 i = i->parent; | 676 to the left one if it exists. We extend it now and split |
672 } | 677 off a part later, if stickyness demands it. */ |
673 | 678 for (temp = prev ? prev : i; ! NULL_INTERVAL_P (temp); temp = temp->parent) |
679 temp->total_length += length; | |
680 | |
681 /* If at least one interval has sticky properties, | |
682 we check the stickyness property by property. */ | |
683 if (END_NONSTICKY_P (prev) || FRONT_STICKY_P (i)) | |
684 { | |
685 Lisp_Object pleft = NULL_INTERVAL_P (prev) ? Qnil : prev->plist; | |
686 Lisp_Object pright = NULL_INTERVAL_P (i) ? Qnil : i->plist; | |
687 struct interval newi; | |
688 | |
689 newi.plist = merge_properties_sticky (pleft, pright); | |
690 | |
691 if(! prev) /* i.e. position == BEG */ | |
692 { | |
693 if (! intervals_equal (i, &newi)) | |
694 { | |
695 i = split_interval_left (i, length); | |
696 i->plist = newi.plist; | |
697 } | |
698 } | |
699 else if (! intervals_equal (prev, &newi)) | |
700 { | |
701 prev = split_interval_right (prev, | |
702 position - prev->position); | |
703 prev->plist = newi.plist; | |
704 if (! NULL_INTERVAL_P (i) | |
705 && intervals_equal (prev, i)) | |
706 merge_interval_right (prev); | |
707 } | |
708 | |
709 /* We will need to update the cache here later. */ | |
710 } | |
711 else if (! prev && ! NILP (i->plist)) | |
712 { | |
713 /* Just split off a new interval at the left. | |
714 Since I wasn't front-sticky, the empty plist is ok. */ | |
715 i = split_interval_left (i, length); | |
716 } | |
717 } | |
718 | |
719 /* Otherwise just extend the interval. */ | |
720 else | |
721 { | |
722 for (temp = i; ! NULL_INTERVAL_P (temp); temp = temp->parent) | |
723 temp->total_length += length; | |
724 } | |
725 | |
674 return tree; | 726 return tree; |
675 } | 727 } |
728 | |
729 Lisp_Object | |
730 merge_properties_sticky (pleft, pright) | |
731 Lisp_Object pleft, pright; | |
732 { | |
733 register Lisp_Object props = Qnil, front = Qnil, rear = Qnil; | |
734 | |
735 Lisp_Object lfront = textget (pleft, Qfront_sticky); | |
736 Lisp_Object lrear = textget (pleft, Qrear_nonsticky); | |
737 Lisp_Object rfront = textget (pright, Qfront_sticky); | |
738 Lisp_Object rrear = textget (pright, Qrear_nonsticky); | |
739 | |
740 register Lisp_Object tail1, tail2, sym; | |
741 | |
742 /* Go through each element of PLEFT. */ | |
743 for (tail1 = pleft; ! NILP (tail1); tail1 = Fcdr (Fcdr (tail1))) | |
744 { | |
745 sym = Fcar (tail1); | |
746 | |
747 /* Sticky properties get special treatment. */ | |
748 if (EQ (sym, Qrear_nonsticky) || EQ (sym, Qfront_sticky)) | |
749 continue; | |
750 | |
751 if (NILP (Fmemq (sym, lrear))) | |
752 { | |
753 /* rear-sticky is dominant, we needn't search in PRIGHT. */ | |
754 | |
755 props = Fcons (sym, Fcons (Fcar (Fcdr (tail1)), props)); | |
756 if (! NILP (Fmemq (sym, lfront))) | |
757 front = Fcons (sym, front); | |
758 } | |
759 else | |
760 { | |
761 /* Go through PRIGHT, looking for sym. */ | |
762 for (tail2 = pright; ! NILP (tail2); tail2 = Fcdr (Fcdr (tail2))) | |
763 if (EQ (sym, Fcar (tail2))) | |
764 { | |
765 | |
766 if (! NILP (Fmemq (sym, rfront))) | |
767 { | |
768 /* Nonsticky at the left and sticky at the right, | |
769 so take the right one. */ | |
770 props = Fcons (sym, Fcons (Fcar (Fcdr (tail2)), props)); | |
771 front = Fcons (sym, front); | |
772 if (! NILP (Fmemq (sym, rrear))) | |
773 rear = Fcons (sym, rear); | |
774 } | |
775 break; | |
776 } | |
777 } | |
778 } | |
779 /* Now let's see what to keep from PRIGHT. */ | |
780 for (tail2 = pright; ! NILP (tail2); tail2 = Fcdr (Fcdr (tail2))) | |
781 { | |
782 sym = Fcar (tail2); | |
783 | |
784 /* Sticky properties get special treatment. */ | |
785 if (EQ (sym, Qrear_nonsticky) || EQ (sym, Qfront_sticky)) | |
786 continue; | |
787 | |
788 /* If it ain't sticky, we don't take it. */ | |
789 if (NILP (Fmemq (sym, rfront))) | |
790 continue; | |
791 | |
792 /* If sym is in PLEFT we already got it. */ | |
793 for (tail1 = pleft; ! NILP (tail1); tail1 = Fcdr (Fcdr (tail1))) | |
794 if (EQ (sym, Fcar (tail1))) | |
795 break; | |
796 | |
797 if (NILP (tail1)) | |
798 { | |
799 props = Fcons (sym, Fcons (Fcar (Fcdr (tail2)), props)); | |
800 front = Fcons (sym, front); | |
801 if (! NILP (Fmemq (sym, rrear))) | |
802 rear = Fcons (sym, rear); | |
803 } | |
804 } | |
805 if (! NILP (front)) | |
806 props = Fcons (Qfront_sticky, Fcons (front, props)); | |
807 if (! NILP (rear)) | |
808 props = Fcons (Qrear_nonsticky, Fcons (rear, props)); | |
809 return props; | |
810 | |
811 } | |
812 | |
676 | 813 |
677 /* Delete an node I from its interval tree by merging its subtrees | 814 /* Delete an node I from its interval tree by merging its subtrees |
678 into one subtree which is then returned. Caller is responsible for | 815 into one subtree which is then returned. Caller is responsible for |
679 storing the resulting subtree into its parent. */ | 816 storing the resulting subtree into its parent. */ |
680 | 817 |
681 static INTERVAL | 818 static INTERVAL |
682 delete_node (i) | 819 delete_node (i) |
683 register INTERVAL i; | 820 register INTERVAL i; |
684 { | 821 { |
707 | 844 |
708 /* Delete interval I from its tree by calling `delete_node' | 845 /* Delete interval I from its tree by calling `delete_node' |
709 and properly connecting the resultant subtree. | 846 and properly connecting the resultant subtree. |
710 | 847 |
711 I is presumed to be empty; that is, no adjustments are made | 848 I is presumed to be empty; that is, no adjustments are made |
712 for the length of I. */ | 849 for the length of I. */ |
713 | 850 |
714 void | 851 void |
715 delete_interval (i) | 852 delete_interval (i) |
716 register INTERVAL i; | 853 register INTERVAL i; |
717 { | 854 { |
718 register INTERVAL parent; | 855 register INTERVAL parent; |
719 int amt = LENGTH (i); | 856 int amt = LENGTH (i); |
720 | 857 |
721 if (amt > 0) /* Only used on zero-length intervals now. */ | 858 if (amt > 0) /* Only used on zero-length intervals now. */ |
722 abort (); | 859 abort (); |
723 | 860 |
724 if (ROOT_INTERVAL_P (i)) | 861 if (ROOT_INTERVAL_P (i)) |
725 { | 862 { |
726 Lisp_Object owner = (Lisp_Object) i->parent; | 863 Lisp_Object owner = (Lisp_Object) i->parent; |
761 Note that FROM is actually origin zero, aka relative to the | 898 Note that FROM is actually origin zero, aka relative to the |
762 leftmost edge of tree. This is appropriate since we call ourselves | 899 leftmost edge of tree. This is appropriate since we call ourselves |
763 recursively on subtrees. | 900 recursively on subtrees. |
764 | 901 |
765 Do this by recursing down TREE to the interval in question, and | 902 Do this by recursing down TREE to the interval in question, and |
766 deleting the appropriate amount of text. */ | 903 deleting the appropriate amount of text. */ |
767 | 904 |
768 static int | 905 static int |
769 interval_deletion_adjustment (tree, from, amount) | 906 interval_deletion_adjustment (tree, from, amount) |
770 register INTERVAL tree; | 907 register INTERVAL tree; |
771 register int from, amount; | 908 register int from, amount; |
796 relative_position, | 933 relative_position, |
797 amount); | 934 amount); |
798 tree->total_length -= subtract; | 935 tree->total_length -= subtract; |
799 return subtract; | 936 return subtract; |
800 } | 937 } |
801 /* Here -- this node */ | 938 /* Here -- this node. */ |
802 else | 939 else |
803 { | 940 { |
804 /* How much can we delete from this interval? */ | 941 /* How much can we delete from this interval? */ |
805 int my_amount = ((tree->total_length | 942 int my_amount = ((tree->total_length |
806 - RIGHT_TOTAL_LENGTH (tree)) | 943 - RIGHT_TOTAL_LENGTH (tree)) |
814 delete_interval (tree); | 951 delete_interval (tree); |
815 | 952 |
816 return amount; | 953 return amount; |
817 } | 954 } |
818 | 955 |
819 /* Never reach here */ | 956 /* Never reach here. */ |
820 } | 957 } |
821 | 958 |
822 /* Effect the adjustments necessary to the interval tree of BUFFER to | 959 /* Effect the adjustments necessary to the interval tree of BUFFER to |
823 correspond to the deletion of LENGTH characters from that buffer | 960 correspond to the deletion of LENGTH characters from that buffer |
824 text. The deletion is effected at position START (which is a | 961 text. The deletion is effected at position START (which is a |
825 buffer position, i.e. origin 1). */ | 962 buffer position, i.e. origin 1). */ |
826 | 963 |
827 static void | 964 static void |
828 adjust_intervals_for_deletion (buffer, start, length) | 965 adjust_intervals_for_deletion (buffer, start, length) |
829 struct buffer *buffer; | 966 struct buffer *buffer; |
830 int start, length; | 967 int start, length; |
868 } | 1005 } |
869 | 1006 |
870 /* Make the adjustments necessary to the interval tree of BUFFER to | 1007 /* Make the adjustments necessary to the interval tree of BUFFER to |
871 represent an addition or deletion of LENGTH characters starting | 1008 represent an addition or deletion of LENGTH characters starting |
872 at position START. Addition or deletion is indicated by the sign | 1009 at position START. Addition or deletion is indicated by the sign |
873 of LENGTH. */ | 1010 of LENGTH. */ |
874 | 1011 |
875 INLINE void | 1012 INLINE void |
876 offset_intervals (buffer, start, length) | 1013 offset_intervals (buffer, start, length) |
877 struct buffer *buffer; | 1014 struct buffer *buffer; |
878 int start, length; | 1015 int start, length; |
891 successor. The properties of I are lost. I is removed from the | 1028 successor. The properties of I are lost. I is removed from the |
892 interval tree. | 1029 interval tree. |
893 | 1030 |
894 IMPORTANT: | 1031 IMPORTANT: |
895 The caller must verify that this is not the last (rightmost) | 1032 The caller must verify that this is not the last (rightmost) |
896 interval. */ | 1033 interval. */ |
897 | 1034 |
898 INTERVAL | 1035 INTERVAL |
899 merge_interval_right (i) | 1036 merge_interval_right (i) |
900 register INTERVAL i; | 1037 register INTERVAL i; |
901 { | 1038 { |
902 register int absorb = LENGTH (i); | 1039 register int absorb = LENGTH (i); |
903 register INTERVAL successor; | 1040 register INTERVAL successor; |
904 | 1041 |
905 /* Zero out this interval. */ | 1042 /* Zero out this interval. */ |
906 i->total_length -= absorb; | 1043 i->total_length -= absorb; |
907 | 1044 |
908 /* Find the succeeding interval. */ | 1045 /* Find the succeeding interval. */ |
909 if (! NULL_RIGHT_CHILD (i)) /* It's below us. Add absorb | 1046 if (! NULL_RIGHT_CHILD (i)) /* It's below us. Add absorb |
910 as we descend. */ | 1047 as we descend. */ |
911 { | 1048 { |
912 successor = i->right; | 1049 successor = i->right; |
913 while (! NULL_LEFT_CHILD (successor)) | 1050 while (! NULL_LEFT_CHILD (successor)) |
914 { | 1051 { |
915 successor->total_length += absorb; | 1052 successor->total_length += absorb; |
921 return successor; | 1058 return successor; |
922 } | 1059 } |
923 | 1060 |
924 successor = i; | 1061 successor = i; |
925 while (! NULL_PARENT (successor)) /* It's above us. Subtract as | 1062 while (! NULL_PARENT (successor)) /* It's above us. Subtract as |
926 we ascend. */ | 1063 we ascend. */ |
927 { | 1064 { |
928 if (AM_LEFT_CHILD (successor)) | 1065 if (AM_LEFT_CHILD (successor)) |
929 { | 1066 { |
930 successor = successor->parent; | 1067 successor = successor->parent; |
931 delete_interval (i); | 1068 delete_interval (i); |
935 successor = successor->parent; | 1072 successor = successor->parent; |
936 successor->total_length -= absorb; | 1073 successor->total_length -= absorb; |
937 } | 1074 } |
938 | 1075 |
939 /* This must be the rightmost or last interval and cannot | 1076 /* This must be the rightmost or last interval and cannot |
940 be merged right. The caller should have known. */ | 1077 be merged right. The caller should have known. */ |
941 abort (); | 1078 abort (); |
942 } | 1079 } |
943 | 1080 |
944 /* Merge interval I with its lexicographic predecessor. The resulting | 1081 /* Merge interval I with its lexicographic predecessor. The resulting |
945 interval is returned, and has the properties of the original predecessor. | 1082 interval is returned, and has the properties of the original predecessor. |
946 The properties of I are lost. Interval node I is removed from the tree. | 1083 The properties of I are lost. Interval node I is removed from the tree. |
947 | 1084 |
948 IMPORTANT: | 1085 IMPORTANT: |
949 The caller must verify that this is not the first (leftmost) interval. */ | 1086 The caller must verify that this is not the first (leftmost) interval. */ |
950 | 1087 |
951 INTERVAL | 1088 INTERVAL |
952 merge_interval_left (i) | 1089 merge_interval_left (i) |
953 register INTERVAL i; | 1090 register INTERVAL i; |
954 { | 1091 { |
955 register int absorb = LENGTH (i); | 1092 register int absorb = LENGTH (i); |
956 register INTERVAL predecessor; | 1093 register INTERVAL predecessor; |
957 | 1094 |
958 /* Zero out this interval. */ | 1095 /* Zero out this interval. */ |
959 i->total_length -= absorb; | 1096 i->total_length -= absorb; |
960 | 1097 |
961 /* Find the preceding interval. */ | 1098 /* Find the preceding interval. */ |
962 if (! NULL_LEFT_CHILD (i)) /* It's below us. Go down, | 1099 if (! NULL_LEFT_CHILD (i)) /* It's below us. Go down, |
963 adding ABSORB as we go. */ | 1100 adding ABSORB as we go. */ |
964 { | 1101 { |
965 predecessor = i->left; | 1102 predecessor = i->left; |
966 while (! NULL_RIGHT_CHILD (predecessor)) | 1103 while (! NULL_RIGHT_CHILD (predecessor)) |
967 { | 1104 { |
968 predecessor->total_length += absorb; | 1105 predecessor->total_length += absorb; |
974 return predecessor; | 1111 return predecessor; |
975 } | 1112 } |
976 | 1113 |
977 predecessor = i; | 1114 predecessor = i; |
978 while (! NULL_PARENT (predecessor)) /* It's above us. Go up, | 1115 while (! NULL_PARENT (predecessor)) /* It's above us. Go up, |
979 subtracting ABSORB. */ | 1116 subtracting ABSORB. */ |
980 { | 1117 { |
981 if (AM_RIGHT_CHILD (predecessor)) | 1118 if (AM_RIGHT_CHILD (predecessor)) |
982 { | 1119 { |
983 predecessor = predecessor->parent; | 1120 predecessor = predecessor->parent; |
984 delete_interval (i); | 1121 delete_interval (i); |
988 predecessor = predecessor->parent; | 1125 predecessor = predecessor->parent; |
989 predecessor->total_length -= absorb; | 1126 predecessor->total_length -= absorb; |
990 } | 1127 } |
991 | 1128 |
992 /* This must be the leftmost or first interval and cannot | 1129 /* This must be the leftmost or first interval and cannot |
993 be merged left. The caller should have known. */ | 1130 be merged left. The caller should have known. */ |
994 abort (); | 1131 abort (); |
995 } | 1132 } |
996 | 1133 |
997 /* Make an exact copy of interval tree SOURCE which descends from | 1134 /* Make an exact copy of interval tree SOURCE which descends from |
998 PARENT. This is done by recursing through SOURCE, copying | 1135 PARENT. This is done by recursing through SOURCE, copying |
999 the current interval and its properties, and then adjusting | 1136 the current interval and its properties, and then adjusting |
1000 the pointers of the copy. */ | 1137 the pointers of the copy. */ |
1001 | 1138 |
1002 static INTERVAL | 1139 static INTERVAL |
1003 reproduce_tree (source, parent) | 1140 reproduce_tree (source, parent) |
1004 INTERVAL source, parent; | 1141 INTERVAL source, parent; |
1005 { | 1142 { |
1022 /* Make a new interval of length LENGTH starting at START in the | 1159 /* Make a new interval of length LENGTH starting at START in the |
1023 group of intervals INTERVALS, which is actually an interval tree. | 1160 group of intervals INTERVALS, which is actually an interval tree. |
1024 Returns the new interval. | 1161 Returns the new interval. |
1025 | 1162 |
1026 Generate an error if the new positions would overlap an existing | 1163 Generate an error if the new positions would overlap an existing |
1027 interval. */ | 1164 interval. */ |
1028 | 1165 |
1029 static INTERVAL | 1166 static INTERVAL |
1030 make_new_interval (intervals, start, length) | 1167 make_new_interval (intervals, start, length) |
1031 INTERVAL intervals; | 1168 INTERVAL intervals; |
1032 int start, length; | 1169 int start, length; |
1040 if (start == slot->position && length == LENGTH (slot)) | 1177 if (start == slot->position && length == LENGTH (slot)) |
1041 return slot; | 1178 return slot; |
1042 | 1179 |
1043 if (slot->position == start) | 1180 if (slot->position == start) |
1044 { | 1181 { |
1045 /* New right node. */ | 1182 /* New right node. */ |
1046 split_interval_right (slot, length); | 1183 split_interval_right (slot, length); |
1047 return slot; | 1184 return slot; |
1048 } | 1185 } |
1049 | 1186 |
1050 if (slot->position + LENGTH (slot) == start + length) | 1187 if (slot->position + LENGTH (slot) == start + length) |
1051 { | 1188 { |
1052 /* New left node. */ | 1189 /* New left node. */ |
1053 split_interval_left (slot, LENGTH (slot) - length); | 1190 split_interval_left (slot, LENGTH (slot) - length); |
1054 return slot; | 1191 return slot; |
1055 } | 1192 } |
1056 | 1193 |
1057 /* Convert interval SLOT into three intervals. */ | 1194 /* Convert interval SLOT into three intervals. */ |
1058 split_interval_left (slot, start - slot->position); | 1195 split_interval_left (slot, start - slot->position); |
1059 split_interval_right (slot, length); | 1196 split_interval_right (slot, length); |
1060 return slot; | 1197 return slot; |
1061 } | 1198 } |
1062 #endif | 1199 #endif |
1089 is set, then the new text "sticks" to that region and its properties | 1226 is set, then the new text "sticks" to that region and its properties |
1090 depend on merging as above. If both the preceding and succeeding | 1227 depend on merging as above. If both the preceding and succeeding |
1091 intervals to the new text are "sticky", then the new text retains | 1228 intervals to the new text are "sticky", then the new text retains |
1092 only its properties, as if neither sticky property were set. Perhaps | 1229 only its properties, as if neither sticky property were set. Perhaps |
1093 we should consider merging all three sets of properties onto the new | 1230 we should consider merging all three sets of properties onto the new |
1094 text... */ | 1231 text... */ |
1095 | 1232 |
1096 void | 1233 void |
1097 graft_intervals_into_buffer (source, position, buffer) | 1234 graft_intervals_into_buffer (source, position, buffer) |
1098 INTERVAL source; | 1235 INTERVAL source; |
1099 int position; | 1236 int position; |
1102 register INTERVAL under, over, this, prev; | 1239 register INTERVAL under, over, this, prev; |
1103 register INTERVAL tree = buffer->intervals; | 1240 register INTERVAL tree = buffer->intervals; |
1104 int middle; | 1241 int middle; |
1105 | 1242 |
1106 /* If the new text has no properties, it becomes part of whatever | 1243 /* If the new text has no properties, it becomes part of whatever |
1107 interval it was inserted into. */ | 1244 interval it was inserted into. */ |
1108 if (NULL_INTERVAL_P (source)) | 1245 if (NULL_INTERVAL_P (source)) |
1109 return; | 1246 return; |
1110 | 1247 |
1111 if (NULL_INTERVAL_P (tree)) | 1248 if (NULL_INTERVAL_P (tree)) |
1112 { | 1249 { |
1113 /* The inserted text constitutes the whole buffer, so | 1250 /* The inserted text constitutes the whole buffer, so |
1114 simply copy over the interval structure. */ | 1251 simply copy over the interval structure. */ |
1115 if ((BUF_Z (buffer) - BUF_BEG (buffer)) == TOTAL_LENGTH (source)) | 1252 if ((BUF_Z (buffer) - BUF_BEG (buffer)) == TOTAL_LENGTH (source)) |
1116 { | 1253 { |
1117 Lisp_Object buf; | 1254 Lisp_Object buf; |
1118 XSET (buf, Lisp_Buffer, buffer); | 1255 XSET (buf, Lisp_Buffer, buffer); |
1119 buffer->intervals = reproduce_tree (source, buf); | 1256 buffer->intervals = reproduce_tree (source, buf); |
1120 /* Explicitly free the old tree here. */ | 1257 /* Explicitly free the old tree here. */ |
1121 | 1258 |
1122 return; | 1259 return; |
1123 } | 1260 } |
1124 | 1261 |
1125 /* Create an interval tree in which to place a copy | 1262 /* Create an interval tree in which to place a copy |
1126 of the intervals of the inserted string. */ | 1263 of the intervals of the inserted string. */ |
1127 { | 1264 { |
1128 Lisp_Object buf; | 1265 Lisp_Object buf; |
1129 XSET (buf, Lisp_Buffer, buffer); | 1266 XSET (buf, Lisp_Buffer, buffer); |
1130 tree = create_root_interval (buf); | 1267 tree = create_root_interval (buf); |
1131 } | 1268 } |
1133 else | 1270 else |
1134 if (TOTAL_LENGTH (tree) == TOTAL_LENGTH (source)) | 1271 if (TOTAL_LENGTH (tree) == TOTAL_LENGTH (source)) |
1135 /* If the buffer contains only the new string, but | 1272 /* If the buffer contains only the new string, but |
1136 there was already some interval tree there, then it may be | 1273 there was already some interval tree there, then it may be |
1137 some zero length intervals. Eventually, do something clever | 1274 some zero length intervals. Eventually, do something clever |
1138 about inserting properly. For now, just waste the old intervals. */ | 1275 about inserting properly. For now, just waste the old intervals. */ |
1139 { | 1276 { |
1140 buffer->intervals = reproduce_tree (source, tree->parent); | 1277 buffer->intervals = reproduce_tree (source, tree->parent); |
1141 /* Explicitly free the old tree here. */ | 1278 /* Explicitly free the old tree here. */ |
1142 | 1279 |
1143 return; | 1280 return; |
1144 } | 1281 } |
1145 else | 1282 else |
1146 /* Paranoia -- the text has already been added, so this buffer | 1283 /* Paranoia -- the text has already been added, so this buffer |
1147 should be of non-zero length. */ | 1284 should be of non-zero length. */ |
1148 if (TOTAL_LENGTH (tree) == 0) | 1285 if (TOTAL_LENGTH (tree) == 0) |
1149 abort (); | 1286 abort (); |
1150 | 1287 |
1151 this = under = find_interval (tree, position); | 1288 this = under = find_interval (tree, position); |
1152 if (NULL_INTERVAL_P (under)) /* Paranoia */ | 1289 if (NULL_INTERVAL_P (under)) /* Paranoia */ |
1167 middle = 1; | 1304 middle = 1; |
1168 } | 1305 } |
1169 else | 1306 else |
1170 { | 1307 { |
1171 prev = previous_interval (under); | 1308 prev = previous_interval (under); |
1172 if (prev && !END_STICKY_P (prev)) | 1309 if (prev && !END_NONSTICKY_P (prev)) |
1173 prev = 0; | 1310 prev = 0; |
1174 } | 1311 } |
1175 | 1312 |
1176 /* Insertion is now at beginning of UNDER. */ | 1313 /* Insertion is now at beginning of UNDER. */ |
1177 | 1314 |
1178 /* The inserted text "sticks" to the interval `under', | 1315 /* The inserted text "sticks" to the interval `under', |
1179 which means it gets those properties. */ | 1316 which means it gets those properties. |
1317 The properties of under are the result of | |
1318 adjust_intervals_for_insertion, so stickyness has | |
1319 already been taken care of. */ | |
1320 | |
1180 while (! NULL_INTERVAL_P (over)) | 1321 while (! NULL_INTERVAL_P (over)) |
1181 { | 1322 { |
1182 if (LENGTH (over) + 1 < LENGTH (under)) | 1323 if (LENGTH (over) + 1 < LENGTH (under)) |
1183 this = split_interval_left (under, LENGTH (over)); | 1324 { |
1325 this = split_interval_left (under, LENGTH (over)); | |
1326 copy_properties (under, this); | |
1327 } | |
1184 else | 1328 else |
1185 this = under; | 1329 this = under; |
1186 copy_properties (over, this); | 1330 copy_properties (over, this); |
1187 /* Insertion at the end of an interval, PREV, | 1331 if (MERGE_INSERTIONS (this)) |
1188 inherits from PREV if PREV is sticky at the end. */ | 1332 merge_properties (over, this); |
1189 if (prev && ! FRONT_STICKY_P (under) | 1333 else |
1190 && MERGE_INSERTIONS (prev)) | 1334 copy_properties (over, this); |
1191 merge_properties (prev, this); | |
1192 /* Maybe it inherits from the following interval | |
1193 if that is sticky at the front. */ | |
1194 else if ((FRONT_STICKY_P (under) || middle) | |
1195 && MERGE_INSERTIONS (under)) | |
1196 merge_properties (under, this); | |
1197 over = next_interval (over); | 1335 over = next_interval (over); |
1198 } | 1336 } |
1199 | 1337 |
1200 buffer->intervals = balance_intervals (buffer->intervals); | 1338 buffer->intervals = balance_intervals (buffer->intervals); |
1201 return; | 1339 return; |
1222 if (EQ (tem, Qcategory)) | 1360 if (EQ (tem, Qcategory)) |
1223 fallback = Fget (Fcar (Fcdr (tail)), prop); | 1361 fallback = Fget (Fcar (Fcdr (tail)), prop); |
1224 } | 1362 } |
1225 | 1363 |
1226 return fallback; | 1364 return fallback; |
1365 } | |
1366 | |
1367 /* Get the value of property PROP from PLIST, | |
1368 which is the plist of an interval. | |
1369 We check for direct properties only! */ | |
1370 | |
1371 Lisp_Object | |
1372 textget_direct (plist, prop) | |
1373 Lisp_Object plist; | |
1374 register Lisp_Object prop; | |
1375 { | |
1376 register Lisp_Object tail; | |
1377 | |
1378 for (tail = plist; !NILP (tail); tail = Fcdr (Fcdr (tail))) | |
1379 { | |
1380 if (EQ (prop, Fcar (tail))) | |
1381 return Fcar (Fcdr (tail)); | |
1382 } | |
1383 | |
1384 return Qnil; | |
1227 } | 1385 } |
1228 | 1386 |
1229 /* Set point in BUFFER to POSITION. If the target position is | 1387 /* Set point in BUFFER to POSITION. If the target position is |
1230 before an invisible character which is not displayed with a special glyph, | 1388 before an invisible character which is not displayed with a special glyph, |
1231 move back to an ok place to display. */ | 1389 move back to an ok place to display. */ |
1272 : BUF_PT (buffer)); | 1430 : BUF_PT (buffer)); |
1273 | 1431 |
1274 /* Set FROM to the interval containing the char after PT, | 1432 /* Set FROM to the interval containing the char after PT, |
1275 and FROMPREV to the interval containing the char before PT. | 1433 and FROMPREV to the interval containing the char before PT. |
1276 Either one may be null. They may be equal. */ | 1434 Either one may be null. They may be equal. */ |
1277 /* We could cache this and save time. */ | 1435 /* We could cache this and save time. */ |
1278 from = find_interval (buffer->intervals, buffer_point); | 1436 from = find_interval (buffer->intervals, buffer_point); |
1279 if (from->position == BUF_BEGV (buffer)) | 1437 if (buffer_point == BUF_BEGV (buffer)) |
1280 fromprev = 0; | 1438 fromprev = 0; |
1281 else if (from->position == BUF_PT (buffer)) | 1439 else if (from->position == BUF_PT (buffer)) |
1282 fromprev = previous_interval (from); | 1440 fromprev = previous_interval (from); |
1283 else if (buffer_point != BUF_PT (buffer)) | 1441 else if (buffer_point != BUF_PT (buffer)) |
1284 fromprev = from, from = 0; | 1442 fromprev = from, from = 0; |
1285 else | 1443 else |
1286 fromprev = from; | 1444 fromprev = from; |
1287 | 1445 |
1288 /* Moving within an interval */ | 1446 /* Moving within an interval. */ |
1289 if (to == from && toprev == fromprev && INTERVAL_VISIBLE_P (to)) | 1447 if (to == from && toprev == fromprev && INTERVAL_VISIBLE_P (to)) |
1290 { | 1448 { |
1291 buffer->text.pt = position; | 1449 buffer->text.pt = position; |
1292 return; | 1450 return; |
1293 } | 1451 } |
1294 | 1452 |
1295 /* If the new position is before an invisible character, | 1453 /* If the new position is before an invisible character |
1454 that has an `invisible' property of value `hidden', | |
1296 move forward over all such. */ | 1455 move forward over all such. */ |
1297 while (! NULL_INTERVAL_P (to) | 1456 while (! NULL_INTERVAL_P (to) |
1298 && ! INTERVAL_VISIBLE_P (to) | 1457 && EQ (textget (to->plist, Qinvisible), Qhidden) |
1299 && ! DISPLAY_INVISIBLE_GLYPH (to)) | 1458 && ! DISPLAY_INVISIBLE_GLYPH (to)) |
1300 { | 1459 { |
1301 toprev = to; | 1460 toprev = to; |
1302 to = next_interval (to); | 1461 to = next_interval (to); |
1303 if (NULL_INTERVAL_P (to)) | 1462 if (NULL_INTERVAL_P (to)) |
1345 if (! EQ (enter_after, leave_after) && !NILP (enter_after)) | 1504 if (! EQ (enter_after, leave_after) && !NILP (enter_after)) |
1346 call2 (enter_after, old_position, position); | 1505 call2 (enter_after, old_position, position); |
1347 } | 1506 } |
1348 } | 1507 } |
1349 | 1508 |
1350 /* Set point temporarily, without checking any text properties. */ | 1509 /* Set point temporarily, without checking any text properties. */ |
1351 | 1510 |
1352 INLINE void | 1511 INLINE void |
1353 temp_set_point (position, buffer) | 1512 temp_set_point (position, buffer) |
1354 int position; | 1513 int position; |
1355 struct buffer *buffer; | 1514 struct buffer *buffer; |
1370 Lisp_Object prop, tem; | 1529 Lisp_Object prop, tem; |
1371 | 1530 |
1372 if (NULL_INTERVAL_P (buffer->intervals)) | 1531 if (NULL_INTERVAL_P (buffer->intervals)) |
1373 return current_buffer->keymap; | 1532 return current_buffer->keymap; |
1374 | 1533 |
1375 /* Perhaps we should just change `position' to the limit. */ | 1534 /* Perhaps we should just change `position' to the limit. */ |
1376 if (position > BUF_Z (buffer) || position < BUF_BEG (buffer)) | 1535 if (position > BUF_Z (buffer) || position < BUF_BEG (buffer)) |
1377 abort (); | 1536 abort (); |
1378 | 1537 |
1379 interval = find_interval (buffer->intervals, position); | 1538 interval = find_interval (buffer->intervals, position); |
1380 prop = textget (interval->plist, Qlocal_map); | 1539 prop = textget (interval->plist, Qlocal_map); |
1408 /* Check for read-only intervals and signal an error if we find one. | 1567 /* Check for read-only intervals and signal an error if we find one. |
1409 Then check for any modification hooks in the range START up to | 1568 Then check for any modification hooks in the range START up to |
1410 (but not including) TO. Create a list of all these hooks in | 1569 (but not including) TO. Create a list of all these hooks in |
1411 lexicographic order, eliminating consecutive extra copies of the | 1570 lexicographic order, eliminating consecutive extra copies of the |
1412 same hook. Then call those hooks in order, with START and END - 1 | 1571 same hook. Then call those hooks in order, with START and END - 1 |
1413 as arguments. */ | 1572 as arguments. */ |
1414 | 1573 |
1415 void | 1574 void |
1416 verify_interval_modification (buf, start, end) | 1575 verify_interval_modification (buf, start, end) |
1417 struct buffer *buf; | 1576 struct buffer *buf; |
1418 int start, end; | 1577 int start, end; |
1449 Either one may be null. They may be equal. */ | 1608 Either one may be null. They may be equal. */ |
1450 i = find_interval (intervals, start); | 1609 i = find_interval (intervals, start); |
1451 | 1610 |
1452 if (start == BUF_BEGV (buf)) | 1611 if (start == BUF_BEGV (buf)) |
1453 prev = 0; | 1612 prev = 0; |
1454 if (i->position == start) | 1613 else if (i->position == start) |
1455 prev = previous_interval (i); | 1614 prev = previous_interval (i); |
1456 else if (i->position < start) | 1615 else if (i->position < start) |
1457 prev = i; | 1616 prev = i; |
1458 if (start == BUF_ZV (buf)) | 1617 if (start == BUF_ZV (buf)) |
1459 i = 0; | 1618 i = 0; |
1460 | 1619 |
1461 if (NULL_INTERVAL_P (prev)) | 1620 /* If Vinhibit_read_only is set and is not a list, we can |
1462 { | 1621 skip the read_only checks. */ |
1463 if (! INTERVAL_WRITABLE_P (i)) | 1622 if (NILP (Vinhibit_read_only) || CONSP (Vinhibit_read_only)) |
1464 error ("Attempt to insert within read-only text"); | 1623 { |
1465 } | 1624 /* If I and PREV differ we need to check for the read-only |
1466 else if (NULL_INTERVAL_P (i)) | 1625 property together with its stickyness. If either I or |
1467 { | 1626 PREV are 0, this check is all we need. |
1468 if (! INTERVAL_WRITABLE_P (prev)) | 1627 We have to take special care, since read-only may be |
1469 error ("Attempt to insert within read-only text"); | 1628 indirectly defined via the category property. */ |
1470 } | 1629 if (i != prev) |
1471 else | 1630 { |
1472 { | 1631 if (! NULL_INTERVAL_P (i)) |
1473 before = textget (prev->plist, Qread_only); | 1632 { |
1474 after = textget (i->plist, Qread_only); | 1633 after = textget (i->plist, Qread_only); |
1475 if (! NILP (before) && EQ (before, after) | 1634 |
1476 /* This checks Vinhibit_read_only properly | 1635 /* If interval I is read-only and read-only is |
1477 for the common value of the read-only property. */ | 1636 front-sticky, inhibit insertion. |
1478 && ! INTERVAL_WRITABLE_P (i)) | 1637 Check for read-only as well as category. */ |
1479 error ("Attempt to insert within read-only text"); | 1638 if (! NILP (after) |
1639 && NILP (Fmemq (after, Vinhibit_read_only)) | |
1640 && (! NILP (Fmemq (Qread_only, | |
1641 textget (i->plist, Qfront_sticky))) | |
1642 || (NILP (textget_direct (i->plist, Qread_only)) | |
1643 && ! NILP (Fmemq (Qcategory, | |
1644 textget (i->plist, | |
1645 Qfront_sticky)))))) | |
1646 error ("Attempt to insert within read-only text"); | |
1647 } | |
1648 else | |
1649 after = Qnil; | |
1650 if (! NULL_INTERVAL_P (prev)) | |
1651 { | |
1652 before = textget (prev->plist, Qread_only); | |
1653 | |
1654 /* If interval PREV is read-only and read-only isn't | |
1655 rear-nonsticky, inhibit insertion. | |
1656 Check for read-only as well as category. */ | |
1657 if (! NILP (before) | |
1658 && NILP (Fmemq (before, Vinhibit_read_only)) | |
1659 && NILP (Fmemq (Qread_only, | |
1660 textget (prev->plist, Qrear_nonsticky))) | |
1661 && (! NILP (textget_direct (prev->plist,Qread_only)) | |
1662 || NILP (Fmemq (Qcategory, | |
1663 textget (prev->plist, | |
1664 Qrear_nonsticky))))) | |
1665 error ("Attempt to insert within read-only text"); | |
1666 } | |
1667 else | |
1668 before = Qnil; | |
1669 } | |
1670 else if (! NULL_INTERVAL_P (i)) | |
1671 before = after = textget (i->plist, Qread_only); | |
1672 if (! NULL_INTERVAL_P (i) && ! NULL_INTERVAL_P (prev)) | |
1673 { | |
1674 /* If I and PREV differ, neither of them has a sticky | |
1675 read-only property. It only remains to check, whether | |
1676 they have a common read-only property. */ | |
1677 if (! NILP (before) && EQ (before, after)) | |
1678 error ("Attempt to insert within read-only text"); | |
1679 } | |
1480 } | 1680 } |
1481 | 1681 |
1482 /* Run both insert hooks (just once if they're the same). */ | 1682 /* Run both insert hooks (just once if they're the same). */ |
1483 if (!NULL_INTERVAL_P (prev)) | 1683 if (!NULL_INTERVAL_P (prev)) |
1484 prev_mod_hooks = textget (prev->plist, Qinsert_behind_hooks); | 1684 prev_mod_hooks = textget (prev->plist, Qinsert_behind_hooks); |
1527 } | 1727 } |
1528 } | 1728 } |
1529 | 1729 |
1530 /* Balance an interval node if the amount of text in its left and right | 1730 /* Balance an interval node if the amount of text in its left and right |
1531 subtrees differs by more than the percentage specified by | 1731 subtrees differs by more than the percentage specified by |
1532 `interval-balance-threshold'. */ | 1732 `interval-balance-threshold'. */ |
1533 | 1733 |
1534 static INTERVAL | 1734 static INTERVAL |
1535 balance_an_interval (i) | 1735 balance_an_interval (i) |
1536 INTERVAL i; | 1736 INTERVAL i; |
1537 { | 1737 { |
1567 | 1767 |
1568 return i; | 1768 return i; |
1569 } | 1769 } |
1570 | 1770 |
1571 /* Balance the interval tree TREE. Balancing is by weight | 1771 /* Balance the interval tree TREE. Balancing is by weight |
1572 (the amount of text). */ | 1772 (the amount of text). */ |
1573 | 1773 |
1574 INTERVAL | 1774 INTERVAL |
1575 balance_intervals (tree) | 1775 balance_intervals (tree) |
1576 register INTERVAL tree; | 1776 register INTERVAL tree; |
1577 { | 1777 { |
1590 | 1790 |
1591 return new_tree; | 1791 return new_tree; |
1592 } | 1792 } |
1593 | 1793 |
1594 /* Produce an interval tree reflecting the intervals in | 1794 /* Produce an interval tree reflecting the intervals in |
1595 TREE from START to START + LENGTH. */ | 1795 TREE from START to START + LENGTH. */ |
1596 | 1796 |
1597 INTERVAL | 1797 INTERVAL |
1598 copy_intervals (tree, start, length) | 1798 copy_intervals (tree, start, length) |
1599 INTERVAL tree; | 1799 INTERVAL tree; |
1600 int start, length; | 1800 int start, length; |
1607 | 1807 |
1608 i = find_interval (tree, start); | 1808 i = find_interval (tree, start); |
1609 if (NULL_INTERVAL_P (i) || LENGTH (i) == 0) | 1809 if (NULL_INTERVAL_P (i) || LENGTH (i) == 0) |
1610 abort (); | 1810 abort (); |
1611 | 1811 |
1612 /* If there is only one interval and it's the default, return nil. */ | 1812 /* If there is only one interval and it's the default, return nil. */ |
1613 if ((start - i->position + 1 + length) < LENGTH (i) | 1813 if ((start - i->position + 1 + length) < LENGTH (i) |
1614 && DEFAULT_INTERVAL_P (i)) | 1814 && DEFAULT_INTERVAL_P (i)) |
1615 return NULL_INTERVAL; | 1815 return NULL_INTERVAL; |
1616 | 1816 |
1617 new = make_interval (); | 1817 new = make_interval (); |
1632 } | 1832 } |
1633 | 1833 |
1634 return balance_intervals (new); | 1834 return balance_intervals (new); |
1635 } | 1835 } |
1636 | 1836 |
1637 /* Give STRING the properties of BUFFER from POSITION to LENGTH. */ | 1837 /* Give STRING the properties of BUFFER from POSITION to LENGTH. */ |
1638 | 1838 |
1639 INLINE void | 1839 INLINE void |
1640 copy_intervals_to_string (string, buffer, position, length) | 1840 copy_intervals_to_string (string, buffer, position, length) |
1641 Lisp_Object string, buffer; | 1841 Lisp_Object string, buffer; |
1642 int position, length; | 1842 int position, length; |