(Fforward_comment): Undo the previous change, since cc-mode
[emacs.git] / src / intervals.c
blobbba25d7de8cd48e595918e14fc4c4486ba7b7365
1 /* Code for doing intervals.
2 Copyright (C) 1993, 1994, 1995, 1997, 1998 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 2, 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, Inc., 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */
22 /* NOTES:
24 Have to ensure that we can't put symbol nil on a plist, or some
25 functions may work incorrectly.
27 An idea: Have the owner of the tree keep count of splits and/or
28 insertion lengths (in intervals), and balance after every N.
30 Need to call *_left_hook when buffer is killed.
32 Scan for zero-length, or 0-length to see notes about handling
33 zero length interval-markers.
35 There are comments around about freeing intervals. It might be
36 faster to explicitly free them (put them on the free list) than
37 to GC them.
42 #include <config.h>
43 #include "lisp.h"
44 #include "intervals.h"
45 #include "buffer.h"
46 #include "puresize.h"
47 #include "keyboard.h"
49 /* Test for membership, allowing for t (actually any non-cons) to mean the
50 universal set. */
52 #define TMEM(sym, set) (CONSP (set) ? ! NILP (Fmemq (sym, set)) : ! NILP (set))
54 #define min(x, y) ((x) < (y) ? (x) : (y))
56 Lisp_Object merge_properties_sticky ();
58 /* Utility functions for intervals. */
61 /* Create the root interval of some object, a buffer or string. */
63 INTERVAL
64 create_root_interval (parent)
65 Lisp_Object parent;
67 INTERVAL new;
69 CHECK_IMPURE (parent);
71 new = make_interval ();
73 if (BUFFERP (parent))
75 new->total_length = (BUF_Z (XBUFFER (parent))
76 - BUF_BEG (XBUFFER (parent)));
77 BUF_INTERVALS (XBUFFER (parent)) = new;
78 new->position = 1;
80 else if (STRINGP (parent))
82 new->total_length = XSTRING (parent)->size;
83 XSTRING (parent)->intervals = new;
84 new->position = 0;
87 new->parent = (INTERVAL) XFASTINT (parent);
89 return new;
92 /* Make the interval TARGET have exactly the properties of SOURCE */
94 void
95 copy_properties (source, target)
96 register INTERVAL source, target;
98 if (DEFAULT_INTERVAL_P (source) && DEFAULT_INTERVAL_P (target))
99 return;
101 COPY_INTERVAL_CACHE (source, target);
102 target->plist = Fcopy_sequence (source->plist);
105 /* Merge the properties of interval SOURCE into the properties
106 of interval TARGET. That is to say, each property in SOURCE
107 is added to TARGET if TARGET has no such property as yet. */
109 static void
110 merge_properties (source, target)
111 register INTERVAL source, target;
113 register Lisp_Object o, sym, val;
115 if (DEFAULT_INTERVAL_P (source) && DEFAULT_INTERVAL_P (target))
116 return;
118 MERGE_INTERVAL_CACHE (source, target);
120 o = source->plist;
121 while (! EQ (o, Qnil))
123 sym = Fcar (o);
124 val = Fmemq (sym, target->plist);
126 if (NILP (val))
128 o = Fcdr (o);
129 val = Fcar (o);
130 target->plist = Fcons (sym, Fcons (val, target->plist));
131 o = Fcdr (o);
133 else
134 o = Fcdr (Fcdr (o));
138 /* Return 1 if the two intervals have the same properties,
139 0 otherwise. */
142 intervals_equal (i0, i1)
143 INTERVAL i0, i1;
145 register Lisp_Object i0_cdr, i0_sym, i1_val;
146 register int i1_len;
148 if (DEFAULT_INTERVAL_P (i0) && DEFAULT_INTERVAL_P (i1))
149 return 1;
151 if (DEFAULT_INTERVAL_P (i0) || DEFAULT_INTERVAL_P (i1))
152 return 0;
154 i1_len = XFASTINT (Flength (i1->plist));
155 if (i1_len & 0x1) /* Paranoia -- plists are always even */
156 abort ();
157 i1_len /= 2;
158 i0_cdr = i0->plist;
159 while (!NILP (i0_cdr))
161 /* Lengths of the two plists were unequal. */
162 if (i1_len == 0)
163 return 0;
165 i0_sym = Fcar (i0_cdr);
166 i1_val = Fmemq (i0_sym, i1->plist);
168 /* i0 has something i1 doesn't. */
169 if (EQ (i1_val, Qnil))
170 return 0;
172 /* i0 and i1 both have sym, but it has different values in each. */
173 i0_cdr = Fcdr (i0_cdr);
174 if (! EQ (Fcar (Fcdr (i1_val)), Fcar (i0_cdr)))
175 return 0;
177 i0_cdr = Fcdr (i0_cdr);
178 i1_len--;
181 /* Lengths of the two plists were unequal. */
182 if (i1_len > 0)
183 return 0;
185 return 1;
189 /* Traverse an interval tree TREE, performing FUNCTION on each node.
190 Pass FUNCTION two args: an interval, and ARG. */
192 void
193 traverse_intervals (tree, position, depth, function, arg)
194 INTERVAL tree;
195 int position, depth;
196 void (* function) P_ ((INTERVAL, Lisp_Object));
197 Lisp_Object arg;
199 if (NULL_INTERVAL_P (tree))
200 return;
202 traverse_intervals (tree->left, position, depth + 1, function, arg);
203 position += LEFT_TOTAL_LENGTH (tree);
204 tree->position = position;
205 (*function) (tree, arg);
206 position += LENGTH (tree);
207 traverse_intervals (tree->right, position, depth + 1, function, arg);
210 #if 0
212 static int icount;
213 static int idepth;
214 static int zero_length;
216 /* These functions are temporary, for debugging purposes only. */
218 INTERVAL search_interval, found_interval;
220 void
221 check_for_interval (i)
222 register INTERVAL i;
224 if (i == search_interval)
226 found_interval = i;
227 icount++;
231 INTERVAL
232 search_for_interval (i, tree)
233 register INTERVAL i, tree;
235 icount = 0;
236 search_interval = i;
237 found_interval = NULL_INTERVAL;
238 traverse_intervals (tree, 1, 0, &check_for_interval, Qnil);
239 return found_interval;
242 static void
243 inc_interval_count (i)
244 INTERVAL i;
246 icount++;
247 if (LENGTH (i) == 0)
248 zero_length++;
249 if (depth > idepth)
250 idepth = depth;
254 count_intervals (i)
255 register INTERVAL i;
257 icount = 0;
258 idepth = 0;
259 zero_length = 0;
260 traverse_intervals (i, 1, 0, &inc_interval_count, Qnil);
262 return icount;
265 static INTERVAL
266 root_interval (interval)
267 INTERVAL interval;
269 register INTERVAL i = interval;
271 while (! ROOT_INTERVAL_P (i))
272 i = i->parent;
274 return i;
276 #endif
278 /* Assuming that a left child exists, perform the following operation:
281 / \ / \
282 B => A
283 / \ / \
287 static INTERVAL
288 rotate_right (interval)
289 INTERVAL interval;
291 INTERVAL i;
292 INTERVAL B = interval->left;
293 int old_total = interval->total_length;
295 /* Deal with any Parent of A; make it point to B. */
296 if (! ROOT_INTERVAL_P (interval))
298 if (AM_LEFT_CHILD (interval))
299 interval->parent->left = B;
300 else
301 interval->parent->right = B;
303 B->parent = interval->parent;
305 /* Make B the parent of A */
306 i = B->right;
307 B->right = interval;
308 interval->parent = B;
310 /* Make A point to c */
311 interval->left = i;
312 if (! NULL_INTERVAL_P (i))
313 i->parent = interval;
315 /* A's total length is decreased by the length of B and its left child. */
316 interval->total_length -= B->total_length - LEFT_TOTAL_LENGTH (interval);
318 /* B must have the same total length of A. */
319 B->total_length = old_total;
321 return B;
324 /* Assuming that a right child exists, perform the following operation:
326 A B
327 / \ / \
328 B => A
329 / \ / \
333 static INTERVAL
334 rotate_left (interval)
335 INTERVAL interval;
337 INTERVAL i;
338 INTERVAL B = interval->right;
339 int old_total = interval->total_length;
341 /* Deal with any parent of A; make it point to B. */
342 if (! ROOT_INTERVAL_P (interval))
344 if (AM_LEFT_CHILD (interval))
345 interval->parent->left = B;
346 else
347 interval->parent->right = B;
349 B->parent = interval->parent;
351 /* Make B the parent of A */
352 i = B->left;
353 B->left = interval;
354 interval->parent = B;
356 /* Make A point to c */
357 interval->right = i;
358 if (! NULL_INTERVAL_P (i))
359 i->parent = interval;
361 /* A's total length is decreased by the length of B and its right child. */
362 interval->total_length -= B->total_length - RIGHT_TOTAL_LENGTH (interval);
364 /* B must have the same total length of A. */
365 B->total_length = old_total;
367 return B;
370 /* Balance an interval tree with the assumption that the subtrees
371 themselves are already balanced. */
373 static INTERVAL
374 balance_an_interval (i)
375 INTERVAL i;
377 register int old_diff, new_diff;
379 while (1)
381 old_diff = LEFT_TOTAL_LENGTH (i) - RIGHT_TOTAL_LENGTH (i);
382 if (old_diff > 0)
384 new_diff = i->total_length - i->left->total_length
385 + RIGHT_TOTAL_LENGTH (i->left) - LEFT_TOTAL_LENGTH (i->left);
386 if (abs (new_diff) >= old_diff)
387 break;
388 i = rotate_right (i);
389 balance_an_interval (i->right);
391 else if (old_diff < 0)
393 new_diff = i->total_length - i->right->total_length
394 + LEFT_TOTAL_LENGTH (i->right) - RIGHT_TOTAL_LENGTH (i->right);
395 if (abs (new_diff) >= -old_diff)
396 break;
397 i = rotate_left (i);
398 balance_an_interval (i->left);
400 else
401 break;
403 return i;
406 /* Balance INTERVAL, potentially stuffing it back into its parent
407 Lisp Object. */
409 static INLINE INTERVAL
410 balance_possible_root_interval (interval)
411 register INTERVAL interval;
413 Lisp_Object parent;
415 if (interval->parent == NULL_INTERVAL)
416 return interval;
418 XSETFASTINT (parent, (EMACS_INT) interval->parent);
419 interval = balance_an_interval (interval);
421 if (BUFFERP (parent))
422 BUF_INTERVALS (XBUFFER (parent)) = interval;
423 else if (STRINGP (parent))
424 XSTRING (parent)->intervals = interval;
426 return interval;
429 /* Balance the interval tree TREE. Balancing is by weight
430 (the amount of text). */
432 static INTERVAL
433 balance_intervals_internal (tree)
434 register INTERVAL tree;
436 /* Balance within each side. */
437 if (tree->left)
438 balance_intervals_internal (tree->left);
439 if (tree->right)
440 balance_intervals_internal (tree->right);
441 return balance_an_interval (tree);
444 /* Advertised interface to balance intervals. */
446 INTERVAL
447 balance_intervals (tree)
448 INTERVAL tree;
450 if (tree == NULL_INTERVAL)
451 return NULL_INTERVAL;
453 return balance_intervals_internal (tree);
456 /* Split INTERVAL into two pieces, starting the second piece at
457 character position OFFSET (counting from 0), relative to INTERVAL.
458 INTERVAL becomes the left-hand piece, and the right-hand piece
459 (second, lexicographically) is returned.
461 The size and position fields of the two intervals are set based upon
462 those of the original interval. The property list of the new interval
463 is reset, thus it is up to the caller to do the right thing with the
464 result.
466 Note that this does not change the position of INTERVAL; if it is a root,
467 it is still a root after this operation. */
469 INTERVAL
470 split_interval_right (interval, offset)
471 INTERVAL interval;
472 int offset;
474 INTERVAL new = make_interval ();
475 int position = interval->position;
476 int new_length = LENGTH (interval) - offset;
478 new->position = position + offset;
479 new->parent = interval;
481 if (NULL_RIGHT_CHILD (interval))
483 interval->right = new;
484 new->total_length = new_length;
486 else
488 /* Insert the new node between INTERVAL and its right child. */
489 new->right = interval->right;
490 interval->right->parent = new;
491 interval->right = new;
492 new->total_length = new_length + new->right->total_length;
493 balance_an_interval (new);
496 balance_possible_root_interval (interval);
498 return new;
501 /* Split INTERVAL into two pieces, starting the second piece at
502 character position OFFSET (counting from 0), relative to INTERVAL.
503 INTERVAL becomes the right-hand piece, and the left-hand piece
504 (first, lexicographically) is returned.
506 The size and position fields of the two intervals are set based upon
507 those of the original interval. The property list of the new interval
508 is reset, thus it is up to the caller to do the right thing with the
509 result.
511 Note that this does not change the position of INTERVAL; if it is a root,
512 it is still a root after this operation. */
514 INTERVAL
515 split_interval_left (interval, offset)
516 INTERVAL interval;
517 int offset;
519 INTERVAL new = make_interval ();
520 int new_length = offset;
522 new->position = interval->position;
523 interval->position = interval->position + offset;
524 new->parent = interval;
526 if (NULL_LEFT_CHILD (interval))
528 interval->left = new;
529 new->total_length = new_length;
531 else
533 /* Insert the new node between INTERVAL and its left child. */
534 new->left = interval->left;
535 new->left->parent = new;
536 interval->left = new;
537 new->total_length = new_length + new->left->total_length;
538 balance_an_interval (new);
541 balance_possible_root_interval (interval);
543 return new;
546 /* Return the proper position for the first character
547 described by the interval tree SOURCE.
548 This is 1 if the parent is a buffer,
549 0 if the parent is a string or if there is no parent.
551 Don't use this function on an interval which is the child
552 of another interval! */
555 interval_start_pos (source)
556 INTERVAL source;
558 Lisp_Object parent;
560 if (NULL_INTERVAL_P (source))
561 return 0;
563 XSETFASTINT (parent, (EMACS_INT) source->parent);
564 if (BUFFERP (parent))
565 return BUF_BEG (XBUFFER (parent));
566 return 0;
569 /* Find the interval containing text position POSITION in the text
570 represented by the interval tree TREE. POSITION is a buffer
571 position (starting from 1) or a string index (starting from 0).
572 If POSITION is at the end of the buffer or string,
573 return the interval containing the last character.
575 The `position' field, which is a cache of an interval's position,
576 is updated in the interval found. Other functions (e.g., next_interval)
577 will update this cache based on the result of find_interval. */
579 INTERVAL
580 find_interval (tree, position)
581 register INTERVAL tree;
582 register int position;
584 /* The distance from the left edge of the subtree at TREE
585 to POSITION. */
586 register int relative_position;
587 Lisp_Object parent;
589 if (NULL_INTERVAL_P (tree))
590 return NULL_INTERVAL;
592 XSETFASTINT (parent, (EMACS_INT) tree->parent);
593 relative_position = position;
594 if (BUFFERP (parent))
595 relative_position -= BUF_BEG (XBUFFER (parent));
597 if (relative_position > TOTAL_LENGTH (tree))
598 abort (); /* Paranoia */
600 tree = balance_possible_root_interval (tree);
602 while (1)
604 if (relative_position < LEFT_TOTAL_LENGTH (tree))
606 tree = tree->left;
608 else if (! NULL_RIGHT_CHILD (tree)
609 && relative_position >= (TOTAL_LENGTH (tree)
610 - RIGHT_TOTAL_LENGTH (tree)))
612 relative_position -= (TOTAL_LENGTH (tree)
613 - RIGHT_TOTAL_LENGTH (tree));
614 tree = tree->right;
616 else
618 tree->position
619 = (position - relative_position /* the left edge of *tree */
620 + LEFT_TOTAL_LENGTH (tree)); /* the left edge of this interval */
622 return tree;
627 /* Find the succeeding interval (lexicographically) to INTERVAL.
628 Sets the `position' field based on that of INTERVAL (see
629 find_interval). */
631 INTERVAL
632 next_interval (interval)
633 register INTERVAL interval;
635 register INTERVAL i = interval;
636 register int next_position;
638 if (NULL_INTERVAL_P (i))
639 return NULL_INTERVAL;
640 next_position = interval->position + LENGTH (interval);
642 if (! NULL_RIGHT_CHILD (i))
644 i = i->right;
645 while (! NULL_LEFT_CHILD (i))
646 i = i->left;
648 i->position = next_position;
649 return i;
652 while (! NULL_PARENT (i))
654 if (AM_LEFT_CHILD (i))
656 i = i->parent;
657 i->position = next_position;
658 return i;
661 i = i->parent;
664 return NULL_INTERVAL;
667 /* Find the preceding interval (lexicographically) to INTERVAL.
668 Sets the `position' field based on that of INTERVAL (see
669 find_interval). */
671 INTERVAL
672 previous_interval (interval)
673 register INTERVAL interval;
675 register INTERVAL i;
677 if (NULL_INTERVAL_P (interval))
678 return NULL_INTERVAL;
680 if (! NULL_LEFT_CHILD (interval))
682 i = interval->left;
683 while (! NULL_RIGHT_CHILD (i))
684 i = i->right;
686 i->position = interval->position - LENGTH (i);
687 return i;
690 i = interval;
691 while (! NULL_PARENT (i))
693 if (AM_RIGHT_CHILD (i))
695 i = i->parent;
697 i->position = interval->position - LENGTH (i);
698 return i;
700 i = i->parent;
703 return NULL_INTERVAL;
706 /* Find the interval containing POS given some non-NULL INTERVAL
707 in the same tree. Note that we need to update interval->position
708 if we go down the tree. */
709 INTERVAL
710 update_interval (i, pos)
711 register INTERVAL i;
712 int pos;
714 if (NULL_INTERVAL_P (i))
715 return NULL_INTERVAL;
717 while (1)
719 if (pos < i->position)
721 /* Move left. */
722 if (pos >= i->position - TOTAL_LENGTH (i->left))
724 i->left->position = i->position - TOTAL_LENGTH (i->left)
725 + LEFT_TOTAL_LENGTH (i->left);
726 i = i->left; /* Move to the left child */
728 else if (NULL_PARENT (i))
729 error ("Point before start of properties");
730 else
731 i = i->parent;
732 continue;
734 else if (pos >= INTERVAL_LAST_POS (i))
736 /* Move right. */
737 if (pos < INTERVAL_LAST_POS (i) + TOTAL_LENGTH (i->right))
739 i->right->position = INTERVAL_LAST_POS (i) +
740 LEFT_TOTAL_LENGTH (i->right);
741 i = i->right; /* Move to the right child */
743 else if (NULL_PARENT (i))
744 error ("Point after end of properties");
745 else
746 i = i->parent;
747 continue;
749 else
750 return i;
755 #if 0
756 /* Traverse a path down the interval tree TREE to the interval
757 containing POSITION, adjusting all nodes on the path for
758 an addition of LENGTH characters. Insertion between two intervals
759 (i.e., point == i->position, where i is second interval) means
760 text goes into second interval.
762 Modifications are needed to handle the hungry bits -- after simply
763 finding the interval at position (don't add length going down),
764 if it's the beginning of the interval, get the previous interval
765 and check the hungry bits of both. Then add the length going back up
766 to the root. */
768 static INTERVAL
769 adjust_intervals_for_insertion (tree, position, length)
770 INTERVAL tree;
771 int position, length;
773 register int relative_position;
774 register INTERVAL this;
776 if (TOTAL_LENGTH (tree) == 0) /* Paranoia */
777 abort ();
779 /* If inserting at point-max of a buffer, that position
780 will be out of range */
781 if (position > TOTAL_LENGTH (tree))
782 position = TOTAL_LENGTH (tree);
783 relative_position = position;
784 this = tree;
786 while (1)
788 if (relative_position <= LEFT_TOTAL_LENGTH (this))
790 this->total_length += length;
791 this = this->left;
793 else if (relative_position > (TOTAL_LENGTH (this)
794 - RIGHT_TOTAL_LENGTH (this)))
796 relative_position -= (TOTAL_LENGTH (this)
797 - RIGHT_TOTAL_LENGTH (this));
798 this->total_length += length;
799 this = this->right;
801 else
803 /* If we are to use zero-length intervals as buffer pointers,
804 then this code will have to change. */
805 this->total_length += length;
806 this->position = LEFT_TOTAL_LENGTH (this)
807 + position - relative_position + 1;
808 return tree;
812 #endif
814 /* Effect an adjustment corresponding to the addition of LENGTH characters
815 of text. Do this by finding the interval containing POSITION in the
816 interval tree TREE, and then adjusting all of its ancestors by adding
817 LENGTH to them.
819 If POSITION is the first character of an interval, meaning that point
820 is actually between the two intervals, make the new text belong to
821 the interval which is "sticky".
823 If both intervals are "sticky", then make them belong to the left-most
824 interval. Another possibility would be to create a new interval for
825 this text, and make it have the merged properties of both ends. */
827 static INTERVAL
828 adjust_intervals_for_insertion (tree, position, length)
829 INTERVAL tree;
830 int position, length;
832 register INTERVAL i;
833 register INTERVAL temp;
834 int eobp = 0;
835 Lisp_Object parent;
836 int offset;
838 if (TOTAL_LENGTH (tree) == 0) /* Paranoia */
839 abort ();
841 XSETFASTINT (parent, (EMACS_INT) tree->parent);
842 offset = (BUFFERP (parent) ? BUF_BEG (XBUFFER (parent)) : 0);
844 /* If inserting at point-max of a buffer, that position will be out
845 of range. Remember that buffer positions are 1-based. */
846 if (position >= TOTAL_LENGTH (tree) + offset)
848 position = TOTAL_LENGTH (tree) + offset;
849 eobp = 1;
852 i = find_interval (tree, position);
854 /* If in middle of an interval which is not sticky either way,
855 we must not just give its properties to the insertion.
856 So split this interval at the insertion point.
858 Originally, the if condition here was this:
859 (! (position == i->position || eobp)
860 && END_NONSTICKY_P (i)
861 && FRONT_NONSTICKY_P (i))
862 But, these macros are now unreliable because of introduction of
863 Vtext_property_default_nonsticky. So, we always check properties
864 one by one if POSITION is in middle of an interval. */
865 if (! (position == i->position || eobp))
867 Lisp_Object tail;
868 Lisp_Object front, rear;
870 tail = i->plist;
872 /* Properties font-sticky and rear-nonsticky override
873 Vtext_property_default_nonsticky. So, if they are t, we can
874 skip one by one checking of properties. */
875 rear = textget (i->plist, Qrear_nonsticky);
876 if (! CONSP (rear) && ! NILP (rear))
878 /* All properties are nonsticky. We split the interval. */
879 goto check_done;
881 front = textget (i->plist, Qfront_sticky);
882 if (! CONSP (front) && ! NILP (front))
884 /* All properties are sticky. We don't split the interval. */
885 tail = Qnil;
886 goto check_done;
889 /* Does any actual property pose an actual problem? We break
890 the loop if we find a nonsticky property. */
891 for (; CONSP (tail); tail = Fcdr (XCDR (tail)))
893 Lisp_Object prop, tmp;
894 prop = XCAR (tail);
896 /* Is this particular property front-sticky? */
897 if (CONSP (front) && ! NILP (Fmemq (prop, front)))
898 continue;
900 /* Is this particular property rear-nonsticky? */
901 if (CONSP (rear) && ! NILP (Fmemq (prop, rear)))
902 break;
904 /* Is this particular property recorded as sticky or
905 nonsticky in Vtext_property_default_nonsticky? */
906 tmp = Fassq (prop, Vtext_property_default_nonsticky);
907 if (CONSP (tmp))
909 if (NILP (tmp))
910 continue;
911 break;
914 /* By default, a text property is rear-sticky, thus we
915 continue the loop. */
918 check_done:
919 /* If any property is a real problem, split the interval. */
920 if (! NILP (tail))
922 temp = split_interval_right (i, position - i->position);
923 copy_properties (i, temp);
924 i = temp;
928 /* If we are positioned between intervals, check the stickiness of
929 both of them. We have to do this too, if we are at BEG or Z. */
930 if (position == i->position || eobp)
932 register INTERVAL prev;
934 if (position == BEG)
935 prev = 0;
936 else if (eobp)
938 prev = i;
939 i = 0;
941 else
942 prev = previous_interval (i);
944 /* Even if we are positioned between intervals, we default
945 to the left one if it exists. We extend it now and split
946 off a part later, if stickiness demands it. */
947 for (temp = prev ? prev : i;! NULL_INTERVAL_P (temp); temp = temp->parent)
949 temp->total_length += length;
950 temp = balance_possible_root_interval (temp);
953 /* If at least one interval has sticky properties,
954 we check the stickiness property by property.
956 Originally, the if condition here was this:
957 (END_NONSTICKY_P (prev) || FRONT_STICKY_P (i))
958 But, these macros are now unreliable because of introduction
959 of Vtext_property_default_nonsticky. So, we always have to
960 check stickiness of properties one by one. If cache of
961 stickiness is implemented in the future, we may be able to
962 use those macros again. */
963 if (1)
965 Lisp_Object pleft, pright;
966 struct interval newi;
968 pleft = NULL_INTERVAL_P (prev) ? Qnil : prev->plist;
969 pright = NULL_INTERVAL_P (i) ? Qnil : i->plist;
970 newi.plist = merge_properties_sticky (pleft, pright);
972 if (! prev) /* i.e. position == BEG */
974 if (! intervals_equal (i, &newi))
976 i = split_interval_left (i, length);
977 i->plist = newi.plist;
980 else if (! intervals_equal (prev, &newi))
982 prev = split_interval_right (prev,
983 position - prev->position);
984 prev->plist = newi.plist;
985 if (! NULL_INTERVAL_P (i)
986 && intervals_equal (prev, i))
987 merge_interval_right (prev);
990 /* We will need to update the cache here later. */
992 else if (! prev && ! NILP (i->plist))
994 /* Just split off a new interval at the left.
995 Since I wasn't front-sticky, the empty plist is ok. */
996 i = split_interval_left (i, length);
1000 /* Otherwise just extend the interval. */
1001 else
1003 for (temp = i; ! NULL_INTERVAL_P (temp); temp = temp->parent)
1005 temp->total_length += length;
1006 temp = balance_possible_root_interval (temp);
1010 return tree;
1013 /* Any property might be front-sticky on the left, rear-sticky on the left,
1014 front-sticky on the right, or rear-sticky on the right; the 16 combinations
1015 can be arranged in a matrix with rows denoting the left conditions and
1016 columns denoting the right conditions:
1017 _ __ _
1018 _ FR FR FR FR
1019 FR__ 0 1 2 3
1020 _FR 4 5 6 7
1021 FR 8 9 A B
1022 FR C D E F
1024 left-props = '(front-sticky (p8 p9 pa pb pc pd pe pf)
1025 rear-nonsticky (p4 p5 p6 p7 p8 p9 pa pb)
1026 p0 L p1 L p2 L p3 L p4 L p5 L p6 L p7 L
1027 p8 L p9 L pa L pb L pc L pd L pe L pf L)
1028 right-props = '(front-sticky (p2 p3 p6 p7 pa pb pe pf)
1029 rear-nonsticky (p1 p2 p5 p6 p9 pa pd pe)
1030 p0 R p1 R p2 R p3 R p4 R p5 R p6 R p7 R
1031 p8 R p9 R pa R pb R pc R pd R pe R pf R)
1033 We inherit from whoever has a sticky side facing us. If both sides
1034 do (cases 2, 3, E, and F), then we inherit from whichever side has a
1035 non-nil value for the current property. If both sides do, then we take
1036 from the left.
1038 When we inherit a property, we get its stickiness as well as its value.
1039 So, when we merge the above two lists, we expect to get this:
1041 result = '(front-sticky (p6 p7 pa pb pc pd pe pf)
1042 rear-nonsticky (p6 pa)
1043 p0 L p1 L p2 L p3 L p6 R p7 R
1044 pa R pb R pc L pd L pe L pf L)
1046 The optimizable special cases are:
1047 left rear-nonsticky = nil, right front-sticky = nil (inherit left)
1048 left rear-nonsticky = t, right front-sticky = t (inherit right)
1049 left rear-nonsticky = t, right front-sticky = nil (inherit none)
1052 Lisp_Object
1053 merge_properties_sticky (pleft, pright)
1054 Lisp_Object pleft, pright;
1056 register Lisp_Object props, front, rear;
1057 Lisp_Object lfront, lrear, rfront, rrear;
1058 register Lisp_Object tail1, tail2, sym, lval, rval, cat;
1059 int use_left, use_right;
1060 int lpresent;
1062 props = Qnil;
1063 front = Qnil;
1064 rear = Qnil;
1065 lfront = textget (pleft, Qfront_sticky);
1066 lrear = textget (pleft, Qrear_nonsticky);
1067 rfront = textget (pright, Qfront_sticky);
1068 rrear = textget (pright, Qrear_nonsticky);
1070 /* Go through each element of PRIGHT. */
1071 for (tail1 = pright; CONSP (tail1); tail1 = Fcdr (Fcdr (tail1)))
1073 Lisp_Object tmp;
1075 sym = Fcar (tail1);
1077 /* Sticky properties get special treatment. */
1078 if (EQ (sym, Qrear_nonsticky) || EQ (sym, Qfront_sticky))
1079 continue;
1081 rval = Fcar (Fcdr (tail1));
1082 for (tail2 = pleft; CONSP (tail2); tail2 = Fcdr (Fcdr (tail2)))
1083 if (EQ (sym, Fcar (tail2)))
1084 break;
1086 /* Indicate whether the property is explicitly defined on the left.
1087 (We know it is defined explicitly on the right
1088 because otherwise we don't get here.) */
1089 lpresent = ! NILP (tail2);
1090 lval = (NILP (tail2) ? Qnil : Fcar (Fcdr (tail2)));
1092 /* Even if lrear or rfront say nothing about the stickiness of
1093 SYM, Vtext_property_default_nonsticky may give default
1094 stickiness to SYM. */
1095 tmp = Fassq (sym, Vtext_property_default_nonsticky);
1096 use_left = (lpresent
1097 && ! (TMEM (sym, lrear)
1098 || CONSP (tmp) && ! NILP (XCDR (tmp))));
1099 use_right = (TMEM (sym, rfront)
1100 || (CONSP (tmp) && NILP (XCDR (tmp))));
1101 if (use_left && use_right)
1103 if (NILP (lval))
1104 use_left = 0;
1105 else if (NILP (rval))
1106 use_right = 0;
1108 if (use_left)
1110 /* We build props as (value sym ...) rather than (sym value ...)
1111 because we plan to nreverse it when we're done. */
1112 props = Fcons (lval, Fcons (sym, props));
1113 if (TMEM (sym, lfront))
1114 front = Fcons (sym, front);
1115 if (TMEM (sym, lrear))
1116 rear = Fcons (sym, rear);
1118 else if (use_right)
1120 props = Fcons (rval, Fcons (sym, props));
1121 if (TMEM (sym, rfront))
1122 front = Fcons (sym, front);
1123 if (TMEM (sym, rrear))
1124 rear = Fcons (sym, rear);
1128 /* Now go through each element of PLEFT. */
1129 for (tail2 = pleft; CONSP (tail2); tail2 = Fcdr (Fcdr (tail2)))
1131 Lisp_Object tmp;
1133 sym = Fcar (tail2);
1135 /* Sticky properties get special treatment. */
1136 if (EQ (sym, Qrear_nonsticky) || EQ (sym, Qfront_sticky))
1137 continue;
1139 /* If sym is in PRIGHT, we've already considered it. */
1140 for (tail1 = pright; CONSP (tail1); tail1 = Fcdr (Fcdr (tail1)))
1141 if (EQ (sym, Fcar (tail1)))
1142 break;
1143 if (! NILP (tail1))
1144 continue;
1146 lval = Fcar (Fcdr (tail2));
1148 /* Even if lrear or rfront say nothing about the stickiness of
1149 SYM, Vtext_property_default_nonsticky may give default
1150 stickiness to SYM. */
1151 tmp = Fassq (sym, Vtext_property_default_nonsticky);
1153 /* Since rval is known to be nil in this loop, the test simplifies. */
1154 if (! (TMEM (sym, lrear) || (CONSP (tmp) && ! NILP (XCDR (tmp)))))
1156 props = Fcons (lval, Fcons (sym, props));
1157 if (TMEM (sym, lfront))
1158 front = Fcons (sym, front);
1160 else if (TMEM (sym, rfront) || (CONSP (tmp) && NILP (XCDR (tmp))))
1162 /* The value is nil, but we still inherit the stickiness
1163 from the right. */
1164 front = Fcons (sym, front);
1165 if (TMEM (sym, rrear))
1166 rear = Fcons (sym, rear);
1169 props = Fnreverse (props);
1170 if (! NILP (rear))
1171 props = Fcons (Qrear_nonsticky, Fcons (Fnreverse (rear), props));
1173 cat = textget (props, Qcategory);
1174 if (! NILP (front)
1176 /* If we have inherited a front-stick category property that is t,
1177 we don't need to set up a detailed one. */
1178 ! (! NILP (cat) && SYMBOLP (cat)
1179 && EQ (Fget (cat, Qfront_sticky), Qt)))
1180 props = Fcons (Qfront_sticky, Fcons (Fnreverse (front), props));
1181 return props;
1185 /* Delete an node I from its interval tree by merging its subtrees
1186 into one subtree which is then returned. Caller is responsible for
1187 storing the resulting subtree into its parent. */
1189 static INTERVAL
1190 delete_node (i)
1191 register INTERVAL i;
1193 register INTERVAL migrate, this;
1194 register int migrate_amt;
1196 if (NULL_INTERVAL_P (i->left))
1197 return i->right;
1198 if (NULL_INTERVAL_P (i->right))
1199 return i->left;
1201 migrate = i->left;
1202 migrate_amt = i->left->total_length;
1203 this = i->right;
1204 this->total_length += migrate_amt;
1205 while (! NULL_INTERVAL_P (this->left))
1207 this = this->left;
1208 this->total_length += migrate_amt;
1210 this->left = migrate;
1211 migrate->parent = this;
1213 return i->right;
1216 /* Delete interval I from its tree by calling `delete_node'
1217 and properly connecting the resultant subtree.
1219 I is presumed to be empty; that is, no adjustments are made
1220 for the length of I. */
1222 void
1223 delete_interval (i)
1224 register INTERVAL i;
1226 register INTERVAL parent;
1227 int amt = LENGTH (i);
1229 if (amt > 0) /* Only used on zero-length intervals now. */
1230 abort ();
1232 if (ROOT_INTERVAL_P (i))
1234 Lisp_Object owner;
1235 XSETFASTINT (owner, (EMACS_INT) i->parent);
1236 parent = delete_node (i);
1237 if (! NULL_INTERVAL_P (parent))
1238 parent->parent = (INTERVAL) XFASTINT (owner);
1240 if (BUFFERP (owner))
1241 BUF_INTERVALS (XBUFFER (owner)) = parent;
1242 else if (STRINGP (owner))
1243 XSTRING (owner)->intervals = parent;
1244 else
1245 abort ();
1247 return;
1250 parent = i->parent;
1251 if (AM_LEFT_CHILD (i))
1253 parent->left = delete_node (i);
1254 if (! NULL_INTERVAL_P (parent->left))
1255 parent->left->parent = parent;
1257 else
1259 parent->right = delete_node (i);
1260 if (! NULL_INTERVAL_P (parent->right))
1261 parent->right->parent = parent;
1265 /* Find the interval in TREE corresponding to the relative position
1266 FROM and delete as much as possible of AMOUNT from that interval.
1267 Return the amount actually deleted, and if the interval was
1268 zeroed-out, delete that interval node from the tree.
1270 Note that FROM is actually origin zero, aka relative to the
1271 leftmost edge of tree. This is appropriate since we call ourselves
1272 recursively on subtrees.
1274 Do this by recursing down TREE to the interval in question, and
1275 deleting the appropriate amount of text. */
1277 static int
1278 interval_deletion_adjustment (tree, from, amount)
1279 register INTERVAL tree;
1280 register int from, amount;
1282 register int relative_position = from;
1284 if (NULL_INTERVAL_P (tree))
1285 return 0;
1287 /* Left branch */
1288 if (relative_position < LEFT_TOTAL_LENGTH (tree))
1290 int subtract = interval_deletion_adjustment (tree->left,
1291 relative_position,
1292 amount);
1293 tree->total_length -= subtract;
1294 return subtract;
1296 /* Right branch */
1297 else if (relative_position >= (TOTAL_LENGTH (tree)
1298 - RIGHT_TOTAL_LENGTH (tree)))
1300 int subtract;
1302 relative_position -= (tree->total_length
1303 - RIGHT_TOTAL_LENGTH (tree));
1304 subtract = interval_deletion_adjustment (tree->right,
1305 relative_position,
1306 amount);
1307 tree->total_length -= subtract;
1308 return subtract;
1310 /* Here -- this node. */
1311 else
1313 /* How much can we delete from this interval? */
1314 int my_amount = ((tree->total_length
1315 - RIGHT_TOTAL_LENGTH (tree))
1316 - relative_position);
1318 if (amount > my_amount)
1319 amount = my_amount;
1321 tree->total_length -= amount;
1322 if (LENGTH (tree) == 0)
1323 delete_interval (tree);
1325 return amount;
1328 /* Never reach here. */
1331 /* Effect the adjustments necessary to the interval tree of BUFFER to
1332 correspond to the deletion of LENGTH characters from that buffer
1333 text. The deletion is effected at position START (which is a
1334 buffer position, i.e. origin 1). */
1336 static void
1337 adjust_intervals_for_deletion (buffer, start, length)
1338 struct buffer *buffer;
1339 int start, length;
1341 register int left_to_delete = length;
1342 register INTERVAL tree = BUF_INTERVALS (buffer);
1343 Lisp_Object parent;
1344 int offset;
1346 XSETFASTINT (parent, (EMACS_INT) tree->parent);
1347 offset = (BUFFERP (parent) ? BUF_BEG (XBUFFER (parent)) : 0);
1349 if (NULL_INTERVAL_P (tree))
1350 return;
1352 if (start > offset + TOTAL_LENGTH (tree)
1353 || start + length > offset + TOTAL_LENGTH (tree))
1354 abort ();
1356 if (length == TOTAL_LENGTH (tree))
1358 BUF_INTERVALS (buffer) = NULL_INTERVAL;
1359 return;
1362 if (ONLY_INTERVAL_P (tree))
1364 tree->total_length -= length;
1365 return;
1368 if (start > offset + TOTAL_LENGTH (tree))
1369 start = offset + TOTAL_LENGTH (tree);
1370 while (left_to_delete > 0)
1372 left_to_delete -= interval_deletion_adjustment (tree, start - offset,
1373 left_to_delete);
1374 tree = BUF_INTERVALS (buffer);
1375 if (left_to_delete == tree->total_length)
1377 BUF_INTERVALS (buffer) = NULL_INTERVAL;
1378 return;
1383 /* Make the adjustments necessary to the interval tree of BUFFER to
1384 represent an addition or deletion of LENGTH characters starting
1385 at position START. Addition or deletion is indicated by the sign
1386 of LENGTH. */
1388 INLINE void
1389 offset_intervals (buffer, start, length)
1390 struct buffer *buffer;
1391 int start, length;
1393 if (NULL_INTERVAL_P (BUF_INTERVALS (buffer)) || length == 0)
1394 return;
1396 if (length > 0)
1397 adjust_intervals_for_insertion (BUF_INTERVALS (buffer), start, length);
1398 else
1399 adjust_intervals_for_deletion (buffer, start, -length);
1402 /* Merge interval I with its lexicographic successor. The resulting
1403 interval is returned, and has the properties of the original
1404 successor. The properties of I are lost. I is removed from the
1405 interval tree.
1407 IMPORTANT:
1408 The caller must verify that this is not the last (rightmost)
1409 interval. */
1411 INTERVAL
1412 merge_interval_right (i)
1413 register INTERVAL i;
1415 register int absorb = LENGTH (i);
1416 register INTERVAL successor;
1418 /* Zero out this interval. */
1419 i->total_length -= absorb;
1421 /* Find the succeeding interval. */
1422 if (! NULL_RIGHT_CHILD (i)) /* It's below us. Add absorb
1423 as we descend. */
1425 successor = i->right;
1426 while (! NULL_LEFT_CHILD (successor))
1428 successor->total_length += absorb;
1429 successor = successor->left;
1432 successor->total_length += absorb;
1433 delete_interval (i);
1434 return successor;
1437 successor = i;
1438 while (! NULL_PARENT (successor)) /* It's above us. Subtract as
1439 we ascend. */
1441 if (AM_LEFT_CHILD (successor))
1443 successor = successor->parent;
1444 delete_interval (i);
1445 return successor;
1448 successor = successor->parent;
1449 successor->total_length -= absorb;
1452 /* This must be the rightmost or last interval and cannot
1453 be merged right. The caller should have known. */
1454 abort ();
1457 /* Merge interval I with its lexicographic predecessor. The resulting
1458 interval is returned, and has the properties of the original predecessor.
1459 The properties of I are lost. Interval node I is removed from the tree.
1461 IMPORTANT:
1462 The caller must verify that this is not the first (leftmost) interval. */
1464 INTERVAL
1465 merge_interval_left (i)
1466 register INTERVAL i;
1468 register int absorb = LENGTH (i);
1469 register INTERVAL predecessor;
1471 /* Zero out this interval. */
1472 i->total_length -= absorb;
1474 /* Find the preceding interval. */
1475 if (! NULL_LEFT_CHILD (i)) /* It's below us. Go down,
1476 adding ABSORB as we go. */
1478 predecessor = i->left;
1479 while (! NULL_RIGHT_CHILD (predecessor))
1481 predecessor->total_length += absorb;
1482 predecessor = predecessor->right;
1485 predecessor->total_length += absorb;
1486 delete_interval (i);
1487 return predecessor;
1490 predecessor = i;
1491 while (! NULL_PARENT (predecessor)) /* It's above us. Go up,
1492 subtracting ABSORB. */
1494 if (AM_RIGHT_CHILD (predecessor))
1496 predecessor = predecessor->parent;
1497 delete_interval (i);
1498 return predecessor;
1501 predecessor = predecessor->parent;
1502 predecessor->total_length -= absorb;
1505 /* This must be the leftmost or first interval and cannot
1506 be merged left. The caller should have known. */
1507 abort ();
1510 /* Make an exact copy of interval tree SOURCE which descends from
1511 PARENT. This is done by recursing through SOURCE, copying
1512 the current interval and its properties, and then adjusting
1513 the pointers of the copy. */
1515 static INTERVAL
1516 reproduce_tree (source, parent)
1517 INTERVAL source, parent;
1519 register INTERVAL t = make_interval ();
1521 bcopy (source, t, INTERVAL_SIZE);
1522 copy_properties (source, t);
1523 t->parent = parent;
1524 if (! NULL_LEFT_CHILD (source))
1525 t->left = reproduce_tree (source->left, t);
1526 if (! NULL_RIGHT_CHILD (source))
1527 t->right = reproduce_tree (source->right, t);
1529 return t;
1532 #if 0
1533 /* Nobody calls this. Perhaps it's a vestige of an earlier design. */
1535 /* Make a new interval of length LENGTH starting at START in the
1536 group of intervals INTERVALS, which is actually an interval tree.
1537 Returns the new interval.
1539 Generate an error if the new positions would overlap an existing
1540 interval. */
1542 static INTERVAL
1543 make_new_interval (intervals, start, length)
1544 INTERVAL intervals;
1545 int start, length;
1547 INTERVAL slot;
1549 slot = find_interval (intervals, start);
1550 if (start + length > slot->position + LENGTH (slot))
1551 error ("Interval would overlap");
1553 if (start == slot->position && length == LENGTH (slot))
1554 return slot;
1556 if (slot->position == start)
1558 /* New right node. */
1559 split_interval_right (slot, length);
1560 return slot;
1563 if (slot->position + LENGTH (slot) == start + length)
1565 /* New left node. */
1566 split_interval_left (slot, LENGTH (slot) - length);
1567 return slot;
1570 /* Convert interval SLOT into three intervals. */
1571 split_interval_left (slot, start - slot->position);
1572 split_interval_right (slot, length);
1573 return slot;
1575 #endif
1577 /* Insert the intervals of SOURCE into BUFFER at POSITION.
1578 LENGTH is the length of the text in SOURCE.
1580 The `position' field of the SOURCE intervals is assumed to be
1581 consistent with its parent; therefore, SOURCE must be an
1582 interval tree made with copy_interval or must be the whole
1583 tree of a buffer or a string.
1585 This is used in insdel.c when inserting Lisp_Strings into the
1586 buffer. The text corresponding to SOURCE is already in the buffer
1587 when this is called. The intervals of new tree are a copy of those
1588 belonging to the string being inserted; intervals are never
1589 shared.
1591 If the inserted text had no intervals associated, and we don't
1592 want to inherit the surrounding text's properties, this function
1593 simply returns -- offset_intervals should handle placing the
1594 text in the correct interval, depending on the sticky bits.
1596 If the inserted text had properties (intervals), then there are two
1597 cases -- either insertion happened in the middle of some interval,
1598 or between two intervals.
1600 If the text goes into the middle of an interval, then new
1601 intervals are created in the middle with only the properties of
1602 the new text, *unless* the macro MERGE_INSERTIONS is true, in
1603 which case the new text has the union of its properties and those
1604 of the text into which it was inserted.
1606 If the text goes between two intervals, then if neither interval
1607 had its appropriate sticky property set (front_sticky, rear_sticky),
1608 the new text has only its properties. If one of the sticky properties
1609 is set, then the new text "sticks" to that region and its properties
1610 depend on merging as above. If both the preceding and succeeding
1611 intervals to the new text are "sticky", then the new text retains
1612 only its properties, as if neither sticky property were set. Perhaps
1613 we should consider merging all three sets of properties onto the new
1614 text... */
1616 void
1617 graft_intervals_into_buffer (source, position, length, buffer, inherit)
1618 INTERVAL source;
1619 int position, length;
1620 struct buffer *buffer;
1621 int inherit;
1623 register INTERVAL under, over, this, prev;
1624 register INTERVAL tree;
1625 int middle;
1627 tree = BUF_INTERVALS (buffer);
1629 /* If the new text has no properties, it becomes part of whatever
1630 interval it was inserted into. */
1631 if (NULL_INTERVAL_P (source))
1633 Lisp_Object buf;
1634 if (!inherit && ! NULL_INTERVAL_P (tree))
1636 int saved_inhibit_modification_hooks = inhibit_modification_hooks;
1637 XSETBUFFER (buf, buffer);
1638 inhibit_modification_hooks = 1;
1639 Fset_text_properties (make_number (position),
1640 make_number (position + length),
1641 Qnil, buf);
1642 inhibit_modification_hooks = saved_inhibit_modification_hooks;
1644 if (! NULL_INTERVAL_P (BUF_INTERVALS (buffer)))
1645 BUF_INTERVALS (buffer) = balance_an_interval (BUF_INTERVALS (buffer));
1646 return;
1649 if (NULL_INTERVAL_P (tree))
1651 /* The inserted text constitutes the whole buffer, so
1652 simply copy over the interval structure. */
1653 if ((BUF_Z (buffer) - BUF_BEG (buffer)) == TOTAL_LENGTH (source))
1655 Lisp_Object buf;
1656 XSETBUFFER (buf, buffer);
1657 BUF_INTERVALS (buffer) = reproduce_tree (source, buf);
1658 BUF_INTERVALS (buffer)->position = 1;
1660 /* Explicitly free the old tree here? */
1662 return;
1665 /* Create an interval tree in which to place a copy
1666 of the intervals of the inserted string. */
1668 Lisp_Object buf;
1669 XSETBUFFER (buf, buffer);
1670 tree = create_root_interval (buf);
1673 else if (TOTAL_LENGTH (tree) == TOTAL_LENGTH (source))
1674 /* If the buffer contains only the new string, but
1675 there was already some interval tree there, then it may be
1676 some zero length intervals. Eventually, do something clever
1677 about inserting properly. For now, just waste the old intervals. */
1679 BUF_INTERVALS (buffer) = reproduce_tree (source, tree->parent);
1680 BUF_INTERVALS (buffer)->position = 1;
1681 /* Explicitly free the old tree here. */
1683 return;
1685 /* Paranoia -- the text has already been added, so this buffer
1686 should be of non-zero length. */
1687 else if (TOTAL_LENGTH (tree) == 0)
1688 abort ();
1690 this = under = find_interval (tree, position);
1691 if (NULL_INTERVAL_P (under)) /* Paranoia */
1692 abort ();
1693 over = find_interval (source, interval_start_pos (source));
1695 /* Here for insertion in the middle of an interval.
1696 Split off an equivalent interval to the right,
1697 then don't bother with it any more. */
1699 if (position > under->position)
1701 INTERVAL end_unchanged
1702 = split_interval_left (this, position - under->position);
1703 copy_properties (under, end_unchanged);
1704 under->position = position;
1705 #if 0
1706 /* This code has no effect. */
1707 prev = 0;
1708 middle = 1;
1709 #endif /* 0 */
1711 else
1713 /* This call may have some effect because previous_interval may
1714 update `position' fields of intervals. Thus, don't ignore it
1715 for the moment. Someone please tell me the truth (K.Handa). */
1716 prev = previous_interval (under);
1717 #if 0
1718 /* But, this code surely has no effect. And, anyway,
1719 END_NONSTICKY_P is unreliable now. */
1720 if (prev && !END_NONSTICKY_P (prev))
1721 prev = 0;
1722 #endif /* 0 */
1725 /* Insertion is now at beginning of UNDER. */
1727 /* The inserted text "sticks" to the interval `under',
1728 which means it gets those properties.
1729 The properties of under are the result of
1730 adjust_intervals_for_insertion, so stickiness has
1731 already been taken care of. */
1733 while (! NULL_INTERVAL_P (over))
1735 if (LENGTH (over) < LENGTH (under))
1737 this = split_interval_left (under, LENGTH (over));
1738 copy_properties (under, this);
1740 else
1741 this = under;
1742 copy_properties (over, this);
1743 if (inherit)
1744 merge_properties (over, this);
1745 else
1746 copy_properties (over, this);
1747 over = next_interval (over);
1750 if (! NULL_INTERVAL_P (BUF_INTERVALS (buffer)))
1751 BUF_INTERVALS (buffer) = balance_an_interval (BUF_INTERVALS (buffer));
1752 return;
1755 /* Get the value of property PROP from PLIST,
1756 which is the plist of an interval.
1757 We check for direct properties, for categories with property PROP,
1758 and for PROP appearing on the default-text-properties list. */
1760 Lisp_Object
1761 textget (plist, prop)
1762 Lisp_Object plist;
1763 register Lisp_Object prop;
1765 register Lisp_Object tail, fallback;
1766 fallback = Qnil;
1768 for (tail = plist; !NILP (tail); tail = Fcdr (Fcdr (tail)))
1770 register Lisp_Object tem;
1771 tem = Fcar (tail);
1772 if (EQ (prop, tem))
1773 return Fcar (Fcdr (tail));
1774 if (EQ (tem, Qcategory))
1776 tem = Fcar (Fcdr (tail));
1777 if (SYMBOLP (tem))
1778 fallback = Fget (tem, prop);
1782 if (! NILP (fallback))
1783 return fallback;
1784 if (CONSP (Vdefault_text_properties))
1785 return Fplist_get (Vdefault_text_properties, prop);
1786 return Qnil;
1790 /* Set point "temporarily", without checking any text properties. */
1792 INLINE void
1793 temp_set_point (buffer, charpos)
1794 struct buffer *buffer;
1795 int charpos;
1797 temp_set_point_both (buffer, charpos,
1798 buf_charpos_to_bytepos (buffer, charpos));
1801 /* Set point in BUFFER "temporarily" to CHARPOS, which corresponds to
1802 byte position BYTEPOS. */
1804 INLINE void
1805 temp_set_point_both (buffer, charpos, bytepos)
1806 int charpos, bytepos;
1807 struct buffer *buffer;
1809 /* In a single-byte buffer, the two positions must be equal. */
1810 if (BUF_ZV (buffer) == BUF_ZV_BYTE (buffer)
1811 && charpos != bytepos)
1812 abort ();
1814 if (charpos > bytepos)
1815 abort ();
1817 if (charpos > BUF_ZV (buffer) || charpos < BUF_BEGV (buffer))
1818 abort ();
1820 BUF_PT_BYTE (buffer) = bytepos;
1821 BUF_PT (buffer) = charpos;
1824 /* Set point in BUFFER to CHARPOS. If the target position is
1825 before an intangible character, move to an ok place. */
1827 void
1828 set_point (buffer, charpos)
1829 register struct buffer *buffer;
1830 register int charpos;
1832 set_point_both (buffer, charpos, buf_charpos_to_bytepos (buffer, charpos));
1835 /* Set point in BUFFER to CHARPOS, which corresponds to byte
1836 position BYTEPOS. If the target position is
1837 before an intangible character, move to an ok place. */
1839 void
1840 set_point_both (buffer, charpos, bytepos)
1841 register struct buffer *buffer;
1842 register int charpos, bytepos;
1844 register INTERVAL to, from, toprev, fromprev;
1845 int buffer_point;
1846 int old_position = BUF_PT (buffer);
1847 int backwards = (charpos < old_position ? 1 : 0);
1848 int have_overlays;
1849 int original_position;
1851 buffer->point_before_scroll = Qnil;
1853 if (charpos == BUF_PT (buffer))
1854 return;
1856 /* In a single-byte buffer, the two positions must be equal. */
1857 if (BUF_ZV (buffer) == BUF_ZV_BYTE (buffer)
1858 && charpos != bytepos)
1859 abort ();
1861 /* Check this now, before checking if the buffer has any intervals.
1862 That way, we can catch conditions which break this sanity check
1863 whether or not there are intervals in the buffer. */
1864 if (charpos > BUF_ZV (buffer) || charpos < BUF_BEGV (buffer))
1865 abort ();
1867 have_overlays = (! NILP (buffer->overlays_before)
1868 || ! NILP (buffer->overlays_after));
1870 /* If we have no text properties and overlays,
1871 then we can do it quickly. */
1872 if (NULL_INTERVAL_P (BUF_INTERVALS (buffer)) && ! have_overlays)
1874 temp_set_point_both (buffer, charpos, bytepos);
1875 return;
1878 /* Set TO to the interval containing the char after CHARPOS,
1879 and TOPREV to the interval containing the char before CHARPOS.
1880 Either one may be null. They may be equal. */
1881 to = find_interval (BUF_INTERVALS (buffer), charpos);
1882 if (charpos == BUF_BEGV (buffer))
1883 toprev = 0;
1884 else if (to && to->position == charpos)
1885 toprev = previous_interval (to);
1886 else
1887 toprev = to;
1889 buffer_point = (BUF_PT (buffer) == BUF_ZV (buffer)
1890 ? BUF_ZV (buffer) - 1
1891 : BUF_PT (buffer));
1893 /* Set FROM to the interval containing the char after PT,
1894 and FROMPREV to the interval containing the char before PT.
1895 Either one may be null. They may be equal. */
1896 /* We could cache this and save time. */
1897 from = find_interval (BUF_INTERVALS (buffer), buffer_point);
1898 if (buffer_point == BUF_BEGV (buffer))
1899 fromprev = 0;
1900 else if (from && from->position == BUF_PT (buffer))
1901 fromprev = previous_interval (from);
1902 else if (buffer_point != BUF_PT (buffer))
1903 fromprev = from, from = 0;
1904 else
1905 fromprev = from;
1907 /* Moving within an interval. */
1908 if (to == from && toprev == fromprev && INTERVAL_VISIBLE_P (to)
1909 && ! have_overlays)
1911 temp_set_point_both (buffer, charpos, bytepos);
1912 return;
1915 original_position = charpos;
1917 /* If the new position is between two intangible characters
1918 with the same intangible property value,
1919 move forward or backward until a change in that property. */
1920 if (NILP (Vinhibit_point_motion_hooks)
1921 && ((! NULL_INTERVAL_P (to) && ! NULL_INTERVAL_P (toprev))
1922 || have_overlays)
1923 /* Intangibility never stops us from positioning at the beginning
1924 or end of the buffer, so don't bother checking in that case. */
1925 && charpos != BEGV && charpos != ZV)
1927 Lisp_Object intangible_propval;
1928 Lisp_Object pos;
1930 XSETINT (pos, charpos);
1932 if (backwards)
1934 intangible_propval = Fget_char_property (make_number (charpos),
1935 Qintangible, Qnil);
1937 /* If following char is intangible,
1938 skip back over all chars with matching intangible property. */
1939 if (! NILP (intangible_propval))
1940 while (XINT (pos) > BUF_BEGV (buffer)
1941 && EQ (Fget_char_property (make_number (XINT (pos) - 1),
1942 Qintangible, Qnil),
1943 intangible_propval))
1944 pos = Fprevious_char_property_change (pos, Qnil);
1946 else
1948 intangible_propval = Fget_char_property (make_number (charpos - 1),
1949 Qintangible, Qnil);
1951 /* If following char is intangible,
1952 skip forward over all chars with matching intangible property. */
1953 if (! NILP (intangible_propval))
1954 while (XINT (pos) < BUF_ZV (buffer)
1955 && EQ (Fget_char_property (pos, Qintangible, Qnil),
1956 intangible_propval))
1957 pos = Fnext_char_property_change (pos, Qnil);
1961 charpos = XINT (pos);
1962 bytepos = buf_charpos_to_bytepos (buffer, charpos);
1965 if (charpos != original_position)
1967 /* Set TO to the interval containing the char after CHARPOS,
1968 and TOPREV to the interval containing the char before CHARPOS.
1969 Either one may be null. They may be equal. */
1970 to = find_interval (BUF_INTERVALS (buffer), charpos);
1971 if (charpos == BUF_BEGV (buffer))
1972 toprev = 0;
1973 else if (to && to->position == charpos)
1974 toprev = previous_interval (to);
1975 else
1976 toprev = to;
1979 /* Here TO is the interval after the stopping point
1980 and TOPREV is the interval before the stopping point.
1981 One or the other may be null. */
1983 temp_set_point_both (buffer, charpos, bytepos);
1985 /* We run point-left and point-entered hooks here, iff the
1986 two intervals are not equivalent. These hooks take
1987 (old_point, new_point) as arguments. */
1988 if (NILP (Vinhibit_point_motion_hooks)
1989 && (! intervals_equal (from, to)
1990 || ! intervals_equal (fromprev, toprev)))
1992 Lisp_Object leave_after, leave_before, enter_after, enter_before;
1994 if (fromprev)
1995 leave_after = textget (fromprev->plist, Qpoint_left);
1996 else
1997 leave_after = Qnil;
1998 if (from)
1999 leave_before = textget (from->plist, Qpoint_left);
2000 else
2001 leave_before = Qnil;
2003 if (toprev)
2004 enter_after = textget (toprev->plist, Qpoint_entered);
2005 else
2006 enter_after = Qnil;
2007 if (to)
2008 enter_before = textget (to->plist, Qpoint_entered);
2009 else
2010 enter_before = Qnil;
2012 if (! EQ (leave_before, enter_before) && !NILP (leave_before))
2013 call2 (leave_before, make_number (old_position),
2014 make_number (charpos));
2015 if (! EQ (leave_after, enter_after) && !NILP (leave_after))
2016 call2 (leave_after, make_number (old_position),
2017 make_number (charpos));
2019 if (! EQ (enter_before, leave_before) && !NILP (enter_before))
2020 call2 (enter_before, make_number (old_position),
2021 make_number (charpos));
2022 if (! EQ (enter_after, leave_after) && !NILP (enter_after))
2023 call2 (enter_after, make_number (old_position),
2024 make_number (charpos));
2028 /* Move point to POSITION, unless POSITION is inside an intangible
2029 segment that reaches all the way to point. */
2031 void
2032 move_if_not_intangible (position)
2033 int position;
2035 Lisp_Object pos;
2036 Lisp_Object intangible_propval;
2038 XSETINT (pos, position);
2040 if (! NILP (Vinhibit_point_motion_hooks))
2041 /* If intangible is inhibited, always move point to POSITION. */
2043 else if (PT < position && XINT (pos) < ZV)
2045 /* We want to move forward, so check the text before POSITION. */
2047 intangible_propval = Fget_char_property (pos,
2048 Qintangible, Qnil);
2050 /* If following char is intangible,
2051 skip back over all chars with matching intangible property. */
2052 if (! NILP (intangible_propval))
2053 while (XINT (pos) > BEGV
2054 && EQ (Fget_char_property (make_number (XINT (pos) - 1),
2055 Qintangible, Qnil),
2056 intangible_propval))
2057 pos = Fprevious_char_property_change (pos, Qnil);
2059 else if (XINT (pos) > BEGV)
2061 /* We want to move backward, so check the text after POSITION. */
2063 intangible_propval = Fget_char_property (make_number (XINT (pos) - 1),
2064 Qintangible, Qnil);
2066 /* If following char is intangible,
2067 skip forward over all chars with matching intangible property. */
2068 if (! NILP (intangible_propval))
2069 while (XINT (pos) < ZV
2070 && EQ (Fget_char_property (pos, Qintangible, Qnil),
2071 intangible_propval))
2072 pos = Fnext_char_property_change (pos, Qnil);
2076 /* If the whole stretch between PT and POSITION isn't intangible,
2077 try moving to POSITION (which means we actually move farther
2078 if POSITION is inside of intangible text). */
2080 if (XINT (pos) != PT)
2081 SET_PT (position);
2084 /* If text at position POS has property PROP, set *VAL to the property
2085 value, *START and *END to the beginning and end of a region that
2086 has the same property, and return 1. Otherwise return 0.
2088 OBJECT is the string or buffer to look for the property in;
2089 nil means the current buffer. */
2092 get_property_and_range (pos, prop, val, start, end, object)
2093 int pos;
2094 Lisp_Object prop, *val;
2095 int *start, *end;
2096 Lisp_Object object;
2098 INTERVAL i, prev, next;
2100 if (NILP (object))
2101 i = find_interval (BUF_INTERVALS (current_buffer), pos);
2102 else if (BUFFERP (object))
2103 i = find_interval (BUF_INTERVALS (XBUFFER (object)), pos);
2104 else if (STRINGP (object))
2105 i = find_interval (XSTRING (object)->intervals, pos);
2106 else
2107 abort ();
2109 if (NULL_INTERVAL_P (i) || (i->position + LENGTH (i) <= pos))
2110 return 0;
2111 *val = textget (i->plist, prop);
2112 if (NILP (*val))
2113 return 0;
2115 next = i; /* remember it in advance */
2116 prev = previous_interval (i);
2117 while (! NULL_INTERVAL_P (prev)
2118 && EQ (*val, textget (prev->plist, prop)))
2119 i = prev, prev = previous_interval (prev);
2120 *start = i->position;
2122 next = next_interval (i);
2123 while (! NULL_INTERVAL_P (next)
2124 && EQ (*val, textget (next->plist, prop)))
2125 i = next, next = next_interval (next);
2126 *end = i->position + LENGTH (i);
2128 return 1;
2131 /* Return the proper local map for position POSITION in BUFFER.
2132 Use the map specified by the local-map property, if any.
2133 Otherwise, use BUFFER's local map. */
2135 Lisp_Object
2136 get_local_map (position, buffer)
2137 register int position;
2138 register struct buffer *buffer;
2140 Lisp_Object prop, tem, lispy_position, lispy_buffer;
2141 int old_begv, old_zv, old_begv_byte, old_zv_byte;
2143 /* Perhaps we should just change `position' to the limit. */
2144 if (position > BUF_Z (buffer) || position < BUF_BEG (buffer))
2145 abort ();
2147 /* Ignore narrowing, so that a local map continues to be valid even if
2148 the visible region contains no characters and hence no properties. */
2149 old_begv = BUF_BEGV (buffer);
2150 old_zv = BUF_ZV (buffer);
2151 old_begv_byte = BUF_BEGV_BYTE (buffer);
2152 old_zv_byte = BUF_ZV_BYTE (buffer);
2153 BUF_BEGV (buffer) = BUF_BEG (buffer);
2154 BUF_ZV (buffer) = BUF_Z (buffer);
2155 BUF_BEGV_BYTE (buffer) = BUF_BEG_BYTE (buffer);
2156 BUF_ZV_BYTE (buffer) = BUF_Z_BYTE (buffer);
2158 /* There are no properties at the end of the buffer, so in that case
2159 check for a local map on the last character of the buffer instead. */
2160 if (position == BUF_Z (buffer) && BUF_Z (buffer) > BUF_BEG (buffer))
2161 --position;
2162 XSETFASTINT (lispy_position, position);
2163 XSETBUFFER (lispy_buffer, buffer);
2164 prop = Fget_char_property (lispy_position, Qlocal_map, lispy_buffer);
2166 BUF_BEGV (buffer) = old_begv;
2167 BUF_ZV (buffer) = old_zv;
2168 BUF_BEGV_BYTE (buffer) = old_begv_byte;
2169 BUF_ZV_BYTE (buffer) = old_zv_byte;
2171 /* Use the local map only if it is valid. */
2172 /* Do allow symbols that are defined as keymaps. */
2173 if (SYMBOLP (prop) && !NILP (prop))
2174 prop = indirect_function (prop);
2175 if (!NILP (prop)
2176 && (tem = Fkeymapp (prop), !NILP (tem)))
2177 return prop;
2179 return buffer->keymap;
2182 /* Produce an interval tree reflecting the intervals in
2183 TREE from START to START + LENGTH.
2184 The new interval tree has no parent and has a starting-position of 0. */
2186 INTERVAL
2187 copy_intervals (tree, start, length)
2188 INTERVAL tree;
2189 int start, length;
2191 register INTERVAL i, new, t;
2192 register int got, prevlen;
2194 if (NULL_INTERVAL_P (tree) || length <= 0)
2195 return NULL_INTERVAL;
2197 i = find_interval (tree, start);
2198 if (NULL_INTERVAL_P (i) || LENGTH (i) == 0)
2199 abort ();
2201 /* If there is only one interval and it's the default, return nil. */
2202 if ((start - i->position + 1 + length) < LENGTH (i)
2203 && DEFAULT_INTERVAL_P (i))
2204 return NULL_INTERVAL;
2206 new = make_interval ();
2207 new->position = 0;
2208 got = (LENGTH (i) - (start - i->position));
2209 new->total_length = length;
2210 copy_properties (i, new);
2212 t = new;
2213 prevlen = got;
2214 while (got < length)
2216 i = next_interval (i);
2217 t = split_interval_right (t, prevlen);
2218 copy_properties (i, t);
2219 prevlen = LENGTH (i);
2220 got += prevlen;
2223 return balance_an_interval (new);
2226 /* Give STRING the properties of BUFFER from POSITION to LENGTH. */
2228 INLINE void
2229 copy_intervals_to_string (string, buffer, position, length)
2230 Lisp_Object string;
2231 struct buffer *buffer;
2232 int position, length;
2234 INTERVAL interval_copy = copy_intervals (BUF_INTERVALS (buffer),
2235 position, length);
2236 if (NULL_INTERVAL_P (interval_copy))
2237 return;
2239 interval_copy->parent = (INTERVAL) XFASTINT (string);
2240 XSTRING (string)->intervals = interval_copy;
2243 /* Return 1 if strings S1 and S2 have identical properties; 0 otherwise.
2244 Assume they have identical characters. */
2247 compare_string_intervals (s1, s2)
2248 Lisp_Object s1, s2;
2250 INTERVAL i1, i2;
2251 int pos = 0;
2252 int end = XSTRING (s1)->size;
2254 i1 = find_interval (XSTRING (s1)->intervals, 0);
2255 i2 = find_interval (XSTRING (s2)->intervals, 0);
2257 while (pos < end)
2259 /* Determine how far we can go before we reach the end of I1 or I2. */
2260 int len1 = (i1 != 0 ? INTERVAL_LAST_POS (i1) : end) - pos;
2261 int len2 = (i2 != 0 ? INTERVAL_LAST_POS (i2) : end) - pos;
2262 int distance = min (len1, len2);
2264 /* If we ever find a mismatch between the strings,
2265 they differ. */
2266 if (! intervals_equal (i1, i2))
2267 return 0;
2269 /* Advance POS till the end of the shorter interval,
2270 and advance one or both interval pointers for the new position. */
2271 pos += distance;
2272 if (len1 == distance)
2273 i1 = next_interval (i1);
2274 if (len2 == distance)
2275 i2 = next_interval (i2);
2277 return 1;
2280 /* Recursively adjust interval I in the current buffer
2281 for setting enable_multibyte_characters to MULTI_FLAG.
2282 The range of interval I is START ... END in characters,
2283 START_BYTE ... END_BYTE in bytes. */
2285 static void
2286 set_intervals_multibyte_1 (i, multi_flag, start, start_byte, end, end_byte)
2287 INTERVAL i;
2288 int multi_flag;
2289 int start, start_byte, end, end_byte;
2291 /* Fix the length of this interval. */
2292 if (multi_flag)
2293 i->total_length = end - start;
2294 else
2295 i->total_length = end_byte - start_byte;
2297 /* Recursively fix the length of the subintervals. */
2298 if (i->left)
2300 int left_end, left_end_byte;
2302 if (multi_flag)
2304 left_end_byte = start_byte + LEFT_TOTAL_LENGTH (i);
2305 left_end = BYTE_TO_CHAR (left_end_byte);
2307 else
2309 left_end = start + LEFT_TOTAL_LENGTH (i);
2310 left_end_byte = CHAR_TO_BYTE (left_end);
2313 set_intervals_multibyte_1 (i->left, multi_flag, start, start_byte,
2314 left_end, left_end_byte);
2316 if (i->right)
2318 int right_start_byte, right_start;
2320 if (multi_flag)
2322 right_start_byte = end_byte - RIGHT_TOTAL_LENGTH (i);
2323 right_start = BYTE_TO_CHAR (right_start_byte);
2325 else
2327 right_start = end - RIGHT_TOTAL_LENGTH (i);
2328 right_start_byte = CHAR_TO_BYTE (right_start);
2331 set_intervals_multibyte_1 (i->right, multi_flag,
2332 right_start, right_start_byte,
2333 end, end_byte);
2337 /* Update the intervals of the current buffer
2338 to fit the contents as multibyte (if MULTI_FLAG is 1)
2339 or to fit them as non-multibyte (if MULTI_FLAG is 0). */
2341 void
2342 set_intervals_multibyte (multi_flag)
2343 int multi_flag;
2345 if (BUF_INTERVALS (current_buffer))
2346 set_intervals_multibyte_1 (BUF_INTERVALS (current_buffer), multi_flag,
2347 BEG, BEG_BYTE, Z, Z_BYTE);