aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJoseph Arceneaux1992-09-19 01:11:21 +0000
committerJoseph Arceneaux1992-09-19 01:11:21 +0000
commit90ba40fc70903dbf33dc131c767a0e00c6fc1dd6 (patch)
treee351f47d56422736f7b638aef7c85946448a72d5 /src
parentcfe158ab3463c1ed31e78719daaafaedb875bea1 (diff)
downloademacs-90ba40fc70903dbf33dc131c767a0e00c6fc1dd6.tar.gz
emacs-90ba40fc70903dbf33dc131c767a0e00c6fc1dd6.zip
entered into RCS
Diffstat (limited to 'src')
-rw-r--r--src/intervals.c147
-rw-r--r--src/intervals.h214
2 files changed, 319 insertions, 42 deletions
diff --git a/src/intervals.c b/src/intervals.c
index 8a985199f8e..0a653748da9 100644
--- a/src/intervals.c
+++ b/src/intervals.c
@@ -345,24 +345,28 @@ rotate_left (interval)
345 return B; 345 return B;
346} 346}
347 347
348/* Split an interval into two. The second (RIGHT) half is returned as 348/* Split INTERVAL into two pieces, starting the second piece at character
349 the new interval. The size and position of the interval being split are 349 position OFFSET (counting from 1), relative to INTERVAL. The right-hand
350 stored within it, having been found by find_interval (). The properties 350 piece (second, lexicographically) is returned.
351 are reset; it is up to the caller to do the right thing. 351
352 The size and position fields of the two intervals are set based upon
353 those of the original interval. The property list of the new interval
354 is reset, thus it is up to the caller to do the right thing with the
355 result.
352 356
353 Note that this does not change the position of INTERVAL; if it is a root, 357 Note that this does not change the position of INTERVAL; if it is a root,
354 it is still a root after this operation. */ 358 it is still a root after this operation. */
355 359
356INTERVAL 360INTERVAL
357split_interval_right (interval, relative_position) 361split_interval_right (interval, offset)
358 INTERVAL interval; 362 INTERVAL interval;
359 int relative_position; 363 int offset;
360{ 364{
361 INTERVAL new = make_interval (); 365 INTERVAL new = make_interval ();
362 int position = interval->position; 366 int position = interval->position;
363 int new_length = LENGTH (interval) - relative_position + 1; 367 int new_length = LENGTH (interval) - offset + 1;
364 368
365 new->position = position + relative_position - 1; 369 new->position = position + offset - 1;
366 new->parent = interval; 370 new->parent = interval;
367#if 0 371#if 0
368 copy_properties (interval, new); 372 copy_properties (interval, new);
@@ -386,22 +390,26 @@ split_interval_right (interval, relative_position)
386 return new; 390 return new;
387} 391}
388 392
389/* Split an interval into two. The first (LEFT) half is returned as 393/* Split INTERVAL into two pieces, starting the second piece at character
390 the new interval. The size and position of the interval being split 394 position OFFSET (counting from 1), relative to INTERVAL. The left-hand
391 are stored within it, having been found by find_interval (). The 395 piece (first, lexicographically) is returned.
392 properties are reset; it is up to the caller to do the right thing.
393 396
394 Note that this does not change the position of INTERVAL in the tree; if it 397 The size and position fields of the two intervals are set based upon
395 is a root, it is still a root after this operation. */ 398 those of the original interval. The property list of the new interval
399 is reset, thus it is up to the caller to do the right thing with the
400 result.
401
402 Note that this does not change the position of INTERVAL; if it is a root,
403 it is still a root after this operation. */
396 404
397INTERVAL 405INTERVAL
398split_interval_left (interval, relative_position) 406split_interval_left (interval, offset)
399 INTERVAL interval; 407 INTERVAL interval;
400 int relative_position; 408 int offset;
401{ 409{
402 INTERVAL new = make_interval (); 410 INTERVAL new = make_interval ();
403 int position = interval->position; 411 int position = interval->position;
404 int new_length = relative_position - 1; 412 int new_length = offset - 1;
405 413
406#if 0 414#if 0
407 copy_properties (interval, new); 415 copy_properties (interval, new);
@@ -409,7 +417,7 @@ split_interval_left (interval, relative_position)
409 417
410 new->position = interval->position; 418 new->position = interval->position;
411 419
412 interval->position = interval->position + relative_position - 1; 420 interval->position = interval->position + offset - 1;
413 new->parent = interval; 421 new->parent = interval;
414 422
415 if (NULL_LEFT_CHILD (interval)) 423 if (NULL_LEFT_CHILD (interval))
@@ -429,10 +437,15 @@ split_interval_left (interval, relative_position)
429 return new; 437 return new;
430} 438}
431 439
432/* Find the interval containing POSITION in TREE. POSITION is relative 440/* Find the interval containing text position POSITION in the text
433 to the start of TREE. */ 441 represented by the interval tree TREE. POSITION is relative to
442 the beginning of that text.
434 443
435INTERVAL 444 The `position' field, which is a cache of an interval's position,
445 is updated in the interval found. Other functions (e.g., next_interval)
446 will update this cache based on the result of find_interval. */
447
448INLINE INTERVAL
436find_interval (tree, position) 449find_interval (tree, position)
437 register INTERVAL tree; 450 register INTERVAL tree;
438 register int position; 451 register int position;
@@ -471,10 +484,8 @@ find_interval (tree, position)
471} 484}
472 485
473/* Find the succeeding interval (lexicographically) to INTERVAL. 486/* Find the succeeding interval (lexicographically) to INTERVAL.
474 Sets the `position' field based on that of INTERVAL. 487 Sets the `position' field based on that of INTERVAL (see
475 488 find_interval). */
476 Note that those values are only correct if they were also correct
477 in INTERVAL. */
478 489
479INTERVAL 490INTERVAL
480next_interval (interval) 491next_interval (interval)
@@ -513,10 +524,8 @@ next_interval (interval)
513} 524}
514 525
515/* Find the preceding interval (lexicographically) to INTERVAL. 526/* Find the preceding interval (lexicographically) to INTERVAL.
516 Sets the `position' field based on that of INTERVAL. 527 Sets the `position' field based on that of INTERVAL (see
517 528 find_interval). */
518 Note that those values are only correct if they were also correct
519 in INTERVAL. */
520 529
521INTERVAL 530INTERVAL
522previous_interval (interval) 531previous_interval (interval)
@@ -554,6 +563,7 @@ previous_interval (interval)
554 return NULL_INTERVAL; 563 return NULL_INTERVAL;
555} 564}
556 565
566#if 0
557/* Traverse a path down the interval tree TREE to the interval 567/* Traverse a path down the interval tree TREE to the interval
558 containing POSITION, adjusting all nodes on the path for 568 containing POSITION, adjusting all nodes on the path for
559 an addition of LENGTH characters. Insertion between two intervals 569 an addition of LENGTH characters. Insertion between two intervals
@@ -610,6 +620,59 @@ adjust_intervals_for_insertion (tree, position, length)
610 } 620 }
611 } 621 }
612} 622}
623#endif
624
625/* Effect an adjustment corresponding to the addition of LENGTH characters
626 of text. Do this by finding the interval containing POSITION in the
627 interval tree TREE, and then adjusting all of it's ancestors by adding
628 LENGTH to them.
629
630 If POSITION is the first character of an interval, meaning that point
631 is actually between the two intervals, make the new text belong to
632 the interval which is "sticky".
633
634 If both intervals are "stick", then make them belong to the left-most
635 interval. Another possibility would be to create a new interval for
636 this text, and make it have the merged properties of both ends. */
637
638static INTERVAL
639adjust_intervals_for_insertion (tree, position, length)
640 INTERVAL tree;
641 int position, length;
642{
643 register INTERVAL i;
644
645 if (TOTAL_LENGTH (tree) == 0) /* Paranoia */
646 abort ();
647
648 /* If inserting at point-max of a buffer, that position
649 will be out of range. */
650 if (position > TOTAL_LENGTH (tree))
651 position = TOTAL_LENGTH (tree);
652
653 i = find_interval (tree, position);
654 /* If we are positioned between intervals, check the stickiness of
655 both of them. */
656 if (position == i->position
657 && position != 1)
658 {
659 register prev = previous_interval (i);
660
661 /* If both intervals are sticky here, then default to the
662 left-most one. But perhaps we should create a new
663 interval here instead... */
664 if (END_STICKY (prev))
665 i = prev;
666 }
667
668 while (! NULL_INTERVAL_P (i))
669 {
670 i->total_length += length;
671 i = i->parent
672 }
673
674 return tree;
675}
613 676
614/* Merge interval I with its lexicographic successor. Note that 677/* Merge interval I with its lexicographic successor. Note that
615 this does not deal with the properties, or delete I. */ 678 this does not deal with the properties, or delete I. */
@@ -697,8 +760,8 @@ merge_interval_left (i)
697 return NULL_INTERVAL; 760 return NULL_INTERVAL;
698} 761}
699 762
700/* Delete an interval node from its btree by merging its subtrees 763/* Delete an node I from its interval tree by merging its subtrees
701 into one subtree which is returned. Caller is responsible for 764 into one subtree which is then returned. Caller is responsible for
702 storing the resulting subtree into its parent. */ 765 storing the resulting subtree into its parent. */
703 766
704static INTERVAL 767static INTERVAL
@@ -1002,7 +1065,7 @@ map_intervals (source, destination, position)
1002 1065
1003 If the inserted text had no intervals associated, this function 1066 If the inserted text had no intervals associated, this function
1004 simply returns -- offset_intervals should handle placing the 1067 simply returns -- offset_intervals should handle placing the
1005 text in the correct interval, depending on the hungry bits. 1068 text in the correct interval, depending on the sticky bits.
1006 1069
1007 If the inserted text had properties (intervals), then there are two 1070 If the inserted text had properties (intervals), then there are two
1008 cases -- either insertion happened in the middle of some interval, 1071 cases -- either insertion happened in the middle of some interval,
@@ -1015,12 +1078,12 @@ map_intervals (source, destination, position)
1015 of the text into which it was inserted. 1078 of the text into which it was inserted.
1016 1079
1017 If the text goes between two intervals, then if neither interval 1080 If the text goes between two intervals, then if neither interval
1018 had its appropriate hungry property set (front_hungry, rear_hungry), 1081 had its appropriate sticky property set (front_sticky, rear_sticky),
1019 the new text has only its properties. If one of the hungry properties 1082 the new text has only its properties. If one of the sticky properties
1020 is set, then the new text "sticks" to that region and its properties 1083 is set, then the new text "sticks" to that region and its properties
1021 depend on merging as above. If both the preceding and succeding 1084 depend on merging as above. If both the preceding and succeding
1022 intervals to the new text are "hungry", then the new text retains 1085 intervals to the new text are "sticky", then the new text retains
1023 only its properties, as if neither hungry property were set. Perhaps 1086 only its properties, as if neither sticky property were set. Perhaps
1024 we should consider merging all three sets of properties onto the new 1087 we should consider merging all three sets of properties onto the new
1025 text... */ 1088 text... */
1026 1089
@@ -1088,7 +1151,7 @@ graft_intervals_into_buffer (new_tree, position, b)
1088 /* First interval -- none precede it. */ 1151 /* First interval -- none precede it. */
1089 if (position == 1) 1152 if (position == 1)
1090 { 1153 {
1091 if (! under->front_hungry) 1154 if (! FRONT_STICKY (under))
1092 /* The inserted string keeps its own properties. */ 1155 /* The inserted string keeps its own properties. */
1093 while (! NULL_INTERVAL_P (over)) 1156 while (! NULL_INTERVAL_P (over))
1094 { 1157 {
@@ -1115,10 +1178,10 @@ graft_intervals_into_buffer (new_tree, position, b)
1115 if (NULL_INTERVAL_P (prev)) 1178 if (NULL_INTERVAL_P (prev))
1116 abort (); 1179 abort ();
1117 1180
1118 if (prev->rear_hungry) 1181 if (END_STICKY (prev))
1119 { 1182 {
1120 if (under->front_hungry) 1183 if (FRONT_STICKY (under))
1121 /* The intervals go inbetween as the two hungry 1184 /* The intervals go inbetween as the two sticky
1122 properties cancel each other. Should we change 1185 properties cancel each other. Should we change
1123 this policy? */ 1186 this policy? */
1124 while (! NULL_INTERVAL_P (over)) 1187 while (! NULL_INTERVAL_P (over))
@@ -1142,7 +1205,7 @@ graft_intervals_into_buffer (new_tree, position, b)
1142 } 1205 }
1143 else 1206 else
1144 { 1207 {
1145 if (under->front_hungry) 1208 if (FRONT_STICKY (under))
1146 /* The intervals stick to under */ 1209 /* The intervals stick to under */
1147 while (! NULL_INTERVAL_P (over)) 1210 while (! NULL_INTERVAL_P (over))
1148 { 1211 {
@@ -1334,7 +1397,7 @@ verify_interval_modification (buf, start, end)
1334 abort (); 1397 abort ();
1335 1398
1336 i = find_interval (intervals, start - 1); 1399 i = find_interval (intervals, start - 1);
1337 if (! END_HUNGRY_P (i)) 1400 if (! END_STICKY_P (i))
1338 return; 1401 return;
1339 } 1402 }
1340 else 1403 else
diff --git a/src/intervals.h b/src/intervals.h
new file mode 100644
index 00000000000..48d3daeaad1
--- /dev/null
+++ b/src/intervals.h
@@ -0,0 +1,214 @@
1/* Definitions and global variables for intervals.
2 Copyright (C) 1990, 1992 Free Software Foundation, Inc.
3
4This file is part of GNU Emacs.
5
6GNU Emacs is free software; you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
8the Free Software Foundation; either version 1, or (at your option)
9any later version.
10
11GNU Emacs is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with GNU Emacs; see the file COPYING. If not, write to
18the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
19
20#ifdef USE_INTERVALS
21#include "dispextern.h"
22
23#define NULL_INTERVAL 0
24#define INTERVAL_DEFAULT NULL_INTERVAL
25
26/* These are macros for dealing with the interval tree. */
27
28/* Size of the structure used to represent an interval */
29#define INTERVAL_SIZE (sizeof (struct interval))
30
31/* Size of a pointer to an interval structure */
32#define INTERVAL_PTR_SIZE (sizeof (struct interval *))
33
34/* True if an interval pointer is null, or is a Lisp_Buffer or
35 Lisp_String pointer (meaning it points to the owner of this
36 interval tree.) */
37#define NULL_INTERVAL_P(i) ((i) == NULL_INTERVAL || \
38 XTYPE ((Lisp_Object)(i)) == Lisp_Buffer || \
39 XTYPE ((Lisp_Object)(i)) == Lisp_String)
40
41/* True if this interval has no right child. */
42#define NULL_RIGHT_CHILD(i) (NULL_INTERVAL_P((i)->right))
43
44/* True if this interval has no left child. */
45#define NULL_LEFT_CHILD(i) (NULL_INTERVAL_P((i)->left))
46
47/* True if this interval has no parent. */
48#define NULL_PARENT(i) (NULL_INTERVAL_P((i)->parent))
49
50/* True if this interval is the left child of some other interval. */
51#define AM_LEFT_CHILD(i) (! NULL_INTERVAL_P ((i)->parent) \
52 && (i)->parent->left == (i))
53
54/* True if this interval is the right ehild of some other interval. */
55#define AM_RIGHT_CHILD(i) (! NULL_INTERVAL_P ((i)->parent) \
56 && (i)->parent->right == (i))
57
58/* True if this interval has no children. */
59#define LEAF_INTERVAL_P(i) ((i)->left == NULL_INTERVAL \
60 && (i)->right == NULL_INTERVAL)
61
62/* True if this interval has no parent and is therefore the root. */
63#define ROOT_INTERVAL_P(i) (NULL_PARENT (i))
64
65/* True if this interval is the only interval in the interval tree. */
66#define ONLY_INTERVAL_P(i) (ROOT_INTERVAL_P((i)) && LEAF_INTERVAL_P ((i)))
67
68/* True if this interval has both left and right children. */
69#define BOTH_KIDS_P(i) ((i)->left != NULL_INTERVAL \
70 && (i)->right != NULL_INTERVAL)
71
72/* The total size of all text represented by this interval and all its
73 children in the tree. This is zero if the interval is null. */
74#define TOTAL_LENGTH(i) ((i) == NULL_INTERVAL ? 0 : (i)->total_length)
75
76/* The size of text represented by this interval alone. */
77#define LENGTH(i) ((i) == NULL_INTERVAL ? 0 : (TOTAL_LENGTH ((i)) \
78 - TOTAL_LENGTH ((i)->right) \
79 - TOTAL_LENGTH ((i)->left)))
80
81/* The absolute index of the last character belonging to I. Note that
82 the position cache i->position must be valid for this to work. */
83#define INTERVAL_LAST_POS(i) ((i)->position + LENGTH ((i)) - 1)
84
85/* The total size of the left subtree of this interval. */
86#define LEFT_TOTAL_LENGTH(i) ((i)->left ? (i)->left->total_length : 0)
87
88/* The total size of the right subtree of this interval. */
89#define RIGHT_TOTAL_LENGTH(i) ((i)->right ? (i)->right->total_length : 0)
90
91
92/* These macros are for dealing with the interval properties. */
93
94/* True if this is a default interval, which is the same as being null
95 or having no properties. */
96#define DEFAULT_INTERVAL_P(i) (NULL_INTERVAL_P (i) || EQ ((i)->plist, Qnil))
97
98/* Reset this interval to its vanilla, or no-property state. */
99#define RESET_INTERVAL(i) { \
100 (i)->total_length = (i)->position = 0; \
101 (i)->left = (i)->right = NULL_INTERVAL; \
102 (i)->parent = NULL_INTERVAL; \
103 (i)->write_protect = 0; \
104 (i)->visible = 0; \
105 (i)->front_sticky = (i)->rear_sticky = 0; \
106 (i)->plist = Qnil; \
107 }
108
109/* Copy the cached property values of interval FROM to interval TO. */
110#define COPY_INTERVAL_CACHE(from,to) \
111{ \
112 (to)->write_protect = (from)->write_protect; \
113 (to)->visible = (from)->visible; \
114 (to)->front_sticky = (from)->front_sticky; \
115 (to)->rear_sticky = (from)->rear_sticky; \
116}
117
118/* Copy only the set bits of FROM's cache. */
119#define MERGE_INTERVAL_CACHE(from,to) \
120{ \
121 if ((from)->write_protect) (to)->write_protect = 1; \
122 if ((from)->visible) (to)->visible = 1; \
123 if ((from)->front_sticky) (to)->front_sticky = 1; \
124 if ((from)->rear_sticky) (to)->rear_sticky = 1; \
125}
126
127/* Macro determining whether the properties of an interval being
128 inserted should be merged with the properties of the text where
129 they are being inserted. */
130#define MERGE_INSERTIONS(i) 0
131
132/* Macro determining if an invisible interval should be displayed
133 as a special glyph, or not at all. */
134#define DISPLAY_INVISIBLE_GLYPH(i) 0
135
136/* Is this interval visible? Replace later with cache access */
137#define INTERVAL_VISIBLE_P(i) \
138 (! NULL_INTERVAL_P (i) && ! NILP (Fmemq (Qinvisible, (i)->plist)))
139
140/* Is this interval writable? Replace later with cache access */
141#define INTERVAL_WRITABLE_P(i) \
142 (! NULL_INTERVAL_P (i) && NILP (Fmemq (Qread_only, (i)->plist)))
143
144/* Macros to tell whether insertions before or after this interval
145 should stick to it. */
146#define FRONT_STICKY_P(i) ((i)->front_sticky != 0)
147#define END_STICKY_P(i) ((i)->rear_sticky != 0)
148
149
150/* Declared in alloc.c */
151
152extern INTERVAL make_interval ();
153
154/* Declared in intervals.c */
155
156extern INTERVAL mouse_interval;
157extern Lisp_Object Vmouse_buffer;
158extern int mouse_buffer_offset;
159extern Lisp_Object interval_balance_threshold;
160
161extern INTERVAL create_root_interval ();
162extern void copy_properties ();
163extern int intervals_equal ();
164extern void traverse_intervals ();
165extern INTERVAL split_interval_right (), split_interval_left ();
166extern INTERVAL find_interval (), next_interval (), previous_interval ();
167extern INTERVAL merge_interval_left (), merge_interval_right ();
168extern void delete_interval ();
169extern INLINE void offset_intervals ();
170extern void map_intervals ();
171extern void graft_intervals_into_buffer ();
172extern void set_point ();
173extern void verify_interval_modification ();
174extern INTERVAL balance_intervals ();
175extern void insert_interval_copy();
176extern void copy_intervals_to_string ();
177extern INTERVAL make_string_interval ();
178extern INTERVAL make_buffer_interval ();
179
180/* Declared in textprop.c */
181
182/* Types of hooks. */
183extern Lisp_Object Qmouse_left;
184extern Lisp_Object Qmouse_entered;
185extern Lisp_Object Qpoint_left;
186extern Lisp_Object Qpoint_entered;
187extern Lisp_Object Qmodification;
188
189/* Visual properties text (including strings) may have. */
190extern Lisp_Object Qforeground, Qbackground, Qfont, Qunderline, Qstipple;
191extern Lisp_Object Qinvisible, Qread_only;
192
193extern void run_hooks ();
194
195extern Lisp_Object Ftext_properties_at ();
196extern Lisp_Object Fnext_property_change (), Fprevious_property_change ();
197extern Lisp_Object Fadd_text_properties (), Fset_text_properties ();
198extern Lisp_Object Fremove_text_properties (), Ferase_text_properties ();
199
200extern void syms_of_textprop ();
201
202#else /* intervals not used */
203
204#define NULL_INTERVAL_P(i) 1
205#define INTERVAL_SIZE 0
206#define INTERVAL_PTR_SIZE 0
207
208#define copy_intervals_to_string(string,buffer,position,length)
209#define verify_interval_modification(buffer,start,end)
210#define insert_interval_copy(source,position,end,sink,at)
211#define graft_intervals_into_buffer(tree,position,bufferptr)
212#define offset_intervals(buffer,position,length)
213
214#endif /* intervals not used */