(rmail-edit-map): Inherit properly from text-mode-map;
[emacs.git] / src / intervals.c
blob0922a074a96dc57c1ba1ea1e4663ed03da4e4299
1 /* Code for doing intervals.
2 Copyright (C) 1993 Free Software Foundation, Inc.
4 This file is part of GNU Emacs.
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
8 the Free Software Foundation; either version 1, or (at your option)
9 any later version.
11 GNU Emacs is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Emacs; see the file COPYING. If not, write to
18 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
21 /* NOTES:
23 Have to ensure that we can't put symbol nil on a plist, or some
24 functions may work incorrectly.
26 An idea: Have the owner of the tree keep count of splits and/or
27 insertion lengths (in intervals), and balance after every N.
29 Need to call *_left_hook when buffer is killed.
31 Scan for zero-length, or 0-length to see notes about handling
32 zero length interval-markers.
34 There are comments around about freeing intervals. It might be
35 faster to explicitly free them (put them on the free list) than
36 to GC them.
41 #include "config.h"
42 #include "lisp.h"
43 #include "intervals.h"
44 #include "buffer.h"
46 /* The rest of the file is within this conditional. */
47 #ifdef USE_TEXT_PROPERTIES
49 /* Factor for weight-balancing interval trees. */
50 Lisp_Object interval_balance_threshold;
52 /* Utility functions for intervals. */
55 /* Create the root interval of some object, a buffer or string. */
57 INTERVAL
58 create_root_interval (parent)
59 Lisp_Object parent;
61 INTERVAL new = make_interval ();
63 if (XTYPE (parent) == Lisp_Buffer)
65 new->total_length = (BUF_Z (XBUFFER (parent))
66 - BUF_BEG (XBUFFER (parent)));
67 XBUFFER (parent)->intervals = new;
69 else if (XTYPE (parent) == Lisp_String)
71 new->total_length = XSTRING (parent)->size;
72 XSTRING (parent)->intervals = new;
75 new->parent = (INTERVAL) parent;
76 new->position = 1;
78 return new;
81 /* Make the interval TARGET have exactly the properties of SOURCE */
83 void
84 copy_properties (source, target)
85 register INTERVAL source, target;
87 if (DEFAULT_INTERVAL_P (source) && DEFAULT_INTERVAL_P (target))
88 return;
90 COPY_INTERVAL_CACHE (source, target);
91 target->plist = Fcopy_sequence (source->plist);
94 /* Merge the properties of interval SOURCE into the properties
95 of interval TARGET. That is to say, each property in SOURCE
96 is added to TARGET if TARGET has no such property as yet. */
98 static void
99 merge_properties (source, target)
100 register INTERVAL source, target;
102 register Lisp_Object o, sym, val;
104 if (DEFAULT_INTERVAL_P (source) && DEFAULT_INTERVAL_P (target))
105 return;
107 MERGE_INTERVAL_CACHE (source, target);
109 o = source->plist;
110 while (! EQ (o, Qnil))
112 sym = Fcar (o);
113 val = Fmemq (sym, target->plist);
115 if (NILP (val))
117 o = Fcdr (o);
118 val = Fcar (o);
119 target->plist = Fcons (sym, Fcons (val, target->plist));
120 o = Fcdr (o);
122 else
123 o = Fcdr (Fcdr (o));
127 /* Return 1 if the two intervals have the same properties,
128 0 otherwise. */
131 intervals_equal (i0, i1)
132 INTERVAL i0, i1;
134 register Lisp_Object i0_cdr, i0_sym, i1_val;
135 register i1_len;
137 if (DEFAULT_INTERVAL_P (i0) && DEFAULT_INTERVAL_P (i1))
138 return 1;
140 if (DEFAULT_INTERVAL_P (i0) || DEFAULT_INTERVAL_P (i1))
141 return 0;
143 i1_len = XFASTINT (Flength (i1->plist));
144 if (i1_len & 0x1) /* Paranoia -- plists are always even */
145 abort ();
146 i1_len /= 2;
147 i0_cdr = i0->plist;
148 while (!NILP (i0_cdr))
150 /* Lengths of the two plists were unequal */
151 if (i1_len == 0)
152 return 0;
154 i0_sym = Fcar (i0_cdr);
155 i1_val = Fmemq (i0_sym, i1->plist);
157 /* i0 has something i1 doesn't */
158 if (EQ (i1_val, Qnil))
159 return 0;
161 /* i0 and i1 both have sym, but it has different values in each */
162 i0_cdr = Fcdr (i0_cdr);
163 if (! EQ (i1_val, Fcar (i0_cdr)))
164 return 0;
166 i0_cdr = Fcdr (i0_cdr);
167 i1_len--;
170 /* Lengths of the two plists were unequal */
171 if (i1_len > 0)
172 return 0;
174 return 1;
177 static int icount;
178 static int idepth;
179 static int zero_length;
181 /* Traverse an interval tree TREE, performing FUNCTION on each node.
182 Pass FUNCTION two args: an interval, and ARG. */
184 void
185 traverse_intervals (tree, position, depth, function, arg)
186 INTERVAL tree;
187 int position, depth;
188 void (* function) ();
189 Lisp_Object arg;
191 if (NULL_INTERVAL_P (tree))
192 return;
194 traverse_intervals (tree->left, position, depth + 1, function, arg);
195 position += LEFT_TOTAL_LENGTH (tree);
196 tree->position = position;
197 (*function) (tree, arg);
198 position += LENGTH (tree);
199 traverse_intervals (tree->right, position, depth + 1, function, arg);
202 #if 0
203 /* These functions are temporary, for debugging purposes only. */
205 INTERVAL search_interval, found_interval;
207 void
208 check_for_interval (i)
209 register INTERVAL i;
211 if (i == search_interval)
213 found_interval = i;
214 icount++;
218 INTERVAL
219 search_for_interval (i, tree)
220 register INTERVAL i, tree;
222 icount = 0;
223 search_interval = i;
224 found_interval = NULL_INTERVAL;
225 traverse_intervals (tree, 1, 0, &check_for_interval, Qnil);
226 return found_interval;
229 static void
230 inc_interval_count (i)
231 INTERVAL i;
233 icount++;
234 if (LENGTH (i) == 0)
235 zero_length++;
236 if (depth > idepth)
237 idepth = depth;
241 count_intervals (i)
242 register INTERVAL i;
244 icount = 0;
245 idepth = 0;
246 zero_length = 0;
247 traverse_intervals (i, 1, 0, &inc_interval_count, Qnil);
249 return icount;
252 static INTERVAL
253 root_interval (interval)
254 INTERVAL interval;
256 register INTERVAL i = interval;
258 while (! ROOT_INTERVAL_P (i))
259 i = i->parent;
261 return i;
263 #endif
265 /* Assuming that a left child exists, perform the following operation:
268 / \ / \
269 B => A
270 / \ / \
274 static INTERVAL
275 rotate_right (interval)
276 INTERVAL interval;
278 INTERVAL i;
279 INTERVAL B = interval->left;
280 int len = LENGTH (interval);
282 /* Deal with any Parent of A; make it point to B. */
283 if (! ROOT_INTERVAL_P (interval))
284 if (AM_LEFT_CHILD (interval))
285 interval->parent->left = interval->left;
286 else
287 interval->parent->right = interval->left;
288 interval->left->parent = interval->parent;
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;
293 /* B becomes the parent of A. */
294 i = interval->left->right;
295 interval->left->right = interval;
296 interval->parent = interval->left;
298 /* A gets c as left child. */
299 interval->left = i;
300 if (! NULL_INTERVAL_P (i))
301 i->parent = interval;
302 interval->total_length = (len + LEFT_TOTAL_LENGTH (interval)
303 + RIGHT_TOTAL_LENGTH (interval));
305 return B;
308 /* Assuming that a right child exists, perform the following operation:
310 A B
311 / \ / \
312 B => A
313 / \ / \
317 static INTERVAL
318 rotate_left (interval)
319 INTERVAL interval;
321 INTERVAL i;
322 INTERVAL B = interval->right;
323 int len = LENGTH (interval);
325 /* Deal with the parent of A. */
326 if (! ROOT_INTERVAL_P (interval))
327 if (AM_LEFT_CHILD (interval))
328 interval->parent->left = interval->right;
329 else
330 interval->parent->right = interval->right;
331 interval->right->parent = interval->parent;
333 /* B must have the same total length of A. */
334 interval->right->total_length = interval->total_length;
336 /* Make B the parent of A */
337 i = interval->right->left;
338 interval->right->left = interval;
339 interval->parent = interval->right;
341 /* Make A point to c */
342 interval->right = i;
343 if (! NULL_INTERVAL_P (i))
344 i->parent = interval;
345 interval->total_length = (len + LEFT_TOTAL_LENGTH (interval)
346 + RIGHT_TOTAL_LENGTH (interval));
348 return B;
351 /* Split INTERVAL into two pieces, starting the second piece at
352 character position OFFSET (counting from 0), relative to INTERVAL.
353 INTERVAL becomes the left-hand piece, and the right-hand piece
354 (second, lexicographically) is returned.
356 The size and position fields of the two intervals are set based upon
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
359 result.
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. */
364 INTERVAL
365 split_interval_right (interval, offset)
366 INTERVAL interval;
367 int offset;
369 INTERVAL new = make_interval ();
370 int position = interval->position;
371 int new_length = LENGTH (interval) - offset;
373 new->position = position + offset;
374 new->parent = interval;
376 if (LEAF_INTERVAL_P (interval) || NULL_RIGHT_CHILD (interval))
378 interval->right = new;
379 new->total_length = new_length;
381 return new;
384 /* Insert the new node between INTERVAL and its right child. */
385 new->right = interval->right;
386 interval->right->parent = new;
387 interval->right = new;
389 new->total_length = new_length + new->right->total_length;
391 return new;
394 /* Split INTERVAL into two pieces, starting the second piece at
395 character position OFFSET (counting from 0), relative to INTERVAL.
396 INTERVAL becomes the right-hand piece, and the left-hand piece
397 (first, lexicographically) is returned.
399 The size and position fields of the two intervals are set based upon
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
402 result.
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. */
407 INTERVAL
408 split_interval_left (interval, offset)
409 INTERVAL interval;
410 int offset;
412 INTERVAL new = make_interval ();
413 int position = interval->position;
414 int new_length = offset;
416 new->position = interval->position;
417 interval->position = interval->position + offset;
418 new->parent = interval;
420 if (NULL_LEFT_CHILD (interval))
422 interval->left = new;
423 new->total_length = new_length;
425 return new;
428 /* Insert the new node between INTERVAL and its left child. */
429 new->left = interval->left;
430 new->left->parent = new;
431 interval->left = new;
432 new->total_length = new_length + LEFT_TOTAL_LENGTH (new);
434 return new;
437 /* Find the interval containing text position POSITION in the text
438 represented by the interval tree TREE. POSITION is a buffer
439 position; the earliest position is 1. If POSITION is at the end of
440 the buffer, return the interval containing the last character.
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)
444 will update this cache based on the result of find_interval. */
446 INLINE INTERVAL
447 find_interval (tree, position)
448 register INTERVAL tree;
449 register int position;
451 /* The distance from the left edge of the subtree at TREE
452 to POSITION. */
453 register int relative_position = position - BEG;
455 if (NULL_INTERVAL_P (tree))
456 return NULL_INTERVAL;
458 if (relative_position > TOTAL_LENGTH (tree))
459 abort (); /* Paranoia */
461 while (1)
463 if (relative_position < LEFT_TOTAL_LENGTH (tree))
465 tree = tree->left;
467 else if (! NULL_RIGHT_CHILD (tree)
468 && relative_position >= (TOTAL_LENGTH (tree)
469 - RIGHT_TOTAL_LENGTH (tree)))
471 relative_position -= (TOTAL_LENGTH (tree)
472 - RIGHT_TOTAL_LENGTH (tree));
473 tree = tree->right;
475 else
477 tree->position =
478 (position - relative_position /* the left edge of *tree */
479 + LEFT_TOTAL_LENGTH (tree)); /* the left edge of this interval */
481 return tree;
486 /* Find the succeeding interval (lexicographically) to INTERVAL.
487 Sets the `position' field based on that of INTERVAL (see
488 find_interval). */
490 INTERVAL
491 next_interval (interval)
492 register INTERVAL interval;
494 register INTERVAL i = interval;
495 register int next_position;
497 if (NULL_INTERVAL_P (i))
498 return NULL_INTERVAL;
499 next_position = interval->position + LENGTH (interval);
501 if (! NULL_RIGHT_CHILD (i))
503 i = i->right;
504 while (! NULL_LEFT_CHILD (i))
505 i = i->left;
507 i->position = next_position;
508 return i;
511 while (! NULL_PARENT (i))
513 if (AM_LEFT_CHILD (i))
515 i = i->parent;
516 i->position = next_position;
517 return i;
520 i = i->parent;
523 return NULL_INTERVAL;
526 /* Find the preceding interval (lexicographically) to INTERVAL.
527 Sets the `position' field based on that of INTERVAL (see
528 find_interval). */
530 INTERVAL
531 previous_interval (interval)
532 register INTERVAL interval;
534 register INTERVAL i;
535 register position_of_previous;
537 if (NULL_INTERVAL_P (interval))
538 return NULL_INTERVAL;
540 if (! NULL_LEFT_CHILD (interval))
542 i = interval->left;
543 while (! NULL_RIGHT_CHILD (i))
544 i = i->right;
546 i->position = interval->position - LENGTH (i);
547 return i;
550 i = interval;
551 while (! NULL_PARENT (i))
553 if (AM_RIGHT_CHILD (i))
555 i = i->parent;
557 i->position = interval->position - LENGTH (i);
558 return i;
560 i = i->parent;
563 return NULL_INTERVAL;
566 #if 0
567 /* Traverse a path down the interval tree TREE to the interval
568 containing POSITION, adjusting all nodes on the path for
569 an addition of LENGTH characters. Insertion between two intervals
570 (i.e., point == i->position, where i is second interval) means
571 text goes into second interval.
573 Modifications are needed to handle the hungry bits -- after simply
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
576 and check the hugry bits of both. Then add the length going back up
577 to the root. */
579 static INTERVAL
580 adjust_intervals_for_insertion (tree, position, length)
581 INTERVAL tree;
582 int position, length;
584 register int relative_position;
585 register INTERVAL this;
587 if (TOTAL_LENGTH (tree) == 0) /* Paranoia */
588 abort ();
590 /* If inserting at point-max of a buffer, that position
591 will be out of range */
592 if (position > TOTAL_LENGTH (tree))
593 position = TOTAL_LENGTH (tree);
594 relative_position = position;
595 this = tree;
597 while (1)
599 if (relative_position <= LEFT_TOTAL_LENGTH (this))
601 this->total_length += length;
602 this = this->left;
604 else if (relative_position > (TOTAL_LENGTH (this)
605 - RIGHT_TOTAL_LENGTH (this)))
607 relative_position -= (TOTAL_LENGTH (this)
608 - RIGHT_TOTAL_LENGTH (this));
609 this->total_length += length;
610 this = this->right;
612 else
614 /* If we are to use zero-length intervals as buffer pointers,
615 then this code will have to change. */
616 this->total_length += length;
617 this->position = LEFT_TOTAL_LENGTH (this)
618 + position - relative_position + 1;
619 return tree;
623 #endif
625 /* Effect an adjustment corresponding to the addition of LENGTH characters
626 of text. Do this by finding the interval containing POSITION in the
627 interval tree TREE, and then adjusting all of it's ancestors by adding
628 LENGTH to them.
630 If POSITION is the first character of an interval, meaning that point
631 is actually between the two intervals, make the new text belong to
632 the interval which is "sticky".
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
636 this text, and make it have the merged properties of both ends. */
638 static INTERVAL
639 adjust_intervals_for_insertion (tree, position, length)
640 INTERVAL tree;
641 int position, length;
643 register INTERVAL i;
645 if (TOTAL_LENGTH (tree) == 0) /* Paranoia */
646 abort ();
648 /* If inserting at point-max of a buffer, that position will be out
649 of range. Remember that buffer positions are 1-based. */
650 if (position > BEG + TOTAL_LENGTH (tree))
651 position = BEG + TOTAL_LENGTH (tree);
653 i = find_interval (tree, position);
654 /* If we are positioned between intervals, check the stickiness of
655 both of them. */
656 if (position == i->position
657 && position != BEG)
659 register INTERVAL prev = previous_interval (i);
661 /* If both intervals are sticky here, then default to the
662 left-most one. But perhaps we should create a new
663 interval here instead... */
664 if (END_STICKY_P (prev) || ! FRONT_STICKY_P (i))
665 i = prev;
668 while (! NULL_INTERVAL_P (i))
670 i->total_length += length;
671 i = i->parent;
674 return tree;
677 /* Delete an node I from its interval tree by merging its subtrees
678 into one subtree which is then returned. Caller is responsible for
679 storing the resulting subtree into its parent. */
681 static INTERVAL
682 delete_node (i)
683 register INTERVAL i;
685 register INTERVAL migrate, this;
686 register int migrate_amt;
688 if (NULL_INTERVAL_P (i->left))
689 return i->right;
690 if (NULL_INTERVAL_P (i->right))
691 return i->left;
693 migrate = i->left;
694 migrate_amt = i->left->total_length;
695 this = i->right;
696 this->total_length += migrate_amt;
697 while (! NULL_INTERVAL_P (this->left))
699 this = this->left;
700 this->total_length += migrate_amt;
702 this->left = migrate;
703 migrate->parent = this;
705 return i->right;
708 /* Delete interval I from its tree by calling `delete_node'
709 and properly connecting the resultant subtree.
711 I is presumed to be empty; that is, no adjustments are made
712 for the length of I. */
714 void
715 delete_interval (i)
716 register INTERVAL i;
718 register INTERVAL parent;
719 int amt = LENGTH (i);
721 if (amt > 0) /* Only used on zero-length intervals now. */
722 abort ();
724 if (ROOT_INTERVAL_P (i))
726 Lisp_Object owner = (Lisp_Object) i->parent;
727 parent = delete_node (i);
728 if (! NULL_INTERVAL_P (parent))
729 parent->parent = (INTERVAL) owner;
731 if (XTYPE (owner) == Lisp_Buffer)
732 XBUFFER (owner)->intervals = parent;
733 else if (XTYPE (owner) == Lisp_String)
734 XSTRING (owner)->intervals = parent;
735 else
736 abort ();
738 return;
741 parent = i->parent;
742 if (AM_LEFT_CHILD (i))
744 parent->left = delete_node (i);
745 if (! NULL_INTERVAL_P (parent->left))
746 parent->left->parent = parent;
748 else
750 parent->right = delete_node (i);
751 if (! NULL_INTERVAL_P (parent->right))
752 parent->right->parent = parent;
756 /* Find the interval in TREE corresponding to the relative position
757 FROM and delete as much as possible of AMOUNT from that interval.
758 Return the amount actually deleted, and if the interval was
759 zeroed-out, delete that interval node from the tree.
761 Note that FROM is actually origin zero, aka relative to the
762 leftmost edge of tree. This is appropriate since we call ourselves
763 recursively on subtrees.
765 Do this by recursing down TREE to the interval in question, and
766 deleting the appropriate amount of text. */
768 static int
769 interval_deletion_adjustment (tree, from, amount)
770 register INTERVAL tree;
771 register int from, amount;
773 register int relative_position = from;
775 if (NULL_INTERVAL_P (tree))
776 return 0;
778 /* Left branch */
779 if (relative_position < LEFT_TOTAL_LENGTH (tree))
781 int subtract = interval_deletion_adjustment (tree->left,
782 relative_position,
783 amount);
784 tree->total_length -= subtract;
785 return subtract;
787 /* Right branch */
788 else if (relative_position >= (TOTAL_LENGTH (tree)
789 - RIGHT_TOTAL_LENGTH (tree)))
791 int subtract;
793 relative_position -= (tree->total_length
794 - RIGHT_TOTAL_LENGTH (tree));
795 subtract = interval_deletion_adjustment (tree->right,
796 relative_position,
797 amount);
798 tree->total_length -= subtract;
799 return subtract;
801 /* Here -- this node */
802 else
804 /* How much can we delete from this interval? */
805 int my_amount = ((tree->total_length
806 - RIGHT_TOTAL_LENGTH (tree))
807 - relative_position);
809 if (amount > my_amount)
810 amount = my_amount;
812 tree->total_length -= amount;
813 if (LENGTH (tree) == 0)
814 delete_interval (tree);
816 return amount;
819 /* Never reach here */
822 /* Effect the adjustments necessary to the interval tree of BUFFER to
823 correspond to the deletion of LENGTH characters from that buffer
824 text. The deletion is effected at position START (which is a
825 buffer position, i.e. origin 1). */
827 static void
828 adjust_intervals_for_deletion (buffer, start, length)
829 struct buffer *buffer;
830 int start, length;
832 register int left_to_delete = length;
833 register INTERVAL tree = buffer->intervals;
834 register int deleted;
836 if (NULL_INTERVAL_P (tree))
837 return;
839 if (start > BEG + TOTAL_LENGTH (tree)
840 || start + length > BEG + TOTAL_LENGTH (tree))
841 abort ();
843 if (length == TOTAL_LENGTH (tree))
845 buffer->intervals = NULL_INTERVAL;
846 return;
849 if (ONLY_INTERVAL_P (tree))
851 tree->total_length -= length;
852 return;
855 if (start > BEG + TOTAL_LENGTH (tree))
856 start = BEG + TOTAL_LENGTH (tree);
857 while (left_to_delete > 0)
859 left_to_delete -= interval_deletion_adjustment (tree, start - 1,
860 left_to_delete);
861 tree = buffer->intervals;
862 if (left_to_delete == tree->total_length)
864 buffer->intervals = NULL_INTERVAL;
865 return;
870 /* Make the adjustments necessary to the interval tree of BUFFER to
871 represent an addition or deletion of LENGTH characters starting
872 at position START. Addition or deletion is indicated by the sign
873 of LENGTH. */
875 INLINE void
876 offset_intervals (buffer, start, length)
877 struct buffer *buffer;
878 int start, length;
880 if (NULL_INTERVAL_P (buffer->intervals) || length == 0)
881 return;
883 if (length > 0)
884 adjust_intervals_for_insertion (buffer->intervals, start, length);
885 else
886 adjust_intervals_for_deletion (buffer, start, -length);
889 /* Merge interval I with its lexicographic successor. The resulting
890 interval is returned, and has the properties of the original
891 successor. The properties of I are lost. I is removed from the
892 interval tree.
894 IMPORTANT:
895 The caller must verify that this is not the last (rightmost)
896 interval. */
898 INTERVAL
899 merge_interval_right (i)
900 register INTERVAL i;
902 register int absorb = LENGTH (i);
903 register INTERVAL successor;
905 /* Zero out this interval. */
906 i->total_length -= absorb;
908 /* Find the succeeding interval. */
909 if (! NULL_RIGHT_CHILD (i)) /* It's below us. Add absorb
910 as we descend. */
912 successor = i->right;
913 while (! NULL_LEFT_CHILD (successor))
915 successor->total_length += absorb;
916 successor = successor->left;
919 successor->total_length += absorb;
920 delete_interval (i);
921 return successor;
924 successor = i;
925 while (! NULL_PARENT (successor)) /* It's above us. Subtract as
926 we ascend. */
928 if (AM_LEFT_CHILD (successor))
930 successor = successor->parent;
931 delete_interval (i);
932 return successor;
935 successor = successor->parent;
936 successor->total_length -= absorb;
939 /* This must be the rightmost or last interval and cannot
940 be merged right. The caller should have known. */
941 abort ();
944 /* Merge interval I with its lexicographic predecessor. The resulting
945 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.
948 IMPORTANT:
949 The caller must verify that this is not the first (leftmost) interval. */
951 INTERVAL
952 merge_interval_left (i)
953 register INTERVAL i;
955 register int absorb = LENGTH (i);
956 register INTERVAL predecessor;
958 /* Zero out this interval. */
959 i->total_length -= absorb;
961 /* Find the preceding interval. */
962 if (! NULL_LEFT_CHILD (i)) /* It's below us. Go down,
963 adding ABSORB as we go. */
965 predecessor = i->left;
966 while (! NULL_RIGHT_CHILD (predecessor))
968 predecessor->total_length += absorb;
969 predecessor = predecessor->right;
972 predecessor->total_length += absorb;
973 delete_interval (i);
974 return predecessor;
977 predecessor = i;
978 while (! NULL_PARENT (predecessor)) /* It's above us. Go up,
979 subtracting ABSORB. */
981 if (AM_RIGHT_CHILD (predecessor))
983 predecessor = predecessor->parent;
984 delete_interval (i);
985 return predecessor;
988 predecessor = predecessor->parent;
989 predecessor->total_length -= absorb;
992 /* This must be the leftmost or first interval and cannot
993 be merged left. The caller should have known. */
994 abort ();
997 /* Make an exact copy of interval tree SOURCE which descends from
998 PARENT. This is done by recursing through SOURCE, copying
999 the current interval and its properties, and then adjusting
1000 the pointers of the copy. */
1002 static INTERVAL
1003 reproduce_tree (source, parent)
1004 INTERVAL source, parent;
1006 register INTERVAL t = make_interval ();
1008 bcopy (source, t, INTERVAL_SIZE);
1009 copy_properties (source, t);
1010 t->parent = parent;
1011 if (! NULL_LEFT_CHILD (source))
1012 t->left = reproduce_tree (source->left, t);
1013 if (! NULL_RIGHT_CHILD (source))
1014 t->right = reproduce_tree (source->right, t);
1016 return t;
1019 #if 0
1020 /* Nobody calls this. Perhaps it's a vestige of an earlier design. */
1022 /* Make a new interval of length LENGTH starting at START in the
1023 group of intervals INTERVALS, which is actually an interval tree.
1024 Returns the new interval.
1026 Generate an error if the new positions would overlap an existing
1027 interval. */
1029 static INTERVAL
1030 make_new_interval (intervals, start, length)
1031 INTERVAL intervals;
1032 int start, length;
1034 INTERVAL slot;
1036 slot = find_interval (intervals, start);
1037 if (start + length > slot->position + LENGTH (slot))
1038 error ("Interval would overlap");
1040 if (start == slot->position && length == LENGTH (slot))
1041 return slot;
1043 if (slot->position == start)
1045 /* New right node. */
1046 split_interval_right (slot, length);
1047 return slot;
1050 if (slot->position + LENGTH (slot) == start + length)
1052 /* New left node. */
1053 split_interval_left (slot, LENGTH (slot) - length);
1054 return slot;
1057 /* Convert interval SLOT into three intervals. */
1058 split_interval_left (slot, start - slot->position);
1059 split_interval_right (slot, length);
1060 return slot;
1062 #endif
1064 /* Insert the intervals of SOURCE into BUFFER at POSITION.
1066 This is used in insdel.c when inserting Lisp_Strings into the
1067 buffer. The text corresponding to SOURCE is already in the buffer
1068 when this is called. The intervals of new tree are a copy of those
1069 belonging to the string being inserted; intervals are never
1070 shared.
1072 If the inserted text had no intervals associated, this function
1073 simply returns -- offset_intervals should handle placing the
1074 text in the correct interval, depending on the sticky bits.
1076 If the inserted text had properties (intervals), then there are two
1077 cases -- either insertion happened in the middle of some interval,
1078 or between two intervals.
1080 If the text goes into the middle of an interval, then new
1081 intervals are created in the middle with only the properties of
1082 the new text, *unless* the macro MERGE_INSERTIONS is true, in
1083 which case the new text has the union of its properties and those
1084 of the text into which it was inserted.
1086 If the text goes between two intervals, then if neither interval
1087 had its appropriate sticky property set (front_sticky, rear_sticky),
1088 the new text has only its properties. If one of the sticky properties
1089 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
1091 intervals to the new text are "sticky", then the new text retains
1092 only its properties, as if neither sticky property were set. Perhaps
1093 we should consider merging all three sets of properties onto the new
1094 text... */
1096 void
1097 graft_intervals_into_buffer (source, position, buffer)
1098 INTERVAL source;
1099 int position;
1100 struct buffer *buffer;
1102 register INTERVAL under, over, this, prev;
1103 register INTERVAL tree = buffer->intervals;
1104 int middle;
1106 /* If the new text has no properties, it becomes part of whatever
1107 interval it was inserted into. */
1108 if (NULL_INTERVAL_P (source))
1109 return;
1111 if (NULL_INTERVAL_P (tree))
1113 /* The inserted text constitutes the whole buffer, so
1114 simply copy over the interval structure. */
1115 if ((BUF_Z (buffer) - BUF_BEG (buffer)) == TOTAL_LENGTH (source))
1117 buffer->intervals = reproduce_tree (source, tree->parent);
1118 /* Explicitly free the old tree here. */
1120 return;
1123 /* Create an interval tree in which to place a copy
1124 of the intervals of the inserted string. */
1126 Lisp_Object buf;
1127 XSET (buf, Lisp_Buffer, buffer);
1128 tree = create_root_interval (buf);
1131 else
1132 if (TOTAL_LENGTH (tree) == TOTAL_LENGTH (source))
1133 /* If the buffer contains only the new string, but
1134 there was already some interval tree there, then it may be
1135 some zero length intervals. Eventually, do something clever
1136 about inserting properly. For now, just waste the old intervals. */
1138 buffer->intervals = reproduce_tree (source, tree->parent);
1139 /* Explicitly free the old tree here. */
1141 return;
1143 else
1144 /* Paranoia -- the text has already been added, so this buffer
1145 should be of non-zero length. */
1146 if (TOTAL_LENGTH (tree) == 0)
1147 abort ();
1149 this = under = find_interval (tree, position);
1150 if (NULL_INTERVAL_P (under)) /* Paranoia */
1151 abort ();
1152 over = find_interval (source, 1);
1154 /* Here for insertion in the middle of an interval.
1155 Split off an equivalent interval to the right,
1156 then don't bother with it any more. */
1158 if (position > under->position)
1160 INTERVAL end_unchanged
1161 = split_interval_left (this, position - under->position);
1162 copy_properties (under, end_unchanged);
1163 under->position = position;
1164 prev = 0;
1165 middle = 1;
1167 else
1169 prev = previous_interval (under);
1170 if (prev && !END_STICKY_P (prev))
1171 prev = 0;
1174 /* Insertion is now at beginning of UNDER. */
1176 /* The inserted text "sticks" to the interval `under',
1177 which means it gets those properties. */
1178 while (! NULL_INTERVAL_P (over))
1180 if (LENGTH (over) + 1 < LENGTH (under))
1181 this = split_interval_left (under, LENGTH (over));
1182 else
1183 this = under;
1184 copy_properties (over, this);
1185 /* Insertion at the end of an interval, PREV,
1186 inherits from PREV if PREV is sticky at the end. */
1187 if (prev && ! FRONT_STICKY_P (under)
1188 && MERGE_INSERTIONS (prev))
1189 merge_properties (prev, this);
1190 /* Maybe it inherits from the following interval
1191 if that is sticky at the front. */
1192 else if ((FRONT_STICKY_P (under) || middle)
1193 && MERGE_INSERTIONS (under))
1194 merge_properties (under, this);
1195 over = next_interval (over);
1198 buffer->intervals = balance_intervals (buffer->intervals);
1199 return;
1202 /* Get the value of property PROP from PLIST,
1203 which is the plist of an interval.
1204 We check for direct properties and for categories with property PROP. */
1206 Lisp_Object
1207 textget (plist, prop)
1208 Lisp_Object plist;
1209 register Lisp_Object prop;
1211 register Lisp_Object tail, fallback;
1212 fallback = Qnil;
1214 for (tail = plist; !NILP (tail); tail = Fcdr (Fcdr (tail)))
1216 register Lisp_Object tem;
1217 tem = Fcar (tail);
1218 if (EQ (prop, tem))
1219 return Fcar (Fcdr (tail));
1220 if (EQ (tem, Qcategory))
1221 fallback = Fget (Fcar (Fcdr (tail)), prop);
1224 return fallback;
1227 /* Set point in BUFFER to POSITION. If the target position is
1228 before an invisible character which is not displayed with a special glyph,
1229 move back to an ok place to display. */
1231 void
1232 set_point (position, buffer)
1233 register int position;
1234 register struct buffer *buffer;
1236 register INTERVAL to, from, toprev, fromprev, target;
1237 int buffer_point;
1238 register Lisp_Object obj;
1239 int backwards = (position < BUF_PT (buffer)) ? 1 : 0;
1240 int old_position = buffer->text.pt;
1242 if (position == buffer->text.pt)
1243 return;
1245 /* Check this now, before checking if the buffer has any intervals.
1246 That way, we can catch conditions which break this sanity check
1247 whether or not there are intervals in the buffer. */
1248 if (position > BUF_Z (buffer) || position < BUF_BEG (buffer))
1249 abort ();
1251 if (NULL_INTERVAL_P (buffer->intervals))
1253 buffer->text.pt = position;
1254 return;
1257 /* Set TO to the interval containing the char after POSITION,
1258 and TOPREV to the interval containing the char before POSITION.
1259 Either one may be null. They may be equal. */
1260 to = find_interval (buffer->intervals, position);
1261 if (position == BUF_BEGV (buffer))
1262 toprev = 0;
1263 else if (to->position == position)
1264 toprev = previous_interval (to);
1265 else
1266 toprev = to;
1268 buffer_point = (BUF_PT (buffer) == BUF_ZV (buffer)
1269 ? BUF_ZV (buffer) - 1
1270 : BUF_PT (buffer));
1272 /* Set FROM to the interval containing the char after PT,
1273 and FROMPREV to the interval containing the char before PT.
1274 Either one may be null. They may be equal. */
1275 /* We could cache this and save time. */
1276 from = find_interval (buffer->intervals, buffer_point);
1277 if (from->position == BUF_BEGV (buffer))
1278 fromprev = 0;
1279 else if (from->position == BUF_PT (buffer))
1280 fromprev = previous_interval (from);
1281 else if (buffer_point != BUF_PT (buffer))
1282 fromprev = from, from = 0;
1283 else
1284 fromprev = from;
1286 /* Moving within an interval */
1287 if (to == from && toprev == fromprev && INTERVAL_VISIBLE_P (to))
1289 buffer->text.pt = position;
1290 return;
1293 /* If the new position is before an invisible character,
1294 move forward over all such. */
1295 while (! NULL_INTERVAL_P (to)
1296 && ! INTERVAL_VISIBLE_P (to)
1297 && ! DISPLAY_INVISIBLE_GLYPH (to))
1299 toprev = to;
1300 to = next_interval (to);
1301 if (NULL_INTERVAL_P (to))
1302 position = BUF_ZV (buffer);
1303 else
1304 position = to->position;
1307 buffer->text.pt = position;
1309 /* We run point-left and point-entered hooks here, iff the
1310 two intervals are not equivalent. These hooks take
1311 (old_point, new_point) as arguments. */
1312 if (! intervals_equal (from, to)
1313 || ! intervals_equal (fromprev, toprev))
1315 Lisp_Object leave_after, leave_before, enter_after, enter_before;
1317 if (fromprev)
1318 leave_after = textget (fromprev->plist, Qpoint_left);
1319 else
1320 leave_after = Qnil;
1321 if (from)
1322 leave_before = textget (from->plist, Qpoint_left);
1323 else
1324 leave_before = Qnil;
1326 if (toprev)
1327 enter_after = textget (toprev->plist, Qpoint_entered);
1328 else
1329 enter_after = Qnil;
1330 if (to)
1331 enter_before = textget (to->plist, Qpoint_entered);
1332 else
1333 enter_before = Qnil;
1335 if (! EQ (leave_before, enter_before) && !NILP (leave_before))
1336 call2 (leave_before, old_position, position);
1337 if (! EQ (leave_after, enter_after) && !NILP (leave_after))
1338 call2 (leave_after, old_position, position);
1340 if (! EQ (enter_before, leave_before) && !NILP (enter_before))
1341 call2 (enter_before, old_position, position);
1342 if (! EQ (enter_after, leave_after) && !NILP (enter_after))
1343 call2 (enter_after, old_position, position);
1347 /* Set point temporarily, without checking any text properties. */
1349 INLINE void
1350 temp_set_point (position, buffer)
1351 int position;
1352 struct buffer *buffer;
1354 buffer->text.pt = position;
1357 /* Return the proper local map for position POSITION in BUFFER.
1358 Use the map specified by the local-map property, if any.
1359 Otherwise, use BUFFER's local map. */
1361 Lisp_Object
1362 get_local_map (position, buffer)
1363 register int position;
1364 register struct buffer *buffer;
1366 register INTERVAL interval;
1367 Lisp_Object prop, tem;
1369 if (NULL_INTERVAL_P (buffer->intervals))
1370 return current_buffer->keymap;
1372 /* Perhaps we should just change `position' to the limit. */
1373 if (position > BUF_Z (buffer) || position < BUF_BEG (buffer))
1374 abort ();
1376 interval = find_interval (buffer->intervals, position);
1377 prop = textget (interval->plist, Qlocal_map);
1378 if (NILP (prop))
1379 return current_buffer->keymap;
1381 /* Use the local map only if it is valid. */
1382 tem = Fkeymapp (prop);
1383 if (!NILP (tem))
1384 return prop;
1386 return current_buffer->keymap;
1389 /* Call the modification hook functions in LIST, each with START and END. */
1391 static void
1392 call_mod_hooks (list, start, end)
1393 Lisp_Object list, start, end;
1395 struct gcpro gcpro1;
1396 GCPRO1 (list);
1397 while (!NILP (list))
1399 call2 (Fcar (list), start, end);
1400 list = Fcdr (list);
1402 UNGCPRO;
1405 /* Check for read-only intervals and signal an error if we find one.
1406 Then check for any modification hooks in the range START up to
1407 (but not including) TO. Create a list of all these hooks in
1408 lexicographic order, eliminating consecutive extra copies of the
1409 same hook. Then call those hooks in order, with START and END - 1
1410 as arguments. */
1412 void
1413 verify_interval_modification (buf, start, end)
1414 struct buffer *buf;
1415 int start, end;
1417 register INTERVAL intervals = buf->intervals;
1418 register INTERVAL i, prev;
1419 Lisp_Object hooks;
1420 register Lisp_Object prev_mod_hooks;
1421 Lisp_Object mod_hooks;
1422 struct gcpro gcpro1;
1424 hooks = Qnil;
1425 prev_mod_hooks = Qnil;
1426 mod_hooks = Qnil;
1428 if (NULL_INTERVAL_P (intervals))
1429 return;
1431 if (start > end)
1433 int temp = start;
1434 start = end;
1435 end = temp;
1438 /* For an insert operation, check the two chars around the position. */
1439 if (start == end)
1441 INTERVAL prev;
1442 Lisp_Object before, after;
1444 /* Set I to the interval containing the char after START,
1445 and PREV to the interval containing the char before START.
1446 Either one may be null. They may be equal. */
1447 i = find_interval (intervals, start);
1449 if (start == BUF_BEGV (buf))
1450 prev = 0;
1451 if (i->position == start)
1452 prev = previous_interval (i);
1453 else if (i->position < start)
1454 prev = i;
1455 if (start == BUF_ZV (buf))
1456 i = 0;
1458 if (NULL_INTERVAL_P (prev))
1460 if (! INTERVAL_WRITABLE_P (i))
1461 error ("Attempt to insert within read-only text");
1463 else if (NULL_INTERVAL_P (i))
1465 if (! INTERVAL_WRITABLE_P (prev))
1466 error ("Attempt to insert within read-only text");
1468 else
1470 before = textget (prev->plist, Qread_only);
1471 after = textget (i->plist, Qread_only);
1472 if (! NILP (before) && EQ (before, after)
1473 /* This checks Vinhibit_read_only properly
1474 for the common value of the read-only property. */
1475 && ! INTERVAL_WRITABLE_P (i))
1476 error ("Attempt to insert within read-only text");
1479 /* Run both insert hooks (just once if they're the same). */
1480 if (!NULL_INTERVAL_P (prev))
1481 prev_mod_hooks = textget (prev->plist, Qinsert_behind_hooks);
1482 if (!NULL_INTERVAL_P (i))
1483 mod_hooks = textget (i->plist, Qinsert_in_front_hooks);
1484 GCPRO1 (mod_hooks);
1485 if (! NILP (prev_mod_hooks))
1486 call_mod_hooks (prev_mod_hooks, make_number (start),
1487 make_number (end));
1488 UNGCPRO;
1489 if (! NILP (mod_hooks) && ! EQ (mod_hooks, prev_mod_hooks))
1490 call_mod_hooks (mod_hooks, make_number (start), make_number (end));
1492 else
1494 /* Loop over intervals on or next to START...END,
1495 collecting their hooks. */
1497 i = find_interval (intervals, start);
1500 if (! INTERVAL_WRITABLE_P (i))
1501 error ("Attempt to modify read-only text");
1503 mod_hooks = textget (i->plist, Qmodification_hooks);
1504 if (! NILP (mod_hooks) && ! EQ (mod_hooks, prev_mod_hooks))
1506 hooks = Fcons (mod_hooks, hooks);
1507 prev_mod_hooks = mod_hooks;
1510 i = next_interval (i);
1512 /* Keep going thru the interval containing the char before END. */
1513 while (! NULL_INTERVAL_P (i) && i->position < end);
1515 GCPRO1 (hooks);
1516 hooks = Fnreverse (hooks);
1517 while (! EQ (hooks, Qnil))
1519 call_mod_hooks (Fcar (hooks), make_number (start),
1520 make_number (end));
1521 hooks = Fcdr (hooks);
1523 UNGCPRO;
1527 /* Balance an interval node if the amount of text in its left and right
1528 subtrees differs by more than the percentage specified by
1529 `interval-balance-threshold'. */
1531 static INTERVAL
1532 balance_an_interval (i)
1533 INTERVAL i;
1535 register int total_children_size = (LEFT_TOTAL_LENGTH (i)
1536 + RIGHT_TOTAL_LENGTH (i));
1537 register int threshold = (XFASTINT (interval_balance_threshold)
1538 * (total_children_size / 100));
1540 /* Balance within each side. */
1541 balance_intervals (i->left);
1542 balance_intervals (i->right);
1544 if (LEFT_TOTAL_LENGTH (i) > RIGHT_TOTAL_LENGTH (i)
1545 && (LEFT_TOTAL_LENGTH (i) - RIGHT_TOTAL_LENGTH (i)) > threshold)
1547 i = rotate_right (i);
1548 /* If that made it unbalanced the other way, take it back. */
1549 if (RIGHT_TOTAL_LENGTH (i) > LEFT_TOTAL_LENGTH (i)
1550 && (RIGHT_TOTAL_LENGTH (i) - LEFT_TOTAL_LENGTH (i)) > threshold)
1551 return rotate_left (i);
1552 return i;
1555 if (RIGHT_TOTAL_LENGTH (i) > LEFT_TOTAL_LENGTH (i)
1556 && (RIGHT_TOTAL_LENGTH (i) - LEFT_TOTAL_LENGTH (i)) > threshold)
1558 i = rotate_left (i);
1559 if (LEFT_TOTAL_LENGTH (i) > RIGHT_TOTAL_LENGTH (i)
1560 && (LEFT_TOTAL_LENGTH (i) - RIGHT_TOTAL_LENGTH (i)) > threshold)
1561 return rotate_right (i);
1562 return i;
1565 return i;
1568 /* Balance the interval tree TREE. Balancing is by weight
1569 (the amount of text). */
1571 INTERVAL
1572 balance_intervals (tree)
1573 register INTERVAL tree;
1575 register INTERVAL new_tree;
1577 if (NULL_INTERVAL_P (tree))
1578 return NULL_INTERVAL;
1580 new_tree = tree;
1583 tree = new_tree;
1584 new_tree = balance_an_interval (new_tree);
1586 while (new_tree != tree);
1588 return new_tree;
1591 /* Produce an interval tree reflecting the intervals in
1592 TREE from START to START + LENGTH. */
1594 INTERVAL
1595 copy_intervals (tree, start, length)
1596 INTERVAL tree;
1597 int start, length;
1599 register INTERVAL i, new, t;
1600 register int got, prevlen;
1602 if (NULL_INTERVAL_P (tree) || length <= 0)
1603 return NULL_INTERVAL;
1605 i = find_interval (tree, start);
1606 if (NULL_INTERVAL_P (i) || LENGTH (i) == 0)
1607 abort ();
1609 /* If there is only one interval and it's the default, return nil. */
1610 if ((start - i->position + 1 + length) < LENGTH (i)
1611 && DEFAULT_INTERVAL_P (i))
1612 return NULL_INTERVAL;
1614 new = make_interval ();
1615 new->position = 1;
1616 got = (LENGTH (i) - (start - i->position));
1617 new->total_length = length;
1618 copy_properties (i, new);
1620 t = new;
1621 prevlen = got;
1622 while (got < length)
1624 i = next_interval (i);
1625 t = split_interval_right (t, prevlen);
1626 copy_properties (i, t);
1627 prevlen = LENGTH (i);
1628 got += prevlen;
1631 return balance_intervals (new);
1634 /* Give STRING the properties of BUFFER from POSITION to LENGTH. */
1636 INLINE void
1637 copy_intervals_to_string (string, buffer, position, length)
1638 Lisp_Object string, buffer;
1639 int position, length;
1641 INTERVAL interval_copy = copy_intervals (XBUFFER (buffer)->intervals,
1642 position, length);
1643 if (NULL_INTERVAL_P (interval_copy))
1644 return;
1646 interval_copy->parent = (INTERVAL) string;
1647 XSTRING (string)->intervals = interval_copy;
1650 #endif /* USE_TEXT_PROPERTIES */