Coverity fixes
[sxemacs] / src / extents.c
1 /* Copyright (c) 1994, 1995 Free Software Foundation, Inc.
2    Copyright (c) 1995 Sun Microsystems, Inc.
3    Copyright (c) 1995, 1996, 2000 Ben Wing.
4
5 This file is part of SXEmacs
6
7 SXEmacs is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
11
12 SXEmacs is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program.  If not, see <http://www.gnu.org/licenses/>. */
19
20
21 /* Synched up with: Not in FSF. */
22
23 /* This file has been Mule-ized. */
24
25 /* Written by Ben Wing <ben@xemacs.org>.
26
27    [Originally written by some people at Lucid.
28    Hacked on by jwz.
29    Start/end-open stuff added by John Rose (john.rose@eng.sun.com).
30    Rewritten from scratch by Ben Wing, December 1994.] */
31
32 /* Commentary:
33
34    Extents are regions over a buffer, with a start and an end position
35    denoting the region of the buffer included in the extent.  In
36    addition, either end can be closed or open, meaning that the endpoint
37    is or is not logically included in the extent.  Insertion of a character
38    at a closed endpoint causes the character to go inside the extent;
39    insertion at an open endpoint causes the character to go outside.
40
41    Extent endpoints are stored using memory indices (see insdel.c),
42    to minimize the amount of adjusting that needs to be done when
43    characters are inserted or deleted.
44
45    (Formerly, extent endpoints at the gap could be either before or
46    after the gap, depending on the open/closedness of the endpoint.
47    The intent of this was to make it so that insertions would
48    automatically go inside or out of extents as necessary with no
49    further work needing to be done.  It didn't work out that way,
50    however, and just ended up complexifying and buggifying all the
51    rest of the code.)
52
53    Extents are compared using memory indices.  There are two orderings
54    for extents and both orders are kept current at all times.  The normal
55    or "display" order is as follows:
56
57    Extent A is "less than" extent B, that is, earlier in the display order,
58    if:    A-start < B-start,
59    or if: A-start = B-start, and A-end > B-end
60
61    So if two extents begin at the same position, the larger of them is the
62    earlier one in the display order (EXTENT_LESS is true).
63
64    For the e-order, the same thing holds: Extent A is "less than" extent B
65    in e-order, that is, later in the buffer,
66    if:    A-end < B-end,
67    or if: A-end = B-end, and A-start > B-start
68
69    So if two extents end at the same position, the smaller of them is the
70    earlier one in the e-order (EXTENT_E_LESS is true).
71
72    The display order and the e-order are complementary orders: any
73    theorem about the display order also applies to the e-order if you
74    swap all occurrences of "display order" and "e-order", "less than"
75    and "greater than", and "extent start" and "extent end".
76
77    Extents can be zero-length, and will end up that way if their endpoints
78    are explicitly set that way or if their detachable property is nil
79    and all the text in the extent is deleted. (The exception is open-open
80    zero-length extents, which are barred from existing because there is
81    no sensible way to define their properties.  Deletion of the text in
82    an open-open extent causes it to be converted into a closed-open
83    extent.)  Zero-length extents are primarily used to represent
84    annotations, and behave as follows:
85
86    1) Insertion at the position of a zero-length extent expands the extent
87    if both endpoints are closed; goes after the extent if it is closed-open;
88    and goes before the extent if it is open-closed.
89
90    2) Deletion of a character on a side of a zero-length extent whose
91    corresponding endpoint is closed causes the extent to be detached if
92    it is detachable; if the extent is not detachable or the corresponding
93    endpoint is open, the extent remains in the buffer, moving as necessary.
94
95    Note that closed-open, non-detachable zero-length extents behave exactly
96    like markers and that open-closed, non-detachable zero-length extents
97    behave like the "point-type" marker in Mule.
98
99    #### The following information is wrong in places.
100
101    More about the different orders:
102    --------------------------------
103
104    The extents in a buffer are ordered by "display order" because that
105    is that order that the redisplay mechanism needs to process them in.
106    The e-order is an auxiliary ordering used to facilitate operations
107    over extents.  The operations that can be performed on the ordered
108    list of extents in a buffer are
109
110    1) Locate where an extent would go if inserted into the list.
111    2) Insert an extent into the list.
112    3) Remove an extent from the list.
113    4) Map over all the extents that overlap a range.
114
115    (4) requires being able to determine the first and last extents
116    that overlap a range.
117
118    NOTE: "overlap" is used as follows:
119
120    -- two ranges overlap if they have at least one point in common.
121       Whether the endpoints are open or closed makes a difference here.
122    -- a point overlaps a range if the point is contained within the
123       range; this is equivalent to treating a point P as the range
124       [P, P].
125    -- In the case of an *extent* overlapping a point or range, the
126       extent is normally treated as having closed endpoints.  This
127       applies consistently in the discussion of stacks of extents
128       and such below.  Note that this definition of overlap is not
129       necessarily consistent with the extents that `map-extents'
130       maps over, since `map-extents' sometimes pays attention to
131       whether the endpoints of an extents are open or closed.
132       But for our purposes, it greatly simplifies things to treat
133       all extents as having closed endpoints.
134
135    First, define >, <, <=, etc. as applied to extents to mean
136      comparison according to the display order.  Comparison between an
137      extent E and an index I means comparison between E and the range
138      [I, I].
139    Also define e>, e<, e<=, etc. to mean comparison according to the
140      e-order.
141    For any range R, define R(0) to be the starting index of the range
142      and R(1) to be the ending index of the range.
143    For any extent E, define E(next) to be the extent directly following
144      E, and E(prev) to be the extent directly preceding E.  Assume
145      E(next) and E(prev) can be determined from E in constant time.
146      (This is because we store the extent list as a doubly linked
147      list.)
148    Similarly, define E(e-next) and E(e-prev) to be the extents
149      directly following and preceding E in the e-order.
150
151    Now:
152
153    Let R be a range.
154    Let F be the first extent overlapping R.
155    Let L be the last extent overlapping R.
156
157    Theorem 1: R(1) lies between L and L(next), i.e. L <= R(1) < L(next).
158
159    This follows easily from the definition of display order.  The
160    basic reason that this theorem applies is that the display order
161    sorts by increasing starting index.
162
163    Therefore, we can determine L just by looking at where we would
164    insert R(1) into the list, and if we know F and are moving forward
165    over extents, we can easily determine when we've hit L by comparing
166    the extent we're at to R(1).
167
168    Theorem 2: F(e-prev) e< [1, R(0)] e<= F.
169
170    This is the analog of Theorem 1, and applies because the e-order
171    sorts by increasing ending index.
172
173    Therefore, F can be found in the same amount of time as operation (1),
174    i.e. the time that it takes to locate where an extent would go if
175    inserted into the e-order list.
176
177    If the lists were stored as balanced binary trees, then operation (1)
178    would take logarithmic time, which is usually quite fast.  However,
179    currently they're stored as simple doubly-linked lists, and instead
180    we do some caching to try to speed things up.
181
182    Define a "stack of extents" (or "SOE") as the set of extents
183    (ordered in the display order) that overlap an index I, together with
184    the SOE's "previous" extent, which is an extent that precedes I in
185    the e-order. (Hopefully there will not be very many extents between
186    I and the previous extent.)
187
188    Now:
189
190    Let I be an index, let S be the stack of extents on I, let F be
191    the first extent in S, and let P be S's previous extent.
192
193    Theorem 3: The first extent in S is the first extent that overlaps
194    any range [I, J].
195
196    Proof: Any extent that overlaps [I, J] but does not include I must
197    have a start index > I, and thus be greater than any extent in S.
198
199    Therefore, finding the first extent that overlaps a range R is the
200    same as finding the first extent that overlaps R(0).
201
202    Theorem 4: Let I2 be an index such that I2 > I, and let F2 be the
203    first extent that overlaps I2.  Then, either F2 is in S or F2 is
204    greater than any extent in S.
205
206    Proof: If F2 does not include I then its start index is greater
207    than I and thus it is greater than any extent in S, including F.
208    Otherwise, F2 includes I and thus is in S, and thus F2 >= F.
209
210 */
211
212 #include <config.h>
213 #include "lisp.h"
214
215 #include "buffer.h"
216 #include "debug.h"
217 #include "ui/device.h"
218 #include "elhash.h"
219 #include "extents.h"
220 #include "ui/faces.h"
221 #include "ui/frame.h"
222 #include "ui/glyphs.h"
223 #include "ui/insdel.h"
224 #include "ui/keymap.h"
225 #include "opaque.h"
226 #include "process.h"
227 #include "ui/redisplay.h"
228 #include "ui/gutter.h"
229
230 /* ------------------------------- */
231 /*            gap array            */
232 /* ------------------------------- */
233
234 /* Note that this object is not extent-specific and should perhaps be
235    moved into another file. */
236
237 typedef struct gap_array_marker_s *gap_array_marker_t;
238 typedef struct gap_array_s *gap_array_t;
239
240 /* Holds a marker that moves as elements in the array are inserted and
241    deleted, similar to standard markers. */
242
243 struct gap_array_marker_s {
244         int pos;
245         gap_array_marker_t next;
246 };
247
248 /* Holds a "gap array", which is an array of elements with a gap located
249    in it.  Insertions and deletions with a high degree of locality
250    are very fast, essentially in constant time.  Array positions as
251    used and returned in the gap array functions are independent of
252    the gap. */
253
254 struct gap_array_s {
255         char *array;
256         int gap;
257         int gapsize;
258         int numels;
259         int elsize;
260         gap_array_marker_t markers;
261 };
262
263 #if !defined HAVE_BDWGC || !defined EF_USE_BDWGC
264 static gap_array_marker_t gap_array_marker_freelist;
265 #endif  /* !BDWGC */
266
267 /* Convert a "memory position" (i.e. taking the gap into account) into
268    the address of the element at (i.e. after) that position.  "Memory
269    positions" are only used internally and are of type Memind.
270    "Array positions" are used externally and are of type int. */
271 #define GAP_ARRAY_MEMEL_ADDR(ga, memel) ((ga)->array + (ga)->elsize*(memel))
272
273 /* Number of elements currently in a gap array */
274 #define GAP_ARRAY_NUM_ELS(ga) ((ga)->numels)
275
276 #define GAP_ARRAY_ARRAY_TO_MEMORY_POS(ga, pos)                  \
277         ((pos) <= (ga)->gap ? (pos) : (pos) + (ga)->gapsize)
278
279 #define GAP_ARRAY_MEMORY_TO_ARRAY_POS(ga, pos)                  \
280         ((pos) <= (ga)->gap ? (pos) : (pos) - (ga)->gapsize)
281
282 /* Convert an array position into the address of the element at
283    (i.e. after) that position. */
284 #define GAP_ARRAY_EL_ADDR(ga, pos)                                      \
285         ((pos) < (ga)->gap                                              \
286          ? GAP_ARRAY_MEMEL_ADDR(ga, pos)                                \
287          : GAP_ARRAY_MEMEL_ADDR(ga, (pos) + (ga)->gapsize))
288
289 /* ------------------------------- */
290 /*          extent list            */
291 /* ------------------------------- */
292
293 typedef struct extent_list_marker_s *extent_list_marker_t;
294 typedef struct extent_list_s *extent_list_t;
295
296 struct extent_list_marker_s {
297         gap_array_marker_t m;
298         int endp;
299         extent_list_marker_t next;
300 };
301
302 struct extent_list_s {
303         gap_array_t start;
304         gap_array_t end;
305         extent_list_marker_t markers;
306 };
307
308 #if !defined HAVE_BDWGC || !defined EF_USE_BDWGC
309 static extent_list_marker_t extent_list_marker_freelist;
310 #endif  /* !BDWGC */
311
312 #define EXTENT_LESS_VALS(e,st,nd)               \
313         ((extent_start (e) < (st)) ||           \
314          ((extent_start (e) == (st)) &&         \
315           (extent_end (e) > (nd))))
316
317 #define EXTENT_EQUAL_VALS(e,st,nd)              \
318         ((extent_start (e) == (st)) &&          \
319          (extent_end (e) == (nd)))
320
321 #define EXTENT_LESS_EQUAL_VALS(e,st,nd)         \
322         ((extent_start (e) < (st)) ||           \
323          ((extent_start (e) == (st)) &&         \
324           (extent_end (e) >= (nd))))
325
326 /* Is extent E1 less than extent E2 in the display order? */
327 #define EXTENT_LESS(e1,e2)                                              \
328         EXTENT_LESS_VALS (e1, extent_start (e2), extent_end (e2))
329
330 /* Is extent E1 equal to extent E2? */
331 #define EXTENT_EQUAL(e1,e2)                                             \
332         EXTENT_EQUAL_VALS (e1, extent_start (e2), extent_end (e2))
333
334 /* Is extent E1 less than or equal to extent E2 in the display order? */
335 #define EXTENT_LESS_EQUAL(e1,e2)                                        \
336         EXTENT_LESS_EQUAL_VALS (e1, extent_start (e2), extent_end (e2))
337
338 #define EXTENT_E_LESS_VALS(e,st,nd)             \
339         ((extent_end (e) < (nd)) ||             \
340          ((extent_end (e) == (nd)) &&           \
341           (extent_start (e) > (st))))
342
343 #define EXTENT_E_LESS_EQUAL_VALS(e,st,nd)       \
344         ((extent_end (e) < (nd)) ||             \
345          ((extent_end (e) == (nd)) &&           \
346           (extent_start (e) >= (st))))
347