various fixes and gratuitous movements.
[bpt/emacs.git] / src / intervals.c
1 /* Code for doing intervals.
2 Copyright (C) 1993, 1994, 1995, 1997, 1998 Free Software Foundation, Inc.
3
4 This file is part of GNU Emacs.
5
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.
10
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.
15
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. */
20
21
22 /* NOTES:
23
24 Have to ensure that we can't put symbol nil on a plist, or some
25 functions may work incorrectly.
26
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.
29
30 Need to call *_left_hook when buffer is killed.
31
32 Scan for zero-length, or 0-length to see notes about handling
33 zero length interval-markers.
34
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.
38
39 */
40
41
42 #include <config.h>
43 #include "lisp.h"
44 #include "intervals.h"
45 #include "buffer.h"
46 #include "puresize.h"
47 #include "keyboard.h"
48
49 /* Test for membership, allowing for t (actually any non-cons) to mean the
50 universal set. */
51
52 #define TMEM(sym, set) (CONSP (set) ? ! NILP (Fmemq (sym, set)) : ! NILP (set))
53
54 #define min(x, y) ((x) < (y) ? (x) : (y))
55
56 Lisp_Object merge_properties_sticky ();
57 \f
58 /* Utility functions for intervals. */
59
60
61 /* Create the root interval of some object, a buffer or string. */
62
63 INTERVAL
64 create_root_interval (parent)
65 Lisp_Object parent;
66 {
67 INTERVAL new;
68
69 CHECK_IMPURE (parent);
70
71 new = make_interval ();
72
73 if (BUFFERP (parent))
74 {
75 new->total_length = (BUF_Z (XBUFFER (parent))
76 - BUF_BEG (XBUFFER (parent)));
77 BUF_INTERVALS (XBUFFER (parent)) = new;
78 new->position = 1;
79 }
80 else if (STRINGP (parent))
81 {
82 new->total_length = XSTRING (parent)->size;
83 XSTRING (parent)->intervals = new;
84 new->position = 0;
85 }
86
87 new->parent = (INTERVAL) XFASTINT (parent);
88
89 return new;
90 }
91
92 /* Make the interval TARGET have exactly the properties of SOURCE */
93
94 void
95 copy_properties (source, target)
96 register INTERVAL source, target;
97 {
98 if (DEFAULT_INTERVAL_P (source) && DEFAULT_INTERVAL_P (target))
99 return;
100
101 COPY_INTERVAL_CACHE (source, target);
102 target->plist = Fcopy_sequence (source->plist);
103 }
104
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. */
108
109 static void
110 merge_properties (source, target)
111 register INTERVAL source, target;
112 {
113 register Lisp_Object o, sym, val;
114
115 if (DEFAULT_INTERVAL_P (source) && DEFAULT_INTERVAL_P (target))
116 return;
117
118 MERGE_INTERVAL_CACHE (source, target);
119
120 o = source->plist;
121 while (! EQ (o, Qnil))
122 {
123 sym = Fcar (o);
124 val = Fmemq (sym, target->plist);
125
126 if (NILP (val))
127 {
128 o = Fcdr (o);
129 val = Fcar (o);
130 target->plist = Fcons (sym, Fcons (val, target->plist));
131 o = Fcdr (o);
132 }
133 else
134 o = Fcdr (Fcdr (o));
135 }
136 }
137
138 /* Return 1 if the two intervals have the same properties,
139 0 otherwise. */
140
141 int
142 intervals_equal (i0, i1)
143 INTERVAL i0, i1;
144 {
145 register Lisp_Object i0_cdr, i0_sym, i1_val;
146 register int i1_len;
147
148 if (DEFAULT_INTERVAL_P (i0) && DEFAULT_INTERVAL_P (i1))
149 return 1;
150
151 if (DEFAULT_INTERVAL_P (i0) || DEFAULT_INTERVAL_P (i1))
152 return 0;
153
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))
160 {
161 /* Lengths of the two plists were unequal. */
162 if (i1_len == 0)
163 return 0;
164
165 i0_sym = Fcar (i0_cdr);
166 i1_val = Fmemq (i0_sym, i1->plist);
167
168 /* i0 has something i1 doesn't. */
169 if (EQ (i1_val, Qnil))
170 return 0;
171
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;
176
177 i0_cdr = Fcdr (i0_cdr);
178 i1_len--;
179 }
180
181 /* Lengths of the two plists were unequal. */
182 if (i1_len > 0)
183 return 0;
184
185 return 1;
186 }
187 \f
188
189 /* Traverse an interval tree TREE, performing FUNCTION on each node.
190 Pass FUNCTION two args: an interval, and ARG. */
191
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;
198 {
199 if (NULL_INTERVAL_P (tree))
200 return;
201
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);
208 }
209 \f
210 #if 0
211
212 static int icount;
213 static int idepth;
214 static int zero_length;
215
216 /* These functions are temporary, for debugging purposes only. */
217
218 INTERVAL search_interval, found_interval;
219
220 void
221 check_for_interval (i)
222 register INTERVAL i;
223 {
224 if (i == search_interval)
225 {
226 found_interval = i;
227 icount++;
228 }
229 }
230
231 INTERVAL
232 search_for_interval (i, tree)
233 register INTERVAL i, tree;
234 {
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;
240 }
241
242 static void
243 inc_interval_count (i)
244 INTERVAL i;
245 {
246 icount++;
247 if (LENGTH (i) == 0)
248 zero_length++;
249 if (depth > idepth)
250 idepth = depth;
251 }
252
253 int
254 count_intervals (i)
255 register INTERVAL i;
256 {
257 icount = 0;
258 idepth = 0;
259 zero_length = 0;
260 traverse_intervals (i, 1, 0, &inc_interval_count, Qnil);
261
262 return icount;
263 }
264
265 static INTERVAL
266 root_interval (interval)
267 INTERVAL interval;
268 {
269 register INTERVAL i = interval;
270
271 while (! ROOT_INTERVAL_P (i))
272 i = i->parent;
273
274 return i;
275 }
276 #endif
277 \f
278 /* Assuming that a left child exists, perform the following operation:
279
280 A B
281 / \ / \
282 B => A
283 / \ / \
284 c c
285 */
286
287 static INTERVAL
288 rotate_right (interval)
289 INTERVAL interval;
290 {
291 INTERVAL i;
292 INTERVAL B = interval->left;
293 int old_total = interval->total_length;
294
295 /* Deal with any Parent of A; make it point to B. */
296 if (! ROOT_INTERVAL_P (interval))
297 {
298 if (AM_LEFT_CHILD (interval))
299 interval->parent->left = B;
300 else
301 interval->parent->right = B;
302 }
303 B->parent = interval->parent;
304
305 /* Make B the parent of A */
306 i = B->right;
307 B->right = interval;
308 interval->parent = B;
309
310 /* Make A point to c */
311 interval->left = i;
312 if (! NULL_INTERVAL_P (i))
313 i->parent = interval;
314
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);
317
318 /* B must have the same total length of A. */
319 B->total_length = old_total;
320
321 return B;
322 }
323
324 /* Assuming that a right child exists, perform the following operation:
325
326 A B
327 / \ / \
328 B => A
329 / \ / \
330 c c
331 */
332
333 static INTERVAL
334 rotate_left (interval)
335 INTERVAL interval;
336 {
337 INTERVAL i;
338 INTERVAL B = interval->right;
339 int old_total = interval->total_length;
340
341 /* Deal with any parent of A; make it point to B. */
342 if (! ROOT_INTERVAL_P (interval))
343 {
344 if (AM_LEFT_CHILD (interval))
345 interval->parent->left = B;
346 else
347 interval->parent->right = B;
348 }
349 B->parent = interval->parent;
350
351 /* Make B the parent of A */
352 i = B->left;
353 B->left = interval;
354 interval->parent = B;
355
356 /* Make A point to c */
357 interval->right = i;
358 if (! NULL_INTERVAL_P (i))
359 i->parent = interval;
360
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);
363
364 /* B must have the same total length of A. */
365 B->total_length = old_total;
366
367 return B;
368 }
369 \f
370 /* Balance an interval tree with the assumption that the subtrees
371 themselves are already balanced. */
372
373 static INTERVAL
374 balance_an_interval (i)
375 INTERVAL i;
376 {
377 register int old_diff, new_diff;
378
379 while (1)
380 {
381 old_diff = LEFT_TOTAL_LENGTH (i) - RIGHT_TOTAL_LENGTH (i);
382 if (old_diff > 0)
383 {
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);
390 }
391 else if (old_diff < 0)
392 {
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);
399 }
400 else
401 break;
402 }
403 return i;
404 }
405
406 /* Balance INTERVAL, potentially stuffing it back into its parent
407 Lisp Object. */
408
409 static INLINE INTERVAL
410 balance_possible_root_interval (interval)
411 register INTERVAL interval;
412 {
413 Lisp_Object parent;
414
415 if (interval->parent == NULL_INTERVAL)
416 return interval;
417
418 XSETFASTINT (parent, (EMACS_INT) interval->parent);
419 interval = balance_an_interval (interval);
420
421 if (BUFFERP (parent))
422 BUF_INTERVALS (XBUFFER (parent)) = interval;
423 else if (STRINGP (parent))
424 XSTRING (parent)->intervals = interval;
425
426 return interval;
427 }
428
429 /* Balance the interval tree TREE. Balancing is by weight
430 (the amount of text). */
431
432 static INTERVAL
433 balance_intervals_internal (tree)
434 register INTERVAL tree;
435 {
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);
442 }
443
444 /* Advertised interface to balance intervals. */
445
446 INTERVAL
447 balance_intervals (tree)
448 INTERVAL tree;
449 {
450 if (tree == NULL_INTERVAL)
451 return NULL_INTERVAL;
452
453 return balance_intervals_internal (tree);
454 }
455 \f
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.
460
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.
465
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. */
468
469 INTERVAL
470 split_interval_right (interval, offset)
471 INTERVAL interval;
472 int offset;
473 {
474 INTERVAL new = make_interval ();
475 int position = interval->position;
476 int new_length = LENGTH (interval) - offset;
477
478 new->position = position + offset;
479 new->parent = interval;
480
481 if (NULL_RIGHT_CHILD (interval))
482 {
483 interval->right = new;
484 new->total_length = new_length;
485 }
486 else
487 {
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);
494 }
495
496 balance_possible_root_interval (interval);
497
498 return new;
499 }
500
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.
505
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.
510
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. */
513
514 INTERVAL
515 split_interval_left (interval, offset)
516 INTERVAL interval;
517 int offset;
518 {
519 INTERVAL new = make_interval ();
520 int new_length = offset;
521
522 new->position = interval->position;
523 interval->position = interval->position + offset;
524 new->parent = interval;
525
526 if (NULL_LEFT_CHILD (interval))
527 {
528 interval->left = new;
529 new->total_length = new_length;
530 }
531 else
532 {
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);
539 }
540
541 balance_possible_root_interval (interval);
542
543 return new;
544 }
545 \f
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.
550
551 Don't use this function on an interval which is the child
552 of another interval! */
553
554 int
555 interval_start_pos (source)
556 INTERVAL source;
557 {
558 Lisp_Object parent;
559
560 if (NULL_INTERVAL_P (source))
561 return 0;
562
563 XSETFASTINT (parent, (EMACS_INT) source->parent);
564 if (BUFFERP (parent))
565 return BUF_BEG (XBUFFER (parent));
566 return 0;
567 }
568
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.
574
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. */
578
579 INTERVAL
580 find_interval (tree, position)
581 register INTERVAL tree;
582 register int position;
583 {
584 /* The distance from the left edge of the subtree at TREE
585 to POSITION. */
586 register int relative_position;
587 Lisp_Object parent;
588
589 if (NULL_INTERVAL_P (tree))
590 return NULL_INTERVAL;
591
592 XSETFASTINT (parent, (EMACS_INT) tree->parent);
593 relative_position = position;
594 if (BUFFERP (parent))
595 relative_position -= BUF_BEG (XBUFFER (parent));
596
597 if (relative_position > TOTAL_LENGTH (tree))
598 abort (); /* Paranoia */
599
600 tree = balance_possible_root_interval (tree);
601
602 while (1)
603 {
604 if (relative_position < LEFT_TOTAL_LENGTH (tree))
605 {
606 tree = tree->left;
607 }
608 else if (! NULL_RIGHT_CHILD (tree)
609 && relative_position >= (TOTAL_LENGTH (tree)
610 - RIGHT_TOTAL_LENGTH (tree)))
611 {
612 relative_position -= (TOTAL_LENGTH (tree)
613 - RIGHT_TOTAL_LENGTH (tree));
614 tree = tree->right;
615 }
616 else
617 {
618 tree->position
619 = (position - relative_position /* the left edge of *tree */
620 + LEFT_TOTAL_LENGTH (tree)); /* the left edge of this interval */
621
622 return tree;
623 }
624 }
625 }
626 \f
627 /* Find the succeeding interval (lexicographically) to INTERVAL.
628 Sets the `position' field based on that of INTERVAL (see
629 find_interval). */
630
631 INTERVAL
632 next_interval (interval)
633 register INTERVAL interval;
634 {
635 register INTERVAL i = interval;
636 register int next_position;
637
638 if (NULL_INTERVAL_P (i))
639 return NULL_INTERVAL;
640 next_position = interval->position + LENGTH (interval);
641
642 if (! NULL_RIGHT_CHILD (i))
643 {
644 i = i->right;
645 while (! NULL_LEFT_CHILD (i))
646 i = i->left;
647
648 i->position = next_position;
649 return i;
650 }
651
652 while (! NULL_PARENT (i))
653 {
654 if (AM_LEFT_CHILD (i))
655 {
656 i = i->parent;
657 i->position = next_position;
658 return i;
659 }
660
661 i = i->parent;
662 }
663
664 return NULL_INTERVAL;
665 }
666
667 /* Find the preceding interval (lexicographically) to INTERVAL.
668 Sets the `position' field based on that of INTERVAL (see
669 find_interval). */
670
671 INTERVAL
672 previous_interval (interval)
673 register INTERVAL interval;
674 {
675 register INTERVAL i;
676
677 if (NULL_INTERVAL_P (interval))
678 return NULL_INTERVAL;
679
680 if (! NULL_LEFT_CHILD (interval))
681 {
682 i = interval->left;
683 while (! NULL_RIGHT_CHILD (i))
684 i = i->right;
685
686 i->position = interval->position - LENGTH (i);
687 return i;
688 }
689
690 i = interval;
691 while (! NULL_PARENT (i))
692 {
693 if (AM_RIGHT_CHILD (i))
694 {
695 i = i->parent;
696
697 i->position = interval->position - LENGTH (i);
698 return i;
699 }
700 i = i->parent;
701 }
702
703 return NULL_INTERVAL;
704 }
705
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;
713 {
714 if (NULL_INTERVAL_P (i))
715 return NULL_INTERVAL;
716
717 while (1)
718 {
719 if (pos < i->position)
720 {
721 /* Move left. */
722 if (pos >= i->position - TOTAL_LENGTH (i->left))
723 {
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 */
727 }
728 else if (NULL_PARENT (i))
729 error ("Point before start of properties");
730 else
731 i = i->parent;
732 continue;
733 }
734 else if (pos >= INTERVAL_LAST_POS (i))
735 {
736 /* Move right. */
737 if (pos < INTERVAL_LAST_POS (i) + TOTAL_LENGTH (i->right))
738 {
739 i->right->position = INTERVAL_LAST_POS (i) +
740 LEFT_TOTAL_LENGTH (i->right);
741 i = i->right; /* Move to the right child */
742 }
743 else if (NULL_PARENT (i))
744 error ("Point after end of properties");
745 else
746 i = i->parent;
747 continue;
748 }
749 else
750 return i;
751 }
752 }
753
754 \f
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.
761
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. */
767
768 static INTERVAL
769 adjust_intervals_for_insertion (tree, position, length)
770 INTERVAL tree;
771 int position, length;
772 {
773 register int relative_position;
774 register INTERVAL this;
775
776 if (TOTAL_LENGTH (tree) == 0) /* Paranoia */
777 abort ();
778
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;
785
786 while (1)
787 {
788 if (relative_position <= LEFT_TOTAL_LENGTH (this))
789 {
790 this->total_length += length;
791 this = this->left;
792 }
793 else if (relative_position > (TOTAL_LENGTH (this)
794 - RIGHT_TOTAL_LENGTH (this)))
795 {
796 relative_position -= (TOTAL_LENGTH (this)
797 - RIGHT_TOTAL_LENGTH (this));
798 this->total_length += length;
799 this = this->right;
800 }
801 else
802 {
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;
809 }
810 }
811 }
812 #endif
813
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.
818
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".
822
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. */
826
827 static INTERVAL
828 adjust_intervals_for_insertion (tree, position, length)
829 INTERVAL tree;
830 int position, length;
831 {
832 register INTERVAL i;
833 register INTERVAL temp;
834 int eobp = 0;
835 Lisp_Object parent;
836 int offset;
837
838 if (TOTAL_LENGTH (tree) == 0) /* Paranoia */
839 abort ();
840
841 XSETFASTINT (parent, (EMACS_INT) tree->parent);
842 offset = (BUFFERP (parent) ? BUF_BEG (XBUFFER (parent)) : 0);
843
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)
847 {
848 position = TOTAL_LENGTH (tree) + offset;
849 eobp = 1;
850 }
851
852 i = find_interval (tree, position);
853
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. */
857 if (! (position == i->position || eobp)
858 && END_NONSTICKY_P (i)
859 && FRONT_NONSTICKY_P (i))
860 {
861 Lisp_Object tail;
862 Lisp_Object front, rear;
863
864 front = textget (i->plist, Qfront_sticky);
865 rear = textget (i->plist, Qrear_nonsticky);
866
867 /* Does any actual property pose an actual problem? */
868 for (tail = i->plist; ! NILP (tail); tail = Fcdr (Fcdr (tail)))
869 {
870 Lisp_Object prop;
871 prop = XCAR (tail);
872
873 /* Is this particular property rear-sticky?
874 Note, if REAR isn't a cons, it must be non-nil,
875 which means that all properties are rear-nonsticky. */
876 if (CONSP (rear) && NILP (Fmemq (prop, rear)))
877 continue;
878
879 /* Is this particular property front-sticky?
880 Note, if FRONT isn't a cons, it must be nil,
881 which means that all properties are front-nonsticky. */
882 if (CONSP (front) && ! NILP (Fmemq (prop, front)))
883 continue;
884
885 /* PROP isn't sticky on either side => it is a real problem. */
886 break;
887 }
888
889 /* If any property is a real problem, split the interval. */
890 if (! NILP (tail))
891 {
892 temp = split_interval_right (i, position - i->position);
893 copy_properties (i, temp);
894 i = temp;
895 }
896 }
897
898 /* If we are positioned between intervals, check the stickiness of
899 both of them. We have to do this too, if we are at BEG or Z. */
900 if (position == i->position || eobp)
901 {
902 register INTERVAL prev;
903
904 if (position == BEG)
905 prev = 0;
906 else if (eobp)
907 {
908 prev = i;
909 i = 0;
910 }
911 else
912 prev = previous_interval (i);
913
914 /* Even if we are positioned between intervals, we default
915 to the left one if it exists. We extend it now and split
916 off a part later, if stickiness demands it. */
917 for (temp = prev ? prev : i;! NULL_INTERVAL_P (temp); temp = temp->parent)
918 {
919 temp->total_length += length;
920 temp = balance_possible_root_interval (temp);
921 }
922
923 /* If at least one interval has sticky properties,
924 we check the stickiness property by property. */
925 if (END_NONSTICKY_P (prev) || FRONT_STICKY_P (i))
926 {
927 Lisp_Object pleft, pright;
928 struct interval newi;
929
930 pleft = NULL_INTERVAL_P (prev) ? Qnil : prev->plist;
931 pright = NULL_INTERVAL_P (i) ? Qnil : i->plist;
932 newi.plist = merge_properties_sticky (pleft, pright);
933
934 if (! prev) /* i.e. position == BEG */
935 {
936 if (! intervals_equal (i, &newi))
937 {
938 i = split_interval_left (i, length);
939 i->plist = newi.plist;
940 }
941 }
942 else if (! intervals_equal (prev, &newi))
943 {
944 prev = split_interval_right (prev,
945 position - prev->position);
946 prev->plist = newi.plist;
947 if (! NULL_INTERVAL_P (i)
948 && intervals_equal (prev, i))
949 merge_interval_right (prev);
950 }
951
952 /* We will need to update the cache here later. */
953 }
954 else if (! prev && ! NILP (i->plist))
955 {
956 /* Just split off a new interval at the left.
957 Since I wasn't front-sticky, the empty plist is ok. */
958 i = split_interval_left (i, length);
959 }
960 }
961
962 /* Otherwise just extend the interval. */
963 else
964 {
965 for (temp = i; ! NULL_INTERVAL_P (temp); temp = temp->parent)
966 {
967 temp->total_length += length;
968 temp = balance_possible_root_interval (temp);
969 }
970 }
971
972 return tree;
973 }
974
975 /* Any property might be front-sticky on the left, rear-sticky on the left,
976 front-sticky on the right, or rear-sticky on the right; the 16 combinations
977 can be arranged in a matrix with rows denoting the left conditions and
978 columns denoting the right conditions:
979 _ __ _
980 _ FR FR FR FR
981 FR__ 0 1 2 3
982 _FR 4 5 6 7
983 FR 8 9 A B
984 FR C D E F
985
986 left-props = '(front-sticky (p8 p9 pa pb pc pd pe pf)
987 rear-nonsticky (p4 p5 p6 p7 p8 p9 pa pb)
988 p0 L p1 L p2 L p3 L p4 L p5 L p6 L p7 L
989 p8 L p9 L pa L pb L pc L pd L pe L pf L)
990 right-props = '(front-sticky (p2 p3 p6 p7 pa pb pe pf)
991 rear-nonsticky (p1 p2 p5 p6 p9 pa pd pe)
992 p0 R p1 R p2 R p3 R p4 R p5 R p6 R p7 R
993 p8 R p9 R pa R pb R pc R pd R pe R pf R)
994
995 We inherit from whoever has a sticky side facing us. If both sides
996 do (cases 2, 3, E, and F), then we inherit from whichever side has a
997 non-nil value for the current property. If both sides do, then we take
998 from the left.
999
1000 When we inherit a property, we get its stickiness as well as its value.
1001 So, when we merge the above two lists, we expect to get this:
1002
1003 result = '(front-sticky (p6 p7 pa pb pc pd pe pf)
1004 rear-nonsticky (p6 pa)
1005 p0 L p1 L p2 L p3 L p6 R p7 R
1006 pa R pb R pc L pd L pe L pf L)
1007
1008 The optimizable special cases are:
1009 left rear-nonsticky = nil, right front-sticky = nil (inherit left)
1010 left rear-nonsticky = t, right front-sticky = t (inherit right)
1011 left rear-nonsticky = t, right front-sticky = nil (inherit none)
1012 */
1013
1014 Lisp_Object
1015 merge_properties_sticky (pleft, pright)
1016 Lisp_Object pleft, pright;
1017 {
1018 register Lisp_Object props, front, rear;
1019 Lisp_Object lfront, lrear, rfront, rrear;
1020 register Lisp_Object tail1, tail2, sym, lval, rval, cat;
1021 int use_left, use_right;
1022 int lpresent;
1023
1024 props = Qnil;
1025 front = Qnil;
1026 rear = Qnil;
1027 lfront = textget (pleft, Qfront_sticky);
1028 lrear = textget (pleft, Qrear_nonsticky);
1029 rfront = textget (pright, Qfront_sticky);
1030 rrear = textget (pright, Qrear_nonsticky);
1031
1032 /* Go through each element of PRIGHT. */
1033 for (tail1 = pright; ! NILP (tail1); tail1 = Fcdr (Fcdr (tail1)))
1034 {
1035 sym = Fcar (tail1);
1036
1037 /* Sticky properties get special treatment. */
1038 if (EQ (sym, Qrear_nonsticky) || EQ (sym, Qfront_sticky))
1039 continue;
1040
1041 rval = Fcar (Fcdr (tail1));
1042 for (tail2 = pleft; ! NILP (tail2); tail2 = Fcdr (Fcdr (tail2)))
1043 if (EQ (sym, Fcar (tail2)))
1044 break;
1045
1046 /* Indicate whether the property is explicitly defined on the left.
1047 (We know it is defined explicitly on the right
1048 because otherwise we don't get here.) */
1049 lpresent = ! NILP (tail2);
1050 lval = (NILP (tail2) ? Qnil : Fcar (Fcdr (tail2)));
1051
1052 use_left = ! TMEM (sym, lrear) && lpresent;
1053 use_right = TMEM (sym, rfront);
1054 if (use_left && use_right)
1055 {
1056 if (NILP (lval))
1057 use_left = 0;
1058 else if (NILP (rval))
1059 use_right = 0;
1060 }
1061 if (use_left)
1062 {
1063 /* We build props as (value sym ...) rather than (sym value ...)
1064 because we plan to nreverse it when we're done. */
1065 props = Fcons (lval, Fcons (sym, props));
1066 if (TMEM (sym, lfront))
1067 front = Fcons (sym, front);
1068 if (TMEM (sym, lrear))
1069 rear = Fcons (sym, rear);
1070 }
1071 else if (use_right)
1072 {
1073 props = Fcons (rval, Fcons (sym, props));
1074 if (TMEM (sym, rfront))
1075 front = Fcons (sym, front);
1076 if (TMEM (sym, rrear))
1077 rear = Fcons (sym, rear);
1078 }
1079 }
1080
1081 /* Now go through each element of PLEFT. */
1082 for (tail2 = pleft; ! NILP (tail2); tail2 = Fcdr (Fcdr (tail2)))
1083 {
1084 sym = Fcar (tail2);
1085
1086 /* Sticky properties get special treatment. */
1087 if (EQ (sym, Qrear_nonsticky) || EQ (sym, Qfront_sticky))
1088 continue;
1089
1090 /* If sym is in PRIGHT, we've already considered it. */
1091 for (tail1 = pright; ! NILP (tail1); tail1 = Fcdr (Fcdr (tail1)))
1092 if (EQ (sym, Fcar (tail1)))
1093 break;
1094 if (! NILP (tail1))
1095 continue;
1096
1097 lval = Fcar (Fcdr (tail2));
1098
1099 /* Since rval is known to be nil in this loop, the test simplifies. */
1100 if (! TMEM (sym, lrear))
1101 {
1102 props = Fcons (lval, Fcons (sym, props));
1103 if (TMEM (sym, lfront))
1104 front = Fcons (sym, front);
1105 }
1106 else if (TMEM (sym, rfront))
1107 {
1108 /* The value is nil, but we still inherit the stickiness
1109 from the right. */
1110 front = Fcons (sym, front);
1111 if (TMEM (sym, rrear))
1112 rear = Fcons (sym, rear);
1113 }
1114 }
1115 props = Fnreverse (props);
1116 if (! NILP (rear))
1117 props = Fcons (Qrear_nonsticky, Fcons (Fnreverse (rear), props));
1118
1119 cat = textget (props, Qcategory);
1120 if (! NILP (front)
1121 &&
1122 /* If we have inherited a front-stick category property that is t,
1123 we don't need to set up a detailed one. */
1124 ! (! NILP (cat) && SYMBOLP (cat)
1125 && EQ (Fget (cat, Qfront_sticky), Qt)))
1126 props = Fcons (Qfront_sticky, Fcons (Fnreverse (front), props));
1127 return props;
1128 }
1129
1130 \f
1131 /* Delete an node I from its interval tree by merging its subtrees
1132 into one subtree which is then returned. Caller is responsible for
1133 storing the resulting subtree into its parent. */
1134
1135 static INTERVAL
1136 delete_node (i)
1137 register INTERVAL i;
1138 {
1139 register INTERVAL migrate, this;
1140 register int migrate_amt;
1141
1142 if (NULL_INTERVAL_P (i->left))
1143 return i->right;
1144 if (NULL_INTERVAL_P (i->right))
1145 return i->left;
1146
1147 migrate = i->left;
1148 migrate_amt = i->left->total_length;
1149 this = i->right;
1150 this->total_length += migrate_amt;
1151 while (! NULL_INTERVAL_P (this->left))
1152 {
1153 this = this->left;
1154 this->total_length += migrate_amt;
1155 }
1156 this->left = migrate;
1157 migrate->parent = this;
1158
1159 return i->right;
1160 }
1161
1162 /* Delete interval I from its tree by calling `delete_node'
1163 and properly connecting the resultant subtree.
1164
1165 I is presumed to be empty; that is, no adjustments are made
1166 for the length of I. */
1167
1168 void
1169 delete_interval (i)
1170 register INTERVAL i;
1171 {
1172 register INTERVAL parent;
1173 int amt = LENGTH (i);
1174
1175 if (amt > 0) /* Only used on zero-length intervals now. */
1176 abort ();
1177
1178 if (ROOT_INTERVAL_P (i))
1179 {
1180 Lisp_Object owner;
1181 XSETFASTINT (owner, (EMACS_INT) i->parent);
1182 parent = delete_node (i);
1183 if (! NULL_INTERVAL_P (parent))
1184 parent->parent = (INTERVAL) XFASTINT (owner);
1185
1186 if (BUFFERP (owner))
1187 BUF_INTERVALS (XBUFFER (owner)) = parent;
1188 else if (STRINGP (owner))
1189 XSTRING (owner)->intervals = parent;
1190 else
1191 abort ();
1192
1193 return;
1194 }
1195
1196 parent = i->parent;
1197 if (AM_LEFT_CHILD (i))
1198 {
1199 parent->left = delete_node (i);
1200 if (! NULL_INTERVAL_P (parent->left))
1201 parent->left->parent = parent;
1202 }
1203 else
1204 {
1205 parent->right = delete_node (i);
1206 if (! NULL_INTERVAL_P (parent->right))
1207 parent->right->parent = parent;
1208 }
1209 }
1210 \f
1211 /* Find the interval in TREE corresponding to the relative position
1212 FROM and delete as much as possible of AMOUNT from that interval.
1213 Return the amount actually deleted, and if the interval was
1214 zeroed-out, delete that interval node from the tree.
1215
1216 Note that FROM is actually origin zero, aka relative to the
1217 leftmost edge of tree. This is appropriate since we call ourselves
1218 recursively on subtrees.
1219
1220 Do this by recursing down TREE to the interval in question, and
1221 deleting the appropriate amount of text. */
1222
1223 static int
1224 interval_deletion_adjustment (tree, from, amount)
1225 register INTERVAL tree;
1226 register int from, amount;
1227 {
1228 register int relative_position = from;
1229
1230 if (NULL_INTERVAL_P (tree))
1231 return 0;
1232
1233 /* Left branch */
1234 if (relative_position < LEFT_TOTAL_LENGTH (tree))
1235 {
1236 int subtract = interval_deletion_adjustment (tree->left,
1237 relative_position,
1238 amount);
1239 tree->total_length -= subtract;
1240 return subtract;
1241 }
1242 /* Right branch */
1243 else if (relative_position >= (TOTAL_LENGTH (tree)
1244 - RIGHT_TOTAL_LENGTH (tree)))
1245 {
1246 int subtract;
1247
1248 relative_position -= (tree->total_length
1249 - RIGHT_TOTAL_LENGTH (tree));
1250 subtract = interval_deletion_adjustment (tree->right,
1251 relative_position,
1252 amount);
1253 tree->total_length -= subtract;
1254 return subtract;
1255 }
1256 /* Here -- this node. */
1257 else
1258 {
1259 /* How much can we delete from this interval? */
1260 int my_amount = ((tree->total_length
1261 - RIGHT_TOTAL_LENGTH (tree))
1262 - relative_position);
1263
1264 if (amount > my_amount)
1265 amount = my_amount;
1266
1267 tree->total_length -= amount;
1268 if (LENGTH (tree) == 0)
1269 delete_interval (tree);
1270
1271 return amount;
1272 }
1273
1274 /* Never reach here. */
1275 }
1276
1277 /* Effect the adjustments necessary to the interval tree of BUFFER to
1278 correspond to the deletion of LENGTH characters from that buffer
1279 text. The deletion is effected at position START (which is a
1280 buffer position, i.e. origin 1). */
1281
1282 static void
1283 adjust_intervals_for_deletion (buffer, start, length)
1284 struct buffer *buffer;
1285 int start, length;
1286 {
1287 register int left_to_delete = length;
1288 register INTERVAL tree = BUF_INTERVALS (buffer);
1289 Lisp_Object parent;
1290 int offset;
1291
1292 XSETFASTINT (parent, (EMACS_INT) tree->parent);
1293 offset = (BUFFERP (parent) ? BUF_BEG (XBUFFER (parent)) : 0);
1294
1295 if (NULL_INTERVAL_P (tree))
1296 return;
1297
1298 if (start > offset + TOTAL_LENGTH (tree)
1299 || start + length > offset + TOTAL_LENGTH (tree))
1300 abort ();
1301
1302 if (length == TOTAL_LENGTH (tree))
1303 {
1304 BUF_INTERVALS (buffer) = NULL_INTERVAL;
1305 return;
1306 }
1307
1308 if (ONLY_INTERVAL_P (tree))
1309 {
1310 tree->total_length -= length;
1311 return;
1312 }
1313
1314 if (start > offset + TOTAL_LENGTH (tree))
1315 start = offset + TOTAL_LENGTH (tree);
1316 while (left_to_delete > 0)
1317 {
1318 left_to_delete -= interval_deletion_adjustment (tree, start - offset,
1319 left_to_delete);
1320 tree = BUF_INTERVALS (buffer);
1321 if (left_to_delete == tree->total_length)
1322 {
1323 BUF_INTERVALS (buffer) = NULL_INTERVAL;
1324 return;
1325 }
1326 }
1327 }
1328 \f
1329 /* Make the adjustments necessary to the interval tree of BUFFER to
1330 represent an addition or deletion of LENGTH characters starting
1331 at position START. Addition or deletion is indicated by the sign
1332 of LENGTH. */
1333
1334 INLINE void
1335 offset_intervals (buffer, start, length)
1336 struct buffer *buffer;
1337 int start, length;
1338 {
1339 if (NULL_INTERVAL_P (BUF_INTERVALS (buffer)) || length == 0)
1340 return;
1341
1342 if (length > 0)
1343 adjust_intervals_for_insertion (BUF_INTERVALS (buffer), start, length);
1344 else
1345 adjust_intervals_for_deletion (buffer, start, -length);
1346 }
1347 \f
1348 /* Merge interval I with its lexicographic successor. The resulting
1349 interval is returned, and has the properties of the original
1350 successor. The properties of I are lost. I is removed from the
1351 interval tree.
1352
1353 IMPORTANT:
1354 The caller must verify that this is not the last (rightmost)
1355 interval. */
1356
1357 INTERVAL
1358 merge_interval_right (i)
1359 register INTERVAL i;
1360 {
1361 register int absorb = LENGTH (i);
1362 register INTERVAL successor;
1363
1364 /* Zero out this interval. */
1365 i->total_length -= absorb;
1366
1367 /* Find the succeeding interval. */
1368 if (! NULL_RIGHT_CHILD (i)) /* It's below us. Add absorb
1369 as we descend. */
1370 {
1371 successor = i->right;
1372 while (! NULL_LEFT_CHILD (successor))
1373 {
1374 successor->total_length += absorb;
1375 successor = successor->left;
1376 }
1377
1378 successor->total_length += absorb;
1379 delete_interval (i);
1380 return successor;
1381 }
1382
1383 successor = i;
1384 while (! NULL_PARENT (successor)) /* It's above us. Subtract as
1385 we ascend. */
1386 {
1387 if (AM_LEFT_CHILD (successor))
1388 {
1389 successor = successor->parent;
1390 delete_interval (i);
1391 return successor;
1392 }
1393
1394 successor = successor->parent;
1395 successor->total_length -= absorb;
1396 }
1397
1398 /* This must be the rightmost or last interval and cannot
1399 be merged right. The caller should have known. */
1400 abort ();
1401 }
1402 \f
1403 /* Merge interval I with its lexicographic predecessor. The resulting
1404 interval is returned, and has the properties of the original predecessor.
1405 The properties of I are lost. Interval node I is removed from the tree.
1406
1407 IMPORTANT:
1408 The caller must verify that this is not the first (leftmost) interval. */
1409
1410 INTERVAL
1411 merge_interval_left (i)
1412 register INTERVAL i;
1413 {
1414 register int absorb = LENGTH (i);
1415 register INTERVAL predecessor;
1416
1417 /* Zero out this interval. */
1418 i->total_length -= absorb;
1419
1420 /* Find the preceding interval. */
1421 if (! NULL_LEFT_CHILD (i)) /* It's below us. Go down,
1422 adding ABSORB as we go. */
1423 {
1424 predecessor = i->left;
1425 while (! NULL_RIGHT_CHILD (predecessor))
1426 {
1427 predecessor->total_length += absorb;
1428 predecessor = predecessor->right;
1429 }
1430
1431 predecessor->total_length += absorb;
1432 delete_interval (i);
1433 return predecessor;
1434 }
1435
1436 predecessor = i;
1437 while (! NULL_PARENT (predecessor)) /* It's above us. Go up,
1438 subtracting ABSORB. */
1439 {
1440 if (AM_RIGHT_CHILD (predecessor))
1441 {
1442 predecessor = predecessor->parent;
1443 delete_interval (i);
1444 return predecessor;
1445 }
1446
1447 predecessor = predecessor->parent;
1448 predecessor->total_length -= absorb;
1449 }
1450
1451 /* This must be the leftmost or first interval and cannot
1452 be merged left. The caller should have known. */
1453 abort ();
1454 }
1455 \f
1456 /* Make an exact copy of interval tree SOURCE which descends from
1457 PARENT. This is done by recursing through SOURCE, copying
1458 the current interval and its properties, and then adjusting
1459 the pointers of the copy. */
1460
1461 static INTERVAL
1462 reproduce_tree (source, parent)
1463 INTERVAL source, parent;
1464 {
1465 register INTERVAL t = make_interval ();
1466
1467 bcopy (source, t, INTERVAL_SIZE);
1468 copy_properties (source, t);
1469 t->parent = parent;
1470 if (! NULL_LEFT_CHILD (source))
1471 t->left = reproduce_tree (source->left, t);
1472 if (! NULL_RIGHT_CHILD (source))
1473 t->right = reproduce_tree (source->right, t);
1474
1475 return t;
1476 }
1477
1478 #if 0
1479 /* Nobody calls this. Perhaps it's a vestige of an earlier design. */
1480
1481 /* Make a new interval of length LENGTH starting at START in the
1482 group of intervals INTERVALS, which is actually an interval tree.
1483 Returns the new interval.
1484
1485 Generate an error if the new positions would overlap an existing
1486 interval. */
1487
1488 static INTERVAL
1489 make_new_interval (intervals, start, length)
1490 INTERVAL intervals;
1491 int start, length;
1492 {
1493 INTERVAL slot;
1494
1495 slot = find_interval (intervals, start);
1496 if (start + length > slot->position + LENGTH (slot))
1497 error ("Interval would overlap");
1498
1499 if (start == slot->position && length == LENGTH (slot))
1500 return slot;
1501
1502 if (slot->position == start)
1503 {
1504 /* New right node. */
1505 split_interval_right (slot, length);
1506 return slot;
1507 }
1508
1509 if (slot->position + LENGTH (slot) == start + length)
1510 {
1511 /* New left node. */
1512 split_interval_left (slot, LENGTH (slot) - length);
1513 return slot;
1514 }
1515
1516 /* Convert interval SLOT into three intervals. */
1517 split_interval_left (slot, start - slot->position);
1518 split_interval_right (slot, length);
1519 return slot;
1520 }
1521 #endif
1522 \f
1523 /* Insert the intervals of SOURCE into BUFFER at POSITION.
1524 LENGTH is the length of the text in SOURCE.
1525
1526 The `position' field of the SOURCE intervals is assumed to be
1527 consistent with its parent; therefore, SOURCE must be an
1528 interval tree made with copy_interval or must be the whole
1529 tree of a buffer or a string.
1530
1531 This is used in insdel.c when inserting Lisp_Strings into the
1532 buffer. The text corresponding to SOURCE is already in the buffer
1533 when this is called. The intervals of new tree are a copy of those
1534 belonging to the string being inserted; intervals are never
1535 shared.
1536
1537 If the inserted text had no intervals associated, and we don't
1538 want to inherit the surrounding text's properties, this function
1539 simply returns -- offset_intervals should handle placing the
1540 text in the correct interval, depending on the sticky bits.
1541
1542 If the inserted text had properties (intervals), then there are two
1543 cases -- either insertion happened in the middle of some interval,
1544 or between two intervals.
1545
1546 If the text goes into the middle of an interval, then new
1547 intervals are created in the middle with only the properties of
1548 the new text, *unless* the macro MERGE_INSERTIONS is true, in
1549 which case the new text has the union of its properties and those
1550 of the text into which it was inserted.
1551
1552 If the text goes between two intervals, then if neither interval
1553 had its appropriate sticky property set (front_sticky, rear_sticky),
1554 the new text has only its properties. If one of the sticky properties
1555 is set, then the new text "sticks" to that region and its properties
1556 depend on merging as above. If both the preceding and succeeding
1557 intervals to the new text are "sticky", then the new text retains
1558 only its properties, as if neither sticky property were set. Perhaps
1559 we should consider merging all three sets of properties onto the new
1560 text... */
1561
1562 void
1563 graft_intervals_into_buffer (source, position, length, buffer, inherit)
1564 INTERVAL source;
1565 int position, length;
1566 struct buffer *buffer;
1567 int inherit;
1568 {
1569 register INTERVAL under, over, this, prev;
1570 register INTERVAL tree;
1571 int middle;
1572
1573 tree = BUF_INTERVALS (buffer);
1574
1575 /* If the new text has no properties, it becomes part of whatever
1576 interval it was inserted into. */
1577 if (NULL_INTERVAL_P (source))
1578 {
1579 Lisp_Object buf;
1580 if (!inherit && ! NULL_INTERVAL_P (tree))
1581 {
1582 int saved_inhibit_modification_hooks = inhibit_modification_hooks;
1583 XSETBUFFER (buf, buffer);
1584 inhibit_modification_hooks = 1;
1585 Fset_text_properties (make_number (position),
1586 make_number (position + length),
1587 Qnil, buf);
1588 inhibit_modification_hooks = saved_inhibit_modification_hooks;
1589 }
1590 if (! NULL_INTERVAL_P (BUF_INTERVALS (buffer)))
1591 BUF_INTERVALS (buffer) = balance_an_interval (BUF_INTERVALS (buffer));
1592 return;
1593 }
1594
1595 if (NULL_INTERVAL_P (tree))
1596 {
1597 /* The inserted text constitutes the whole buffer, so
1598 simply copy over the interval structure. */
1599 if ((BUF_Z (buffer) - BUF_BEG (buffer)) == TOTAL_LENGTH (source))
1600 {
1601 Lisp_Object buf;
1602 XSETBUFFER (buf, buffer);
1603 BUF_INTERVALS (buffer) = reproduce_tree (source, buf);
1604 BUF_INTERVALS (buffer)->position = 1;
1605
1606 /* Explicitly free the old tree here? */
1607
1608 return;
1609 }
1610
1611 /* Create an interval tree in which to place a copy
1612 of the intervals of the inserted string. */
1613 {
1614 Lisp_Object buf;
1615 XSETBUFFER (buf, buffer);
1616 tree = create_root_interval (buf);
1617 }
1618 }
1619 else if (TOTAL_LENGTH (tree) == TOTAL_LENGTH (source))
1620 /* If the buffer contains only the new string, but
1621 there was already some interval tree there, then it may be
1622 some zero length intervals. Eventually, do something clever
1623 about inserting properly. For now, just waste the old intervals. */
1624 {
1625 BUF_INTERVALS (buffer) = reproduce_tree (source, tree->parent);
1626 BUF_INTERVALS (buffer)->position = 1;
1627 /* Explicitly free the old tree here. */
1628
1629 return;
1630 }
1631 /* Paranoia -- the text has already been added, so this buffer
1632 should be of non-zero length. */
1633 else if (TOTAL_LENGTH (tree) == 0)
1634 abort ();
1635
1636 this = under = find_interval (tree, position);
1637 if (NULL_INTERVAL_P (under)) /* Paranoia */
1638 abort ();
1639 over = find_interval (source, interval_start_pos (source));
1640
1641 /* Here for insertion in the middle of an interval.
1642 Split off an equivalent interval to the right,
1643 then don't bother with it any more. */
1644
1645 if (position > under->position)
1646 {
1647 INTERVAL end_unchanged
1648 = split_interval_left (this, position - under->position);
1649 copy_properties (under, end_unchanged);
1650 under->position = position;
1651 prev = 0;
1652 middle = 1;
1653 }
1654 else
1655 {
1656 prev = previous_interval (under);
1657 if (prev && !END_NONSTICKY_P (prev))
1658 prev = 0;
1659 }
1660
1661 /* Insertion is now at beginning of UNDER. */
1662
1663 /* The inserted text "sticks" to the interval `under',
1664 which means it gets those properties.
1665 The properties of under are the result of
1666 adjust_intervals_for_insertion, so stickiness has
1667 already been taken care of. */
1668
1669 while (! NULL_INTERVAL_P (over))
1670 {
1671 if (LENGTH (over) < LENGTH (under))
1672 {
1673 this = split_interval_left (under, LENGTH (over));
1674 copy_properties (under, this);
1675 }
1676 else
1677 this = under;
1678 copy_properties (over, this);
1679 if (inherit)
1680 merge_properties (over, this);
1681 else
1682 copy_properties (over, this);
1683 over = next_interval (over);
1684 }
1685
1686 if (! NULL_INTERVAL_P (BUF_INTERVALS (buffer)))
1687 BUF_INTERVALS (buffer) = balance_an_interval (BUF_INTERVALS (buffer));
1688 return;
1689 }
1690
1691 /* Get the value of property PROP from PLIST,
1692 which is the plist of an interval.
1693 We check for direct properties, for categories with property PROP,
1694 and for PROP appearing on the default-text-properties list. */
1695
1696 Lisp_Object
1697 textget (plist, prop)
1698 Lisp_Object plist;
1699 register Lisp_Object prop;
1700 {
1701 register Lisp_Object tail, fallback;
1702 fallback = Qnil;
1703
1704 for (tail = plist; !NILP (tail); tail = Fcdr (Fcdr (tail)))
1705 {
1706 register Lisp_Object tem;
1707 tem = Fcar (tail);
1708 if (EQ (prop, tem))
1709 return Fcar (Fcdr (tail));
1710 if (EQ (tem, Qcategory))
1711 {
1712 tem = Fcar (Fcdr (tail));
1713 if (SYMBOLP (tem))
1714 fallback = Fget (tem, prop);
1715 }
1716 }
1717
1718 if (! NILP (fallback))
1719 return fallback;
1720 if (CONSP (Vdefault_text_properties))
1721 return Fplist_get (Vdefault_text_properties, prop);
1722 return Qnil;
1723 }
1724
1725 \f
1726 /* Set point "temporarily", without checking any text properties. */
1727
1728 INLINE void
1729 temp_set_point (buffer, charpos)
1730 struct buffer *buffer;
1731 int charpos;
1732 {
1733 temp_set_point_both (buffer, charpos,
1734 buf_charpos_to_bytepos (buffer, charpos));
1735 }
1736
1737 /* Set point in BUFFER "temporarily" to CHARPOS, which corresponds to
1738 byte position BYTEPOS. */
1739
1740 INLINE void
1741 temp_set_point_both (buffer, charpos, bytepos)
1742 int charpos, bytepos;
1743 struct buffer *buffer;
1744 {
1745 /* In a single-byte buffer, the two positions must be equal. */
1746 if (BUF_ZV (buffer) == BUF_ZV_BYTE (buffer)
1747 && charpos != bytepos)
1748 abort ();
1749
1750 if (charpos > bytepos)
1751 abort ();
1752
1753 if (charpos > BUF_ZV (buffer) || charpos < BUF_BEGV (buffer))
1754 abort ();
1755
1756 BUF_PT_BYTE (buffer) = bytepos;
1757 BUF_PT (buffer) = charpos;
1758 }
1759
1760 /* Set point in BUFFER to CHARPOS. If the target position is
1761 before an intangible character, move to an ok place. */
1762
1763 void
1764 set_point (buffer, charpos)
1765 register struct buffer *buffer;
1766 register int charpos;
1767 {
1768 set_point_both (buffer, charpos, buf_charpos_to_bytepos (buffer, charpos));
1769 }
1770
1771 /* Set point in BUFFER to CHARPOS, which corresponds to byte
1772 position BYTEPOS. If the target position is
1773 before an intangible character, move to an ok place. */
1774
1775 void
1776 set_point_both (buffer, charpos, bytepos)
1777 register struct buffer *buffer;
1778 register int charpos, bytepos;
1779 {
1780 register INTERVAL to, from, toprev, fromprev;
1781 int buffer_point;
1782 int old_position = BUF_PT (buffer);
1783 int backwards = (charpos < old_position ? 1 : 0);
1784 int have_overlays;
1785 int original_position;
1786
1787 buffer->point_before_scroll = Qnil;
1788
1789 if (charpos == BUF_PT (buffer))
1790 return;
1791
1792 /* In a single-byte buffer, the two positions must be equal. */
1793 if (BUF_ZV (buffer) == BUF_ZV_BYTE (buffer)
1794 && charpos != bytepos)
1795 abort ();
1796
1797 /* Check this now, before checking if the buffer has any intervals.
1798 That way, we can catch conditions which break this sanity check
1799 whether or not there are intervals in the buffer. */
1800 if (charpos > BUF_ZV (buffer) || charpos < BUF_BEGV (buffer))
1801 abort ();
1802
1803 have_overlays = (! NILP (buffer->overlays_before)
1804 || ! NILP (buffer->overlays_after));
1805
1806 /* If we have no text properties and overlays,
1807 then we can do it quickly. */
1808 if (NULL_INTERVAL_P (BUF_INTERVALS (buffer)) && ! have_overlays)
1809 {
1810 temp_set_point_both (buffer, charpos, bytepos);
1811 return;
1812 }
1813
1814 /* Set TO to the interval containing the char after CHARPOS,
1815 and TOPREV to the interval containing the char before CHARPOS.
1816 Either one may be null. They may be equal. */
1817 to = find_interval (BUF_INTERVALS (buffer), charpos);
1818 if (charpos == BUF_BEGV (buffer))
1819 toprev = 0;
1820 else if (to && to->position == charpos)
1821 toprev = previous_interval (to);
1822 else
1823 toprev = to;
1824
1825 buffer_point = (BUF_PT (buffer) == BUF_ZV (buffer)
1826 ? BUF_ZV (buffer) - 1
1827 : BUF_PT (buffer));
1828
1829 /* Set FROM to the interval containing the char after PT,
1830 and FROMPREV to the interval containing the char before PT.
1831 Either one may be null. They may be equal. */
1832 /* We could cache this and save time. */
1833 from = find_interval (BUF_INTERVALS (buffer), buffer_point);
1834 if (buffer_point == BUF_BEGV (buffer))
1835 fromprev = 0;
1836 else if (from && from->position == BUF_PT (buffer))
1837 fromprev = previous_interval (from);
1838 else if (buffer_point != BUF_PT (buffer))
1839 fromprev = from, from = 0;
1840 else
1841 fromprev = from;
1842
1843 /* Moving within an interval. */
1844 if (to == from && toprev == fromprev && INTERVAL_VISIBLE_P (to)
1845 && ! have_overlays)
1846 {
1847 temp_set_point_both (buffer, charpos, bytepos);
1848 return;
1849 }
1850
1851 original_position = charpos;
1852
1853 /* If the new position is between two intangible characters
1854 with the same intangible property value,
1855 move forward or backward until a change in that property. */
1856 if (NILP (Vinhibit_point_motion_hooks)
1857 && ((! NULL_INTERVAL_P (to) && ! NULL_INTERVAL_P (toprev))
1858 || have_overlays)
1859 /* Intangibility never stops us from positioning at the beginning
1860 or end of the buffer, so don't bother checking in that case. */
1861 && charpos != BEGV && charpos != ZV)
1862 {
1863 Lisp_Object intangible_propval;
1864 Lisp_Object pos;
1865
1866 XSETINT (pos, charpos);
1867
1868 if (backwards)
1869 {
1870 intangible_propval = Fget_char_property (make_number (charpos),
1871 Qintangible, Qnil);
1872
1873 /* If following char is intangible,
1874 skip back over all chars with matching intangible property. */
1875 if (! NILP (intangible_propval))
1876 while (XINT (pos) > BUF_BEGV (buffer)
1877 && EQ (Fget_char_property (make_number (XINT (pos) - 1),
1878 Qintangible, Qnil),
1879 intangible_propval))
1880 pos = Fprevious_char_property_change (pos, Qnil);
1881 }
1882 else
1883 {
1884 intangible_propval = Fget_char_property (make_number (charpos - 1),
1885 Qintangible, Qnil);
1886
1887 /* If following char is intangible,
1888 skip forward over all chars with matching intangible property. */
1889 if (! NILP (intangible_propval))
1890 while (XINT (pos) < BUF_ZV (buffer)
1891 && EQ (Fget_char_property (pos, Qintangible, Qnil),
1892 intangible_propval))
1893 pos = Fnext_char_property_change (pos, Qnil);
1894
1895 }
1896
1897 charpos = XINT (pos);
1898 bytepos = buf_charpos_to_bytepos (buffer, charpos);
1899 }
1900
1901 if (charpos != original_position)
1902 {
1903 /* Set TO to the interval containing the char after CHARPOS,
1904 and TOPREV to the interval containing the char before CHARPOS.
1905 Either one may be null. They may be equal. */
1906 to = find_interval (BUF_INTERVALS (buffer), charpos);
1907 if (charpos == BUF_BEGV (buffer))
1908 toprev = 0;
1909 else if (to && to->position == charpos)
1910 toprev = previous_interval (to);
1911 else
1912 toprev = to;
1913 }
1914
1915 /* Here TO is the interval after the stopping point
1916 and TOPREV is the interval before the stopping point.
1917 One or the other may be null. */
1918
1919 temp_set_point_both (buffer, charpos, bytepos);
1920
1921 /* We run point-left and point-entered hooks here, iff the
1922 two intervals are not equivalent. These hooks take
1923 (old_point, new_point) as arguments. */
1924 if (NILP (Vinhibit_point_motion_hooks)
1925 && (! intervals_equal (from, to)
1926 || ! intervals_equal (fromprev, toprev)))
1927 {
1928 Lisp_Object leave_after, leave_before, enter_after, enter_before;
1929
1930 if (fromprev)
1931 leave_after = textget (fromprev->plist, Qpoint_left);
1932 else
1933 leave_after = Qnil;
1934 if (from)
1935 leave_before = textget (from->plist, Qpoint_left);
1936 else
1937 leave_before = Qnil;
1938
1939 if (toprev)
1940 enter_after = textget (toprev->plist, Qpoint_entered);
1941 else
1942 enter_after = Qnil;
1943 if (to)
1944 enter_before = textget (to->plist, Qpoint_entered);
1945 else
1946 enter_before = Qnil;
1947
1948 if (! EQ (leave_before, enter_before) && !NILP (leave_before))
1949 call2 (leave_before, make_number (old_position),
1950 make_number (charpos));
1951 if (! EQ (leave_after, enter_after) && !NILP (leave_after))
1952 call2 (leave_after, make_number (old_position),
1953 make_number (charpos));
1954
1955 if (! EQ (enter_before, leave_before) && !NILP (enter_before))
1956 call2 (enter_before, make_number (old_position),
1957 make_number (charpos));
1958 if (! EQ (enter_after, leave_after) && !NILP (enter_after))
1959 call2 (enter_after, make_number (old_position),
1960 make_number (charpos));
1961 }
1962 }
1963 \f
1964 /* Move point to POSITION, unless POSITION is inside an intangible
1965 segment that reaches all the way to point. */
1966
1967 void
1968 move_if_not_intangible (position)
1969 int position;
1970 {
1971 Lisp_Object pos;
1972 Lisp_Object intangible_propval;
1973
1974 XSETINT (pos, position);
1975
1976 if (! NILP (Vinhibit_point_motion_hooks))
1977 /* If intangible is inhibited, always move point to POSITION. */
1978 ;
1979 else if (PT < position && XINT (pos) < ZV)
1980 {
1981 /* We want to move forward, so check the text before POSITION. */
1982
1983 intangible_propval = Fget_char_property (pos,
1984 Qintangible, Qnil);
1985
1986 /* If following char is intangible,
1987 skip back over all chars with matching intangible property. */
1988 if (! NILP (intangible_propval))
1989 while (XINT (pos) > BEGV
1990 && EQ (Fget_char_property (make_number (XINT (pos) - 1),
1991 Qintangible, Qnil),
1992 intangible_propval))
1993 pos = Fprevious_char_property_change (pos, Qnil);
1994 }
1995 else if (XINT (pos) > BEGV)
1996 {
1997 /* We want to move backward, so check the text after POSITION. */
1998
1999 intangible_propval = Fget_char_property (make_number (XINT (pos) - 1),
2000 Qintangible, Qnil);
2001
2002 /* If following char is intangible,
2003 skip forward over all chars with matching intangible property. */
2004 if (! NILP (intangible_propval))
2005 while (XINT (pos) < ZV
2006 && EQ (Fget_char_property (pos, Qintangible, Qnil),
2007 intangible_propval))
2008 pos = Fnext_char_property_change (pos, Qnil);
2009
2010 }
2011
2012 /* If the whole stretch between PT and POSITION isn't intangible,
2013 try moving to POSITION (which means we actually move farther
2014 if POSITION is inside of intangible text). */
2015
2016 if (XINT (pos) != PT)
2017 SET_PT (position);
2018 }
2019 \f
2020 /* Return the proper local map for position POSITION in BUFFER.
2021 Use the map specified by the local-map property, if any.
2022 Otherwise, use BUFFER's local map. */
2023
2024 Lisp_Object
2025 get_local_map (position, buffer)
2026 register int position;
2027 register struct buffer *buffer;
2028 {
2029 Lisp_Object prop, tem, lispy_position, lispy_buffer;
2030 int old_begv, old_zv, old_begv_byte, old_zv_byte;
2031
2032 /* Perhaps we should just change `position' to the limit. */
2033 if (position > BUF_Z (buffer) || position < BUF_BEG (buffer))
2034 abort ();
2035
2036 /* Ignore narrowing, so that a local map continues to be valid even if
2037 the visible region contains no characters and hence no properties. */
2038 old_begv = BUF_BEGV (buffer);
2039 old_zv = BUF_ZV (buffer);
2040 old_begv_byte = BUF_BEGV_BYTE (buffer);
2041 old_zv_byte = BUF_ZV_BYTE (buffer);
2042 BUF_BEGV (buffer) = BUF_BEG (buffer);
2043 BUF_ZV (buffer) = BUF_Z (buffer);
2044 BUF_BEGV_BYTE (buffer) = BUF_BEG_BYTE (buffer);
2045 BUF_ZV_BYTE (buffer) = BUF_Z_BYTE (buffer);
2046
2047 /* There are no properties at the end of the buffer, so in that case
2048 check for a local map on the last character of the buffer instead. */
2049 if (position == BUF_Z (buffer) && BUF_Z (buffer) > BUF_BEG (buffer))
2050 --position;
2051 XSETFASTINT (lispy_position, position);
2052 XSETBUFFER (lispy_buffer, buffer);
2053 prop = Fget_char_property (lispy_position, Qlocal_map, lispy_buffer);
2054
2055 BUF_BEGV (buffer) = old_begv;
2056 BUF_ZV (buffer) = old_zv;
2057 BUF_BEGV_BYTE (buffer) = old_begv_byte;
2058 BUF_ZV_BYTE (buffer) = old_zv_byte;
2059
2060 /* Use the local map only if it is valid. */
2061 /* Do allow symbols that are defined as keymaps. */
2062 if (SYMBOLP (prop) && !NILP (prop))
2063 prop = indirect_function (prop);
2064 if (!NILP (prop)
2065 && (tem = Fkeymapp (prop), !NILP (tem)))
2066 return prop;
2067
2068 return buffer->keymap;
2069 }
2070 \f
2071 /* Produce an interval tree reflecting the intervals in
2072 TREE from START to START + LENGTH.
2073 The new interval tree has no parent and has a starting-position of 0. */
2074
2075 INTERVAL
2076 copy_intervals (tree, start, length)
2077 INTERVAL tree;
2078 int start, length;
2079 {
2080 register INTERVAL i, new, t;
2081 register int got, prevlen;
2082
2083 if (NULL_INTERVAL_P (tree) || length <= 0)
2084 return NULL_INTERVAL;
2085
2086 i = find_interval (tree, start);
2087 if (NULL_INTERVAL_P (i) || LENGTH (i) == 0)
2088 abort ();
2089
2090 /* If there is only one interval and it's the default, return nil. */
2091 if ((start - i->position + 1 + length) < LENGTH (i)
2092 && DEFAULT_INTERVAL_P (i))
2093 return NULL_INTERVAL;
2094
2095 new = make_interval ();
2096 new->position = 0;
2097 got = (LENGTH (i) - (start - i->position));
2098 new->total_length = length;
2099 copy_properties (i, new);
2100
2101 t = new;
2102 prevlen = got;
2103 while (got < length)
2104 {
2105 i = next_interval (i);
2106 t = split_interval_right (t, prevlen);
2107 copy_properties (i, t);
2108 prevlen = LENGTH (i);
2109 got += prevlen;
2110 }
2111
2112 return balance_an_interval (new);
2113 }
2114
2115 /* Give STRING the properties of BUFFER from POSITION to LENGTH. */
2116
2117 INLINE void
2118 copy_intervals_to_string (string, buffer, position, length)
2119 Lisp_Object string;
2120 struct buffer *buffer;
2121 int position, length;
2122 {
2123 INTERVAL interval_copy = copy_intervals (BUF_INTERVALS (buffer),
2124 position, length);
2125 if (NULL_INTERVAL_P (interval_copy))
2126 return;
2127
2128 interval_copy->parent = (INTERVAL) XFASTINT (string);
2129 XSTRING (string)->intervals = interval_copy;
2130 }
2131 \f
2132 /* Return 1 if strings S1 and S2 have identical properties; 0 otherwise.
2133 Assume they have identical characters. */
2134
2135 int
2136 compare_string_intervals (s1, s2)
2137 Lisp_Object s1, s2;
2138 {
2139 INTERVAL i1, i2;
2140 int pos = 0;
2141 int end = XSTRING (s1)->size;
2142
2143 i1 = find_interval (XSTRING (s1)->intervals, 0);
2144 i2 = find_interval (XSTRING (s2)->intervals, 0);
2145
2146 while (pos < end)
2147 {
2148 /* Determine how far we can go before we reach the end of I1 or I2. */
2149 int len1 = (i1 != 0 ? INTERVAL_LAST_POS (i1) : end) - pos;
2150 int len2 = (i2 != 0 ? INTERVAL_LAST_POS (i2) : end) - pos;
2151 int distance = min (len1, len2);
2152
2153 /* If we ever find a mismatch between the strings,
2154 they differ. */
2155 if (! intervals_equal (i1, i2))
2156 return 0;
2157
2158 /* Advance POS till the end of the shorter interval,
2159 and advance one or both interval pointers for the new position. */
2160 pos += distance;
2161 if (len1 == distance)
2162 i1 = next_interval (i1);
2163 if (len2 == distance)
2164 i2 = next_interval (i2);
2165 }
2166 return 1;
2167 }
2168 \f
2169 /* Recursively adjust interval I in the current buffer
2170 for setting enable_multibyte_characters to MULTI_FLAG.
2171 The range of interval I is START ... END in characters,
2172 START_BYTE ... END_BYTE in bytes. */
2173
2174 static void
2175 set_intervals_multibyte_1 (i, multi_flag, start, start_byte, end, end_byte)
2176 INTERVAL i;
2177 int multi_flag;
2178 int start, start_byte, end, end_byte;
2179 {
2180 /* Fix the length of this interval. */
2181 if (multi_flag)
2182 i->total_length = end - start;
2183 else
2184 i->total_length = end_byte - start_byte;
2185
2186 /* Recursively fix the length of the subintervals. */
2187 if (i->left)
2188 {
2189 int left_end, left_end_byte;
2190
2191 if (multi_flag)
2192 {
2193 left_end_byte = start_byte + LEFT_TOTAL_LENGTH (i);
2194 left_end = BYTE_TO_CHAR (left_end_byte);
2195 }
2196 else
2197 {
2198 left_end = start + LEFT_TOTAL_LENGTH (i);
2199 left_end_byte = CHAR_TO_BYTE (left_end);
2200 }
2201
2202 set_intervals_multibyte_1 (i->left, multi_flag, start, start_byte,
2203 left_end, left_end_byte);
2204 }
2205 if (i->right)
2206 {
2207 int right_start_byte, right_start;
2208
2209 if (multi_flag)
2210 {
2211 right_start_byte = end_byte - RIGHT_TOTAL_LENGTH (i);
2212 right_start = BYTE_TO_CHAR (right_start_byte);
2213 }
2214 else
2215 {
2216 right_start = end - RIGHT_TOTAL_LENGTH (i);
2217 right_start_byte = CHAR_TO_BYTE (right_start);
2218 }
2219
2220 set_intervals_multibyte_1 (i->right, multi_flag,
2221 right_start, right_start_byte,
2222 end, end_byte);
2223 }
2224 }
2225
2226 /* Update the intervals of the current buffer
2227 to fit the contents as multibyte (if MULTI_FLAG is 1)
2228 or to fit them as non-multibyte (if MULTI_FLAG is 0). */
2229
2230 void
2231 set_intervals_multibyte (multi_flag)
2232 int multi_flag;
2233 {
2234 if (BUF_INTERVALS (current_buffer))
2235 set_intervals_multibyte_1 (BUF_INTERVALS (current_buffer), multi_flag,
2236 BEG, BEG_BYTE, Z, Z_BYTE);
2237 }