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;