This source file includes following definitions.
- set_interval_left
- set_interval_right
- copy_interval_parent
- create_root_interval
- copy_properties
- merge_properties
- intervals_equal_1
- intervals_equal
- traverse_intervals_noorder
- traverse_intervals
- rotate_right
- rotate_left
- balance_an_interval
- balance_possible_root_interval
- balance_intervals_internal
- balance_intervals
- buffer_balance_intervals
- split_interval_right
- split_interval_left
- interval_start_pos
- find_interval
- next_interval
- previous_interval
- update_interval
- adjust_intervals_for_insertion
- merge_properties_sticky
- delete_node
- delete_interval
- interval_deletion_adjustment
- adjust_intervals_for_deletion
- offset_intervals
- merge_interval_right
- merge_interval_left
- reproduce_interval
- reproduce_tree
- reproduce_tree_obj
- graft_intervals_into_buffer
- textget
- lookup_char_property
- temp_set_point_both
- temp_set_point
- set_point
- set_point_from_marker
- adjust_for_invis_intang
- set_point_both
- move_if_not_intangible
- get_property_and_range
- get_local_map
- copy_intervals
- copy_intervals_to_string
- compare_string_intervals
- set_intervals_multibyte_1
- set_intervals_multibyte
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41 #include <config.h>
42
43 #include <intprops.h>
44 #include "lisp.h"
45 #include "intervals.h"
46 #include "buffer.h"
47 #include "puresize.h"
48 #include "keymap.h"
49
50
51
52
53 #define TMEM(sym, set) (CONSP (set) ? ! NILP (Fmemq (sym, set)) : ! NILP (set))
54
55 static Lisp_Object merge_properties_sticky (Lisp_Object, Lisp_Object);
56 static INTERVAL merge_interval_right (INTERVAL);
57 static INTERVAL reproduce_tree (INTERVAL, INTERVAL);
58
59
60
61
62
63 static void
64 set_interval_left (INTERVAL i, INTERVAL left)
65 {
66 i->left = left;
67 }
68
69 static void
70 set_interval_right (INTERVAL i, INTERVAL right)
71 {
72 i->right = right;
73 }
74
75
76
77
78 static void
79 copy_interval_parent (INTERVAL d, INTERVAL s)
80 {
81 d->up = s->up;
82 d->up_obj = s->up_obj;
83 }
84
85
86
87 INTERVAL
88 create_root_interval (Lisp_Object parent)
89 {
90 INTERVAL new;
91
92 new = make_interval ();
93
94 if (! STRINGP (parent))
95 {
96 new->total_length = (BUF_Z (XBUFFER (parent))
97 - BUF_BEG (XBUFFER (parent)));
98 eassert (TOTAL_LENGTH (new) >= 0);
99 set_buffer_intervals (XBUFFER (parent), new);
100 new->position = BEG;
101 }
102 else
103 {
104 CHECK_IMPURE (parent, XSTRING (parent));
105 new->total_length = SCHARS (parent);
106 eassert (TOTAL_LENGTH (new) >= 0);
107 set_string_intervals (parent, new);
108 new->position = 0;
109 }
110 eassert (LENGTH (new) > 0);
111
112 set_interval_object (new, parent);
113
114 return new;
115 }
116
117
118
119 void
120 copy_properties (INTERVAL source, INTERVAL target)
121 {
122 if (DEFAULT_INTERVAL_P (source) && DEFAULT_INTERVAL_P (target))
123 return;
124
125 COPY_INTERVAL_CACHE (source, target);
126 set_interval_plist (target, Fcopy_sequence (source->plist));
127 }
128
129
130
131
132
133 static void
134 merge_properties (register INTERVAL source, register INTERVAL target)
135 {
136 register Lisp_Object o, sym, val;
137
138 if (DEFAULT_INTERVAL_P (source) && DEFAULT_INTERVAL_P (target))
139 return;
140
141 MERGE_INTERVAL_CACHE (source, target);
142
143 o = source->plist;
144 while (CONSP (o))
145 {
146 sym = XCAR (o);
147 o = XCDR (o);
148 CHECK_CONS (o);
149
150 val = target->plist;
151 while (CONSP (val) && !EQ (XCAR (val), sym))
152 {
153 val = XCDR (val);
154 if (!CONSP (val))
155 break;
156 val = XCDR (val);
157 }
158
159 if (NILP (val))
160 {
161 val = XCAR (o);
162 set_interval_plist (target, Fcons (sym, Fcons (val, target->plist)));
163 }
164 o = XCDR (o);
165 }
166 }
167
168
169
170
171 static bool
172 intervals_equal_1 (INTERVAL i0, INTERVAL i1, bool use_equal)
173 {
174 Lisp_Object i0_cdr, i0_sym;
175 Lisp_Object i1_cdr, i1_val;
176
177 if (DEFAULT_INTERVAL_P (i0) && DEFAULT_INTERVAL_P (i1))
178 return true;
179
180 if (DEFAULT_INTERVAL_P (i0) || DEFAULT_INTERVAL_P (i1))
181 return false;
182
183 i0_cdr = i0->plist;
184 i1_cdr = i1->plist;
185 while (CONSP (i0_cdr) && CONSP (i1_cdr))
186 {
187 i0_sym = XCAR (i0_cdr);
188 i0_cdr = XCDR (i0_cdr);
189 if (!CONSP (i0_cdr))
190 return false;
191 i1_val = i1->plist;
192 while (CONSP (i1_val) && !EQ (XCAR (i1_val), i0_sym))
193 {
194 i1_val = XCDR (i1_val);
195 if (!CONSP (i1_val))
196 return false;
197 i1_val = XCDR (i1_val);
198 }
199
200
201 if (NILP (i1_val))
202 return false;
203
204
205 if (!CONSP (i1_val)
206 || (i1_val = XCDR (i1_val), !CONSP (i1_val))
207 || use_equal ? NILP (Fequal (XCAR (i1_val), XCAR (i0_cdr)))
208 : !EQ (XCAR (i1_val), XCAR (i0_cdr)))
209 return false;
210
211 i0_cdr = XCDR (i0_cdr);
212
213 i1_cdr = XCDR (i1_cdr);
214 if (!CONSP (i1_cdr))
215 return false;
216 i1_cdr = XCDR (i1_cdr);
217 }
218
219
220 return (NILP (i0_cdr) && NILP (i1_cdr));
221 }
222
223
224
225 bool
226 intervals_equal (INTERVAL i0, INTERVAL i1)
227 {
228 return intervals_equal_1 (i0, i1, false);
229 }
230
231
232
233
234
235
236 void
237 traverse_intervals_noorder (INTERVAL tree, void (*function) (INTERVAL, void *),
238 void *arg)
239 {
240
241 while (tree)
242 {
243 (*function) (tree, arg);
244 if (!tree->right)
245 tree = tree->left;
246 else
247 {
248 traverse_intervals_noorder (tree->left, function, arg);
249 tree = tree->right;
250 }
251 }
252 }
253
254
255
256
257 void
258 traverse_intervals (INTERVAL tree, ptrdiff_t position,
259 void (*function) (INTERVAL, Lisp_Object), Lisp_Object arg)
260 {
261 while (tree)
262 {
263 traverse_intervals (tree->left, position, function, arg);
264 position += LEFT_TOTAL_LENGTH (tree);
265 tree->position = position;
266 (*function) (tree, arg);
267 position += LENGTH (tree); tree = tree->right;
268 }
269 }
270
271
272
273
274
275
276
277
278
279
280 static INTERVAL
281 rotate_right (INTERVAL A)
282 {
283 INTERVAL B = A->left;
284 INTERVAL c = B->right;
285 ptrdiff_t old_total = A->total_length;
286
287 eassert (old_total > 0);
288 eassert (LENGTH (A) > 0);
289 eassert (LENGTH (B) > 0);
290
291
292 if (! ROOT_INTERVAL_P (A))
293 {
294 if (AM_LEFT_CHILD (A))
295 set_interval_left (INTERVAL_PARENT (A), B);
296 else
297 set_interval_right (INTERVAL_PARENT (A), B);
298 }
299 copy_interval_parent (B, A);
300
301
302 set_interval_right (B, A);
303 set_interval_parent (A, B);
304
305
306 set_interval_left (A, c);
307 if (c)
308 set_interval_parent (c, A);
309
310
311 A->total_length -= TOTAL_LENGTH (B) - TOTAL_LENGTH0 (c);
312 eassert (TOTAL_LENGTH (A) > 0);
313 eassert (LENGTH (A) > 0);
314
315
316 B->total_length = old_total;
317 eassert (LENGTH (B) > 0);
318
319 return B;
320 }
321
322
323
324
325
326
327
328
329
330
331 static INTERVAL
332 rotate_left (INTERVAL A)
333 {
334 INTERVAL B = A->right;
335 INTERVAL c = B->left;
336 ptrdiff_t old_total = A->total_length;
337
338 eassert (old_total > 0);
339 eassert (LENGTH (A) > 0);
340 eassert (LENGTH (B) > 0);
341
342
343 if (! ROOT_INTERVAL_P (A))
344 {
345 if (AM_LEFT_CHILD (A))
346 set_interval_left (INTERVAL_PARENT (A), B);
347 else
348 set_interval_right (INTERVAL_PARENT (A), B);
349 }
350 copy_interval_parent (B, A);
351
352
353 set_interval_left (B, A);
354 set_interval_parent (A, B);
355
356
357 set_interval_right (A, c);
358 if (c)
359 set_interval_parent (c, A);
360
361
362 A->total_length -= TOTAL_LENGTH (B) - TOTAL_LENGTH0 (c);
363 eassert (TOTAL_LENGTH (A) > 0);
364 eassert (LENGTH (A) > 0);
365
366
367 B->total_length = old_total;
368 eassert (LENGTH (B) > 0);
369
370 return B;
371 }
372
373
374
375
376 static INTERVAL
377 balance_an_interval (INTERVAL i)
378 {
379 register ptrdiff_t old_diff, new_diff;
380
381 eassert (LENGTH (i) > 0);
382 eassert (TOTAL_LENGTH (i) >= LENGTH (i));
383
384 while (1)
385 {
386 old_diff = LEFT_TOTAL_LENGTH (i) - RIGHT_TOTAL_LENGTH (i);
387 if (old_diff > 0)
388 {
389
390 new_diff = i->total_length - i->left->total_length
391 + RIGHT_TOTAL_LENGTH (i->left) - LEFT_TOTAL_LENGTH (i->left);
392 if (eabs (new_diff) >= old_diff)
393 break;
394 i = rotate_right (i);
395 balance_an_interval (i->right);
396 }
397 else if (old_diff < 0)
398 {
399
400 new_diff = i->total_length - i->right->total_length
401 + LEFT_TOTAL_LENGTH (i->right) - RIGHT_TOTAL_LENGTH (i->right);
402 if (eabs (new_diff) >= -old_diff)
403 break;
404 i = rotate_left (i);
405 balance_an_interval (i->left);
406 }
407 else
408 break;
409 }
410 return i;
411 }
412
413
414
415
416 static INTERVAL
417 balance_possible_root_interval (INTERVAL interval)
418 {
419 Lisp_Object parent;
420 bool have_parent = false;
421
422 if (INTERVAL_HAS_OBJECT (interval))
423 {
424 have_parent = true;
425 GET_INTERVAL_OBJECT (parent, interval);
426 }
427 else if (!INTERVAL_HAS_PARENT (interval))
428 return interval;
429
430 interval = balance_an_interval (interval);
431
432 if (have_parent)
433 {
434 if (BUFFERP (parent))
435 set_buffer_intervals (XBUFFER (parent), interval);
436 else if (STRINGP (parent))
437 set_string_intervals (parent, interval);
438 }
439
440 return interval;
441 }
442
443
444
445
446 static INTERVAL
447 balance_intervals_internal (register INTERVAL tree)
448 {
449
450 if (tree->left)
451 balance_intervals_internal (tree->left);
452 if (tree->right)
453 balance_intervals_internal (tree->right);
454 return balance_an_interval (tree);
455 }
456
457
458
459 INTERVAL
460 balance_intervals (INTERVAL tree)
461 {
462 return tree ? balance_intervals_internal (tree) : NULL;
463 }
464
465
466
467 static void
468 buffer_balance_intervals (struct buffer *b)
469 {
470 INTERVAL i;
471
472 eassert (b != NULL);
473 i = buffer_intervals (b);
474 if (i)
475 set_buffer_intervals (b, balance_an_interval (i));
476 }
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491 INTERVAL
492 split_interval_right (INTERVAL interval, ptrdiff_t offset)
493 {
494 INTERVAL new = make_interval ();
495 ptrdiff_t position = interval->position;
496 ptrdiff_t new_length = LENGTH (interval) - offset;
497
498 new->position = position + offset;
499 set_interval_parent (new, interval);
500
501 if (NULL_RIGHT_CHILD (interval))
502 {
503 set_interval_right (interval, new);
504 new->total_length = new_length;
505 eassert (LENGTH (new) > 0);
506 }
507 else
508 {
509
510 set_interval_right (new, interval->right);
511 set_interval_parent (interval->right, new);
512 set_interval_right (interval, new);
513 new->total_length = new_length + new->right->total_length;
514 balance_an_interval (new);
515 }
516
517 balance_possible_root_interval (interval);
518
519 return new;
520 }
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535 INTERVAL
536 split_interval_left (INTERVAL interval, ptrdiff_t offset)
537 {
538 INTERVAL new = make_interval ();
539 ptrdiff_t new_length = offset;
540
541 new->position = interval->position;
542 interval->position = interval->position + offset;
543 set_interval_parent (new, interval);
544
545 if (NULL_LEFT_CHILD (interval))
546 {
547 set_interval_left (interval, new);
548 new->total_length = new_length;
549 eassert (LENGTH (new) > 0);
550 }
551 else
552 {
553
554 set_interval_left (new, interval->left);
555 set_interval_parent (new->left, new);
556 set_interval_left (interval, new);
557 new->total_length = new_length + new->left->total_length;
558 balance_an_interval (new);
559 }
560
561 balance_possible_root_interval (interval);
562
563 return new;
564 }
565
566
567
568
569
570
571
572
573
574 static int
575 interval_start_pos (INTERVAL source)
576 {
577 Lisp_Object parent;
578
579 if (!source)
580 return 0;
581
582 if (! INTERVAL_HAS_OBJECT (source))
583 return 0;
584 GET_INTERVAL_OBJECT (parent, source);
585 if (BUFFERP (parent))
586 return BUF_BEG (XBUFFER (parent));
587 return 0;
588 }
589
590
591
592
593
594
595
596
597
598
599
600 INTERVAL
601 find_interval (register INTERVAL tree, register ptrdiff_t position)
602 {
603
604
605 register ptrdiff_t relative_position;
606
607 if (!tree)
608 return NULL;
609
610 relative_position = position;
611 if (INTERVAL_HAS_OBJECT (tree))
612 {
613 Lisp_Object parent;
614 GET_INTERVAL_OBJECT (parent, tree);
615 if (BUFFERP (parent))
616 relative_position -= BUF_BEG (XBUFFER (parent));
617 }
618
619 eassert (relative_position <= TOTAL_LENGTH (tree));
620
621 tree = balance_possible_root_interval (tree);
622
623 while (1)
624 {
625 eassert (tree);
626 if (relative_position < LEFT_TOTAL_LENGTH (tree))
627 {
628 tree = tree->left;
629 }
630 else if (! NULL_RIGHT_CHILD (tree)
631 && relative_position >= (TOTAL_LENGTH (tree)
632 - RIGHT_TOTAL_LENGTH (tree)))
633 {
634 relative_position -= (TOTAL_LENGTH (tree)
635 - RIGHT_TOTAL_LENGTH (tree));
636 tree = tree->right;
637 }
638 else
639 {
640 tree->position
641 = (position - relative_position
642 + LEFT_TOTAL_LENGTH (tree));
643
644 return tree;
645 }
646 }
647 }
648
649
650
651
652
653 INTERVAL
654 next_interval (register INTERVAL interval)
655 {
656 register INTERVAL i = interval;
657 register ptrdiff_t next_position;
658
659 if (!i)
660 return NULL;
661 next_position = interval->position + LENGTH (interval);
662
663 if (! NULL_RIGHT_CHILD (i))
664 {
665 i = i->right;
666 while (! NULL_LEFT_CHILD (i))
667 i = i->left;
668
669 i->position = next_position;
670 return i;
671 }
672
673 while (! NULL_PARENT (i))
674 {
675 if (AM_LEFT_CHILD (i))
676 {
677 i = INTERVAL_PARENT (i);
678 i->position = next_position;
679 return i;
680 }
681
682 i = INTERVAL_PARENT (i);
683 }
684
685 return NULL;
686 }
687
688
689
690
691
692 INTERVAL
693 previous_interval (register INTERVAL interval)
694 {
695 register INTERVAL i;
696
697 if (!interval)
698 return NULL;
699
700 if (! NULL_LEFT_CHILD (interval))
701 {
702 i = interval->left;
703 while (! NULL_RIGHT_CHILD (i))
704 i = i->right;
705
706 i->position = interval->position - LENGTH (i);
707 return i;
708 }
709
710 i = interval;
711 while (! NULL_PARENT (i))
712 {
713 if (AM_RIGHT_CHILD (i))
714 {
715 i = INTERVAL_PARENT (i);
716
717 i->position = interval->position - LENGTH (i);
718 return i;
719 }
720 i = INTERVAL_PARENT (i);
721 }
722
723 return NULL;
724 }
725
726
727 #define SET_PARENT_POSITION(i) \
728 if (AM_LEFT_CHILD (i)) \
729 INTERVAL_PARENT (i)->position = \
730 i->position + TOTAL_LENGTH (i) - LEFT_TOTAL_LENGTH (i); \
731 else \
732 INTERVAL_PARENT (i)->position = \
733 i->position - LEFT_TOTAL_LENGTH (i) \
734 - LENGTH (INTERVAL_PARENT (i))
735
736
737
738
739
740
741 INTERVAL
742 update_interval (INTERVAL i, ptrdiff_t pos)
743 {
744 if (!i)
745 return NULL;
746
747 while (1)
748 {
749 if (pos < i->position)
750 {
751
752 if (pos >= i->position - LEFT_TOTAL_LENGTH (i))
753 {
754 i->left->position = i->position - TOTAL_LENGTH (i->left)
755 + LEFT_TOTAL_LENGTH (i->left);
756 i = i->left;
757 }
758 else if (NULL_PARENT (i))
759 error ("Point before start of properties");
760 else
761 {
762 SET_PARENT_POSITION (i);
763 i = INTERVAL_PARENT (i);
764 }
765 continue;
766 }
767 else if (pos >= INTERVAL_LAST_POS (i))
768 {
769
770 if (pos < INTERVAL_LAST_POS (i) + RIGHT_TOTAL_LENGTH (i))
771 {
772 i->right->position = INTERVAL_LAST_POS (i)
773 + LEFT_TOTAL_LENGTH (i->right);
774 i = i->right;
775 }
776 else if (NULL_PARENT (i))
777 error ("Point %"pD"d after end of properties", pos);
778 else
779 {
780 SET_PARENT_POSITION (i);
781 i = INTERVAL_PARENT (i);
782 }
783 continue;
784 }
785 else
786 return i;
787 }
788 }
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803 static INTERVAL
804 adjust_intervals_for_insertion (INTERVAL tree,
805 ptrdiff_t position, ptrdiff_t length)
806 {
807 INTERVAL i;
808 INTERVAL temp;
809 bool eobp = 0;
810 Lisp_Object parent;
811 ptrdiff_t offset;
812
813 eassert (TOTAL_LENGTH (tree) > 0);
814
815 GET_INTERVAL_OBJECT (parent, tree);
816 offset = (BUFFERP (parent) ? BUF_BEG (XBUFFER (parent)) : 0);
817
818
819
820 if (position >= TOTAL_LENGTH (tree) + offset)
821 {
822 position = TOTAL_LENGTH (tree) + offset;
823 eobp = 1;
824 }
825
826 i = find_interval (tree, position);
827
828
829
830
831
832
833
834
835
836
837
838
839 if (! (position == i->position || eobp))
840 {
841 Lisp_Object tail;
842 Lisp_Object front, rear;
843
844 tail = i->plist;
845
846
847
848
849 rear = textget (i->plist, Qrear_nonsticky);
850 if (! CONSP (rear) && ! NILP (rear))
851 {
852
853 goto check_done;
854 }
855 front = textget (i->plist, Qfront_sticky);
856 if (! CONSP (front) && ! NILP (front))
857 {
858
859 tail = Qnil;
860 goto check_done;
861 }
862
863
864
865 for (; CONSP (tail); tail = Fcdr (XCDR (tail)))
866 {
867 Lisp_Object prop, tmp;
868 prop = XCAR (tail);
869
870
871 if (CONSP (front) && ! NILP (Fmemq (prop, front)))
872 continue;
873
874
875 if (CONSP (rear) && ! NILP (Fmemq (prop, rear)))
876 break;
877
878
879
880 tmp = Fassq (prop, Vtext_property_default_nonsticky);
881 if (CONSP (tmp))
882 {
883 if (NILP (tmp))
884 continue;
885 break;
886 }
887
888
889
890 }
891
892 check_done:
893
894 if (! NILP (tail))
895 {
896 temp = split_interval_right (i, position - i->position);
897 copy_properties (i, temp);
898 i = temp;
899 }
900 }
901
902
903
904 if (position == i->position || eobp)
905 {
906 register INTERVAL prev;
907
908 if (position == BEG)
909 prev = 0;
910 else if (eobp)
911 {
912 prev = i;
913 i = 0;
914 }
915 else
916 prev = previous_interval (i);
917
918
919
920
921 for (temp = prev ? prev : i; temp; temp = INTERVAL_PARENT_OR_NULL (temp))
922 {
923 temp->total_length += length;
924 temp = balance_possible_root_interval (temp);
925 }
926
927
928
929
930
931
932
933
934
935
936
937 if (1)
938 {
939 Lisp_Object pleft, pright;
940 struct interval newi;
941
942 RESET_INTERVAL (&newi);
943 pleft = prev ? prev->plist : Qnil;
944 pright = i ? i->plist : Qnil;
945 set_interval_plist (&newi, merge_properties_sticky (pleft, pright));
946
947 if (! prev)
948 {
949 if (! intervals_equal (i, &newi))
950 {
951 i = split_interval_left (i, length);
952 set_interval_plist (i, newi.plist);
953 }
954 }
955 else if (! intervals_equal (prev, &newi))
956 {
957 prev = split_interval_right (prev, position - prev->position);
958 set_interval_plist (prev, newi.plist);
959 if (i && intervals_equal (prev, i))
960 merge_interval_right (prev);
961 }
962
963
964 }
965 else if (! prev && ! NILP (i->plist))
966 {
967
968
969 i = split_interval_left (i, length);
970 }
971 }
972
973
974 else
975 {
976 for (temp = i; temp; temp = INTERVAL_PARENT_OR_NULL (temp))
977 {
978 temp->total_length += length;
979 temp = balance_possible_root_interval (temp);
980 }
981 }
982
983 return tree;
984 }
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025 static Lisp_Object
1026 merge_properties_sticky (Lisp_Object pleft, Lisp_Object pright)
1027 {
1028 Lisp_Object props, front, rear;
1029 Lisp_Object lfront, lrear, rfront, rrear;
1030 Lisp_Object tail1, tail2, sym, lval, rval, cat;
1031 bool use_left, use_right, lpresent;
1032
1033 props = Qnil;
1034 front = Qnil;
1035 rear = Qnil;
1036 lfront = textget (pleft, Qfront_sticky);
1037 lrear = textget (pleft, Qrear_nonsticky);
1038 rfront = textget (pright, Qfront_sticky);
1039 rrear = textget (pright, Qrear_nonsticky);
1040
1041
1042 for (tail1 = pright; CONSP (tail1); tail1 = Fcdr (XCDR (tail1)))
1043 {
1044 Lisp_Object tmp;
1045
1046 sym = XCAR (tail1);
1047
1048
1049 if (EQ (sym, Qrear_nonsticky) || EQ (sym, Qfront_sticky))
1050 continue;
1051
1052 rval = Fcar (XCDR (tail1));
1053 for (tail2 = pleft; CONSP (tail2); tail2 = Fcdr (XCDR (tail2)))
1054 if (EQ (sym, XCAR (tail2)))
1055 break;
1056
1057
1058
1059
1060 lpresent = ! NILP (tail2);
1061 lval = (NILP (tail2) ? Qnil : Fcar (Fcdr (tail2)));
1062
1063
1064
1065
1066 tmp = Fassq (sym, Vtext_property_default_nonsticky);
1067 use_left = (lpresent
1068 && ! (TMEM (sym, lrear)
1069 || (CONSP (tmp) && ! NILP (XCDR (tmp)))));
1070 use_right = (TMEM (sym, rfront)
1071 || (CONSP (tmp) && NILP (XCDR (tmp))));
1072 if (use_left && use_right)
1073 {
1074 if (NILP (lval))
1075 use_left = 0;
1076 else if (NILP (rval))
1077 use_right = 0;
1078 }
1079 if (use_left)
1080 {
1081
1082
1083 props = Fcons (lval, Fcons (sym, props));
1084 if (TMEM (sym, lfront))
1085 front = Fcons (sym, front);
1086 if (TMEM (sym, lrear))
1087 rear = Fcons (sym, rear);
1088 }
1089 else if (use_right)
1090 {
1091 props = Fcons (rval, Fcons (sym, props));
1092 if (TMEM (sym, rfront))
1093 front = Fcons (sym, front);
1094 if (TMEM (sym, rrear))
1095 rear = Fcons (sym, rear);
1096 }
1097 }
1098
1099
1100 for (tail2 = pleft; CONSP (tail2); tail2 = Fcdr (XCDR (tail2)))
1101 {
1102 Lisp_Object tmp;
1103
1104 sym = XCAR (tail2);
1105
1106
1107 if (EQ (sym, Qrear_nonsticky) || EQ (sym, Qfront_sticky))
1108 continue;
1109
1110
1111 for (tail1 = pright; CONSP (tail1); tail1 = Fcdr (XCDR (tail1)))
1112 if (EQ (sym, XCAR (tail1)))
1113 break;
1114 if (! NILP (tail1))
1115 continue;
1116
1117 lval = Fcar (XCDR (tail2));
1118
1119
1120
1121
1122 tmp = Fassq (sym, Vtext_property_default_nonsticky);
1123
1124
1125 if (! (TMEM (sym, lrear) || (CONSP (tmp) && ! NILP (XCDR (tmp)))))
1126 {
1127 props = Fcons (lval, Fcons (sym, props));
1128 if (TMEM (sym, lfront))
1129 front = Fcons (sym, front);
1130 }
1131 else if (TMEM (sym, rfront) || (CONSP (tmp) && NILP (XCDR (tmp))))
1132 {
1133
1134
1135 front = Fcons (sym, front);
1136 if (TMEM (sym, rrear))
1137 rear = Fcons (sym, rear);
1138 }
1139 }
1140 props = Fnreverse (props);
1141 if (! NILP (rear))
1142 props = Fcons (Qrear_nonsticky, Fcons (Fnreverse (rear), props));
1143
1144 cat = textget (props, Qcategory);
1145 if (! NILP (front)
1146 &&
1147
1148
1149 ! (! NILP (cat) && SYMBOLP (cat)
1150 && EQ (Fget (cat, Qfront_sticky), Qt)))
1151 props = Fcons (Qfront_sticky, Fcons (Fnreverse (front), props));
1152 return props;
1153 }
1154
1155
1156
1157
1158
1159
1160 static INTERVAL
1161 delete_node (register INTERVAL i)
1162 {
1163 register INTERVAL migrate, this;
1164 register ptrdiff_t migrate_amt;
1165
1166 if (!i->left)
1167 return i->right;
1168 if (!i->right)
1169 return i->left;
1170
1171 migrate = i->left;
1172 migrate_amt = i->left->total_length;
1173 this = i->right;
1174 this->total_length += migrate_amt;
1175 while (this->left)
1176 {
1177 this = this->left;
1178 this->total_length += migrate_amt;
1179 }
1180 set_interval_left (this, migrate);
1181 set_interval_parent (migrate, this);
1182 eassert (LENGTH (this) > 0);
1183 eassert (LENGTH (i->right) > 0);
1184
1185 return i->right;
1186 }
1187
1188
1189
1190
1191
1192
1193
1194 static void
1195 delete_interval (register INTERVAL i)
1196 {
1197 register INTERVAL parent;
1198 ptrdiff_t amt = LENGTH (i);
1199
1200 eassert (amt <= 0);
1201
1202 if (ROOT_INTERVAL_P (i))
1203 {
1204 Lisp_Object owner;
1205 GET_INTERVAL_OBJECT (owner, i);
1206 parent = delete_node (i);
1207 if (parent)
1208 set_interval_object (parent, owner);
1209
1210 if (BUFFERP (owner))
1211 set_buffer_intervals (XBUFFER (owner), parent);
1212 else if (STRINGP (owner))
1213 set_string_intervals (owner, parent);
1214 else
1215 emacs_abort ();
1216
1217 return;
1218 }
1219
1220 parent = INTERVAL_PARENT (i);
1221 if (AM_LEFT_CHILD (i))
1222 {
1223 set_interval_left (parent, delete_node (i));
1224 if (parent->left)
1225 set_interval_parent (parent->left, parent);
1226 }
1227 else
1228 {
1229 set_interval_right (parent, delete_node (i));
1230 if (parent->right)
1231 set_interval_parent (parent->right, parent);
1232 }
1233 }
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247 static ptrdiff_t
1248 interval_deletion_adjustment (register INTERVAL tree, register ptrdiff_t from,
1249 register ptrdiff_t amount)
1250 {
1251 register ptrdiff_t relative_position = from;
1252
1253 if (!tree)
1254 return 0;
1255
1256
1257 if (relative_position < LEFT_TOTAL_LENGTH (tree))
1258 {
1259 ptrdiff_t subtract = interval_deletion_adjustment (tree->left,
1260 relative_position,
1261 amount);
1262 tree->total_length -= subtract;
1263 eassert (LENGTH (tree) > 0);
1264 return subtract;
1265 }
1266
1267 else if (relative_position >= (TOTAL_LENGTH (tree)
1268 - RIGHT_TOTAL_LENGTH (tree)))
1269 {
1270 ptrdiff_t subtract;
1271
1272 relative_position -= (tree->total_length
1273 - RIGHT_TOTAL_LENGTH (tree));
1274 subtract = interval_deletion_adjustment (tree->right,
1275 relative_position,
1276 amount);
1277 tree->total_length -= subtract;
1278 eassert (LENGTH (tree) > 0);
1279 return subtract;
1280 }
1281
1282 else
1283 {
1284
1285 ptrdiff_t my_amount = ((tree->total_length
1286 - RIGHT_TOTAL_LENGTH (tree))
1287 - relative_position);
1288
1289 if (amount > my_amount)
1290 amount = my_amount;
1291
1292 tree->total_length -= amount;
1293 eassert (LENGTH (tree) >= 0);
1294 if (LENGTH (tree) == 0)
1295 delete_interval (tree);
1296
1297 return amount;
1298 }
1299
1300
1301 }
1302
1303
1304
1305
1306
1307
1308 static void
1309 adjust_intervals_for_deletion (struct buffer *buffer,
1310 ptrdiff_t start, ptrdiff_t length)
1311 {
1312 ptrdiff_t left_to_delete = length;
1313 INTERVAL tree = buffer_intervals (buffer);
1314 Lisp_Object parent;
1315 ptrdiff_t offset;
1316
1317 GET_INTERVAL_OBJECT (parent, tree);
1318 offset = (BUFFERP (parent) ? BUF_BEG (XBUFFER (parent)) : 0);
1319
1320 if (!tree)
1321 return;
1322
1323 eassert (start <= offset + TOTAL_LENGTH (tree)
1324 && start + length <= offset + TOTAL_LENGTH (tree));
1325
1326 if (length == TOTAL_LENGTH (tree))
1327 {
1328 set_buffer_intervals (buffer, NULL);
1329 return;
1330 }
1331
1332 if (ONLY_INTERVAL_P (tree))
1333 {
1334 tree->total_length -= length;
1335 eassert (LENGTH (tree) > 0);
1336 return;
1337 }
1338
1339 if (start > offset + TOTAL_LENGTH (tree))
1340 start = offset + TOTAL_LENGTH (tree);
1341 while (left_to_delete > 0)
1342 {
1343 left_to_delete -= interval_deletion_adjustment (tree, start - offset,
1344 left_to_delete);
1345 tree = buffer_intervals (buffer);
1346 if (left_to_delete == tree->total_length)
1347 {
1348 set_buffer_intervals (buffer, NULL);
1349 return;
1350 }
1351 }
1352 }
1353
1354
1355
1356
1357
1358
1359 void
1360 offset_intervals (struct buffer *buffer, ptrdiff_t start, ptrdiff_t length)
1361 {
1362 if (!buffer_intervals (buffer) || length == 0)
1363 return;
1364
1365 if (length > 0)
1366 adjust_intervals_for_insertion (buffer_intervals (buffer),
1367 start, length);
1368 else
1369 adjust_intervals_for_deletion (buffer, start, -length);
1370 }
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381 static INTERVAL
1382 merge_interval_right (register INTERVAL i)
1383 {
1384 register ptrdiff_t absorb = LENGTH (i);
1385 register INTERVAL successor;
1386
1387
1388 if (! NULL_RIGHT_CHILD (i))
1389
1390 {
1391 successor = i->right;
1392 while (! NULL_LEFT_CHILD (successor))
1393 {
1394 successor->total_length += absorb;
1395 eassert (LENGTH (successor) > 0);
1396 successor = successor->left;
1397 }
1398
1399 successor->total_length += absorb;
1400 eassert (LENGTH (successor) > 0);
1401 delete_interval (i);
1402 return successor;
1403 }
1404
1405
1406 i->total_length -= absorb;
1407 eassert (TOTAL_LENGTH (i) >= 0);
1408
1409 successor = i;
1410 while (! NULL_PARENT (successor))
1411
1412 {
1413 if (AM_LEFT_CHILD (successor))
1414 {
1415 successor = INTERVAL_PARENT (successor);
1416 delete_interval (i);
1417 return successor;
1418 }
1419
1420 successor = INTERVAL_PARENT (successor);
1421 successor->total_length -= absorb;
1422 eassert (LENGTH (successor) > 0);
1423 }
1424
1425
1426
1427 emacs_abort ();
1428 }
1429
1430
1431
1432
1433
1434
1435
1436
1437 INTERVAL
1438 merge_interval_left (register INTERVAL i)
1439 {
1440 register ptrdiff_t absorb = LENGTH (i);
1441 register INTERVAL predecessor;
1442
1443
1444 if (! NULL_LEFT_CHILD (i))
1445
1446 {
1447 predecessor = i->left;
1448 while (! NULL_RIGHT_CHILD (predecessor))
1449 {
1450 predecessor->total_length += absorb;
1451 eassert (LENGTH (predecessor) > 0);
1452 predecessor = predecessor->right;
1453 }
1454
1455 predecessor->total_length += absorb;
1456 eassert (LENGTH (predecessor) > 0);
1457 delete_interval (i);
1458 return predecessor;
1459 }
1460
1461
1462 i->total_length -= absorb;
1463 eassert (TOTAL_LENGTH (i) >= 0);
1464
1465 predecessor = i;
1466 while (! NULL_PARENT (predecessor))
1467
1468 {
1469 if (AM_RIGHT_CHILD (predecessor))
1470 {
1471 predecessor = INTERVAL_PARENT (predecessor);
1472 delete_interval (i);
1473 return predecessor;
1474 }
1475
1476 predecessor = INTERVAL_PARENT (predecessor);
1477 predecessor->total_length -= absorb;
1478 eassert (LENGTH (predecessor) > 0);
1479 }
1480
1481
1482
1483 emacs_abort ();
1484 }
1485
1486
1487
1488 static INTERVAL
1489 reproduce_interval (INTERVAL source)
1490 {
1491 register INTERVAL target = make_interval ();
1492
1493 eassert (LENGTH (source) > 0);
1494
1495 target->total_length = source->total_length;
1496 target->position = source->position;
1497
1498 copy_properties (source, target);
1499
1500 if (! NULL_LEFT_CHILD (source))
1501 set_interval_left (target, reproduce_tree (source->left, target));
1502 if (! NULL_RIGHT_CHILD (source))
1503 set_interval_right (target, reproduce_tree (source->right, target));
1504
1505 eassert (LENGTH (target) > 0);
1506 return target;
1507 }
1508
1509
1510
1511
1512
1513
1514 static INTERVAL
1515 reproduce_tree (INTERVAL source, INTERVAL parent)
1516 {
1517 INTERVAL target = reproduce_interval (source);
1518 set_interval_parent (target, parent);
1519 return target;
1520 }
1521
1522 static INTERVAL
1523 reproduce_tree_obj (INTERVAL source, Lisp_Object parent)
1524 {
1525 INTERVAL target = reproduce_interval (source);
1526 set_interval_object (target, parent);
1527 return target;
1528 }
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567 void
1568 graft_intervals_into_buffer (INTERVAL source, ptrdiff_t position,
1569 ptrdiff_t length, struct buffer *buffer,
1570 bool inherit)
1571 {
1572 INTERVAL tree = buffer_intervals (buffer);
1573 INTERVAL under, over, this;
1574 ptrdiff_t over_used;
1575
1576
1577
1578
1579
1580 if (!source)
1581 {
1582 Lisp_Object buf;
1583 if (!inherit && tree && length > 0)
1584 {
1585 XSETBUFFER (buf, buffer);
1586 set_text_properties_1 (make_fixnum (position),
1587 make_fixnum (position + length),
1588 Qnil, buf,
1589 find_interval (tree, position));
1590 }
1591
1592 buffer_balance_intervals (buffer);
1593 return;
1594 }
1595
1596 eassert (length == TOTAL_LENGTH (source));
1597
1598 if ((BUF_Z (buffer) - BUF_BEG (buffer)) == length)
1599 {
1600
1601
1602 Lisp_Object buf;
1603
1604 XSETBUFFER (buf, buffer);
1605 set_buffer_intervals (buffer, reproduce_tree_obj (source, buf));
1606 buffer_intervals (buffer)->position = BUF_BEG (buffer);
1607 eassert (buffer_intervals (buffer)->up_obj == 1);
1608 return;
1609 }
1610 else if (!tree)
1611 {
1612
1613
1614 Lisp_Object buf;
1615
1616 XSETBUFFER (buf, buffer);
1617 tree = create_root_interval (buf);
1618 }
1619
1620
1621 eassert (TOTAL_LENGTH (tree) > 0);
1622
1623 this = under = find_interval (tree, position);
1624 eassert (under);
1625 over = find_interval (source, interval_start_pos (source));
1626
1627
1628
1629
1630
1631 if (position > under->position)
1632 {
1633 INTERVAL end_unchanged
1634 = split_interval_left (this, position - under->position);
1635 copy_properties (under, end_unchanged);
1636 under->position = position;
1637 }
1638 else
1639 {
1640
1641
1642
1643 INTERVAL prev = previous_interval (under);
1644 (void) prev;
1645 #if 0
1646
1647
1648 if (prev && !END_NONSTICKY_P (prev))
1649 prev = 0;
1650 #endif
1651 }
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665 over_used = 0;
1666 while (over)
1667 {
1668
1669 if (LENGTH (over) - over_used < LENGTH (under))
1670 {
1671 this = split_interval_left (under, LENGTH (over) - over_used);
1672 copy_properties (under, this);
1673 }
1674 else
1675 this = under;
1676
1677
1678
1679 if (inherit)
1680 merge_properties (over, this);
1681 else
1682 copy_properties (over, this);
1683
1684
1685
1686 if (LENGTH (this) == LENGTH (over) - over_used)
1687 {
1688 over = next_interval (over);
1689 over_used = 0;
1690 }
1691 else
1692
1693 over_used += LENGTH (this);
1694
1695
1696 under = next_interval (this);
1697 }
1698
1699 buffer_balance_intervals (buffer);
1700 }
1701
1702
1703
1704
1705
1706
1707 Lisp_Object
1708 textget (Lisp_Object plist, register Lisp_Object prop)
1709 {
1710 return lookup_char_property (plist, prop, 1);
1711 }
1712
1713 Lisp_Object
1714 lookup_char_property (Lisp_Object plist, Lisp_Object prop, bool textprop)
1715 {
1716 Lisp_Object tail, fallback = Qnil;
1717
1718 for (tail = plist; CONSP (tail); tail = Fcdr (XCDR (tail)))
1719 {
1720 register Lisp_Object tem;
1721 tem = XCAR (tail);
1722 if (EQ (prop, tem))
1723 return Fcar (XCDR (tail));
1724 if (EQ (tem, Qcategory))
1725 {
1726 tem = Fcar (XCDR (tail));
1727 if (SYMBOLP (tem))
1728 fallback = Fget (tem, prop);
1729 }
1730 }
1731
1732 if (! NILP (fallback))
1733 return fallback;
1734
1735 tail = Fassq (prop, Vchar_property_alias_alist);
1736 if (! NILP (tail))
1737 {
1738 tail = XCDR (tail);
1739 for (; NILP (fallback) && CONSP (tail); tail = XCDR (tail))
1740 fallback = plist_get (plist, XCAR (tail));
1741 }
1742
1743 if (textprop && NILP (fallback) && CONSP (Vdefault_text_properties))
1744 fallback = plist_get (Vdefault_text_properties, prop);
1745 return fallback;
1746 }
1747
1748
1749
1750
1751
1752 void
1753 temp_set_point_both (struct buffer *buffer,
1754 ptrdiff_t charpos, ptrdiff_t bytepos)
1755 {
1756
1757 eassert (BUF_ZV (buffer) != BUF_ZV_BYTE (buffer) || charpos == bytepos);
1758
1759 eassert (charpos <= bytepos);
1760 eassert (charpos <= BUF_ZV (buffer) || BUF_BEGV (buffer) <= charpos);
1761
1762 SET_BUF_PT_BOTH (buffer, charpos, bytepos);
1763 }
1764
1765
1766
1767 void
1768 temp_set_point (struct buffer *buffer, ptrdiff_t charpos)
1769 {
1770 temp_set_point_both (buffer, charpos,
1771 buf_charpos_to_bytepos (buffer, charpos));
1772 }
1773
1774
1775
1776
1777 void
1778 set_point (ptrdiff_t charpos)
1779 {
1780 set_point_both (charpos, buf_charpos_to_bytepos (current_buffer, charpos));
1781 }
1782
1783
1784
1785 void
1786 set_point_from_marker (Lisp_Object marker)
1787 {
1788 ptrdiff_t charpos = clip_to_bounds (BEGV, marker_position (marker), ZV);
1789 ptrdiff_t bytepos = marker_byte_position (marker);
1790
1791
1792
1793 if (XMARKER (marker)->buffer != current_buffer)
1794 bytepos = buf_charpos_to_bytepos (current_buffer, charpos);
1795 else
1796 bytepos = clip_to_bounds (BEGV_BYTE, bytepos, ZV_BYTE);
1797 set_point_both (charpos, bytepos);
1798 }
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811 static ptrdiff_t
1812 adjust_for_invis_intang (ptrdiff_t pos, ptrdiff_t test_offs, ptrdiff_t adj,
1813 bool test_intang)
1814 {
1815 Lisp_Object invis_propval, invis_overlay;
1816 Lisp_Object test_pos;
1817
1818 if ((adj < 0 && pos + adj < BEGV) || (adj > 0 && pos + adj > ZV))
1819
1820 return pos;
1821
1822 test_pos = make_fixnum (pos + test_offs);
1823
1824 invis_propval
1825 = get_char_property_and_overlay (test_pos, Qinvisible, Qnil,
1826 &invis_overlay);
1827
1828 if ((!test_intang
1829 || ! NILP (Fget_char_property (test_pos, Qintangible, Qnil)))
1830 && TEXT_PROP_MEANS_INVISIBLE (invis_propval)
1831
1832
1833 && (NILP (invis_overlay)
1834
1835 ? (text_property_stickiness (Qinvisible, make_fixnum (pos), Qnil)
1836 == (test_offs == 0 ? 1 : -1))
1837
1838 : (test_offs == 0
1839 ? ! OVERLAY_FRONT_ADVANCE_P (invis_overlay)
1840 : OVERLAY_REAR_ADVANCE_P (invis_overlay))))
1841 pos += adj;
1842
1843 return pos;
1844 }
1845
1846
1847
1848
1849
1850 void
1851 set_point_both (ptrdiff_t charpos, ptrdiff_t bytepos)
1852 {
1853 register INTERVAL to, from, toprev, fromprev;
1854 ptrdiff_t buffer_point;
1855 ptrdiff_t old_position = PT;
1856
1857
1858
1859
1860 bool backwards = charpos < old_position;
1861 bool have_overlays;
1862 ptrdiff_t original_position;
1863
1864 bset_point_before_scroll (current_buffer, Qnil);
1865
1866 if (charpos == PT)
1867 return;
1868
1869
1870 eassert (ZV != ZV_BYTE || charpos == bytepos);
1871
1872
1873
1874
1875 eassert (charpos <= ZV && charpos >= BEGV);
1876
1877 have_overlays = buffer_has_overlays ();
1878
1879
1880
1881 if (!buffer_intervals (current_buffer) && ! have_overlays)
1882 {
1883 temp_set_point_both (current_buffer, charpos, bytepos);
1884 return;
1885 }
1886
1887
1888
1889
1890 to = find_interval (buffer_intervals (current_buffer), charpos);
1891 if (charpos == BEGV)
1892 toprev = 0;
1893 else if (to && to->position == charpos)
1894 toprev = previous_interval (to);
1895 else
1896 toprev = to;
1897
1898 buffer_point = (PT == ZV ? ZV - 1 : PT);
1899
1900
1901
1902
1903
1904 from = find_interval (buffer_intervals (current_buffer), buffer_point);
1905 if (buffer_point == BEGV)
1906 fromprev = 0;
1907 else if (from && from->position == PT)
1908 fromprev = previous_interval (from);
1909 else if (buffer_point != PT)
1910 fromprev = from, from = 0;
1911 else
1912 fromprev = from;
1913
1914
1915 if (to == from && toprev == fromprev && INTERVAL_VISIBLE_P (to)
1916 && ! have_overlays)
1917 {
1918 temp_set_point_both (current_buffer, charpos, bytepos);
1919 return;
1920 }
1921
1922 original_position = charpos;
1923
1924
1925
1926
1927 if (NILP (Vinhibit_point_motion_hooks)
1928 && ((to && toprev)
1929 || have_overlays)
1930
1931
1932 && charpos != BEGV && charpos != ZV)
1933 {
1934 Lisp_Object pos;
1935 Lisp_Object intangible_propval;
1936
1937 if (backwards)
1938 {
1939
1940
1941
1942
1943
1944 charpos = adjust_for_invis_intang (charpos, -1, -1, 1);
1945
1946 XSETINT (pos, charpos);
1947
1948
1949
1950
1951 intangible_propval = Fget_char_property (pos, Qintangible, Qnil);
1952
1953 if (! NILP (intangible_propval))
1954 {
1955 while (XFIXNUM (pos) > BEGV
1956 && EQ (Fget_char_property (make_fixnum (XFIXNUM (pos) - 1),
1957 Qintangible, Qnil),
1958 intangible_propval))
1959 pos = Fprevious_char_property_change (pos, Qnil);
1960
1961
1962
1963
1964
1965
1966 charpos = adjust_for_invis_intang (XFIXNUM (pos), 0, -1, 0);
1967 }
1968 }
1969 else
1970 {
1971
1972
1973
1974
1975
1976 charpos = adjust_for_invis_intang (charpos, 0, 1, 1);
1977
1978 XSETINT (pos, charpos);
1979
1980
1981
1982
1983 intangible_propval = Fget_char_property (make_fixnum (charpos - 1),
1984 Qintangible, Qnil);
1985
1986 if (! NILP (intangible_propval))
1987 {
1988 while (XFIXNUM (pos) < ZV
1989 && EQ (Fget_char_property (pos, Qintangible, Qnil),
1990 intangible_propval))
1991 pos = Fnext_char_property_change (pos, Qnil);
1992
1993
1994
1995
1996
1997
1998 charpos = adjust_for_invis_intang (XFIXNUM (pos), -1, 1, 0);
1999 }
2000 }
2001
2002 bytepos = buf_charpos_to_bytepos (current_buffer, charpos);
2003 }
2004
2005 if (charpos != original_position)
2006 {
2007
2008
2009
2010 to = find_interval (buffer_intervals (current_buffer), charpos);
2011 if (charpos == BEGV)
2012 toprev = 0;
2013 else if (to && to->position == charpos)
2014 toprev = previous_interval (to);
2015 else
2016 toprev = to;
2017 }
2018
2019
2020
2021
2022
2023 temp_set_point_both (current_buffer, charpos, bytepos);
2024
2025
2026
2027
2028 if (NILP (Vinhibit_point_motion_hooks)
2029 && (! intervals_equal (from, to)
2030 || ! intervals_equal (fromprev, toprev)))
2031 {
2032 Lisp_Object leave_after, leave_before, enter_after, enter_before;
2033
2034 if (fromprev)
2035 leave_before = textget (fromprev->plist, Qpoint_left);
2036 else
2037 leave_before = Qnil;
2038
2039 if (from)
2040 leave_after = textget (from->plist, Qpoint_left);
2041 else
2042 leave_after = Qnil;
2043
2044 if (toprev)
2045 enter_before = textget (toprev->plist, Qpoint_entered);
2046 else
2047 enter_before = Qnil;
2048
2049 if (to)
2050 enter_after = textget (to->plist, Qpoint_entered);
2051 else
2052 enter_after = Qnil;
2053
2054 if (! EQ (leave_before, enter_before) && !NILP (leave_before))
2055 call2 (leave_before, make_fixnum (old_position),
2056 make_fixnum (charpos));
2057 if (! EQ (leave_after, enter_after) && !NILP (leave_after))
2058 call2 (leave_after, make_fixnum (old_position),
2059 make_fixnum (charpos));
2060
2061 if (! EQ (enter_before, leave_before) && !NILP (enter_before))
2062 call2 (enter_before, make_fixnum (old_position),
2063 make_fixnum (charpos));
2064 if (! EQ (enter_after, leave_after) && !NILP (enter_after))
2065 call2 (enter_after, make_fixnum (old_position),
2066 make_fixnum (charpos));
2067 }
2068 }
2069
2070
2071
2072
2073 void
2074 move_if_not_intangible (ptrdiff_t position)
2075 {
2076 Lisp_Object pos;
2077 Lisp_Object intangible_propval;
2078
2079 XSETINT (pos, position);
2080
2081 if (! NILP (Vinhibit_point_motion_hooks))
2082
2083 ;
2084 else if (PT < position && XFIXNUM (pos) < ZV)
2085 {
2086
2087
2088 intangible_propval = Fget_char_property (pos,
2089 Qintangible, Qnil);
2090
2091
2092
2093 if (! NILP (intangible_propval))
2094 while (XFIXNUM (pos) > BEGV
2095 && EQ (Fget_char_property (make_fixnum (XFIXNUM (pos) - 1),
2096 Qintangible, Qnil),
2097 intangible_propval))
2098 pos = Fprevious_char_property_change (pos, Qnil);
2099 }
2100 else if (XFIXNUM (pos) > BEGV)
2101 {
2102
2103
2104 intangible_propval = Fget_char_property (make_fixnum (XFIXNUM (pos) - 1),
2105 Qintangible, Qnil);
2106
2107
2108
2109 if (! NILP (intangible_propval))
2110 while (XFIXNUM (pos) < ZV
2111 && EQ (Fget_char_property (pos, Qintangible, Qnil),
2112 intangible_propval))
2113 pos = Fnext_char_property_change (pos, Qnil);
2114
2115 }
2116 else if (position < BEGV)
2117 position = BEGV;
2118 else if (position > ZV)
2119 position = ZV;
2120
2121
2122
2123
2124
2125 if (XFIXNUM (pos) != PT)
2126 SET_PT (position);
2127 }
2128
2129
2130
2131
2132
2133
2134
2135
2136 bool
2137 get_property_and_range (ptrdiff_t pos, Lisp_Object prop, Lisp_Object *val,
2138 ptrdiff_t *start, ptrdiff_t *end, Lisp_Object object)
2139 {
2140 INTERVAL i, prev, next;
2141
2142 if (NILP (object))
2143 i = find_interval (buffer_intervals (current_buffer), pos);
2144 else if (BUFFERP (object))
2145 i = find_interval (buffer_intervals (XBUFFER (object)), pos);
2146 else if (STRINGP (object))
2147 i = find_interval (string_intervals (object), pos);
2148 else
2149 emacs_abort ();
2150
2151 if (!i || (i->position + LENGTH (i) <= pos))
2152 return 0;
2153 *val = textget (i->plist, prop);
2154 if (NILP (*val))
2155 return 0;
2156
2157 next = i;
2158 prev = previous_interval (i);
2159 while (prev
2160 && EQ (*val, textget (prev->plist, prop)))
2161 i = prev, prev = previous_interval (prev);
2162 *start = i->position;
2163
2164 next = next_interval (i);
2165 while (next && EQ (*val, textget (next->plist, prop)))
2166 i = next, next = next_interval (next);
2167 *end = i->position + LENGTH (i);
2168
2169 return 1;
2170 }
2171
2172
2173
2174
2175
2176
2177 Lisp_Object
2178 get_local_map (ptrdiff_t position, struct buffer *buffer, Lisp_Object type)
2179 {
2180 Lisp_Object prop, lispy_position, lispy_buffer;
2181 ptrdiff_t old_begv, old_zv, old_begv_byte, old_zv_byte;
2182 specpdl_ref count = SPECPDL_INDEX ();
2183
2184 position = clip_to_bounds (BUF_BEGV (buffer), position, BUF_ZV (buffer));
2185
2186
2187
2188 old_begv = BUF_BEGV (buffer);
2189 old_zv = BUF_ZV (buffer);
2190 old_begv_byte = BUF_BEGV_BYTE (buffer);
2191 old_zv_byte = BUF_ZV_BYTE (buffer);
2192
2193 specbind (Qinhibit_quit, Qt);
2194 SET_BUF_BEGV_BOTH (buffer, BUF_BEG (buffer), BUF_BEG_BYTE (buffer));
2195 SET_BUF_ZV_BOTH (buffer, BUF_Z (buffer), BUF_Z_BYTE (buffer));
2196
2197 XSETFASTINT (lispy_position, position);
2198 XSETBUFFER (lispy_buffer, buffer);
2199
2200
2201
2202 prop = Fget_char_property (lispy_position, type, lispy_buffer);
2203
2204
2205
2206 if (NILP (prop))
2207 prop = Fget_pos_property (lispy_position, type, lispy_buffer);
2208
2209 SET_BUF_BEGV_BOTH (buffer, old_begv, old_begv_byte);
2210 SET_BUF_ZV_BOTH (buffer, old_zv, old_zv_byte);
2211 unbind_to (count, Qnil);
2212
2213
2214 prop = get_keymap (prop, 0, 0);
2215 if (CONSP (prop))
2216 return prop;
2217
2218 if (EQ (type, Qkeymap))
2219 return Qnil;
2220 else
2221 return BVAR (buffer, keymap);
2222 }
2223
2224
2225
2226
2227
2228 INTERVAL
2229 copy_intervals (INTERVAL tree, ptrdiff_t start, ptrdiff_t length)
2230 {
2231 register INTERVAL i, new, t;
2232 register ptrdiff_t got, prevlen;
2233
2234 if (!tree || length <= 0)
2235 return NULL;
2236
2237 i = find_interval (tree, start);
2238 eassert (i && LENGTH (i) > 0);
2239
2240
2241 if ((start - i->position + 1 + length) < LENGTH (i)
2242 && DEFAULT_INTERVAL_P (i))
2243 return NULL;
2244
2245 new = make_interval ();
2246 new->position = 0;
2247 got = (LENGTH (i) - (start - i->position));
2248 new->total_length = length;
2249 eassert (TOTAL_LENGTH (new) >= 0);
2250 copy_properties (i, new);
2251
2252 t = new;
2253 prevlen = got;
2254 while (got < length)
2255 {
2256 i = next_interval (i);
2257 t = split_interval_right (t, prevlen);
2258 copy_properties (i, t);
2259 prevlen = LENGTH (i);
2260 got += prevlen;
2261 }
2262
2263 return balance_an_interval (new);
2264 }
2265
2266
2267
2268 void
2269 copy_intervals_to_string (Lisp_Object string, struct buffer *buffer,
2270 ptrdiff_t position, ptrdiff_t length)
2271 {
2272 INTERVAL interval_copy = copy_intervals (buffer_intervals (buffer),
2273 position, length);
2274 if (!interval_copy)
2275 return;
2276
2277 set_interval_object (interval_copy, string);
2278 set_string_intervals (string, interval_copy);
2279 }
2280
2281
2282
2283
2284 bool
2285 compare_string_intervals (Lisp_Object s1, Lisp_Object s2)
2286 {
2287 INTERVAL i1, i2;
2288 ptrdiff_t pos = 0;
2289 ptrdiff_t end = SCHARS (s1);
2290
2291 i1 = find_interval (string_intervals (s1), 0);
2292 i2 = find_interval (string_intervals (s2), 0);
2293
2294 while (pos < end)
2295 {
2296
2297 ptrdiff_t len1 = (i1 != 0 ? INTERVAL_LAST_POS (i1) : end) - pos;
2298 ptrdiff_t len2 = (i2 != 0 ? INTERVAL_LAST_POS (i2) : end) - pos;
2299 ptrdiff_t distance = min (len1, len2);
2300
2301
2302
2303 if (! intervals_equal_1 (i1, i2, true))
2304 return 0;
2305
2306
2307
2308 pos += distance;
2309 if (len1 == distance)
2310 i1 = next_interval (i1);
2311 if (len2 == distance)
2312 i2 = next_interval (i2);
2313 }
2314 return 1;
2315 }
2316
2317
2318
2319
2320
2321
2322 static void
2323 set_intervals_multibyte_1 (INTERVAL i, bool multi_flag,
2324 ptrdiff_t start, ptrdiff_t start_byte,
2325 ptrdiff_t end, ptrdiff_t end_byte)
2326 {
2327
2328 if (multi_flag)
2329 i->total_length = end - start;
2330 else
2331 i->total_length = end_byte - start_byte;
2332 eassert (TOTAL_LENGTH (i) >= 0);
2333
2334 if (TOTAL_LENGTH (i) == 0)
2335 {
2336
2337 i->left = NULL;
2338 i->right = NULL;
2339 delete_interval (i);
2340 return;
2341 }
2342
2343
2344 if (i->left)
2345 {
2346 ptrdiff_t left_end, left_end_byte;
2347
2348 if (multi_flag)
2349 {
2350 left_end_byte
2351 = advance_to_char_boundary (start_byte + LEFT_TOTAL_LENGTH (i));
2352 left_end = BYTE_TO_CHAR (left_end_byte);
2353 eassert (CHAR_TO_BYTE (left_end) == left_end_byte);
2354 }
2355 else
2356 {
2357 left_end = start + LEFT_TOTAL_LENGTH (i);
2358 left_end_byte = CHAR_TO_BYTE (left_end);
2359 }
2360
2361 set_intervals_multibyte_1 (i->left, multi_flag, start, start_byte,
2362 left_end, left_end_byte);
2363 }
2364 if (i->right)
2365 {
2366 ptrdiff_t right_start_byte, right_start;
2367
2368 if (multi_flag)
2369 {
2370 right_start_byte
2371 = advance_to_char_boundary (end_byte - RIGHT_TOTAL_LENGTH (i));
2372 right_start = BYTE_TO_CHAR (right_start_byte);
2373 eassert (CHAR_TO_BYTE (right_start) == right_start_byte);
2374 }
2375 else
2376 {
2377 right_start = end - RIGHT_TOTAL_LENGTH (i);
2378 right_start_byte = CHAR_TO_BYTE (right_start);
2379 }
2380
2381 set_intervals_multibyte_1 (i->right, multi_flag,
2382 right_start, right_start_byte,
2383 end, end_byte);
2384 }
2385
2386
2387
2388
2389 if (LEFT_TOTAL_LENGTH (i) + RIGHT_TOTAL_LENGTH (i) >= TOTAL_LENGTH (i))
2390 {
2391 if ((i)->left)
2392 {
2393 set_interval_plist (i, i->left->plist);
2394 (i)->left->total_length = 0;
2395 delete_interval ((i)->left);
2396 }
2397 else
2398 {
2399 set_interval_plist (i, i->right->plist);
2400 (i)->right->total_length = 0;
2401 delete_interval ((i)->right);
2402 }
2403 }
2404 }
2405
2406
2407
2408
2409
2410 void
2411 set_intervals_multibyte (bool multi_flag)
2412 {
2413 INTERVAL i = buffer_intervals (current_buffer);
2414
2415 if (i)
2416 set_intervals_multibyte_1 (i, multi_flag, BEG, BEG_BYTE, Z, Z_BYTE);
2417 }