Initial revision
[chise/xemacs-chise.git.1] / 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 XEmacs.
6
7 XEmacs is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by the
9 Free Software Foundation; either version 2, or (at your option) any
10 later version.
11
12 XEmacs is distributed in the hope that it will be useful, but WITHOUT
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15 for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with XEmacs; see the file COPYING.  If not, write to
19 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA.  */
21
22 /* Synched up with: Not in FSF. */
23
24 /* This file has been Mule-ized. */
25
26 /* Written by Ben Wing <ben@xemacs.org>.
27
28    [Originally written by some people at Lucid.
29    Hacked on by jwz.
30    Start/end-open stuff added by John Rose (john.rose@eng.sun.com).
31    Rewritten from scratch by Ben Wing, December 1994.] */
32
33 /* Commentary:
34
35    Extents are regions over a buffer, with a start and an end position
36    denoting the region of the buffer included in the extent.  In
37    addition, either end can be closed or open, meaning that the endpoint
38    is or is not logically included in the extent.  Insertion of a character
39    at a closed endpoint causes the character to go inside the extent;
40    insertion at an open endpoint causes the character to go outside.
41
42    Extent endpoints are stored using memory indices (see insdel.c),
43    to minimize the amount of adjusting that needs to be done when
44    characters are inserted or deleted.
45
46    (Formerly, extent endpoints at the gap could be either before or
47    after the gap, depending on the open/closedness of the endpoint.
48    The intent of this was to make it so that insertions would
49    automatically go inside or out of extents as necessary with no
50    further work needing to be done.  It didn't work out that way,
51    however, and just ended up complexifying and buggifying all the
52    rest of the code.)
53
54    Extents are compared using memory indices.  There are two orderings
55    for extents and both orders are kept current at all times.  The normal
56    or "display" order is as follows:
57
58    Extent A is "less than" extent B, that is, earlier in the display order,
59    if:    A-start < B-start,
60    or if: A-start = B-start, and A-end > B-end
61
62    So if two extents begin at the same position, the larger of them is the
63    earlier one in the display order (EXTENT_LESS is true).
64
65    For the e-order, the same thing holds: Extent A is "less than" extent B
66    in e-order, that is, later in the buffer,
67    if:    A-end < B-end,
68    or if: A-end = B-end, and A-start > B-start
69
70    So if two extents end at the same position, the smaller of them is the
71    earlier one in the e-order (EXTENT_E_LESS is true).
72
73    The display order and the e-order are complementary orders: any
74    theorem about the display order also applies to the e-order if you
75    swap all occurrences of "display order" and "e-order", "less than"
76    and "greater than", and "extent start" and "extent end".
77
78    Extents can be zero-length, and will end up that way if their endpoints
79    are explicitly set that way or if their detachable property is nil
80    and all the text in the extent is deleted. (The exception is open-open
81    zero-length extents, which are barred from existing because there is
82    no sensible way to define their properties.  Deletion of the text in
83    an open-open extent causes it to be converted into a closed-open
84    extent.)  Zero-length extents are primarily used to represent
85    annotations, and behave as follows:
86
87    1) Insertion at the position of a zero-length extent expands the extent
88    if both endpoints are closed; goes after the extent if it is closed-open;
89    and goes before the extent if it is open-closed.
90
91    2) Deletion of a character on a side of a zero-length extent whose
92    corresponding endpoint is closed causes the extent to be detached if
93    it is detachable; if the extent is not detachable or the corresponding
94    endpoint is open, the extent remains in the buffer, moving as necessary.
95
96    Note that closed-open, non-detachable zero-length extents behave exactly
97    like markers and that open-closed, non-detachable zero-length extents
98    behave like the "point-type" marker in Mule.
99
100
101    #### The following information is wrong in places.
102
103    More about the different orders:
104    --------------------------------
105
106    The extents in a buffer are ordered by "display order" because that
107    is that order that the redisplay mechanism needs to process them in.
108    The e-order is an auxiliary ordering used to facilitate operations
109    over extents.  The operations that can be performed on the ordered
110    list of extents in a buffer are
111
112    1) Locate where an extent would go if inserted into the list.
113    2) Insert an extent into the list.
114    3) Remove an extent from the list.
115    4) Map over all the extents that overlap a range.
116
117    (4) requires being able to determine the first and last extents
118    that overlap a range.
119
120    NOTE: "overlap" is used as follows:
121
122    -- two ranges overlap if they have at least one point in common.
123       Whether the endpoints are open or closed makes a difference here.
124    -- a point overlaps a range if the point is contained within the
125       range; this is equivalent to treating a point P as the range
126       [P, P].
127    -- In the case of an *extent* overlapping a point or range, the
128       extent is normally treated as having closed endpoints.  This
129       applies consistently in the discussion of stacks of extents
130       and such below.  Note that this definition of overlap is not
131       necessarily consistent with the extents that `map-extents'
132       maps over, since `map-extents' sometimes pays attention to
133       whether the endpoints of an extents are open or closed.
134       But for our purposes, it greatly simplifies things to treat
135       all extents as having closed endpoints.
136
137    First, define >, <, <=, etc. as applied to extents to mean
138      comparison according to the display order.  Comparison between an
139      extent E and an index I means comparison between E and the range
140      [I, I].
141    Also define e>, e<, e<=, etc. to mean comparison according to the
142      e-order.
143    For any range R, define R(0) to be the starting index of the range
144      and R(1) to be the ending index of the range.
145    For any extent E, define E(next) to be the extent directly following
146      E, and E(prev) to be the extent directly preceding E.  Assume
147      E(next) and E(prev) can be determined from E in constant time.
148      (This is because we store the extent list as a doubly linked
149      list.)
150    Similarly, define E(e-next) and E(e-prev) to be the extents
151      directly following and preceding E in the e-order.
152
153    Now:
154
155    Let R be a range.
156    Let F be the first extent overlapping R.
157    Let L be the last extent overlapping R.
158
159    Theorem 1: R(1) lies between L and L(next), i.e. L <= R(1) < L(next).
160
161    This follows easily from the definition of display order.  The
162    basic reason that this theorem applies is that the display order
163    sorts by increasing starting index.
164
165    Therefore, we can determine L just by looking at where we would
166    insert R(1) into the list, and if we know F and are moving forward
167    over extents, we can easily determine when we've hit L by comparing
168    the extent we're at to R(1).
169
170    Theorem 2: F(e-prev) e< [1, R(0)] e<= F.
171
172    This is the analog of Theorem 1, and applies because the e-order
173    sorts by increasing ending index.
174
175    Therefore, F can be found in the same amount of time as operation (1),
176    i.e. the time that it takes to locate where an extent would go if
177    inserted into the e-order list.
178
179    If the lists were stored as balanced binary trees, then operation (1)
180    would take logarithmic time, which is usually quite fast.  However,
181    currently they're stored as simple doubly-linked lists, and instead
182    we do some caching to try to speed things up.
183
184    Define a "stack of extents" (or "SOE") as the set of extents
185    (ordered in the display order) that overlap an index I, together with
186    the SOE's "previous" extent, which is an extent that precedes I in
187    the e-order. (Hopefully there will not be very many extents between
188    I and the previous extent.)
189
190    Now:
191
192    Let I be an index, let S be the stack of extents on I, let F be
193    the first extent in S, and let P be S's previous extent.
194
195    Theorem 3: The first extent in S is the first extent that overlaps
196    any range [I, J].
197
198    Proof: Any extent that overlaps [I, J] but does not include I must
199    have a start index > I, and thus be greater than any extent in S.
200
201    Therefore, finding the first extent that overlaps a range R is the
202    same as finding the first extent that overlaps R(0).
203
204    Theorem 4: Let I2 be an index such that I2 > I, and let F2 be the
205    first extent that overlaps I2.  Then, either F2 is in S or F2 is
206    greater than any extent in S.
207
208    Proof: If F2 does not include I then its start index is greater
209    than I and thus it is greater than any extent in S, including F.
210    Otherwise, F2 includes I and thus is in S, and thus F2 >= F.
211
212 */
213
214 #include <config.h>
215 #include "lisp.h"
216
217 #include "buffer.h"
218 #include "debug.h"
219 #include "device.h"
220 #include "elhash.h"
221 #include "extents.h"
222 #include "faces.h"
223 #include "frame.h"
224 #include "glyphs.h"
225 #include "insdel.h"
226 #include "keymap.h"
227 #include "opaque.h"
228 #include "process.h"
229 #include "redisplay.h"
230 #include "gutter.h"
231
232 /* ------------------------------- */
233 /*            gap array            */
234 /* ------------------------------- */
235
236 /* Note that this object is not extent-specific and should perhaps be
237    moved into another file. */
238
239 /* Holds a marker that moves as elements in the array are inserted and
240    deleted, similar to standard markers. */
241
242 typedef struct gap_array_marker
243 {
244   int pos;
245   struct gap_array_marker *next;
246 } Gap_Array_Marker;
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 typedef struct gap_array
255 {
256   char *array;
257   int gap;
258   int gapsize;
259   int numels;
260   int elsize;
261   Gap_Array_Marker *markers;
262 } Gap_Array;
263
264 static Gap_Array_Marker *gap_array_marker_freelist;
265
266 /* Convert a "memory position" (i.e. taking the gap into account) into
267    the address of the element at (i.e. after) that position.  "Memory
268    positions" are only used internally and are of type Memind.
269    "Array positions" are used externally and are of type int. */
270 #define GAP_ARRAY_MEMEL_ADDR(ga, memel) ((ga)->array + (ga)->elsize*(memel))
271
272 /* Number of elements currently in a gap array */
273 #define GAP_ARRAY_NUM_ELS(ga) ((ga)->numels)
274
275 #define GAP_ARRAY_ARRAY_TO_MEMORY_POS(ga, pos) \
276   ((pos) <= (ga)->gap ? (pos) : (pos) + (ga)->gapsize)
277
278 #define GAP_ARRAY_MEMORY_TO_ARRAY_POS(ga, pos) \
279   ((pos) <= (ga)->gap ? (pos) : (pos) - (ga)->gapsize)
280
281 /* Convert an array position into the address of the element at
282    (i.e. after) that position. */
283 #define GAP_ARRAY_EL_ADDR(ga, pos) ((pos) < (ga)->gap ? \
284   GAP_ARRAY_MEMEL_ADDR(ga, pos) : \
285   GAP_ARRAY_MEMEL_ADDR(ga, (pos) + (ga)->gapsize))
286
287 /* ------------------------------- */
288 /*          extent list            */
289 /* ------------------------------- */
290
291 typedef struct extent_list_marker
292 {
293   Gap_Array_Marker *m;
294   int endp;
295   struct extent_list_marker *next;
296 } Extent_List_Marker;
297
298 typedef struct extent_list
299 {
300   Gap_Array *start;
301   Gap_Array *end;
302   Extent_List_Marker *markers;
303 } Extent_List;
304
305 static Extent_List_Marker *extent_list_marker_freelist;
306
307 #define EXTENT_LESS_VALS(e,st,nd) ((extent_start (e) < (st)) || \
308                                    ((extent_start (e) == (st)) && \
309                                     (extent_end (e) > (nd))))
310
311 #define EXTENT_EQUAL_VALS(e,st,nd) ((extent_start (e) == (st)) && \
312                                     (extent_end (e) == (nd)))
313
314 #define EXTENT_LESS_EQUAL_VALS(e,st,nd) ((extent_start (e) < (st)) || \
315                                          ((extent_start (e) == (st)) && \
316                                           (extent_end (e) >= (nd))))
317
318 /* Is extent E1 less than extent E2 in the display order? */
319 #define EXTENT_LESS(e1,e2) \
320   EXTENT_LESS_VALS (e1, extent_start (e2), extent_end (e2))
321
322 /* Is extent E1 equal to extent E2? */
323 #define EXTENT_EQUAL(e1,e2) \
324   EXTENT_EQUAL_VALS (e1, extent_start (e2), extent_end (e2))
325
326 /* Is extent E1 less than or equal to extent E2 in the display order? */
327 #define EXTENT_LESS_EQUAL(e1,e2) \
328   EXTENT_LESS_EQUAL_VALS (e1, extent_start (e2), extent_end (e2))
329
330 #define EXTENT_E_LESS_VALS(e,st,nd) ((extent_end (e) < (nd)) || \
331                                      ((extent_end (e) == (nd)) && \
332                                       (extent_start (e) > (st))))
333
334 #define EXTENT_E_LESS_EQUAL_VALS(e,st,nd) ((extent_end (e) < (nd)) || \
335                                            ((extent_end (e) == (nd)) && \
336                                             (extent_start (e) >= (st))))
337
338 /* Is extent E1 less than extent E2 in the e-order? */
339 #define EXTENT_E_LESS(e1,e2) \
340         EXTENT_E_LESS_VALS(e1, extent_start (e2), extent_end (e2))
341
342 /* Is extent E1 less than or equal to extent E2 in the e-order? */
343 #define EXTENT_E_LESS_EQUAL(e1,e2) \
344   EXTENT_E_LESS_EQUAL_VALS (e1, extent_start (e2), extent_end (e2))
345
346 #define EXTENT_GAP_ARRAY_AT(ga, pos) (* (EXTENT *) GAP_ARRAY_EL_ADDR(ga, pos))
347
348 /* ------------------------------- */
349 /*    auxiliary extent structure   */
350 /* ------------------------------- */
351
352 struct extent_auxiliary extent_auxiliary_defaults;
353
354 /* ------------------------------- */
355 /*     buffer-extent primitives    */
356 /* ------------------------------- */
357
358 typedef struct stack_of_extents
359 {
360   Extent_List *extents;
361   Memind pos; /* Position of stack of extents.  EXTENTS is the list of
362                  all extents that overlap this position.  This position
363                  can be -1 if the stack of extents is invalid (this
364                  happens when a buffer is first created or a string's
365                  stack of extents is created [a string's stack of extents
366                  is nuked when a GC occurs, to conserve memory]). */
367 } Stack_Of_Extents;
368
369 /* ------------------------------- */
370 /*           map-extents           */
371 /* ------------------------------- */
372
373 typedef int Endpoint_Index;
374
375 #define memind_to_startind(x, start_open) \
376   ((Endpoint_Index) (((x) << 1) + !!(start_open)))
377 #define memind_to_endind(x, end_open) \
378   ((Endpoint_Index) (((x) << 1) - !!(end_open)))
379
380 /* Combination macros */
381 #define bytind_to_startind(buf, x, start_open) \
382   memind_to_startind (bytind_to_memind (buf, x), start_open)
383 #define bytind_to_endind(buf, x, end_open) \
384   memind_to_endind (bytind_to_memind (buf, x), end_open)
385
386 /* ------------------------------- */
387 /*    buffer-or-string primitives  */
388 /* ------------------------------- */
389
390 /* Similar for Bytinds and start/end indices. */
391
392 #define buffer_or_string_bytind_to_startind(obj, ind, start_open)       \
393   memind_to_startind (buffer_or_string_bytind_to_memind (obj, ind),     \
394                       start_open)
395
396 #define buffer_or_string_bytind_to_endind(obj, ind, end_open)           \
397   memind_to_endind (buffer_or_string_bytind_to_memind (obj, ind),       \
398                     end_open)
399
400 /* ------------------------------- */
401 /*      Lisp-level functions       */
402 /* ------------------------------- */
403
404 /* flags for decode_extent() */
405 #define DE_MUST_HAVE_BUFFER 1
406 #define DE_MUST_BE_ATTACHED 2
407
408 Lisp_Object Vlast_highlighted_extent;
409 Fixnum mouse_highlight_priority;
410
411 Lisp_Object Qextentp;
412 Lisp_Object Qextent_live_p;
413
414 Lisp_Object Qall_extents_closed;
415 Lisp_Object Qall_extents_open;
416 Lisp_Object Qall_extents_closed_open;
417 Lisp_Object Qall_extents_open_closed;
418 Lisp_Object Qstart_in_region;
419 Lisp_Object Qend_in_region;
420 Lisp_Object Qstart_and_end_in_region;
421 Lisp_Object Qstart_or_end_in_region;
422 Lisp_Object Qnegate_in_region;
423
424 Lisp_Object Qdetached;
425 Lisp_Object Qdestroyed;
426 Lisp_Object Qbegin_glyph;
427 Lisp_Object Qend_glyph;
428 Lisp_Object Qstart_open;
429 Lisp_Object Qend_open;
430 Lisp_Object Qstart_closed;
431 Lisp_Object Qend_closed;
432 Lisp_Object Qread_only;
433 /* Qhighlight defined in general.c */
434 Lisp_Object Qunique;
435 Lisp_Object Qduplicable;
436 Lisp_Object Qdetachable;
437 Lisp_Object Qpriority;
438 Lisp_Object Qmouse_face;
439 Lisp_Object Qinitial_redisplay_function;
440
441 Lisp_Object Qglyph_layout;  /* This exists only for backwards compatibility. */
442 Lisp_Object Qbegin_glyph_layout, Qend_glyph_layout;
443 Lisp_Object Qoutside_margin;
444 Lisp_Object Qinside_margin;
445 Lisp_Object Qwhitespace;
446 /* Qtext defined in general.c */
447
448 Lisp_Object Qcopy_function;
449 Lisp_Object Qpaste_function;
450
451 /* The idea here is that if we're given a list of faces, we
452    need to "memoize" this so that two lists of faces that are `equal'
453    turn into the same object.  When `set-extent-face' is called, we
454    "memoize" into a list of actual faces; when `extent-face' is called,
455    we do a reverse lookup to get the list of symbols. */
456
457 static Lisp_Object canonicalize_extent_property (Lisp_Object prop,
458                                                  Lisp_Object value);
459 Lisp_Object Vextent_face_memoize_hash_table;
460 Lisp_Object Vextent_face_reverse_memoize_hash_table;
461 Lisp_Object Vextent_face_reusable_list;
462 /* FSFmacs bogosity */
463 Lisp_Object Vdefault_text_properties;
464
465 EXFUN (Fextent_properties, 1);
466 EXFUN (Fset_extent_property, 3);
467
468 /* if true, we don't want to set any redisplay flags on modeline extent
469    changes */
470 int in_modeline_generation;
471
472 \f
473 /************************************************************************/
474 /*                       Generalized gap array                          */
475 /************************************************************************/
476
477 /* This generalizes the "array with a gap" model used to store buffer
478    characters.  This is based on the stuff in insdel.c and should
479    probably be merged with it.  This is not extent-specific and should
480    perhaps be moved into a separate file. */
481
482 /* ------------------------------- */
483 /*        internal functions       */
484 /* ------------------------------- */
485
486 /* Adjust the gap array markers in the range (FROM, TO].  Parallel to
487    adjust_markers() in insdel.c. */
488
489 static void
490 gap_array_adjust_markers (Gap_Array *ga, Memind from,
491                           Memind to, int amount)
492 {
493   Gap_Array_Marker *m;
494
495   for (m = ga->markers; m; m = m->next)
496     m->pos = do_marker_adjustment (m->pos, from, to, amount);
497 }
498
499 /* Move the gap to array position POS.  Parallel to move_gap() in
500    insdel.c but somewhat simplified. */
501
502 static void
503 gap_array_move_gap (Gap_Array *ga, int pos)
504 {
505   int gap = ga->gap;
506   int gapsize = ga->gapsize;
507
508   assert (ga->array);
509   if (pos < gap)
510     {
511       memmove (GAP_ARRAY_MEMEL_ADDR (ga, pos + gapsize),
512                GAP_ARRAY_MEMEL_ADDR (ga, pos),
513                (gap - pos)*ga->elsize);
514       gap_array_adjust_markers (ga, (Memind) pos, (Memind) gap,
515                                 gapsize);
516     }
517   else if (pos > gap)
518     {
519       memmove (GAP_ARRAY_MEMEL_ADDR (ga, gap),
520                GAP_ARRAY_MEMEL_ADDR (ga, gap + gapsize),
521                (pos - gap)*ga->elsize);
522       gap_array_adjust_markers (ga, (Memind) (gap + gapsize),
523                                 (Memind) (pos + gapsize), - gapsize);
524     }
525   ga->gap = pos;
526 }
527
528 /* Make the gap INCREMENT characters longer.  Parallel to make_gap() in
529    insdel.c. */
530
531 static void
532 gap_array_make_gap (Gap_Array *ga, int increment)
533 {
534   char *ptr = ga->array;
535   int real_gap_loc;
536   int old_gap_size;
537
538   /* If we have to get more space, get enough to last a while.  We use
539      a geometric progression that saves on realloc space. */
540   increment += 100 + ga->numels / 8;
541
542   ptr = (char *) xrealloc (ptr,
543                            (ga->numels + ga->gapsize + increment)*ga->elsize);
544   if (ptr == 0)
545     memory_full ();
546   ga->array = ptr;
547
548   real_gap_loc = ga->gap;
549   old_gap_size = ga->gapsize;
550
551   /* Call the newly allocated space a gap at the end of the whole space.  */
552   ga->gap = ga->numels + ga->gapsize;
553   ga->gapsize = increment;
554
555   /* Move the new gap down to be consecutive with the end of the old one.
556      This adjusts the markers properly too.  */
557   gap_array_move_gap (ga, real_gap_loc + old_gap_size);
558
559   /* Now combine the two into one large gap.  */
560   ga->gapsize += old_gap_size;
561   ga->gap = real_gap_loc;
562 }
563
564 /* ------------------------------- */
565 /*        external functions       */
566 /* ------------------------------- */
567
568 /* Insert NUMELS elements (pointed to by ELPTR) into the specified
569    gap array at POS. */
570
571 static void
572 gap_array_insert_els (Gap_Array *ga, int pos, void *elptr, int numels)
573 {
574   assert (pos >= 0 && pos <= ga->numels);
575   if (ga->gapsize < numels)
576     gap_array_make_gap (ga, numels - ga->gapsize);
577   if (pos != ga->gap)
578     gap_array_move_gap (ga, pos);
579
580   memcpy (GAP_ARRAY_MEMEL_ADDR (ga, ga->gap), (char *) elptr,
581           numels*ga->elsize);
582   ga->gapsize -= numels;
583   ga->gap += numels;
584   ga->numels += numels;
585   /* This is the equivalent of insert-before-markers.
586
587      #### Should only happen if marker is "moves forward at insert" type.
588      */
589
590   gap_array_adjust_markers (ga, pos - 1, pos, numels);
591 }
592
593 /* Delete NUMELS elements from the specified gap array, starting at FROM. */
594
595 static void
596 gap_array_delete_els (Gap_Array *ga, int from, int numdel)
597 {
598   int to = from + numdel;
599   int gapsize = ga->gapsize;
600
601   assert (from >= 0);
602   assert (numdel >= 0);
603   assert (to <= ga->numels);
604
605   /* Make sure the gap is somewhere in or next to what we are deleting.  */
606   if (to < ga->gap)
607     gap_array_move_gap (ga, to);
608   if (from > ga->gap)
609     gap_array_move_gap (ga, from);
610
611   /* Relocate all markers pointing into the new, larger gap
612      to point at the end of the text before the gap.  */
613   gap_array_adjust_markers (ga, to + gapsize, to + gapsize,
614                             - numdel - gapsize);
615
616   ga->gapsize += numdel;
617   ga->numels -= numdel;
618   ga->gap = from;
619 }
620
621 static Gap_Array_Marker *
622 gap_array_make_marker (Gap_Array *ga, int pos)
623 {
624   Gap_Array_Marker *m;
625
626   assert (pos >= 0 && pos <= ga->numels);
627   if (gap_array_marker_freelist)
628     {
629       m = gap_array_marker_freelist;
630       gap_array_marker_freelist = gap_array_marker_freelist->next;
631     }
632   else
633     m = xnew (Gap_Array_Marker);
634
635   m->pos = GAP_ARRAY_ARRAY_TO_MEMORY_POS (ga, pos);
636   m->next = ga->markers;
637   ga->markers = m;
638   return m;
639 }
640
641 static void
642 gap_array_delete_marker (Gap_Array *ga, Gap_Array_Marker *m)
643 {
644   Gap_Array_Marker *p, *prev;
645
646   for (prev = 0, p = ga->markers; p && p != m; prev = p, p = p->next)
647     ;
648   assert (p);
649   if (prev)
650     prev->next = p->next;
651   else
652     ga->markers = p->next;
653   m->next = gap_array_marker_freelist;
654   m->pos = 0xDEADBEEF; /* -559038737 as an int */
655   gap_array_marker_freelist = m;
656 }
657
658 static void
659 gap_array_delete_all_markers (Gap_Array *ga)
660 {
661   Gap_Array_Marker *p, *next;
662
663   for (p = ga->markers; p; p = next)
664     {
665       next = p->next;
666       p->next = gap_array_marker_freelist;
667       p->pos = 0xDEADBEEF; /* -559038737 as an int */
668       gap_array_marker_freelist = p;
669     }
670 }
671
672 static void
673 gap_array_move_marker (Gap_Array *ga, Gap_Array_Marker *m, int pos)
674 {
675   assert (pos >= 0 && pos <= ga->numels);
676   m->pos = GAP_ARRAY_ARRAY_TO_MEMORY_POS (ga, pos);
677 }
678
679 #define gap_array_marker_pos(ga, m) \
680   GAP_ARRAY_MEMORY_TO_ARRAY_POS (ga, (m)->pos)
681
682 static Gap_Array *
683 make_gap_array (int elsize)
684 {
685   Gap_Array *ga = xnew_and_zero (Gap_Array);
686   ga->elsize = elsize;
687   return ga;
688 }
689
690 static void
691 free_gap_array (Gap_Array *ga)
692 {
693   if (ga->array)
694     xfree (ga->array);
695   gap_array_delete_all_markers (ga);
696   xfree (ga);
697 }
698
699 \f
700 /************************************************************************/
701 /*                       Extent list primitives                         */
702 /************************************************************************/
703
704 /* A list of extents is maintained as a double gap array: one gap array
705    is ordered by start index (the "display order") and the other is
706    ordered by end index (the "e-order").  Note that positions in an
707    extent list should logically be conceived of as referring *to*
708    a particular extent (as is the norm in programs) rather than
709    sitting between two extents.  Note also that callers of these
710    functions should not be aware of the fact that the extent list is
711    implemented as an array, except for the fact that positions are
712    integers (this should be generalized to handle integers and linked
713    list equally well).
714 */
715
716 /* Number of elements in an extent list */
717 #define extent_list_num_els(el) GAP_ARRAY_NUM_ELS(el->start)
718
719 /* Return the position at which EXTENT is located in the specified extent
720    list (in the display order if ENDP is 0, in the e-order otherwise).
721    If the extent is not found, the position where the extent would
722    be inserted is returned.  If ENDP is 0, the insertion would go after
723    all other equal extents.  If ENDP is not 0, the insertion would go
724    before all other equal extents.  If FOUNDP is not 0, then whether
725    the extent was found will get written into it. */
726
727 static int
728 extent_list_locate (Extent_List *el, EXTENT extent, int endp, int *foundp)
729 {
730   Gap_Array *ga = endp ? el->end : el->start;
731   int left = 0, right = GAP_ARRAY_NUM_ELS (ga);
732   int oldfoundpos, foundpos;
733   int found;
734
735   while (left != right)
736     {
737       /* RIGHT might not point to a valid extent (i.e. it's at the end
738          of the list), so NEWPOS must round down. */
739       unsigned int newpos = (left + right) >> 1;
740       EXTENT e = EXTENT_GAP_ARRAY_AT (ga, (int) newpos);
741
742       if (endp ? EXTENT_E_LESS (e, extent) : EXTENT_LESS (e, extent))
743         left = newpos+1;
744       else
745         right = newpos;
746     }
747
748   /* Now we're at the beginning of all equal extents. */
749   found = 0;
750   oldfoundpos = foundpos = left;
751   while (foundpos < GAP_ARRAY_NUM_ELS (ga))
752     {
753       EXTENT e = EXTENT_GAP_ARRAY_AT (ga, foundpos);
754       if (e == extent)
755         {
756           found = 1;
757           break;
758         }
759       if (!EXTENT_EQUAL (e, extent))
760         break;
761       foundpos++;
762     }
763   if (foundp)
764     *foundp = found;
765   if (found || !endp)
766     return foundpos;
767   else
768     return oldfoundpos;
769 }
770
771 /* Return the position of the first extent that begins at or after POS
772    (or ends at or after POS, if ENDP is not 0).
773
774    An out-of-range value for POS is allowed, and guarantees that the
775    position at the beginning or end of the extent list is returned. */
776
777 static int
778 extent_list_locate_from_pos (Extent_List *el, Memind pos, int endp)
779 {
780   struct extent fake_extent;
781   /*
782
783    Note that if we search for [POS, POS], then we get the following:
784
785    -- if ENDP is 0, then all extents whose start position is <= POS
786       lie before the returned position, and all extents whose start
787       position is > POS lie at or after the returned position.
788
789    -- if ENDP is not 0, then all extents whose end position is < POS
790       lie before the returned position, and all extents whose end
791       position is >= POS lie at or after the returned position.
792
793    */
794   set_extent_start (&fake_extent, endp ? pos : pos-1);
795   set_extent_end (&fake_extent, endp ? pos : pos-1);
796   return extent_list_locate (el, &fake_extent, endp, 0);
797 }
798
799 /* Return the extent at POS. */
800
801 static EXTENT
802 extent_list_at (Extent_List *el, Memind pos, int endp)
803 {
804   Gap_Array *ga = endp ? el->end : el->start;
805
806   assert (pos >= 0 && pos < GAP_ARRAY_NUM_ELS (ga));
807   return EXTENT_GAP_ARRAY_AT (ga, pos);
808 }
809
810 /* Insert an extent into an extent list. */
811
812 static void
813 extent_list_insert (Extent_List *el, EXTENT extent)
814 {
815   int pos, foundp;
816
817   pos = extent_list_locate (el, extent, 0, &foundp);
818   assert (!foundp);
819   gap_array_insert_els (el->start, pos, &extent, 1);
820   pos = extent_list_locate (el, extent, 1, &foundp);
821   assert (!foundp);
822   gap_array_insert_els (el->end, pos, &extent, 1);
823 }
824
825 /* Delete an extent from an extent list. */
826
827 static void
828 extent_list_delete (Extent_List *el, EXTENT extent)
829 {
830   int pos, foundp;
831
832   pos = extent_list_locate (el, extent, 0, &foundp);
833   assert (foundp);
834   gap_array_delete_els (el->start, pos, 1);
835   pos = extent_list_locate (el, extent, 1, &foundp);
836   assert (foundp);
837   gap_array_delete_els (el->end, pos, 1);
838 }
839
840 static void
841 extent_list_delete_all (Extent_List *el)
842 {
843   gap_array_delete_els (el->start, 0, GAP_ARRAY_NUM_ELS (el->start));
844   gap_array_delete_els (el->end, 0, GAP_ARRAY_NUM_ELS (el->end));
845 }
846
847 static Extent_List_Marker *
848 extent_list_make_marker (Extent_List *el, int pos, int endp)
849 {
850   Extent_List_Marker *m;
851
852   if (extent_list_marker_freelist)
853     {
854       m = extent_list_marker_freelist;
855       extent_list_marker_freelist = extent_list_marker_freelist->next;
856     }
857   else
858     m = xnew (Extent_List_Marker);
859
860   m->m = gap_array_make_marker (endp ? el->end : el->start, pos);
861   m->endp = endp;
862   m->next = el->markers;
863   el->markers = m;
864   return m;
865 }
866
867 #define extent_list_move_marker(el, mkr, pos) \
868   gap_array_move_marker((mkr)->endp ? (el)->end : (el)->start, (mkr)->m, pos)
869
870 static void
871 extent_list_delete_marker (Extent_List *el, Extent_List_Marker *m)
872 {
873   Extent_List_Marker *p, *prev;
874
875   for (prev = 0, p = el->markers; p && p != m; prev = p, p = p->next)
876     ;
877   assert (p);
878   if (prev)
879     prev->next = p->next;
880   else
881     el->markers = p->next;
882   m->next = extent_list_marker_freelist;
883   extent_list_marker_freelist = m;
884   gap_array_delete_marker (m->endp ? el->end : el->start, m->m);
885 }
886
887 #define extent_list_marker_pos(el, mkr) \
888   gap_array_marker_pos ((mkr)->endp ? (el)->end : (el)->start, (mkr)->m)
889
890 static Extent_List *
891 allocate_extent_list (void)
892 {
893   Extent_List *el = xnew (Extent_List);
894   el->start = make_gap_array (sizeof (EXTENT));
895   el->end = make_gap_array (sizeof (EXTENT));
896   el->markers = 0;
897   return el;
898 }
899
900 static void
901 free_extent_list (Extent_List *el)
902 {
903   free_gap_array (el->start);
904   free_gap_array (el->end);
905   xfree (el);
906 }
907
908 \f
909 /************************************************************************/
910 /*                       Auxiliary extent structure                     */
911 /************************************************************************/
912
913 static Lisp_Object
914 mark_extent_auxiliary (Lisp_Object obj)
915 {
916   struct extent_auxiliary *data = XEXTENT_AUXILIARY (obj);
917   mark_object (data->begin_glyph);
918   mark_object (data->end_glyph);
919   mark_object (data->invisible);
920   mark_object (data->children);
921   mark_object (data->read_only);
922   mark_object (data->mouse_face);
923   mark_object (data->initial_redisplay_function);
924   mark_object (data->before_change_functions);
925   mark_object (data->after_change_functions);
926   return data->parent;
927 }
928
929 DEFINE_LRECORD_IMPLEMENTATION ("extent-auxiliary", extent_auxiliary,
930                                mark_extent_auxiliary, internal_object_printer,
931                                0, 0, 0, 0, struct extent_auxiliary);
932
933 void
934 allocate_extent_auxiliary (EXTENT ext)
935 {
936   Lisp_Object extent_aux;
937   struct extent_auxiliary *data =
938     alloc_lcrecord_type (struct extent_auxiliary, &lrecord_extent_auxiliary);
939
940   copy_lcrecord (data, &extent_auxiliary_defaults);
941   XSETEXTENT_AUXILIARY (extent_aux, data);
942   ext->plist = Fcons (extent_aux, ext->plist);
943   ext->flags.has_aux = 1;
944 }
945
946 \f
947 /************************************************************************/
948 /*                         Extent info structure                        */
949 /************************************************************************/
950
951 /* An extent-info structure consists of a list of the buffer or string's
952    extents and a "stack of extents" that lists all of the extents over
953    a particular position.  The stack-of-extents info is used for
954    optimization purposes -- it basically caches some info that might
955    be expensive to compute.  Certain otherwise hard computations are easy
956    given the stack of extents over a particular position, and if the
957    stack of extents over a nearby position is known (because it was
958    calculated at some prior point in time), it's easy to move the stack
959    of extents to the proper position.
960
961    Given that the stack of extents is an optimization, and given that
962    it requires memory, a string's stack of extents is wiped out each
963    time a garbage collection occurs.  Therefore, any time you retrieve
964    the stack of extents, it might not be there.  If you need it to
965    be there, use the _force version.
966
967    Similarly, a string may or may not have an extent_info structure.
968    (Generally it won't if there haven't been any extents added to the
969    string.) So use the _force version if you need the extent_info
970    structure to be there. */
971
972 static struct stack_of_extents *allocate_soe (void);
973 static void free_soe (struct stack_of_extents *soe);
974 static void soe_invalidate (Lisp_Object obj);
975
976 static Lisp_Object
977 mark_extent_info (Lisp_Object obj)
978 {
979   struct extent_info *data = (struct extent_info *) XEXTENT_INFO (obj);
980   int i;
981   Extent_List *list = data->extents;
982
983   /* Vbuffer_defaults and Vbuffer_local_symbols are buffer-like
984      objects that are created specially and never have their extent
985      list initialized (or rather, it is set to zero in
986      nuke_all_buffer_slots()).  However, these objects get
987      garbage-collected so we have to deal.
988
989      (Also the list can be zero when we're dealing with a destroyed
990      buffer.) */
991
992   if (list)
993     {
994       for (i = 0; i < extent_list_num_els (list); i++)
995         {
996           struct extent *extent = extent_list_at (list, i, 0);
997           Lisp_Object exobj;
998
999           XSETEXTENT (exobj, extent);
1000           mark_object (exobj);
1001         }
1002     }
1003
1004   return Qnil;
1005 }
1006
1007 static void
1008 finalize_extent_info (void *header, int for_disksave)
1009 {
1010   struct extent_info *data = (struct extent_info *) header;
1011
1012   if (for_disksave)
1013     return;
1014
1015   if (data->soe)
1016     {
1017       free_soe (data->soe);
1018       data->soe = 0;
1019     }
1020   if (data->extents)
1021     {
1022       free_extent_list (data->extents);
1023       data->extents = 0;
1024     }
1025 }
1026
1027 DEFINE_LRECORD_IMPLEMENTATION ("extent-info", extent_info,
1028                                mark_extent_info, internal_object_printer,
1029                                finalize_extent_info, 0, 0, 0,
1030                                struct extent_info);
1031 \f
1032 static Lisp_Object
1033 allocate_extent_info (void)
1034 {
1035   Lisp_Object extent_info;
1036   struct extent_info *data =
1037     alloc_lcrecord_type (struct extent_info, &lrecord_extent_info);
1038
1039   XSETEXTENT_INFO (extent_info, data);
1040   data->extents = allocate_extent_list ();
1041   data->soe = 0;
1042   return extent_info;
1043 }
1044
1045 void
1046 flush_cached_extent_info (Lisp_Object extent_info)
1047 {
1048   struct extent_info *data = XEXTENT_INFO (extent_info);
1049
1050   if (data->soe)
1051     {
1052       free_soe (data->soe);
1053       data->soe = 0;
1054     }
1055 }
1056
1057 \f
1058 /************************************************************************/
1059 /*                    Buffer/string extent primitives                   */
1060 /************************************************************************/
1061
1062 /* The functions in this section are the ONLY ones that should know
1063    about the internal implementation of the extent lists.  Other functions
1064    should only know that there are two orderings on extents, the "display"
1065    order (sorted by start position, basically) and the e-order (sorted
1066    by end position, basically), and that certain operations are provided
1067    to manipulate the list. */
1068
1069 /* ------------------------------- */
1070 /*        basic primitives         */
1071 /* ------------------------------- */
1072
1073 static Lisp_Object
1074 decode_buffer_or_string (Lisp_Object object)
1075 {
1076   if (NILP (object))
1077     XSETBUFFER (object, current_buffer);
1078   else if (BUFFERP (object))
1079     CHECK_LIVE_BUFFER (object);
1080   else if (STRINGP (object))
1081     ;
1082   else
1083     dead_wrong_type_argument (Qbuffer_or_string_p, object);
1084
1085   return object;
1086 }
1087
1088 EXTENT
1089 extent_ancestor_1 (EXTENT e)
1090 {
1091   while (e->flags.has_parent)
1092     {
1093       /* There should be no circularities except in case of a logic
1094          error somewhere in the extent code */
1095       e = XEXTENT (XEXTENT_AUXILIARY (XCAR (e->plist))->parent);
1096     }
1097   return e;
1098 }
1099
1100 /* Given an extent object (string or buffer or nil), return its extent info.
1101    This may be 0 for a string. */
1102
1103 static struct extent_info *
1104 buffer_or_string_extent_info (Lisp_Object object)
1105 {
1106   if (STRINGP (object))
1107     {
1108       Lisp_Object plist = XSTRING (object)->plist;
1109       if (!CONSP (plist) || !EXTENT_INFOP (XCAR (plist)))
1110         return 0;
1111       return XEXTENT_INFO (XCAR (plist));
1112     }
1113   else if (NILP (object))
1114     return 0;
1115   else
1116     return XEXTENT_INFO (XBUFFER (object)->extent_info);
1117 }
1118
1119 /* Given a string or buffer, return its extent list.  This may be
1120    0 for a string. */
1121
1122 static Extent_List *
1123 buffer_or_string_extent_list (Lisp_Object object)
1124 {
1125   struct extent_info *info = buffer_or_string_extent_info (object);
1126
1127   if (!info)
1128     return 0;
1129   return info->extents;
1130 }
1131
1132 /* Given a string or buffer, return its extent info.  If it's not there,
1133    create it. */
1134
1135 static struct extent_info *
1136 buffer_or_string_extent_info_force (Lisp_Object object)
1137 {
1138   struct extent_info *info = buffer_or_string_extent_info (object);
1139
1140   if (!info)
1141     {
1142       Lisp_Object extent_info;
1143
1144       assert (STRINGP (object)); /* should never happen for buffers --
1145                                     the only buffers without an extent
1146                                     info are those after finalization,
1147                                     destroyed buffers, or special
1148                                     Lisp-inaccessible buffer objects. */
1149       extent_info = allocate_extent_info ();
1150       XSTRING (object)->plist = Fcons (extent_info, XSTRING (object)->plist);
1151       return XEXTENT_INFO (extent_info);
1152     }
1153
1154   return info;
1155 }
1156
1157 /* Detach all the extents in OBJECT.  Called from redisplay. */
1158
1159 void
1160 detach_all_extents (Lisp_Object object)
1161 {
1162   struct extent_info *data = buffer_or_string_extent_info (object);
1163
1164   if (data)
1165     {
1166       if (data->extents)
1167         {
1168           int i;
1169
1170           for (i = 0; i < extent_list_num_els (data->extents); i++)
1171             {
1172               EXTENT e = extent_list_at (data->extents, i, 0);
1173               /* No need to do detach_extent().  Just nuke the damn things,
1174                  which results in the equivalent but faster. */
1175               set_extent_start (e, -1);
1176               set_extent_end (e, -1);
1177             }
1178         }
1179
1180       /* But we need to clear all the lists containing extents or
1181          havoc will result. */
1182       extent_list_delete_all (data->extents);
1183       soe_invalidate (object);
1184     }
1185 }
1186
1187
1188 void
1189 init_buffer_extents (struct buffer *b)
1190 {
1191   b->extent_info = allocate_extent_info ();
1192 }
1193
1194 void
1195 uninit_buffer_extents (struct buffer *b)
1196 {
1197   struct extent_info *data = XEXTENT_INFO (b->extent_info);
1198
1199   /* Don't destroy the extents here -- there may still be children
1200      extents pointing to the extents. */
1201   detach_all_extents (make_buffer (b));
1202   finalize_extent_info (data, 0);
1203 }
1204
1205 /* Retrieve the extent list that an extent is a member of; the
1206    return value will never be 0 except in destroyed buffers (in which
1207    case the only extents that can refer to this buffer are detached
1208    ones). */
1209
1210 #define extent_extent_list(e) buffer_or_string_extent_list (extent_object (e))
1211
1212 /* ------------------------------- */
1213 /*        stack of extents         */
1214 /* ------------------------------- */
1215
1216 #ifdef ERROR_CHECK_EXTENTS
1217
1218 void
1219 sledgehammer_extent_check (Lisp_Object object)
1220 {
1221   int i;
1222   int endp;
1223   Extent_List *el = buffer_or_string_extent_list (object);
1224   struct buffer *buf = 0;
1225
1226   if (!el)
1227     return;
1228
1229   if (BUFFERP (object))
1230     buf = XBUFFER (object);
1231
1232   for (endp = 0; endp < 2; endp++)
1233     for (i = 1; i < extent_list_num_els (el); i++)
1234       {
1235         EXTENT e1 = extent_list_at (el, i-1, endp);
1236         EXTENT e2 = extent_list_at (el, i, endp);
1237         if (buf)
1238           {
1239             assert (extent_start (e1) <= buf->text->gpt ||
1240                     extent_start (e1) > buf->text->gpt + buf->text->gap_size);
1241             assert (extent_end (e1) <= buf->text->gpt ||
1242                     extent_end (e1) > buf->text->gpt + buf->text->gap_size);
1243           }
1244         assert (extent_start (e1) <= extent_end (e1));
1245         assert (endp ? (EXTENT_E_LESS_EQUAL (e1, e2)) :
1246                        (EXTENT_LESS_EQUAL (e1, e2)));
1247       }
1248 }
1249
1250 #endif
1251
1252 static Stack_Of_Extents *
1253 buffer_or_string_stack_of_extents (Lisp_Object object)
1254 {
1255   struct extent_info *info = buffer_or_string_extent_info (object);
1256   if (!info)
1257     return 0;
1258   return info->soe;
1259 }
1260
1261 static Stack_Of_Extents *
1262 buffer_or_string_stack_of_extents_force (Lisp_Object object)
1263 {
1264   struct extent_info *info = buffer_or_string_extent_info_force (object);
1265   if (!info->soe)
1266     info->soe = allocate_soe ();
1267   return info->soe;
1268 }
1269
1270 /* #define SOE_DEBUG */
1271
1272 #ifdef SOE_DEBUG
1273
1274 static void print_extent_1 (char *buf, Lisp_Object extent);
1275
1276 static void
1277 print_extent_2 (EXTENT e)
1278 {
1279   Lisp_Object extent;
1280   char buf[200];
1281
1282   XSETEXTENT (extent, e);
1283   print_extent_1 (buf, extent);
1284   fputs (buf, stdout);
1285 }
1286
1287 static void
1288 soe_dump (Lisp_Object obj)
1289 {
1290   int i;
1291   Stack_Of_Extents *soe = buffer_or_string_stack_of_extents (obj);
1292   Extent_List *sel;
1293   int endp;
1294
1295   if (!soe)
1296     {
1297       printf ("No SOE");
1298       return;
1299     }
1300   sel = soe->extents;
1301   printf ("SOE pos is %d (memind %d)\n",
1302           soe->pos < 0 ? soe->pos :
1303           buffer_or_string_memind_to_bytind (obj, soe->pos),
1304           soe->pos);
1305   for (endp = 0; endp < 2; endp++)
1306     {
1307       printf (endp ? "SOE end:" : "SOE start:");
1308       for (i = 0; i < extent_list_num_els (sel); i++)
1309         {
1310           EXTENT e = extent_list_at (sel, i, endp);
1311           putchar ('\t');
1312           print_extent_2 (e);
1313         }
1314       putchar ('\n');
1315     }
1316   putchar ('\n');
1317 }
1318
1319 #endif
1320
1321 /* Insert EXTENT into OBJ's stack of extents, if necessary. */
1322
1323 static void
1324 soe_insert (Lisp_Object obj, EXTENT extent)
1325 {
1326   Stack_Of_Extents *soe = buffer_or_string_stack_of_extents (obj);
1327
1328 #ifdef SOE_DEBUG
1329   printf ("Inserting into SOE: ");
1330   print_extent_2 (extent);
1331   putchar ('\n');
1332 #endif
1333   if (!soe || soe->pos < extent_start (extent) ||
1334       soe->pos > extent_end (extent))
1335     {
1336 #ifdef SOE_DEBUG
1337       printf ("(not needed)\n\n");
1338 #endif
1339       return;
1340     }
1341   extent_list_insert (soe->extents, extent);
1342 #ifdef SOE_DEBUG
1343   puts ("SOE afterwards is:");
1344   soe_dump (obj);
1345 #endif
1346 }
1347
1348 /* Delete EXTENT from OBJ's stack of extents, if necessary. */
1349
1350 static void
1351 soe_delete (Lisp_Object obj, EXTENT extent)
1352 {
1353   Stack_Of_Extents *soe = buffer_or_string_stack_of_extents (obj);
1354
1355 #ifdef SOE_DEBUG
1356   printf ("Deleting from SOE: ");
1357   print_extent_2 (extent);
1358   putchar ('\n');
1359 #endif
1360   if (!soe || soe->pos < extent_start (extent) ||
1361       soe->pos > extent_end (extent))
1362     {
1363 #ifdef SOE_DEBUG
1364       puts ("(not needed)\n");
1365 #endif
1366       return;
1367     }
1368   extent_list_delete (soe->extents, extent);
1369 #ifdef SOE_DEBUG
1370   puts ("SOE afterwards is:");
1371   soe_dump (obj);
1372 #endif
1373 }
1374
1375 /* Move OBJ's stack of extents to lie over the specified position. */
1376
1377 static void
1378 soe_move (Lisp_Object obj, Memind pos)
1379 {
1380   Stack_Of_Extents *soe = buffer_or_string_stack_of_extents_force (obj);
1381   Extent_List *sel = soe->extents;
1382   int numsoe = extent_list_num_els (sel);
1383   Extent_List *bel = buffer_or_string_extent_list (obj);
1384   int direction;
1385   int endp;
1386
1387 #ifdef ERROR_CHECK_EXTENTS
1388   assert (bel);
1389 #endif
1390
1391 #ifdef SOE_DEBUG
1392   printf ("Moving SOE from %d (memind %d) to %d (memind %d)\n",
1393           soe->pos < 0 ? soe->pos :
1394           buffer_or_string_memind_to_bytind (obj, soe->pos), soe->pos,
1395           buffer_or_string_memind_to_bytind (obj, pos), pos);
1396 #endif
1397   if (soe->pos < pos)
1398     {
1399       direction = 1;
1400       endp = 0;
1401     }
1402   else if (soe->pos > pos)
1403     {
1404       direction = -1;
1405       endp = 1;
1406     }
1407   else
1408     {
1409 #ifdef SOE_DEBUG
1410       puts ("(not needed)\n");
1411 #endif
1412       return;
1413     }
1414
1415   /* For DIRECTION = 1: Any extent that overlaps POS is either in the
1416      SOE (if the extent starts at or before SOE->POS) or is greater
1417      (in the display order) than any extent in the SOE (if it starts
1418      after SOE->POS).
1419
1420      For DIRECTION = -1: Any extent that overlaps POS is either in the
1421      SOE (if the extent ends at or after SOE->POS) or is less (in the
1422      e-order) than any extent in the SOE (if it ends before SOE->POS).
1423
1424      We proceed in two stages:
1425
1426      1) delete all extents in the SOE that don't overlap POS.
1427      2) insert all extents into the SOE that start (or end, when
1428         DIRECTION = -1) in (SOE->POS, POS] and that overlap
1429         POS. (Don't include SOE->POS in the range because those
1430         extents would already be in the SOE.)
1431    */
1432
1433   /* STAGE 1. */
1434
1435   if (numsoe > 0)
1436     {
1437       /* Delete all extents in the SOE that don't overlap POS.
1438          This is all extents that end before (or start after,
1439          if DIRECTION = -1) POS.
1440        */
1441
1442       /* Deleting extents from the SOE is tricky because it changes
1443          the positions of extents.  If we are deleting in the forward
1444          direction we have to call extent_list_at() on the same position
1445          over and over again because positions after the deleted element
1446          get shifted back by 1.  To make life simplest, we delete forward
1447          irrespective of DIRECTION.
1448        */
1449       int start, end;
1450       int i;
1451
1452       if (direction > 0)
1453         {
1454           start = 0;
1455           end = extent_list_locate_from_pos (sel, pos, 1);
1456         }
1457       else
1458         {
1459           start = extent_list_locate_from_pos (sel, pos+1, 0);
1460           end = numsoe;
1461         }
1462
1463       for (i = start; i < end; i++)
1464         extent_list_delete (sel, extent_list_at (sel, start /* see above */,
1465                                                  !endp));
1466     }
1467
1468   /* STAGE 2. */
1469
1470   {
1471     int start_pos;
1472
1473     if (direction < 0)
1474       start_pos = extent_list_locate_from_pos (bel, soe->pos, endp) - 1;
1475     else
1476       start_pos = extent_list_locate_from_pos (bel, soe->pos + 1, endp);
1477
1478     for (; start_pos >= 0 && start_pos < extent_list_num_els (bel);
1479          start_pos += direction)
1480       {
1481         EXTENT e = extent_list_at (bel, start_pos, endp);
1482         if ((direction > 0) ?
1483             (extent_start (e) > pos) :
1484             (extent_end (e) < pos))
1485           break; /* All further extents lie on the far side of POS
1486                     and thus can't overlap. */
1487         if ((direction > 0) ?
1488             (extent_end (e) >= pos) :
1489             (extent_start (e) <= pos))
1490           extent_list_insert (sel, e);
1491       }
1492   }
1493
1494   soe->pos = pos;
1495 #ifdef SOE_DEBUG
1496   puts ("SOE afterwards is:");
1497   soe_dump (obj);
1498 #endif
1499 }
1500
1501 static void
1502 soe_invalidate (Lisp_Object obj)
1503 {
1504   Stack_Of_Extents *soe = buffer_or_string_stack_of_extents (obj);
1505
1506   if (soe)
1507     {
1508       extent_list_delete_all (soe->extents);
1509       soe->pos = -1;
1510     }
1511 }
1512
1513 static struct stack_of_extents *
1514 allocate_soe (void)
1515 {
1516   struct stack_of_extents *soe = xnew_and_zero (struct stack_of_extents);
1517   soe->extents = allocate_extent_list ();
1518   soe->pos = -1;
1519   return soe;
1520 }
1521
1522 static void
1523 free_soe (struct stack_of_extents *soe)
1524 {
1525   free_extent_list (soe->extents);
1526   xfree (soe);
1527 }
1528
1529 /* ------------------------------- */
1530 /*        other primitives         */
1531 /* ------------------------------- */
1532
1533 /* Return the start (endp == 0) or end (endp == 1) of an extent as
1534    a byte index.  If you want the value as a memory index, use
1535    extent_endpoint().  If you want the value as a buffer position,
1536    use extent_endpoint_bufpos(). */
1537
1538 static Bytind
1539 extent_endpoint_bytind (EXTENT extent, int endp)
1540 {
1541   assert (EXTENT_LIVE_P (extent));
1542   assert (!extent_detached_p (extent));
1543   {
1544     Memind i = endp ? extent_end (extent) : extent_start (extent);
1545     Lisp_Object obj = extent_object (extent);
1546     return buffer_or_string_memind_to_bytind (obj, i);
1547   }
1548 }
1549
1550 static Bufpos
1551 extent_endpoint_bufpos (EXTENT extent, int endp)
1552 {
1553   assert (EXTENT_LIVE_P (extent));
1554   assert (!extent_detached_p (extent));
1555   {
1556     Memind i = endp ? extent_end (extent) : extent_start (extent);
1557     Lisp_Object obj = extent_object (extent);
1558     return buffer_or_string_memind_to_bufpos (obj, i);
1559   }
1560 }
1561
1562 /* A change to an extent occurred that will change the display, so
1563    notify redisplay.  Maybe also recurse over all the extent's
1564    descendants. */
1565
1566 static void
1567 extent_changed_for_redisplay (EXTENT extent, int descendants_too,
1568                               int invisibility_change)
1569 {
1570   Lisp_Object object;
1571   Lisp_Object rest;
1572
1573   /* we could easily encounter a detached extent while traversing the
1574      children, but we should never be able to encounter a dead extent. */
1575   assert (EXTENT_LIVE_P (extent));
1576
1577   if (descendants_too)
1578     {
1579       Lisp_Object children = extent_children (extent);
1580
1581       if (!NILP (children))
1582         {
1583           /* first mark all of the extent's children.  We will lose big-time
1584              if there are any circularities here, so we sure as hell better
1585              ensure that there aren't. */
1586           LIST_LOOP (rest, XWEAK_LIST_LIST (children))
1587             extent_changed_for_redisplay (XEXTENT (XCAR (rest)), 1,
1588                                           invisibility_change);
1589         }
1590     }
1591
1592   /* now mark the extent itself. */
1593
1594   object = extent_object (extent);
1595
1596   if (extent_detached_p (extent))
1597     return;
1598
1599   else if (STRINGP (object))
1600     {
1601     /* #### Changes to string extents can affect redisplay if they are
1602        in the modeline or in the gutters.
1603
1604        If the extent is in some generated-modeline-string: when we
1605        change an extent in generated-modeline-string, this changes its
1606        parent, which is in `modeline-format', so we should force the
1607        modeline to be updated.  But how to determine whether a string
1608        is a `generated-modeline-string'?  Looping through all buffers
1609        is not very efficient.  Should we add all
1610        `generated-modeline-string' strings to a hash table?  Maybe
1611        efficiency is not the greatest concern here and there's no big
1612        loss in looping over the buffers.
1613
1614        If the extent is in a gutter we mark the gutter as
1615        changed. This means (a) we can update extents in the gutters
1616        when we need it. (b) we don't have to update the gutters when
1617        only extents attached to buffers have changed. */
1618
1619       if (!in_modeline_generation)
1620         MARK_EXTENTS_CHANGED;
1621       gutter_extent_signal_changed_region_maybe (object,
1622                                                  extent_endpoint_bufpos (extent, 0),
1623                                                  extent_endpoint_bufpos (extent, 1));
1624     }
1625   else if (BUFFERP (object))
1626     {
1627       struct buffer *b;
1628       b = XBUFFER (object);
1629       BUF_FACECHANGE (b)++;
1630       MARK_EXTENTS_CHANGED;
1631       if (invisibility_change)
1632         MARK_CLIP_CHANGED;
1633       buffer_extent_signal_changed_region (b,
1634                                            extent_endpoint_bufpos (extent, 0),
1635                                            extent_endpoint_bufpos (extent, 1));
1636     }
1637 }
1638
1639 /* A change to an extent occurred that might affect redisplay.
1640    This is called when properties such as the endpoints, the layout,
1641    or the priority changes.  Redisplay will be affected only if
1642    the extent has any displayable attributes. */
1643
1644 static void
1645 extent_maybe_changed_for_redisplay (EXTENT extent, int descendants_too,
1646                                     int invisibility_change)
1647 {
1648   /* Retrieve the ancestor for efficiency */
1649   EXTENT anc = extent_ancestor (extent);
1650   if (!NILP (extent_face        (anc)) ||
1651       !NILP (extent_begin_glyph (anc)) ||
1652       !NILP (extent_end_glyph   (anc)) ||
1653       !NILP (extent_mouse_face  (anc)) ||
1654       !NILP (extent_invisible   (anc)) ||
1655       !NILP (extent_initial_redisplay_function (anc)) ||
1656       invisibility_change)
1657     extent_changed_for_redisplay (extent, descendants_too,
1658                                   invisibility_change);
1659 }
1660
1661 static EXTENT
1662 make_extent_detached (Lisp_Object object)
1663 {
1664   EXTENT extent = allocate_extent ();
1665
1666   assert (NILP (object) || STRINGP (object) ||
1667           (BUFFERP (object) && BUFFER_LIVE_P (XBUFFER (object))));
1668   extent_object (extent) = object;
1669   /* Now make sure the extent info exists. */
1670   if (!NILP (object))
1671     buffer_or_string_extent_info_force (object);
1672   return extent;
1673 }
1674
1675 /* A "real" extent is any extent other than the internal (not-user-visible)
1676    extents used by `map-extents'. */
1677
1678 static EXTENT
1679 real_extent_at_forward (Extent_List *el, int pos, int endp)
1680 {
1681   for (; pos < extent_list_num_els (el); pos++)
1682     {
1683       EXTENT e = extent_list_at (el, pos, endp);
1684       if (!extent_internal_p (e))
1685         return e;
1686     }
1687   return 0;
1688 }
1689
1690 static EXTENT
1691 real_extent_at_backward (Extent_List *el, int pos, int endp)
1692 {
1693   for (; pos >= 0; pos--)
1694     {
1695       EXTENT e = extent_list_at (el, pos, endp);
1696       if (!extent_internal_p (e))
1697         return e;
1698     }
1699   return 0;
1700 }
1701
1702 static EXTENT
1703 extent_first (Lisp_Object obj)
1704 {
1705   Extent_List *el = buffer_or_string_extent_list (obj);
1706
1707   if (!el)
1708     return 0;
1709   return real_extent_at_forward (el, 0, 0);
1710 }
1711
1712 #ifdef DEBUG_XEMACS
1713 static EXTENT
1714 extent_e_first (Lisp_Object obj)
1715 {
1716   Extent_List *el = buffer_or_string_extent_list (obj);
1717
1718   if (!el)
1719     return 0;
1720   return real_extent_at_forward (el, 0, 1);
1721 }
1722 #endif
1723
1724 static EXTENT
1725 extent_next (EXTENT e)
1726 {
1727   Extent_List *el = extent_extent_list (e);
1728   int foundp;
1729   int pos = extent_list_locate (el, e, 0, &foundp);
1730   assert (foundp);
1731   return real_extent_at_forward (el, pos+1, 0);
1732 }
1733
1734 #ifdef DEBUG_XEMACS
1735 static EXTENT
1736 extent_e_next (EXTENT e)
1737 {
1738   Extent_List *el = extent_extent_list (e);
1739   int foundp;
1740   int pos = extent_list_locate (el, e, 1, &foundp);
1741   assert (foundp);
1742   return real_extent_at_forward (el, pos+1, 1);
1743 }
1744 #endif
1745
1746 static EXTENT
1747 extent_last (Lisp_Object obj)
1748 {
1749   Extent_List *el = buffer_or_string_extent_list (obj);
1750
1751   if (!el)
1752     return 0;
1753   return real_extent_at_backward (el, extent_list_num_els (el) - 1, 0);
1754 }
1755
1756 #ifdef DEBUG_XEMACS
1757 static EXTENT
1758 extent_e_last (Lisp_Object obj)
1759 {
1760   Extent_List *el = buffer_or_string_extent_list (obj);
1761
1762   if (!el)
1763     return 0;
1764   return real_extent_at_backward (el, extent_list_num_els (el) - 1, 1);
1765 }
1766 #endif
1767
1768 static EXTENT
1769 extent_previous (EXTENT e)
1770 {
1771   Extent_List *el = extent_extent_list (e);
1772   int foundp;
1773   int pos = extent_list_locate (el, e, 0, &foundp);
1774   assert (foundp);
1775   return real_extent_at_backward (el, pos-1, 0);
1776 }
1777
1778 #ifdef DEBUG_XEMACS
1779 static EXTENT
1780 extent_e_previous (EXTENT e)
1781 {
1782   Extent_List *el = extent_extent_list (e);
1783   int foundp;
1784   int pos = extent_list_locate (el, e, 1, &foundp);
1785   assert (foundp);
1786   return real_extent_at_backward (el, pos-1, 1);
1787 }
1788 #endif
1789
1790 static void
1791 extent_attach (EXTENT extent)
1792 {
1793   Extent_List *el = extent_extent_list (extent);
1794
1795   extent_list_insert (el, extent);
1796   soe_insert (extent_object (extent), extent);
1797   /* only this extent changed */
1798   extent_maybe_changed_for_redisplay (extent, 0,
1799                                       !NILP (extent_invisible (extent)));
1800 }
1801
1802 static void
1803 extent_detach (EXTENT extent)
1804 {
1805   Extent_List *el;
1806
1807   if (extent_detached_p (extent))
1808     return;
1809   el = extent_extent_list (extent);
1810
1811   /* call this before messing with the extent. */
1812   extent_maybe_changed_for_redisplay (extent, 0,
1813                                       !NILP (extent_invisible (extent)));
1814   extent_list_delete (el, extent);
1815   soe_delete (extent_object (extent), extent);
1816   set_extent_start (extent, -1);
1817   set_extent_end (extent, -1);
1818 }
1819
1820 /* ------------------------------- */
1821 /*        map-extents et al.       */
1822 /* ------------------------------- */
1823
1824 /* Returns true iff map_extents() would visit the given extent.
1825    See the comments at map_extents() for info on the overlap rule.
1826    Assumes that all validation on the extent and buffer positions has
1827    already been performed (see Fextent_in_region_p ()).
1828  */
1829 static int
1830 extent_in_region_p (EXTENT extent, Bytind from, Bytind to,
1831                     unsigned int flags)
1832 {
1833   Lisp_Object obj = extent_object (extent);
1834   Endpoint_Index start, end, exs, exe;
1835   int start_open, end_open;
1836   unsigned int all_extents_flags = flags & ME_ALL_EXTENTS_MASK;
1837   unsigned int in_region_flags   = flags & ME_IN_REGION_MASK;
1838   int retval;
1839
1840   /* A zero-length region is treated as closed-closed. */
1841   if (from == to)
1842     {
1843       flags |= ME_END_CLOSED;
1844       flags &= ~ME_START_OPEN;
1845     }
1846
1847   /* So is a zero-length extent. */
1848   if (extent_start (extent) == extent_end (extent))
1849     start_open = 0, end_open = 0;
1850   /* `all_extents_flags' will almost always be zero. */
1851   else if (all_extents_flags == 0)
1852     {
1853       start_open = extent_start_open_p (extent);
1854       end_open   = extent_end_open_p   (extent);
1855     }
1856   else
1857     switch (all_extents_flags)
1858       {
1859       case ME_ALL_EXTENTS_CLOSED:      start_open = 0, end_open = 0; break;
1860       case ME_ALL_EXTENTS_OPEN:        start_open = 1, end_open = 1; break;
1861       case ME_ALL_EXTENTS_CLOSED_OPEN: start_open = 0, end_open = 1; break;
1862       case ME_ALL_EXTENTS_OPEN_CLOSED: start_open = 1, end_open = 0; break;
1863       default: abort(); return 0;
1864       }
1865
1866   start = buffer_or_string_bytind_to_startind (obj, from,
1867                                                flags & ME_START_OPEN);
1868   end = buffer_or_string_bytind_to_endind (obj, to, ! (flags & ME_END_CLOSED));
1869   exs = memind_to_startind (extent_start (extent), start_open);
1870   exe = memind_to_endind   (extent_end   (extent), end_open);
1871
1872   /* It's easy to determine whether an extent lies *outside* the
1873      region -- just determine whether it's completely before
1874      or completely after the region.  Reject all such extents, so
1875      we're now left with only the extents that overlap the region.
1876    */
1877
1878   if (exs > end || exe < start)
1879     return 0;
1880
1881   /* See if any further restrictions are called for. */
1882   /* in_region_flags will almost always be zero. */
1883   if (in_region_flags == 0)
1884     retval = 1;
1885   else
1886     switch (in_region_flags)
1887       {
1888       case ME_START_IN_REGION:
1889         retval = start <= exs && exs <= end; break;
1890       case ME_END_IN_REGION:
1891         retval = start <= exe && exe <= end; break;
1892       case ME_START_AND_END_IN_REGION:
1893         retval = start <= exs && exe <= end; break;
1894       case ME_START_OR_END_IN_REGION:
1895         retval = (start <= exs && exs <= end) || (start <= exe && exe <= end);
1896         break;
1897       default:
1898         abort(); return 0;
1899       }
1900   return flags & ME_NEGATE_IN_REGION ? !retval : retval;
1901 }
1902
1903 struct map_extents_struct
1904 {
1905   Extent_List *el;
1906   Extent_List_Marker *mkr;
1907   EXTENT range;
1908 };
1909
1910 static Lisp_Object
1911 map_extents_unwind (Lisp_Object obj)
1912 {
1913   struct map_extents_struct *closure =
1914     (struct map_extents_struct *) get_opaque_ptr (obj);
1915   free_opaque_ptr (obj);
1916   if (closure->range)
1917     extent_detach (closure->range);
1918   if (closure->mkr)
1919     extent_list_delete_marker (closure->el, closure->mkr);
1920   return Qnil;
1921 }
1922
1923 /* This is the guts of `map-extents' and the other functions that
1924    map over extents.  In theory the operation of this function is
1925    simple: just figure out what extents we're mapping over, and
1926    call the function on each one of them in the range.  Unfortunately
1927    there are a wide variety of things that the mapping function
1928    might do, and we have to be very tricky to avoid getting messed
1929    up.  Furthermore, this function needs to be very fast (it is
1930    called multiple times every time text is inserted or deleted
1931    from a buffer), and so we can't always afford the overhead of
1932    dealing with all the possible things that the mapping function
1933    might do; thus, there are many flags that can be specified
1934    indicating what the mapping function might or might not do.
1935
1936    The result of all this is that this is the most complicated
1937    function in this file.  Change it at your own risk!
1938
1939    A potential simplification to the logic below is to determine
1940    all the extents that the mapping function should be called on
1941    before any calls are actually made and save them in an array.
1942    That introduces its own complications, however (the array
1943    needs to be marked for garbage-collection, and a static array
1944    cannot be used because map_extents() needs to be reentrant).
1945    Furthermore, the results might be a little less sensible than
1946    the logic below. */
1947
1948
1949 static void
1950 map_extents_bytind (Bytind from, Bytind to, map_extents_fun fn, void *arg,
1951                     Lisp_Object obj, EXTENT after, unsigned int flags)
1952 {
1953   Memind st, en; /* range we're mapping over */
1954   EXTENT range = 0; /* extent for this, if ME_MIGHT_MODIFY_TEXT */
1955   Extent_List *el = 0; /* extent list we're iterating over */
1956   Extent_List_Marker *posm = 0; /* marker for extent list,
1957                                    if ME_MIGHT_MODIFY_EXTENTS */
1958   /* count and struct for unwind-protect, if ME_MIGHT_THROW */
1959   int count = 0;
1960   struct map_extents_struct closure;
1961
1962 #ifdef ERROR_CHECK_EXTENTS
1963   assert (from <= to);
1964   assert (from >= buffer_or_string_absolute_begin_byte (obj) &&
1965           from <= buffer_or_string_absolute_end_byte (obj) &&
1966           to >= buffer_or_string_absolute_begin_byte (obj) &&
1967           to <= buffer_or_string_absolute_end_byte (obj));
1968 #endif
1969
1970   if (after)
1971     {
1972       assert (EQ (obj, extent_object (after)));
1973       assert (!extent_detached_p (after));
1974     }
1975
1976   el = buffer_or_string_extent_list (obj);
1977   if (!el || !extent_list_num_els(el))
1978     return;
1979   el = 0;
1980
1981   st = buffer_or_string_bytind_to_memind (obj, from);
1982   en = buffer_or_string_bytind_to_memind (obj, to);
1983
1984   if (flags & ME_MIGHT_MODIFY_TEXT)
1985     {
1986       /* The mapping function might change the text in the buffer,
1987          so make an internal extent to hold the range we're mapping
1988          over. */
1989       range = make_extent_detached (obj);
1990       set_extent_start (range, st);
1991       set_extent_end (range, en);
1992       range->flags.start_open = flags & ME_START_OPEN;
1993       range->flags.end_open = !(flags & ME_END_CLOSED);
1994       range->flags.internal = 1;
1995       range->flags.detachable = 0;
1996       extent_attach (range);
1997     }
1998
1999   if (flags & ME_MIGHT_THROW)
2000     {
2001       /* The mapping function might throw past us so we need to use an
2002          unwind_protect() to eliminate the internal extent and range
2003          that we use. */
2004       count = specpdl_depth ();
2005       closure.range = range;
2006       closure.mkr = 0;
2007       record_unwind_protect (map_extents_unwind,
2008                              make_opaque_ptr (&closure));
2009     }
2010
2011   /* ---------- Figure out where we start and what direction
2012                 we move in.  This is the trickiest part of this
2013                 function. ---------- */
2014
2015   /* If ME_START_IN_REGION, ME_END_IN_REGION or ME_START_AND_END_IN_REGION
2016      was specified and ME_NEGATE_IN_REGION was not specified, our job
2017      is simple because of the presence of the display order and e-order.
2018      (Note that theoretically do something similar for
2019      ME_START_OR_END_IN_REGION, but that would require more trickiness
2020      than it's worth to avoid hitting the same extent twice.)
2021
2022      In the general case, all the extents that overlap a range can be
2023      divided into two classes: those whose start position lies within
2024      the range (including the range's end but not including the
2025      range's start), and those that overlap the start position,
2026      i.e. those in the SOE for the start position.  Or equivalently,
2027      the extents can be divided into those whose end position lies
2028      within the range and those in the SOE for the end position.  Note
2029      that for this purpose we treat both the range and all extents in
2030      the buffer as closed on both ends.  If this is not what the ME_
2031      flags specified, then we've mapped over a few too many extents,
2032      but no big deal because extent_in_region_p() will filter them
2033      out.   Ideally, we could move the SOE to the closer of the range's
2034      two ends and work forwards or backwards from there.  However, in
2035      order to make the semantics of the AFTER argument work out, we
2036      have to always go in the same direction; so we choose to always
2037      move the SOE to the start position.
2038
2039      When it comes time to do the SOE stage, we first call soe_move()
2040      so that the SOE gets set up.  Note that the SOE might get
2041      changed while we are mapping over its contents.  If we can
2042      guarantee that the SOE won't get moved to a new position, we
2043      simply need to put a marker in the SOE and we will track deletions
2044      and insertions of extents in the SOE.  If the SOE might get moved,
2045      however (this would happen as a result of a recursive invocation
2046      of map-extents or a call to a redisplay-type function), then
2047      trying to track its changes is hopeless, so we just keep a
2048      marker to the first (or last) extent in the SOE and use that as
2049      our bound.
2050
2051      Finally, if DONT_USE_SOE is defined, we don't use the SOE at all
2052      and instead just map from the beginning of the buffer.  This is
2053      used for testing purposes and allows the SOE to be calculated
2054      using map_extents() instead of the other way around. */
2055
2056   {
2057     int range_flag; /* ME_*_IN_REGION subset of flags */
2058     int do_soe_stage = 0; /* Are we mapping over the SOE? */
2059     /* Does the range stage map over start or end positions? */
2060     int range_endp;
2061     /* If type == 0, we include the start position in the range stage mapping.
2062        If type == 1, we exclude the start position in the range stage mapping.
2063        If type == 2, we begin at range_start_pos, an extent-list position.
2064      */
2065     int range_start_type = 0;
2066     int range_start_pos = 0;
2067     int stage;
2068
2069     range_flag = flags & ME_IN_REGION_MASK;
2070     if ((range_flag == ME_START_IN_REGION ||
2071          range_flag == ME_START_AND_END_IN_REGION) &&
2072         !(flags & ME_NEGATE_IN_REGION))
2073       {
2074         /* map over start position in [range-start, range-end].  No SOE
2075            stage. */
2076         range_endp = 0;
2077       }
2078     else if (range_flag == ME_END_IN_REGION && !(flags & ME_NEGATE_IN_REGION))
2079       {
2080         /* map over end position in [range-start, range-end].  No SOE
2081            stage. */
2082         range_endp = 1;
2083       }
2084     else
2085       {
2086         /* Need to include the SOE extents. */
2087 #ifdef DONT_USE_SOE
2088         /* Just brute-force it: start from the beginning. */
2089         range_endp = 0;
2090         range_start_type = 2;
2091         range_start_pos = 0;
2092 #else
2093         Stack_Of_Extents *soe = buffer_or_string_stack_of_extents_force (obj);
2094         int numsoe;
2095
2096         /* Move the SOE to the closer end of the range.  This dictates
2097            whether we map over start positions or end positions. */
2098         range_endp = 0;
2099         soe_move (obj, st);
2100         numsoe = extent_list_num_els (soe->extents);
2101         if (numsoe)
2102           {
2103             if (flags & ME_MIGHT_MOVE_SOE)
2104               {
2105                 int foundp;
2106                 /* Can't map over SOE, so just extend range to cover the
2107                    SOE. */
2108                 EXTENT e = extent_list_at (soe->extents, 0, 0);
2109                 range_start_pos =
2110                   extent_list_locate (buffer_or_string_extent_list (obj), e, 0,
2111                                       &foundp);
2112                 assert (foundp);
2113                 range_start_type = 2;
2114               }
2115             else
2116               {
2117                 /* We can map over the SOE. */
2118                 do_soe_stage = 1;
2119                 range_start_type = 1;
2120               }
2121           }
2122         else
2123           {
2124             /* No extents in the SOE to map over, so we act just as if
2125                ME_START_IN_REGION or ME_END_IN_REGION was specified.
2126                RANGE_ENDP already specified so no need to do anything else. */
2127           }
2128       }
2129 #endif
2130
2131   /* ---------- Now loop over the extents. ---------- */
2132
2133     /* We combine the code for the two stages because much of it
2134        overlaps. */
2135     for (stage = 0; stage < 2; stage++)
2136       {
2137         int pos = 0; /* Position in extent list */
2138
2139         /* First set up start conditions */
2140         if (stage == 0)
2141           { /* The SOE stage */
2142             if (!do_soe_stage)
2143               continue;
2144             el = buffer_or_string_stack_of_extents_force (obj)->extents;
2145             /* We will always be looping over start extents here. */
2146             assert (!range_endp);
2147             pos = 0;
2148           }
2149         else
2150           { /* The range stage */
2151             el = buffer_or_string_extent_list (obj);
2152             switch (range_start_type)
2153               {
2154               case 0:
2155                 pos = extent_list_locate_from_pos (el, st, range_endp);
2156                 break;
2157               case 1:
2158                 pos = extent_list_locate_from_pos (el, st + 1, range_endp);
2159                 break;
2160               case 2:
2161                 pos = range_start_pos;
2162                 break;
2163               }
2164           }
2165
2166         if (flags & ME_MIGHT_MODIFY_EXTENTS)
2167           {
2168             /* Create a marker to track changes to the extent list */
2169             if (posm)
2170               /* Delete the marker used in the SOE stage. */
2171               extent_list_delete_marker
2172                 (buffer_or_string_stack_of_extents_force (obj)->extents, posm);
2173             posm = extent_list_make_marker (el, pos, range_endp);
2174             /* tell the unwind function about the marker. */
2175             closure.el = el;
2176             closure.mkr = posm;
2177           }
2178
2179         /* Now loop! */
2180         for (;;)
2181           {
2182             EXTENT e;
2183             Lisp_Object obj2;
2184
2185             /* ----- update position in extent list
2186                      and fetch next extent ----- */
2187
2188             if (posm)
2189               /* fetch POS again to track extent insertions or deletions */
2190               pos = extent_list_marker_pos (el, posm);
2191             if (pos >= extent_list_num_els (el))
2192               break;
2193             e = extent_list_at (el, pos, range_endp);
2194             pos++;
2195             if (posm)
2196               /* now point the marker to the next one we're going to process.
2197                  This ensures graceful behavior if this extent is deleted. */
2198               extent_list_move_marker (el, posm, pos);
2199
2200             /* ----- deal with internal extents ----- */
2201
2202             if (extent_internal_p (e))
2203               {
2204                 if (!(flags & ME_INCLUDE_INTERNAL))
2205                   continue;
2206                 else if (e == range)
2207                   {
2208                     /* We're processing internal extents and we've
2209                        come across our own special range extent.
2210                        (This happens only in adjust_extents*() and
2211                        process_extents*(), which handle text
2212                        insertion and deletion.) We need to omit
2213                        processing of this extent; otherwise
2214                        we will probably end up prematurely
2215                        terminating this loop. */
2216                     continue;
2217                   }
2218               }
2219
2220             /* ----- deal with AFTER condition ----- */
2221
2222             if (after)
2223               {
2224                 /* if e > after, then we can stop skipping extents. */
2225                 if (EXTENT_LESS (after, e))
2226                   after = 0;
2227                 else /* otherwise, skip this extent. */
2228                   continue;
2229               }
2230
2231             /* ----- stop if we're completely outside the range ----- */
2232
2233             /* fetch ST and EN again to track text insertions or deletions */
2234             if (range)
2235               {
2236                 st = extent_start (range);
2237                 en = extent_end (range);
2238               }
2239             if (extent_endpoint (e, range_endp) > en)
2240               {
2241                 /* Can't be mapping over SOE because all extents in
2242                    there should overlap ST */
2243                 assert (stage == 1);
2244                 break;
2245               }
2246
2247             /* ----- Now actually call the function ----- */
2248
2249             obj2 = extent_object (e);
2250             if (extent_in_region_p (e,
2251                                     buffer_or_string_memind_to_bytind (obj2,
2252                                                                        st),
2253                                     buffer_or_string_memind_to_bytind (obj2,
2254                                                                        en),
2255                                     flags))
2256               {
2257                 if ((*fn)(e, arg))
2258                   {
2259                     /* Function wants us to stop mapping. */
2260                     stage = 1; /* so outer for loop will terminate */
2261                     break;
2262                   }
2263               }
2264           }
2265       }
2266   /* ---------- Finished looping. ---------- */
2267   }
2268
2269   if (flags & ME_MIGHT_THROW)
2270     /* This deletes the range extent and frees the marker. */
2271     unbind_to (count, Qnil);
2272   else
2273     {
2274       /* Delete them ourselves */
2275       if (range)
2276         extent_detach (range);
2277       if (posm)
2278         extent_list_delete_marker (el, posm);
2279     }
2280 }
2281
2282 void
2283 map_extents (Bufpos from, Bufpos to, map_extents_fun fn,
2284              void *arg, Lisp_Object obj, EXTENT after, unsigned int flags)
2285 {
2286   map_extents_bytind (buffer_or_string_bufpos_to_bytind (obj, from),
2287                       buffer_or_string_bufpos_to_bytind (obj, to), fn, arg,
2288                       obj, after, flags);
2289 }
2290
2291 /* ------------------------------- */
2292 /*         adjust_extents()        */
2293 /* ------------------------------- */
2294
2295 /* Add AMOUNT to all extent endpoints in the range (FROM, TO].  This
2296    happens whenever the gap is moved or (under Mule) a character in a
2297    string is substituted for a different-length one.  The reason for
2298    this is that extent endpoints behave just like markers (all memory
2299    indices do) and this adjustment correct for markers -- see
2300    adjust_markers().  Note that it is important that we visit all
2301    extent endpoints in the range, irrespective of whether the
2302    endpoints are open or closed.
2303
2304    We could use map_extents() for this (and in fact the function
2305    was originally written that way), but the gap is in an incoherent
2306    state when this function is called and this function plays
2307    around with extent endpoints without detaching and reattaching
2308    the extents (this is provably correct and saves lots of time),
2309    so for safety we make it just look at the extent lists directly. */
2310
2311 void
2312 adjust_extents (Lisp_Object obj, Memind from, Memind to, int amount)
2313 {
2314   int endp;
2315   int pos;
2316   int startpos[2];
2317   Extent_List *el;
2318   Stack_Of_Extents *soe;
2319
2320 #ifdef ERROR_CHECK_EXTENTS
2321   sledgehammer_extent_check (obj);
2322 #endif
2323   el = buffer_or_string_extent_list (obj);
2324
2325   if (!el || !extent_list_num_els(el))
2326     return;
2327
2328   /* IMPORTANT! Compute the starting positions of the extents to
2329      modify BEFORE doing any modification!  Otherwise the starting
2330      position for the second time through the loop might get
2331      incorrectly calculated (I got bit by this bug real bad). */
2332   startpos[0] = extent_list_locate_from_pos (el, from+1, 0);
2333   startpos[1] = extent_list_locate_from_pos (el, from+1, 1);
2334   for (endp = 0; endp < 2; endp++)
2335     {
2336       for (pos = startpos[endp]; pos < extent_list_num_els (el);
2337            pos++)
2338         {
2339           EXTENT e = extent_list_at (el, pos, endp);
2340           if (extent_endpoint (e, endp) > to)
2341             break;
2342           set_extent_endpoint (e,
2343                                do_marker_adjustment (extent_endpoint (e, endp),
2344                                                      from, to, amount),
2345                                endp);
2346         }
2347     }
2348
2349   /* The index for the buffer's SOE is a memory index and thus
2350      needs to be adjusted like a marker. */
2351   soe = buffer_or_string_stack_of_extents (obj);
2352   if (soe && soe->pos >= 0)
2353     soe->pos = do_marker_adjustment (soe->pos, from, to, amount);
2354 }
2355
2356 /* ------------------------------- */
2357 /*  adjust_extents_for_deletion()  */
2358 /* ------------------------------- */
2359
2360 struct adjust_extents_for_deletion_arg
2361 {
2362   EXTENT_dynarr *list;
2363 };
2364
2365 static int
2366 adjust_extents_for_deletion_mapper (EXTENT extent, void *arg)
2367 {
2368   struct adjust_extents_for_deletion_arg *closure =
2369     (struct adjust_extents_for_deletion_arg *) arg;
2370
2371   Dynarr_add (closure->list, extent);
2372   return 0; /* continue mapping */
2373 }
2374
2375 /* For all extent endpoints in the range (FROM, TO], move them to the beginning
2376    of the new gap.   Note that it is important that we visit all extent
2377    endpoints in the range, irrespective of whether the endpoints are open or
2378    closed.
2379
2380    This function deals with weird stuff such as the fact that extents
2381    may get reordered.
2382
2383    There is no string correspondent for this because you can't
2384    delete characters from a string.
2385  */
2386
2387 void
2388 adjust_extents_for_deletion (Lisp_Object object, Bytind from,
2389                              Bytind to, int gapsize, int numdel,
2390                              int movegapsize)
2391 {
2392   struct adjust_extents_for_deletion_arg closure;
2393   int i;
2394   Memind adjust_to = (Memind) (to + gapsize);
2395   Bytecount amount = - numdel - movegapsize;
2396   Memind oldsoe = 0, newsoe = 0;
2397   Stack_Of_Extents *soe = buffer_or_string_stack_of_extents (object);
2398
2399 #ifdef ERROR_CHECK_EXTENTS
2400   sledgehammer_extent_check (object);
2401 #endif
2402   closure.list = Dynarr_new (EXTENT);
2403
2404   /* We're going to be playing weird games below with extents and the SOE
2405      and such, so compute the list now of all the extents that we're going
2406      to muck with.  If we do the mapping and adjusting together, things can
2407      get all screwed up. */
2408
2409   map_extents_bytind (from, to, adjust_extents_for_deletion_mapper,
2410                       (void *) &closure, object, 0,
2411                       /* extent endpoints move like markers regardless
2412                          of their open/closeness. */
2413                       ME_ALL_EXTENTS_CLOSED | ME_END_CLOSED |
2414                       ME_START_OR_END_IN_REGION | ME_INCLUDE_INTERNAL);
2415
2416   /*
2417     Old and new values for the SOE's position. (It gets adjusted
2418     like a marker, just like extent endpoints.)
2419   */
2420
2421   if (soe)
2422     {
2423       oldsoe = soe->pos;
2424       if (soe->pos >= 0)
2425         newsoe = do_marker_adjustment (soe->pos,
2426                                                 adjust_to, adjust_to,
2427                                                 amount);
2428       else
2429         newsoe = soe->pos;
2430     }
2431
2432   for (i = 0; i < Dynarr_length (closure.list); i++)
2433     {
2434       EXTENT extent = Dynarr_at (closure.list, i);
2435       Memind new_start = extent_start (extent);
2436       Memind new_end = extent_end (extent);
2437
2438       /* do_marker_adjustment() will not adjust values that should not be
2439          adjusted.  We're passing the same funky arguments to
2440          do_marker_adjustment() as buffer_delete_range() does. */
2441       new_start =
2442         do_marker_adjustment (new_start,
2443                                        adjust_to, adjust_to,
2444                                        amount);
2445       new_end =
2446         do_marker_adjustment (new_end,
2447                                        adjust_to, adjust_to,
2448                                        amount);
2449
2450       /* We need to be very careful here so that the SOE doesn't get
2451          corrupted.  We are shrinking extents out of the deleted region
2452          and simultaneously moving the SOE's pos out of the deleted
2453          region, so the SOE should contain the same extents at the end
2454          as at the beginning.  However, extents may get reordered
2455          by this process, so we have to operate by pulling the extents
2456          out of the buffer and SOE, changing their bounds, and then
2457          reinserting them.  In order for the SOE not to get screwed up,
2458          we have to make sure that the SOE's pos points to its old
2459          location whenever we pull an extent out, and points to its
2460          new location whenever we put the extent back in.
2461        */
2462
2463       if (new_start != extent_start (extent) ||
2464           new_end != extent_end (extent))
2465         {
2466           extent_detach (extent);
2467           set_extent_start (extent, new_start);
2468           set_extent_end (extent, new_end);
2469           if (soe)
2470             soe->pos = newsoe;
2471           extent_attach (extent);
2472           if (soe)
2473             soe->pos = oldsoe;
2474         }
2475     }
2476
2477   if (soe)
2478     soe->pos = newsoe;
2479
2480 #ifdef ERROR_CHECK_EXTENTS
2481   sledgehammer_extent_check (object);
2482 #endif
2483   Dynarr_free (closure.list);
2484 }
2485
2486 /* ------------------------------- */
2487 /*         extent fragments        */
2488 /* ------------------------------- */
2489
2490 /* Imagine that the buffer is divided up into contiguous,
2491    nonoverlapping "runs" of text such that no extent
2492    starts or ends within a run (extents that abut the
2493    run don't count).
2494
2495    An extent fragment is a structure that holds data about
2496    the run that contains a particular buffer position (if
2497    the buffer position is at the junction of two runs, the
2498    run after the position is used) -- the beginning and
2499    end of the run, a list of all of the extents in that
2500    run, the "merged face" that results from merging all of
2501    the faces corresponding to those extents, the begin and
2502    end glyphs at the beginning of the run, etc.  This is
2503    the information that redisplay needs in order to
2504    display this run.
2505
2506    Extent fragments have to be very quick to update to
2507    a new buffer position when moving linearly through
2508    the buffer.  They rely on the stack-of-extents code,
2509    which does the heavy-duty algorithmic work of determining
2510    which extents overly a particular position. */
2511
2512 /* This function returns the position of the beginning of
2513    the first run that begins after POS, or returns POS if
2514    there are no such runs. */
2515
2516 static Bytind
2517 extent_find_end_of_run (Lisp_Object obj, Bytind pos, int outside_accessible)
2518 {
2519   Extent_List *sel;
2520   Extent_List *bel = buffer_or_string_extent_list (obj);
2521   Bytind pos1, pos2;
2522   int elind1, elind2;
2523   Memind mempos = buffer_or_string_bytind_to_memind (obj, pos);
2524   Bytind limit = outside_accessible ?
2525     buffer_or_string_absolute_end_byte (obj) :
2526       buffer_or_string_accessible_end_byte (obj);
2527
2528   if (!bel || !extent_list_num_els(bel))
2529     return limit;
2530
2531   sel = buffer_or_string_stack_of_extents_force (obj)->extents;
2532   soe_move (obj, mempos);
2533
2534   /* Find the first start position after POS. */
2535   elind1 = extent_list_locate_from_pos (bel, mempos+1, 0);
2536   if (elind1 < extent_list_num_els (bel))
2537     pos1 = buffer_or_string_memind_to_bytind
2538       (obj, extent_start (extent_list_at (bel, elind1, 0)));
2539   else
2540     pos1 = limit;
2541
2542   /* Find the first end position after POS.  The extent corresponding
2543      to this position is either in the SOE or is greater than or
2544      equal to POS1, so we just have to look in the SOE. */
2545   elind2 = extent_list_locate_from_pos (sel, mempos+1, 1);
2546   if (elind2 < extent_list_num_els (sel))
2547     pos2 = buffer_or_string_memind_to_bytind
2548       (obj, extent_end (extent_list_at (sel, elind2, 1)));
2549   else
2550     pos2 = limit;
2551
2552   return min (min (pos1, pos2), limit);
2553 }
2554
2555 static Bytind
2556 extent_find_beginning_of_run (Lisp_Object obj, Bytind pos,
2557                               int outside_accessible)
2558 {
2559   Extent_List *sel;
2560   Extent_List *bel = buffer_or_string_extent_list (obj);
2561   Bytind pos1, pos2;
2562   int elind1, elind2;
2563   Memind mempos = buffer_or_string_bytind_to_memind (obj, pos);
2564   Bytind limit = outside_accessible ?
2565     buffer_or_string_absolute_begin_byte (obj) :
2566       buffer_or_string_accessible_begin_byte (obj);
2567
2568   if (!bel || !extent_list_num_els(bel))
2569     return limit;
2570
2571   sel = buffer_or_string_stack_of_extents_force (obj)->extents;
2572   soe_move (obj, mempos);
2573
2574   /* Find the first end position before POS. */
2575   elind1 = extent_list_locate_from_pos (bel, mempos, 1);
2576   if (elind1 > 0)
2577     pos1 = buffer_or_string_memind_to_bytind
2578       (obj, extent_end (extent_list_at (bel, elind1 - 1, 1)));
2579   else
2580     pos1 = limit;
2581
2582   /* Find the first start position before POS.  The extent corresponding
2583      to this position is either in the SOE or is less than or
2584      equal to POS1, so we just have to look in the SOE. */
2585   elind2 = extent_list_locate_from_pos (sel, mempos, 0);
2586   if (elind2 > 0)
2587     pos2 = buffer_or_string_memind_to_bytind
2588       (obj, extent_start (extent_list_at (sel, elind2 - 1, 0)));
2589   else
2590     pos2 = limit;
2591
2592   return max (max (pos1, pos2), limit);
2593 }
2594
2595 struct extent_fragment *
2596 extent_fragment_new (Lisp_Object buffer_or_string, struct frame *frm)
2597 {
2598   struct extent_fragment *ef = xnew_and_zero (struct extent_fragment);
2599
2600   ef->object = buffer_or_string;
2601   ef->frm = frm;
2602   ef->extents = Dynarr_new (EXTENT);
2603   ef->begin_glyphs = Dynarr_new (glyph_block);
2604   ef->end_glyphs   = Dynarr_new (glyph_block);
2605
2606   return ef;
2607 }
2608
2609 void
2610 extent_fragment_delete (struct extent_fragment *ef)
2611 {
2612   Dynarr_free (ef->extents);
2613   Dynarr_free (ef->begin_glyphs);
2614   Dynarr_free (ef->end_glyphs);
2615   xfree (ef);
2616 }
2617
2618 static int
2619 extent_priority_sort_function (const void *humpty, const void *dumpty)
2620 {
2621   const EXTENT foo = * (const EXTENT *) humpty;
2622   const EXTENT bar = * (const EXTENT *) dumpty;
2623   if (extent_priority (foo) < extent_priority (bar))
2624     return -1;
2625   return extent_priority (foo) > extent_priority (bar);
2626 }
2627
2628 static void
2629 extent_fragment_sort_by_priority (EXTENT_dynarr *extarr)
2630 {
2631   int i;
2632
2633   /* Sort our copy of the stack by extent_priority.  We use a bubble
2634      sort here because it's going to be faster than qsort() for small
2635      numbers of extents (less than 10 or so), and 99.999% of the time
2636      there won't ever be more extents than this in the stack. */
2637   if (Dynarr_length (extarr) < 10)
2638     {
2639       for (i = 1; i < Dynarr_length (extarr); i++)
2640         {
2641           int j = i - 1;
2642           while (j >= 0 &&
2643                  (extent_priority (Dynarr_at (extarr, j)) >
2644                   extent_priority (Dynarr_at (extarr, j+1))))
2645             {
2646               EXTENT tmp = Dynarr_at (extarr, j);
2647               Dynarr_at (extarr, j) = Dynarr_at (extarr, j+1);
2648               Dynarr_at (extarr, j+1) = tmp;
2649               j--;
2650             }
2651         }
2652     }
2653   else
2654     /* But some loser programs mess up and may create a large number
2655        of extents overlapping the same spot.  This will result in
2656        catastrophic behavior if we use the bubble sort above. */
2657     qsort (Dynarr_atp (extarr, 0), Dynarr_length (extarr),
2658            sizeof (EXTENT), extent_priority_sort_function);
2659 }
2660
2661 /* If PROP is the `invisible' property of an extent,
2662    this is 1 if the extent should be treated as invisible.  */
2663
2664 #define EXTENT_PROP_MEANS_INVISIBLE(buf, prop)                  \
2665   (EQ (buf->invisibility_spec, Qt)                              \
2666    ? ! NILP (prop)                                              \
2667    : invisible_p (prop, buf->invisibility_spec))
2668
2669 /* If PROP is the `invisible' property of a extent,
2670    this is 1 if the extent should be treated as invisible
2671    and should have an ellipsis.  */
2672
2673 #define EXTENT_PROP_MEANS_INVISIBLE_WITH_ELLIPSIS(buf, prop)    \
2674   (EQ (buf->invisibility_spec, Qt)                              \
2675    ? 0                                                          \
2676    : invisible_ellipsis_p (prop, buf->invisibility_spec))
2677
2678 /* This is like a combination of memq and assq.
2679    Return 1 if PROPVAL appears as an element of LIST
2680    or as the car of an element of LIST.
2681    If PROPVAL is a list, compare each element against LIST
2682    in that way, and return 1 if any element of PROPVAL is found in LIST.
2683    Otherwise return 0.
2684    This function cannot quit.  */
2685
2686 static int
2687 invisible_p (REGISTER Lisp_Object propval, Lisp_Object list)
2688 {
2689   REGISTER Lisp_Object tail, proptail;
2690   for (tail = list; CONSP (tail); tail = XCDR (tail))
2691     {
2692       REGISTER Lisp_Object tem;
2693       tem = XCAR (tail);
2694       if (EQ (propval, tem))
2695         return 1;
2696       if (CONSP (tem) && EQ (propval, XCAR (tem)))
2697         return 1;
2698     }
2699   if (CONSP (propval))
2700     for (proptail = propval; CONSP (proptail);
2701          proptail = XCDR (proptail))
2702       {
2703         Lisp_Object propelt;
2704         propelt = XCAR (proptail);
2705         for (tail = list; CONSP (tail); tail = XCDR (tail))
2706           {
2707             REGISTER Lisp_Object tem;
2708             tem = XCAR (tail);
2709             if (EQ (propelt, tem))
2710               return 1;
2711             if (CONSP (tem) && EQ (propelt, XCAR (tem)))
2712               return 1;
2713           }
2714       }
2715   return 0;
2716 }
2717
2718 /* Return 1 if PROPVAL appears as the car of an element of LIST
2719    and the cdr of that element is non-nil.
2720    If PROPVAL is a list, check each element of PROPVAL in that way,
2721    and the first time some element is found,
2722    return 1 if the cdr of that element is non-nil.
2723    Otherwise return 0.
2724    This function cannot quit.  */
2725
2726 static int
2727 invisible_ellipsis_p (REGISTER Lisp_Object propval, Lisp_Object list)
2728 {
2729   REGISTER Lisp_Object tail, proptail;
2730   for (tail = list; CONSP (tail); tail = XCDR (tail))
2731     {
2732       REGISTER Lisp_Object tem;
2733       tem = XCAR (tail);
2734       if (CONSP (tem) && EQ (propval, XCAR (tem)))
2735         return ! NILP (XCDR (tem));
2736     }
2737   if (CONSP (propval))
2738     for (proptail = propval; CONSP (proptail);
2739          proptail = XCDR (proptail))
2740       {
2741         Lisp_Object propelt;
2742         propelt = XCAR (proptail);
2743         for (tail = list; CONSP (tail); tail = XCDR (tail))
2744           {
2745             REGISTER Lisp_Object tem;
2746             tem = XCAR (tail);
2747             if (CONSP (tem) && EQ (propelt, XCAR (tem)))
2748               return ! NILP (XCDR (tem));
2749           }
2750       }
2751   return 0;
2752 }
2753
2754 face_index
2755 extent_fragment_update (struct window *w, struct extent_fragment *ef,
2756                         Bytind pos)
2757 {
2758   int i;
2759   Extent_List *sel =
2760     buffer_or_string_stack_of_extents_force (ef->object)->extents;
2761   EXTENT lhe = 0;
2762   struct extent dummy_lhe_extent;
2763   Memind mempos = buffer_or_string_bytind_to_memind (ef->object, pos);
2764
2765 #ifdef ERROR_CHECK_EXTENTS
2766   assert (pos >= buffer_or_string_accessible_begin_byte (ef->object)
2767           && pos <= buffer_or_string_accessible_end_byte (ef->object));
2768 #endif
2769
2770   Dynarr_reset (ef->extents);
2771   Dynarr_reset (ef->begin_glyphs);
2772   Dynarr_reset (ef->end_glyphs);
2773
2774   ef->previously_invisible = ef->invisible;
2775   if (ef->invisible)
2776     {
2777       if (ef->invisible_ellipses)
2778         ef->invisible_ellipses_already_displayed = 1;
2779     }
2780   else
2781     ef->invisible_ellipses_already_displayed = 0;
2782   ef->invisible = 0;
2783   ef->invisible_ellipses = 0;
2784
2785   /* Set up the begin and end positions. */
2786   ef->pos = pos;
2787   ef->end = extent_find_end_of_run (ef->object, pos, 0);
2788
2789   /* Note that extent_find_end_of_run() already moved the SOE for us. */
2790   /* soe_move (ef->object, mempos); */
2791
2792   /* Determine the begin glyphs at POS. */
2793   for (i = 0; i < extent_list_num_els (sel); i++)
2794     {
2795       EXTENT e = extent_list_at (sel, i, 0);
2796       if (extent_start (e) == mempos && !NILP (extent_begin_glyph (e)))
2797         {
2798           Lisp_Object glyph = extent_begin_glyph (e);
2799           struct glyph_block gb;
2800
2801           gb.glyph = glyph;
2802           XSETEXTENT (gb.extent, e);
2803           Dynarr_add (ef->begin_glyphs, gb);
2804         }
2805     }
2806
2807   /* Determine the end glyphs at POS. */
2808   for (i = 0; i < extent_list_num_els (sel); i++)
2809     {
2810       EXTENT e = extent_list_at (sel, i, 1);
2811       if (extent_end (e) == mempos && !NILP (extent_end_glyph (e)))
2812         {
2813           Lisp_Object glyph = extent_end_glyph (e);
2814           struct glyph_block gb;
2815
2816           gb.glyph = glyph;
2817           XSETEXTENT (gb.extent, e);
2818           Dynarr_add (ef->end_glyphs, gb);
2819         }
2820     }
2821
2822   /* We tried determining all the charsets used in the run here,
2823      but that fails even if we only do the current line -- display
2824      tables or non-printable characters might cause other charsets
2825      to be used. */
2826
2827   /* Determine whether the last-highlighted-extent is present. */
2828   if (EXTENTP (Vlast_highlighted_extent))
2829     lhe = XEXTENT (Vlast_highlighted_extent);
2830
2831   /* Now add all extents that overlap the character after POS and
2832      have a non-nil face.  Also check if the character is invisible. */
2833   for (i = 0; i < extent_list_num_els (sel); i++)
2834     {
2835       EXTENT e = extent_list_at (sel, i, 0);
2836       if (extent_end (e) > mempos)
2837         {
2838           Lisp_Object invis_prop = extent_invisible (e);
2839
2840           if (!NILP (invis_prop))
2841             {
2842               if (!BUFFERP (ef->object))
2843                 /* #### no `string-invisibility-spec' */
2844                 ef->invisible = 1;
2845               else
2846                 {
2847                   if (!ef->invisible_ellipses_already_displayed &&
2848                       EXTENT_PROP_MEANS_INVISIBLE_WITH_ELLIPSIS
2849                       (XBUFFER (ef->object), invis_prop))
2850                     {
2851                       ef->invisible = 1;
2852                       ef->invisible_ellipses = 1;
2853                     }
2854                   else if (EXTENT_PROP_MEANS_INVISIBLE
2855                            (XBUFFER (ef->object), invis_prop))
2856                     ef->invisible = 1;
2857                 }
2858             }
2859
2860           /* Remember that one of the extents in the list might be our
2861              dummy extent representing the highlighting that is
2862              attached to some other extent that is currently
2863              mouse-highlighted.  When an extent is mouse-highlighted,
2864              it is as if there are two extents there, of potentially
2865              different priorities: the extent being highlighted, with
2866              whatever face and priority it has; and an ephemeral
2867              extent in the `mouse-face' face with
2868              `mouse-highlight-priority'.
2869              */
2870
2871           if (!NILP (extent_face (e)))
2872             Dynarr_add (ef->extents, e);
2873           if (e == lhe)
2874             {
2875               Lisp_Object f;
2876               /* zeroing isn't really necessary; we only deref `priority'
2877                  and `face' */
2878               xzero (dummy_lhe_extent);
2879               set_extent_priority (&dummy_lhe_extent,
2880                                    mouse_highlight_priority);
2881               /* Need to break up the following expression, due to an */
2882               /* error in the Digital UNIX 3.2g C compiler (Digital */
2883               /* UNIX Compiler Driver 3.11). */
2884               f = extent_mouse_face (lhe);
2885               extent_face (&dummy_lhe_extent) = f;
2886               Dynarr_add (ef->extents, &dummy_lhe_extent);
2887             }
2888           /* since we are looping anyway, we might as well do this here */
2889           if ((!NILP(extent_initial_redisplay_function (e))) &&
2890               !extent_in_red_event_p(e))
2891             {
2892               Lisp_Object function = extent_initial_redisplay_function (e);
2893               Lisp_Object obj;
2894
2895               /* printf ("initial redisplay function called!\n "); */
2896
2897               /* print_extent_2 (e);
2898                  printf ("\n"); */
2899
2900               /* FIXME: One should probably inhibit the displaying of
2901                  this extent to reduce flicker */
2902               extent_in_red_event_p(e) = 1;
2903
2904               /* call the function */
2905               XSETEXTENT(obj,e);
2906               if(!NILP(function))
2907                  Fenqueue_eval_event(function,obj);
2908             }
2909         }
2910     }
2911
2912   extent_fragment_sort_by_priority (ef->extents);
2913
2914   /* Now merge the faces together into a single face.  The code to
2915      do this is in faces.c because it involves manipulating faces. */
2916   return get_extent_fragment_face_cache_index (w, ef);
2917 }
2918
2919 \f
2920 /************************************************************************/
2921 /*                      extent-object methods                           */
2922 /************************************************************************/
2923
2924 /* These are the basic helper functions for handling the allocation of
2925    extent objects.  They are similar to the functions for other
2926    lrecord objects.  allocate_extent() is in alloc.c, not here. */
2927
2928 static Lisp_Object
2929 mark_extent (Lisp_Object obj)
2930 {
2931   struct extent *extent = XEXTENT (obj);
2932
2933   mark_object (extent_object (extent));
2934   mark_object (extent_no_chase_normal_field (extent, face));
2935   return extent->plist;
2936 }
2937
2938 static void
2939 print_extent_1 (Lisp_Object obj, Lisp_Object printcharfun, int escapeflag)
2940 {
2941   EXTENT ext = XEXTENT (obj);
2942   EXTENT anc = extent_ancestor (ext);
2943   Lisp_Object tail;
2944   char buf[64], *bp = buf;
2945
2946   /* Retrieve the ancestor and use it, for faster retrieval of properties */
2947
2948   if (!NILP (extent_begin_glyph (anc))) *bp++ = '*';
2949   *bp++ = (extent_start_open_p (anc) ? '(': '[');
2950   if (extent_detached_p (ext))
2951     strcpy (bp, "detached");
2952   else
2953     sprintf (bp, "%ld, %ld",
2954              (long) XINT (Fextent_start_position (obj)),
2955              (long) XINT (Fextent_end_position (obj)));
2956   bp += strlen (bp);
2957   *bp++ = (extent_end_open_p (anc) ? ')': ']');
2958   if (!NILP (extent_end_glyph (anc))) *bp++ = '*';
2959   *bp++ = ' ';
2960
2961   if (!NILP (extent_read_only (anc))) *bp++ = '%';
2962   if (!NILP (extent_mouse_face (anc))) *bp++ = 'H';
2963   if (extent_unique_p (anc)) *bp++ = 'U';
2964   else if (extent_duplicable_p (anc)) *bp++ = 'D';
2965   if (!NILP (extent_invisible (anc))) *bp++ = 'I';
2966
2967   if (!NILP (extent_read_only (anc)) || !NILP (extent_mouse_face (anc)) ||
2968       extent_unique_p (anc) ||
2969       extent_duplicable_p (anc) || !NILP (extent_invisible (anc)))
2970     *bp++ = ' ';
2971   *bp = '\0';
2972   write_c_string (buf, printcharfun);
2973
2974   tail = extent_plist_slot (anc);
2975
2976   for (; !NILP (tail); tail = Fcdr (Fcdr (tail)))
2977     {
2978       Lisp_Object v = XCAR (XCDR (tail));
2979       if (NILP (v)) continue;
2980       print_internal (XCAR (tail), printcharfun, escapeflag);
2981       write_c_string (" ", printcharfun);
2982     }
2983
2984   sprintf (buf, "0x%lx", (long) ext);
2985   write_c_string (buf, printcharfun);
2986 }
2987
2988 static void
2989 print_extent (Lisp_Object obj, Lisp_Object printcharfun, int escapeflag)
2990 {
2991   if (escapeflag)
2992     {
2993       const char *title = "";
2994       const char *name = "";
2995       const char *posttitle = "";
2996       Lisp_Object obj2 = Qnil;
2997
2998       /* Destroyed extents have 't' in the object field, causing
2999          extent_object() to abort (maybe). */
3000       if (EXTENT_LIVE_P (XEXTENT (obj)))
3001         obj2 = extent_object (XEXTENT (obj));
3002
3003       if (NILP (obj2))
3004         title = "no buffer";
3005       else if (BUFFERP (obj2))
3006         {
3007           if (BUFFER_LIVE_P (XBUFFER (obj2)))
3008             {
3009               title = "buffer ";
3010               name = (char *) XSTRING_DATA (XBUFFER (obj2)->name);
3011             }
3012           else
3013             {
3014               title = "Killed Buffer";
3015               name = "";
3016             }
3017         }
3018       else
3019         {
3020           assert (STRINGP (obj2));
3021           title = "string \"";
3022           posttitle = "\"";
3023           name = (char *) XSTRING_DATA (obj2);
3024         }
3025
3026       if (print_readably)
3027         {
3028           if (!EXTENT_LIVE_P (XEXTENT (obj)))
3029             error ("printing unreadable object #<destroyed extent>");
3030           else
3031             error ("printing unreadable object #<extent 0x%lx>",
3032                    (long) XEXTENT (obj));
3033         }
3034
3035       if (!EXTENT_LIVE_P (XEXTENT (obj)))
3036         write_c_string ("#<destroyed extent", printcharfun);
3037       else
3038         {
3039           char *buf = (char *)
3040             alloca (strlen (title) + strlen (name) + strlen (posttitle) + 1);
3041           write_c_string ("#<extent ", printcharfun);
3042           print_extent_1 (obj, printcharfun, escapeflag);
3043           write_c_string (extent_detached_p (XEXTENT (obj))
3044                           ? " from " : " in ", printcharfun);
3045           sprintf (buf, "%s%s%s", title, name, posttitle);
3046           write_c_string (buf, printcharfun);
3047         }
3048     }
3049   else
3050     {
3051       if (print_readably)
3052         error ("printing unreadable object #<extent>");
3053       write_c_string ("#<extent", printcharfun);
3054     }
3055   write_c_string (">", printcharfun);
3056 }
3057
3058 static int
3059 properties_equal (EXTENT e1, EXTENT e2, int depth)
3060 {
3061   /* When this function is called, all indirections have been followed.
3062      Thus, the indirection checks in the various macros below will not
3063      amount to anything, and could be removed.  However, the time
3064      savings would probably not be significant. */
3065   if (!(EQ (extent_face (e1), extent_face (e2)) &&
3066         extent_priority (e1) == extent_priority (e2) &&
3067         internal_equal (extent_begin_glyph (e1), extent_begin_glyph (e2),
3068                         depth + 1) &&
3069         internal_equal (extent_end_glyph (e1), extent_end_glyph (e2),
3070                         depth + 1)))
3071     return 0;
3072
3073   /* compare the bit flags. */
3074   {
3075     /* The has_aux field should not be relevant. */
3076     int e1_has_aux = e1->flags.has_aux;
3077     int e2_has_aux = e2->flags.has_aux;
3078     int value;
3079
3080     e1->flags.has_aux = e2->flags.has_aux = 0;
3081     value = memcmp (&e1->flags, &e2->flags, sizeof (e1->flags));
3082     e1->flags.has_aux = e1_has_aux;
3083     e2->flags.has_aux = e2_has_aux;
3084     if (value)
3085       return 0;
3086   }
3087
3088   /* compare the random elements of the plists. */
3089   return !plists_differ (extent_no_chase_plist (e1),
3090                          extent_no_chase_plist (e2),
3091                          0, 0, depth + 1);
3092 }
3093
3094 static int
3095 extent_equal (Lisp_Object obj1, Lisp_Object obj2, int depth)
3096 {
3097   struct extent *e1 = XEXTENT (obj1);
3098   struct extent *e2 = XEXTENT (obj2);
3099   return
3100     (extent_start (e1) == extent_start (e2) &&
3101      extent_end   (e1) == extent_end   (e2) &&
3102      internal_equal (extent_object (e1), extent_object (e2), depth + 1) &&
3103      properties_equal (extent_ancestor (e1), extent_ancestor (e2),
3104                        depth));
3105 }
3106
3107 static unsigned long
3108 extent_hash (Lisp_Object obj, int depth)
3109 {
3110   struct extent *e = XEXTENT (obj);
3111   /* No need to hash all of the elements; that would take too long.
3112      Just hash the most common ones. */
3113   return HASH3 (extent_start (e), extent_end (e),
3114                 internal_hash (extent_object (e), depth + 1));
3115 }
3116
3117 static const struct lrecord_description extent_description[] = {
3118   { XD_LISP_OBJECT, offsetof (struct extent, object) },
3119   { XD_LISP_OBJECT, offsetof (struct extent, flags.face) },
3120   { XD_LISP_OBJECT, offsetof (struct extent, plist) },
3121   { XD_END }
3122 };
3123
3124 static Lisp_Object
3125 extent_getprop (Lisp_Object obj, Lisp_Object prop)
3126 {
3127   return Fextent_property (obj, prop, Qunbound);
3128 }
3129
3130 static int
3131 extent_putprop (Lisp_Object obj, Lisp_Object prop, Lisp_Object value)
3132 {
3133   Fset_extent_property (obj, prop, value);
3134   return 1;
3135 }
3136
3137 static int
3138 extent_remprop (Lisp_Object obj, Lisp_Object prop)
3139 {
3140   EXTENT ext = XEXTENT (obj);
3141
3142   /* This list is taken from Fset_extent_property, and should be kept
3143      in synch.  */
3144   if (EQ (prop, Qread_only)
3145       || EQ (prop, Qunique)
3146       || EQ (prop, Qduplicable)
3147       || EQ (prop, Qinvisible)
3148       || EQ (prop, Qdetachable)
3149       || EQ (prop, Qdetached)
3150       || EQ (prop, Qdestroyed)
3151       || EQ (prop, Qpriority)
3152       || EQ (prop, Qface)
3153       || EQ (prop, Qinitial_redisplay_function)
3154       || EQ (prop, Qafter_change_functions)
3155       || EQ (prop, Qbefore_change_functions)
3156       || EQ (prop, Qmouse_face)
3157       || EQ (prop, Qhighlight)
3158       || EQ (prop, Qbegin_glyph_layout)
3159       || EQ (prop, Qend_glyph_layout)
3160       || EQ (prop, Qglyph_layout)
3161       || EQ (prop, Qbegin_glyph)
3162       || EQ (prop, Qend_glyph)
3163       || EQ (prop, Qstart_open)
3164       || EQ (prop, Qend_open)
3165       || EQ (prop, Qstart_closed)
3166       || EQ (prop, Qend_closed)
3167       || EQ (prop, Qkeymap))
3168     {
3169       /* #### Is this correct, anyway?  */
3170       return -1;
3171     }
3172
3173   return external_remprop (extent_plist_addr (ext), prop, 0, ERROR_ME);
3174 }
3175
3176 static Lisp_Object
3177 extent_plist (Lisp_Object obj)
3178 {
3179   return Fextent_properties (obj);
3180 }
3181
3182 DEFINE_BASIC_LRECORD_IMPLEMENTATION_WITH_PROPS ("extent", extent,
3183                                                 mark_extent,
3184                                                 print_extent,
3185                                                 /* NOTE: If you declare a
3186                                                    finalization method here,
3187                                                    it will NOT be called.
3188                                                    Shaft city. */
3189                                                 0,
3190                                                 extent_equal, extent_hash,
3191                                                 extent_description,
3192                                                 extent_getprop, extent_putprop,
3193                                                 extent_remprop, extent_plist,
3194                                                 struct extent);
3195
3196 \f
3197 /************************************************************************/
3198 /*                      basic extent accessors                          */
3199 /************************************************************************/
3200
3201 /* These functions are for checking externally-passed extent objects
3202    and returning an extent's basic properties, which include the
3203    buffer the extent is associated with, the endpoints of the extent's
3204    range, the open/closed-ness of those endpoints, and whether the
3205    extent is detached.  Manipulating these properties requires
3206    manipulating the ordered lists that hold extents; thus, functions
3207    to do that are in a later section. */
3208
3209 /* Given a Lisp_Object that is supposed to be an extent, make sure it
3210    is OK and return an extent pointer.  Extents can be in one of four
3211    states:
3212
3213    1) destroyed
3214    2) detached and not associated with a buffer
3215    3) detached and associated with a buffer
3216    4) attached to a buffer
3217
3218    If FLAGS is 0, types 2-4 are allowed.  If FLAGS is DE_MUST_HAVE_BUFFER,
3219    types 3-4 are allowed.  If FLAGS is DE_MUST_BE_ATTACHED, only type 4
3220    is allowed.
3221    */
3222
3223 static EXTENT
3224 decode_extent (Lisp_Object extent_obj, unsigned int flags)
3225 {
3226   EXTENT extent;
3227   Lisp_Object obj;
3228
3229   CHECK_LIVE_EXTENT (extent_obj);
3230   extent = XEXTENT (extent_obj);
3231   obj = extent_object (extent);
3232
3233   /* the following condition will fail if we're dealing with a freed extent */
3234   assert (NILP (obj) || BUFFERP (obj) || STRINGP (obj));
3235
3236   if (flags & DE_MUST_BE_ATTACHED)
3237     flags |= DE_MUST_HAVE_BUFFER;
3238
3239   /* if buffer is dead, then convert extent to have no buffer. */
3240   if (BUFFERP (obj) && !BUFFER_LIVE_P (XBUFFER (obj)))
3241     obj = extent_object (extent) = Qnil;
3242
3243   assert (!NILP (obj) || extent_detached_p (extent));
3244
3245   if ((NILP (obj) && (flags & DE_MUST_HAVE_BUFFER))
3246       || (extent_detached_p (extent) && (flags & DE_MUST_BE_ATTACHED)))
3247     {
3248       invalid_argument ("extent doesn't belong to a buffer or string",
3249                          extent_obj);
3250     }
3251
3252   return extent;
3253 }
3254
3255 /* Note that the returned value is a buffer position, not a byte index. */
3256
3257 static Lisp_Object
3258 extent_endpoint_external (Lisp_Object extent_obj, int endp)
3259 {
3260   EXTENT extent = decode_extent (extent_obj, 0);
3261
3262   if (extent_detached_p (extent))
3263     return Qnil;
3264   else
3265     return make_int (extent_endpoint_bufpos (extent, endp));
3266 }
3267
3268 DEFUN ("extentp", Fextentp, 1, 1, 0, /*
3269 Return t if OBJECT is an extent.
3270 */
3271        (object))
3272 {
3273   return EXTENTP (object) ? Qt : Qnil;
3274 }
3275
3276 DEFUN ("extent-live-p", Fextent_live_p, 1, 1, 0, /*
3277 Return t if OBJECT is an extent that has not been destroyed.
3278 */
3279        (object))
3280 {
3281   return EXTENTP (object) && EXTENT_LIVE_P (XEXTENT (object)) ? Qt : Qnil;
3282 }
3283
3284 DEFUN ("extent-detached-p", Fextent_detached_p, 1, 1, 0, /*
3285 Return t if EXTENT is detached.
3286 */
3287        (extent))
3288 {
3289   return extent_detached_p (decode_extent (extent, 0)) ? Qt : Qnil;
3290 }
3291
3292 DEFUN ("extent-object", Fextent_object, 1, 1, 0, /*
3293 Return object (buffer or string) that EXTENT refers to.
3294 */
3295        (extent))
3296 {
3297   return extent_object (decode_extent (extent, 0));
3298 }
3299
3300 DEFUN ("extent-start-position", Fextent_start_position, 1, 1, 0, /*
3301 Return start position of EXTENT, or nil if EXTENT is detached.
3302 */
3303        (extent))
3304 {
3305   return extent_endpoint_external (extent, 0);
3306 }
3307
3308 DEFUN ("extent-end-position", Fextent_end_position, 1, 1, 0, /*
3309 Return end position of EXTENT, or nil if EXTENT is detached.
3310 */
3311        (extent))
3312 {
3313   return extent_endpoint_external (extent, 1);
3314 }
3315
3316 DEFUN ("extent-length", Fextent_length, 1, 1, 0, /*
3317 Return length of EXTENT in characters.
3318 */
3319        (extent))
3320 {
3321   EXTENT e = decode_extent (extent, DE_MUST_BE_ATTACHED);
3322   return make_int (extent_endpoint_bufpos (e, 1)
3323                    - extent_endpoint_bufpos (e, 0));
3324 }
3325
3326 DEFUN ("next-extent", Fnext_extent, 1, 1, 0, /*
3327 Find next extent after EXTENT.
3328 If EXTENT is a buffer return the first extent in the buffer; likewise
3329  for strings.
3330 Extents in a buffer are ordered in what is called the "display"
3331  order, which sorts by increasing start positions and then by *decreasing*
3332  end positions.
3333 If you want to perform an operation on a series of extents, use
3334  `map-extents' instead of this function; it is much more efficient.
3335  The primary use of this function should be to enumerate all the
3336  extents in a buffer.
3337 Note: The display order is not necessarily the order that `map-extents'
3338  processes extents in!
3339 */
3340        (extent))
3341 {
3342   Lisp_Object val;
3343   EXTENT next;
3344
3345   if (EXTENTP (extent))
3346     next = extent_next (decode_extent (extent, DE_MUST_BE_ATTACHED));
3347   else
3348     next = extent_first (decode_buffer_or_string (extent));
3349
3350   if (!next)
3351     return Qnil;
3352   XSETEXTENT (val, next);
3353   return val;
3354 }
3355
3356 DEFUN ("previous-extent", Fprevious_extent, 1, 1, 0, /*
3357 Find last extent before EXTENT.
3358 If EXTENT is a buffer return the last extent in the buffer; likewise
3359  for strings.
3360 This function is analogous to `next-extent'.
3361 */
3362        (extent))
3363 {
3364   Lisp_Object val;
3365   EXTENT prev;
3366
3367   if (EXTENTP (extent))
3368     prev = extent_previous (decode_extent (extent, DE_MUST_BE_ATTACHED));
3369   else
3370     prev = extent_last (decode_buffer_or_string (extent));
3371
3372   if (!prev)
3373     return Qnil;
3374   XSETEXTENT (val, prev);
3375   return val;
3376 }
3377
3378 #ifdef DEBUG_XEMACS
3379
3380 DEFUN ("next-e-extent", Fnext_e_extent, 1, 1, 0, /*
3381 Find next extent after EXTENT using the "e" order.
3382 If EXTENT is a buffer return the first extent in the buffer; likewise
3383  for strings.
3384 */
3385        (extent))
3386 {
3387   Lisp_Object val;
3388   EXTENT next;
3389
3390   if (EXTENTP (extent))
3391     next = extent_e_next (decode_extent (extent, DE_MUST_BE_ATTACHED));
3392   else
3393     next = extent_e_first (decode_buffer_or_string (extent));
3394
3395   if (!next)
3396     return Qnil;
3397   XSETEXTENT (val, next);
3398   return val;
3399 }
3400
3401 DEFUN ("previous-e-extent", Fprevious_e_extent, 1, 1, 0, /*
3402 Find last extent before EXTENT using the "e" order.
3403 If EXTENT is a buffer return the last extent in the buffer; likewise
3404  for strings.
3405 This function is analogous to `next-e-extent'.
3406 */
3407        (extent))
3408 {
3409   Lisp_Object val;
3410   EXTENT prev;
3411
3412   if (EXTENTP (extent))
3413     prev = extent_e_previous (decode_extent (extent, DE_MUST_BE_ATTACHED));
3414   else
3415     prev = extent_e_last (decode_buffer_or_string (extent));
3416
3417   if (!prev)
3418     return Qnil;
3419   XSETEXTENT (val, prev);
3420   return val;
3421 }
3422
3423 #endif
3424
3425 DEFUN ("next-extent-change", Fnext_extent_change, 1, 2, 0, /*
3426 Return the next position after POS where an extent begins or ends.
3427 If POS is at the end of the buffer or string, POS will be returned;
3428  otherwise a position greater than POS will always be returned.
3429 If OBJECT is nil, the current buffer is assumed.
3430 */
3431        (pos, object))
3432 {
3433   Lisp_Object obj = decode_buffer_or_string (object);
3434   Bytind bpos;
3435
3436   bpos = get_buffer_or_string_pos_byte (obj, pos, GB_ALLOW_PAST_ACCESSIBLE);
3437   bpos = extent_find_end_of_run (obj, bpos, 1);
3438   return make_int (buffer_or_string_bytind_to_bufpos (obj, bpos));
3439 }
3440
3441 DEFUN ("previous-extent-change", Fprevious_extent_change, 1, 2, 0, /*
3442 Return the last position before POS where an extent begins or ends.
3443 If POS is at the beginning of the buffer or string, POS will be returned;
3444  otherwise a position less than POS will always be returned.
3445 If OBJECT is nil, the current buffer is assumed.
3446 */
3447        (pos, object))
3448 {
3449   Lisp_Object obj = decode_buffer_or_string (object);
3450   Bytind bpos;
3451
3452   bpos = get_buffer_or_string_pos_byte (obj, pos, GB_ALLOW_PAST_ACCESSIBLE);
3453   bpos = extent_find_beginning_of_run (obj, bpos, 1);
3454   return make_int (buffer_or_string_bytind_to_bufpos (obj, bpos));
3455 }
3456
3457 \f
3458 /************************************************************************/
3459 /*                      parent and children stuff                       */
3460 /************************************************************************/
3461
3462 DEFUN ("extent-parent", Fextent_parent, 1, 1, 0, /*
3463 Return the parent (if any) of EXTENT.
3464 If an extent has a parent, it derives all its properties from that extent
3465 and has no properties of its own. (The only "properties" that the
3466 extent keeps are the buffer/string it refers to and the start and end
3467 points.) It is possible for an extent's parent to itself have a parent.
3468 */
3469        (extent))
3470 /* do I win the prize for the strangest split infinitive? */
3471 {
3472   EXTENT e = decode_extent (extent, 0);
3473   return extent_parent (e);
3474 }
3475
3476 DEFUN ("extent-children", Fextent_children, 1, 1, 0, /*
3477 Return a list of the children (if any) of EXTENT.
3478 The children of an extent are all those extents whose parent is that extent.
3479 This function does not recursively trace children of children.
3480 \(To do that, use `extent-descendants'.)
3481 */
3482        (extent))
3483 {
3484   EXTENT e = decode_extent (extent, 0);
3485   Lisp_Object children = extent_children (e);
3486
3487   if (!NILP (children))
3488     return Fcopy_sequence (XWEAK_LIST_LIST (children));
3489   else
3490     return Qnil;
3491 }
3492
3493 static void
3494 remove_extent_from_children_list (EXTENT e, Lisp_Object child)
3495 {
3496   Lisp_Object children = extent_children (e);
3497
3498 #ifdef ERROR_CHECK_EXTENTS
3499   assert (!NILP (memq_no_quit (child, XWEAK_LIST_LIST (children))));
3500 #endif
3501   XWEAK_LIST_LIST (children) =
3502     delq_no_quit (child, XWEAK_LIST_LIST (children));
3503 }
3504
3505 static void
3506 add_extent_to_children_list (EXTENT e, Lisp_Object child)
3507 {
3508   Lisp_Object children = extent_children (e);
3509
3510   if (NILP (children))
3511     {
3512       children = make_weak_list (WEAK_LIST_SIMPLE);
3513       set_extent_no_chase_aux_field (e, children, children);
3514     }
3515
3516 #ifdef ERROR_CHECK_EXTENTS
3517   assert (NILP (memq_no_quit (child, XWEAK_LIST_LIST (children))));
3518 #endif
3519   XWEAK_LIST_LIST (children) = Fcons (child, XWEAK_LIST_LIST (children));
3520 }
3521
3522 DEFUN ("set-extent-parent", Fset_extent_parent, 2, 2, 0, /*
3523 Set the parent of EXTENT to PARENT (may be nil).
3524 See `extent-parent'.
3525 */
3526        (extent, parent))
3527 {
3528   EXTENT e = decode_extent (extent, 0);
3529   Lisp_Object cur_parent = extent_parent (e);
3530   Lisp_Object rest;
3531
3532   XSETEXTENT (extent, e);
3533   if (!NILP (parent))
3534     CHECK_LIVE_EXTENT (parent);
3535   if (EQ (parent, cur_parent))
3536     return Qnil;
3537   for (rest = parent; !NILP (rest); rest = extent_parent (XEXTENT (rest)))
3538     if (EQ (rest, extent))
3539       signal_type_error (Qinvalid_change,
3540                          "Circular parent chain would result",
3541                          extent);
3542   if (NILP (parent))
3543     {
3544       remove_extent_from_children_list (XEXTENT (cur_parent), extent);
3545       set_extent_no_chase_aux_field (e, parent, Qnil);
3546       e->flags.has_parent = 0;
3547     }
3548   else
3549     {
3550       add_extent_to_children_list (XEXTENT (parent), extent);
3551       set_extent_no_chase_aux_field (e, parent, parent);
3552       e->flags.has_parent = 1;
3553     }
3554   /* changing the parent also changes the properties of all children. */
3555   {
3556     int old_invis = (!NILP (cur_parent) &&
3557                      !NILP (extent_invisible (XEXTENT (cur_parent))));
3558     int new_invis = (!NILP (parent) &&
3559                      !NILP (extent_invisible (XEXTENT (parent))));
3560
3561     extent_maybe_changed_for_redisplay (e, 1, new_invis != old_invis);
3562   }
3563
3564   return Qnil;
3565 }
3566
3567 \f
3568 /************************************************************************/
3569 /*                      basic extent mutators                           */
3570 /************************************************************************/
3571
3572 /* Note:  If you track non-duplicable extents by undo, you'll get bogus
3573    undo records for transient extents via update-extent.
3574    For example, query-replace will do this.
3575  */
3576
3577 static void
3578 set_extent_endpoints_1 (EXTENT extent, Memind start, Memind end)
3579 {
3580 #ifdef ERROR_CHECK_EXTENTS
3581   Lisp_Object obj = extent_object (extent);
3582
3583   assert (start <= end);
3584   if (BUFFERP (obj))
3585     {
3586       assert (valid_memind_p (XBUFFER (obj), start));
3587       assert (valid_memind_p (XBUFFER (obj), end));
3588     }
3589 #endif
3590
3591   /* Optimization: if the extent is already where we want it to be,
3592      do nothing. */
3593   if (!extent_detached_p (extent) && extent_start (extent) == start &&
3594       extent_end (extent) == end)
3595     return;
3596
3597   if (extent_detached_p (extent))
3598     {
3599       if (extent_duplicable_p (extent))
3600         {
3601           Lisp_Object extent_obj;
3602           XSETEXTENT (extent_obj, extent);
3603           record_extent (extent_obj, 1);
3604         }
3605     }
3606   else
3607     extent_detach (extent);
3608
3609   set_extent_start (extent, start);
3610   set_extent_end (extent, end);
3611   extent_attach (extent);
3612 }
3613
3614 /* Set extent's endpoints to S and E, and put extent in buffer or string
3615    OBJECT. (If OBJECT is nil, do not change the extent's object.) */
3616
3617 void
3618 set_extent_endpoints (EXTENT extent, Bytind s, Bytind e, Lisp_Object object)
3619 {
3620   Memind start, end;
3621
3622   if (NILP (object))
3623     {
3624       object = extent_object (extent);
3625       assert (!NILP (object));
3626     }
3627   else if (!EQ (object, extent_object (extent)))
3628     {
3629       extent_detach (extent);
3630       extent_object (extent) = object;
3631     }
3632
3633   start = s < 0 ? extent_start (extent) :
3634     buffer_or_string_bytind_to_memind (object, s);
3635   end = e < 0 ? extent_end (extent) :
3636     buffer_or_string_bytind_to_memind (object, e);
3637   set_extent_endpoints_1 (extent, start, end);
3638 }
3639
3640 static void
3641 set_extent_openness (EXTENT extent, int start_open, int end_open)
3642 {
3643   if (start_open != -1)
3644     extent_start_open_p (extent) = start_open;
3645   if (end_open != -1)
3646     extent_end_open_p (extent) = end_open;
3647   /* changing the open/closedness of an extent does not affect
3648      redisplay. */
3649 }
3650
3651 static EXTENT
3652 make_extent_internal (Lisp_Object object, Bytind from, Bytind to)
3653 {
3654   EXTENT extent;
3655
3656   extent = make_extent_detached (object);
3657   set_extent_endpoints (extent, from, to, Qnil);
3658   return extent;
3659 }
3660
3661 static EXTENT
3662 copy_extent (EXTENT original, Bytind from, Bytind to, Lisp_Object object)
3663 {
3664   EXTENT e;
3665
3666   e = make_extent_detached (object);
3667   if (from >= 0)
3668     set_extent_endpoints (e, from, to, Qnil);
3669
3670   e->plist = Fcopy_sequence (original->plist);
3671   memcpy (&e->flags, &original->flags, sizeof (e->flags));
3672   if (e->flags.has_aux)
3673     {
3674       /* also need to copy the aux struct.  It won't work for
3675          this extent to share the same aux struct as the original
3676          one. */
3677       struct extent_auxiliary *data =
3678         alloc_lcrecord_type (struct extent_auxiliary,
3679                              &lrecord_extent_auxiliary);
3680
3681       copy_lcrecord (data, XEXTENT_AUXILIARY (XCAR (original->plist)));
3682       XSETEXTENT_AUXILIARY (XCAR (e->plist), data);
3683     }
3684
3685   {
3686     /* we may have just added another child to the parent extent. */
3687     Lisp_Object parent = extent_parent (e);
3688     if (!NILP (parent))
3689       {
3690         Lisp_Object extent;
3691         XSETEXTENT (extent, e);
3692         add_extent_to_children_list (XEXTENT (parent), extent);
3693       }
3694   }
3695
3696   return e;
3697 }
3698
3699 static void
3700 destroy_extent (EXTENT extent)
3701 {
3702   Lisp_Object rest, nextrest, children;
3703   Lisp_Object extent_obj;
3704
3705   if (!extent_detached_p (extent))
3706     extent_detach (extent);
3707   /* disassociate the extent from its children and parent */
3708   children = extent_children (extent);
3709   if (!NILP (children))
3710     {
3711       LIST_LOOP_DELETING (rest, nextrest, XWEAK_LIST_LIST (children))
3712         Fset_extent_parent (XCAR (rest), Qnil);
3713     }
3714   XSETEXTENT (extent_obj, extent);
3715   Fset_extent_parent (extent_obj, Qnil);
3716   /* mark the extent as destroyed */
3717   extent_object (extent) = Qt;
3718 }
3719
3720 DEFUN ("make-extent", Fmake_extent, 2, 3, 0, /*
3721 Make an extent for the range [FROM, TO) in BUFFER-OR-STRING.
3722 BUFFER-OR-STRING defaults to the current buffer.  Insertions at point
3723 TO will be outside of the extent; insertions at FROM will be inside the
3724 extent, causing the extent to grow. (This is the same way that markers
3725 behave.) You can change the behavior of insertions at the endpoints
3726 using `set-extent-property'.  The extent is initially detached if both
3727 FROM and TO are nil, and in this case BUFFER-OR-STRING defaults to nil,
3728 meaning the extent is in no buffer and no string.
3729 */
3730        (from, to, buffer_or_string))
3731 {
3732   Lisp_Object extent_obj;
3733   Lisp_Object obj;
3734
3735   obj = decode_buffer_or_string (buffer_or_string);
3736   if (NILP (from) && NILP (to))
3737     {
3738       if (NILP (buffer_or_string))
3739         obj = Qnil;
3740       XSETEXTENT (extent_obj, make_extent_detached (obj));
3741     }
3742   else
3743     {
3744       Bytind start, end;
3745
3746       get_buffer_or_string_range_byte (obj, from, to, &start, &end,
3747                                        GB_ALLOW_PAST_ACCESSIBLE);
3748       XSETEXTENT (extent_obj, make_extent_internal (obj, start, end));
3749     }
3750   return extent_obj;
3751 }
3752
3753 DEFUN ("copy-extent", Fcopy_extent, 1, 2, 0, /*
3754 Make a copy of EXTENT.  It is initially detached.
3755 Optional argument BUFFER-OR-STRING defaults to EXTENT's buffer or string.
3756 */
3757        (extent, buffer_or_string))
3758 {
3759   EXTENT ext = decode_extent (extent, 0);
3760
3761   if (NILP (buffer_or_string))
3762     buffer_or_string = extent_object (ext);
3763   else
3764     buffer_or_string = decode_buffer_or_string (buffer_or_string);
3765
3766   XSETEXTENT (extent, copy_extent (ext, -1, -1, buffer_or_string));
3767   return extent;
3768 }
3769
3770 DEFUN ("delete-extent", Fdelete_extent, 1, 1, 0, /*
3771 Remove EXTENT from its buffer and destroy it.
3772 This does not modify the buffer's text, only its display properties.
3773 The extent cannot be used thereafter.
3774 */
3775        (extent))
3776 {
3777   EXTENT ext;
3778
3779   /* We do not call decode_extent() here because already-destroyed
3780      extents are OK. */
3781   CHECK_EXTENT (extent);
3782   ext = XEXTENT (extent);
3783
3784   if (!EXTENT_LIVE_P (ext))
3785     return Qnil;
3786   destroy_extent (ext);
3787   return Qnil;
3788 }
3789
3790 DEFUN ("detach-extent", Fdetach_extent, 1, 1, 0, /*
3791 Remove EXTENT from its buffer in such a way that it can be re-inserted.
3792 An extent is also detached when all of its characters are all killed by a
3793 deletion, unless its `detachable' property has been unset.
3794
3795 Extents which have the `duplicable' attribute are tracked by the undo
3796 mechanism.  Detachment via `detach-extent' and string deletion is recorded,
3797 as is attachment via `insert-extent' and string insertion.  Extent motion,
3798 face changes, and attachment via `make-extent' and `set-extent-endpoints'
3799 are not recorded.  This means that extent changes which are to be undo-able
3800 must be performed by character editing, or by insertion and detachment of
3801 duplicable extents.
3802 */
3803        (extent))
3804 {
3805   EXTENT ext = decode_extent (extent, 0);
3806
3807   if (extent_detached_p (ext))
3808     return extent;
3809   if (extent_duplicable_p (ext))
3810     record_extent (extent, 0);
3811   extent_detach (ext);
3812
3813   return extent;
3814 }
3815
3816 DEFUN ("set-extent-endpoints", Fset_extent_endpoints, 3, 4, 0, /*
3817 Set the endpoints of EXTENT to START, END.
3818 If START and END are null, call detach-extent on EXTENT.
3819 BUFFER-OR-STRING specifies the new buffer or string that the extent should
3820 be in, and defaults to EXTENT's buffer or string. (If nil, and EXTENT
3821 is in no buffer and no string, it defaults to the current buffer.)
3822 See documentation on `detach-extent' for a discussion of undo recording.
3823 */
3824        (extent, start, end, buffer_or_string))
3825 {
3826   EXTENT ext;
3827   Bytind s, e;
3828
3829   ext = decode_extent (extent, 0);
3830
3831   if (NILP (buffer_or_string))
3832     {
3833       buffer_or_string = extent_object (ext);
3834       if (NILP (buffer_or_string))
3835         buffer_or_string = Fcurrent_buffer ();
3836     }
3837   else
3838     buffer_or_string = decode_buffer_or_string (buffer_or_string);
3839
3840   if (NILP (start) && NILP (end))
3841     return Fdetach_extent (extent);
3842
3843   get_buffer_or_string_range_byte (buffer_or_string, start, end, &s, &e,
3844                                    GB_ALLOW_PAST_ACCESSIBLE);
3845
3846   buffer_or_string_extent_info_force (buffer_or_string);
3847   set_extent_endpoints (ext, s, e, buffer_or_string);
3848   return extent;
3849 }
3850
3851 \f
3852 /************************************************************************/
3853 /*                         mapping over extents                         */
3854 /************************************************************************/
3855
3856 static unsigned int
3857 decode_map_extents_flags (Lisp_Object flags)
3858 {
3859   unsigned int retval = 0;
3860   unsigned int all_extents_specified = 0;
3861   unsigned int in_region_specified = 0;
3862
3863   if (EQ (flags, Qt)) /* obsoleteness compatibility */
3864     return ME_END_CLOSED;
3865   if (NILP (flags))
3866     return 0;
3867   if (SYMBOLP (flags))
3868     flags = Fcons (flags, Qnil);
3869   while (!NILP (flags))
3870     {
3871       Lisp_Object sym;
3872       CHECK_CONS (flags);
3873       sym = XCAR (flags);
3874       CHECK_SYMBOL (sym);
3875       if (EQ (sym, Qall_extents_closed) || EQ (sym, Qall_extents_open) ||
3876           EQ (sym, Qall_extents_closed_open) ||
3877           EQ (sym, Qall_extents_open_closed))
3878         {
3879           if (all_extents_specified)
3880             error ("Only one `all-extents-*' flag may be specified");
3881           all_extents_specified = 1;
3882         }
3883       if (EQ (sym, Qstart_in_region) || EQ (sym, Qend_in_region) ||
3884           EQ (sym, Qstart_and_end_in_region) ||
3885           EQ (sym, Qstart_or_end_in_region))
3886         {
3887           if (in_region_specified)
3888             error ("Only one `*-in-region' flag may be specified");
3889           in_region_specified = 1;
3890         }
3891
3892       /* I do so love that conditional operator ... */
3893       retval |=
3894         EQ (sym, Qend_closed)              ? ME_END_CLOSED :
3895         EQ (sym, Qstart_open)              ? ME_START_OPEN :
3896         EQ (sym, Qall_extents_closed)      ? ME_ALL_EXTENTS_CLOSED :
3897         EQ (sym, Qall_extents_open)        ? ME_ALL_EXTENTS_OPEN :
3898         EQ (sym, Qall_extents_closed_open) ? ME_ALL_EXTENTS_CLOSED_OPEN :
3899         EQ (sym, Qall_extents_open_closed) ? ME_ALL_EXTENTS_OPEN_CLOSED :
3900         EQ (sym, Qstart_in_region)         ? ME_START_IN_REGION :
3901         EQ (sym, Qend_in_region)           ? ME_END_IN_REGION :
3902         EQ (sym, Qstart_and_end_in_region) ? ME_START_AND_END_IN_REGION :
3903         EQ (sym, Qstart_or_end_in_region)  ? ME_START_OR_END_IN_REGION :
3904         EQ (sym, Qnegate_in_region)        ? ME_NEGATE_IN_REGION :
3905         (invalid_argument ("Invalid `map-extents' flag", sym), 0);
3906
3907       flags = XCDR (flags);
3908     }
3909   return retval;
3910 }
3911
3912 DEFUN ("extent-in-region-p", Fextent_in_region_p, 1, 4, 0, /*
3913 Return whether EXTENT overlaps a specified region.
3914 This is equivalent to whether `map-extents' would visit EXTENT when called
3915 with these args.
3916 */
3917        (extent, from, to, flags))
3918 {
3919   Bytind start, end;
3920   EXTENT ext = decode_extent (extent, DE_MUST_BE_ATTACHED);
3921   Lisp_Object obj = extent_object (ext);
3922
3923   get_buffer_or_string_range_byte (obj, from, to, &start, &end, GB_ALLOW_NIL |
3924                                    GB_ALLOW_PAST_ACCESSIBLE);
3925
3926   return extent_in_region_p (ext, start, end, decode_map_extents_flags (flags)) ?
3927     Qt : Qnil;
3928 }
3929
3930 struct slow_map_extents_arg
3931 {
3932   Lisp_Object map_arg;
3933   Lisp_Object map_routine;
3934   Lisp_Object result;
3935   Lisp_Object property;
3936   Lisp_Object value;
3937 };
3938
3939 static int
3940 slow_map_extents_function (EXTENT extent, void *arg)
3941 {
3942   /* This function can GC */
3943   struct slow_map_extents_arg *closure = (struct slow_map_extents_arg *) arg;
3944   Lisp_Object extent_obj;
3945
3946   XSETEXTENT (extent_obj, extent);
3947
3948   /* make sure this extent qualifies according to the PROPERTY
3949      and VALUE args */
3950
3951   if (!NILP (closure->property))
3952     {
3953       Lisp_Object value = Fextent_property (extent_obj, closure->property,
3954                                             Qnil);
3955       if ((NILP (closure->value) && NILP (value)) ||
3956           (!NILP (closure->value) && !EQ (value, closure->value)))
3957         return 0;
3958     }
3959
3960   closure->result = call2 (closure->map_routine, extent_obj,
3961                            closure->map_arg);
3962   return !NILP (closure->result);
3963 }
3964
3965 DEFUN ("map-extents", Fmap_extents, 1, 8, 0, /*
3966 Map FUNCTION over the extents which overlap a region in OBJECT.
3967 OBJECT is normally a buffer or string but could be an extent (see below).
3968 The region is normally bounded by [FROM, TO) (i.e. the beginning of the
3969 region is closed and the end of the region is open), but this can be
3970 changed with the FLAGS argument (see below for a complete discussion).
3971
3972 FUNCTION is called with the arguments (extent, MAPARG).  The arguments
3973 OBJECT, FROM, TO, MAPARG, and FLAGS are all optional and default to
3974 the current buffer, the beginning of OBJECT, the end of OBJECT, nil,
3975 and nil, respectively.  `map-extents' returns the first non-nil result
3976 produced by FUNCTION, and no more calls to FUNCTION are made after it
3977 returns non-nil.
3978
3979 If OBJECT is an extent, FROM and TO default to the extent's endpoints,
3980 and the mapping omits that extent and its predecessors.  This feature
3981 supports restarting a loop based on `map-extents'.  Note: OBJECT must
3982 be attached to a buffer or string, and the mapping is done over that
3983 buffer or string.
3984
3985 An extent overlaps the region if there is any point in the extent that is
3986 also in the region. (For the purpose of overlap, zero-length extents and
3987 regions are treated as closed on both ends regardless of their endpoints'
3988 specified open/closedness.) Note that the endpoints of an extent or region
3989 are considered to be in that extent or region if and only if the
3990 corresponding end is closed.  For example, the extent [5,7] overlaps the
3991 region [2,5] because 5 is in both the extent and the region.  However, (5,7]
3992 does not overlap [2,5] because 5 is not in the extent, and neither [5,7] nor
3993 \(5,7] overlaps the region [2,5) because 5 is not in the region.
3994
3995 The optional FLAGS can be a symbol or a list of one or more symbols,
3996 modifying the behavior of `map-extents'.  Allowed symbols are:
3997
3998 end-closed              The region's end is closed.
3999
4000 start-open              The region's start is open.
4001
4002 all-extents-closed      Treat all extents as closed on both ends for the
4003                         purpose of determining whether they overlap the
4004                         region, irrespective of their actual open- or
4005                         closedness.
4006 all-extents-open        Treat all extents as open on both ends.
4007 all-extents-closed-open Treat all extents as start-closed, end-open.
4008 all-extents-open-closed Treat all extents as start-open, end-closed.
4009
4010 start-in-region         In addition to the above conditions for extent
4011                         overlap, the extent's start position must lie within
4012                         the specified region.  Note that, for this
4013                         condition, open start positions are treated as if
4014                         0.5 was added to the endpoint's value, and open
4015                         end positions are treated as if 0.5 was subtracted
4016                         from the endpoint's value.
4017 end-in-region           The extent's end position must lie within the
4018                         region.
4019 start-and-end-in-region Both the extent's start and end positions must lie
4020                         within the region.
4021 start-or-end-in-region  Either the extent's start or end position must lie
4022                         within the region.
4023
4024 negate-in-region        The condition specified by a `*-in-region' flag
4025                         must NOT hold for the extent to be considered.
4026
4027
4028 At most one of `all-extents-closed', `all-extents-open',
4029 `all-extents-closed-open', and `all-extents-open-closed' may be specified.
4030
4031 At most one of `start-in-region', `end-in-region',
4032 `start-and-end-in-region', and `start-or-end-in-region' may be specified.
4033
4034 If optional arg PROPERTY is non-nil, only extents with that property set
4035 on them will be visited.  If optional arg VALUE is non-nil, only extents
4036 whose value for that property is `eq' to VALUE will be visited.
4037 */
4038   (function, object, from, to, maparg, flags, property, value))
4039 {
4040   /* This function can GC */
4041   struct slow_map_extents_arg closure;
4042   unsigned int me_flags;
4043   Bytind start, end;
4044   struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5;
4045   EXTENT after = 0;
4046
4047   if (EXTENTP (object))
4048     {
4049       after = decode_extent (object, DE_MUST_BE_ATTACHED);
4050       if (NILP (from))
4051         from = Fextent_start_position (object);
4052       if (NILP (to))
4053         to = Fextent_end_position (object);
4054       object = extent_object (after);
4055     }
4056   else
4057     object = decode_buffer_or_string (object);
4058
4059   get_buffer_or_string_range_byte (object, from, to, &start, &end,
4060                                    GB_ALLOW_NIL | GB_ALLOW_PAST_ACCESSIBLE);
4061
4062   me_flags = decode_map_extents_flags (flags);
4063
4064   if (!NILP (property))
4065     {
4066       if (!NILP (value))
4067         value = canonicalize_extent_property (property, value);
4068     }
4069
4070   GCPRO5 (function, maparg, object, property, value);
4071
4072   closure.map_arg = maparg;
4073   closure.map_routine = function;
4074   closure.result = Qnil;
4075   closure.property = property;
4076   closure.value = value;
4077
4078   map_extents_bytind (start, end, slow_map_extents_function,
4079                       (void *) &closure, object, after,
4080                       /* You never know what the user might do ... */
4081                       me_flags | ME_MIGHT_CALL_ELISP);
4082
4083   UNGCPRO;
4084   return closure.result;
4085 }
4086
4087 \f
4088 /************************************************************************/
4089 /*              mapping over extents -- other functions                 */
4090 /************************************************************************/
4091
4092 /* ------------------------------- */
4093 /*      map-extent-children        */
4094 /* ------------------------------- */
4095
4096 struct slow_map_extent_children_arg
4097 {
4098   Lisp_Object map_arg;
4099   Lisp_Object map_routine;
4100   Lisp_Object result;
4101   Lisp_Object property;
4102   Lisp_Object value;
4103   Bytind start_min;
4104   Bytind prev_start;
4105   Bytind prev_end;
4106 };
4107
4108 static int
4109 slow_map_extent_children_function (EXTENT extent, void *arg)
4110 {
4111   /* This function can GC */
4112   struct slow_map_extent_children_arg *closure =
4113     (struct slow_map_extent_children_arg *) arg;
4114   Lisp_Object extent_obj;
4115   Bytind start = extent_endpoint_bytind (extent, 0);
4116   Bytind end = extent_endpoint_bytind (extent, 1);
4117   /* Make sure the extent starts inside the region of interest,
4118      rather than just overlaps it.
4119      */
4120   if (start < closure->start_min)
4121     return 0;
4122   /* Make sure the extent is not a child of a previous visited one.
4123      We know already, because of extent ordering,
4124      that start >= prev_start, and that if
4125      start == prev_start, then end <= prev_end.
4126      */
4127   if (start == closure->prev_start)
4128     {
4129       if (end < closure->prev_end)
4130         return 0;
4131     }
4132   else /* start > prev_start */
4133     {
4134       if (start < closure->prev_end)
4135         return 0;
4136       /* corner case:  prev_end can be -1 if there is no prev */
4137     }
4138   XSETEXTENT (extent_obj, extent);
4139
4140   /* make sure this extent qualifies according to the PROPERTY
4141      and VALUE args */
4142
4143   if (!NILP (closure->property))
4144     {
4145       Lisp_Object value = Fextent_property (extent_obj, closure->property,
4146                                             Qnil);
4147       if ((NILP (closure->value) && NILP (value)) ||
4148           (!NILP (closure->value) && !EQ (value, closure->value)))
4149         return 0;
4150     }
4151
4152   closure->result = call2 (closure->map_routine, extent_obj,
4153                            closure->map_arg);
4154
4155   /* Since the callback may change the buffer, compute all stored
4156      buffer positions here.
4157      */
4158   closure->start_min = -1;      /* no need for this any more */
4159   closure->prev_start = extent_endpoint_bytind (extent, 0);
4160   closure->prev_end = extent_endpoint_bytind (extent, 1);
4161
4162   return !NILP (closure->result);
4163 }
4164
4165 DEFUN ("map-extent-children", Fmap_extent_children, 1, 8, 0, /*
4166 Map FUNCTION over the extents in the region from FROM to TO.
4167 FUNCTION is called with arguments (extent, MAPARG).  See `map-extents'
4168 for a full discussion of the arguments FROM, TO, and FLAGS.
4169
4170 The arguments are the same as for `map-extents', but this function differs
4171 in that it only visits extents which start in the given region, and also
4172 in that, after visiting an extent E, it skips all other extents which start
4173 inside E but end before E's end.
4174
4175 Thus, this function may be used to walk a tree of extents in a buffer:
4176         (defun walk-extents (buffer &optional ignore)
4177          (map-extent-children 'walk-extents buffer))
4178 */
4179        (function, object, from, to, maparg, flags, property, value))
4180 {
4181   /* This function can GC */
4182   struct slow_map_extent_children_arg closure;
4183   unsigned int me_flags;
4184   Bytind start, end;
4185   struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5;
4186   EXTENT after = 0;
4187
4188   if (EXTENTP (object))
4189     {
4190       after = decode_extent (object, DE_MUST_BE_ATTACHED);
4191       if (NILP (from))
4192         from = Fextent_start_position (object);
4193       if (NILP (to))
4194         to = Fextent_end_position (object);
4195       object = extent_object (after);
4196     }
4197   else
4198     object = decode_buffer_or_string (object);
4199
4200   get_buffer_or_string_range_byte (object, from, to, &start, &end,
4201                                    GB_ALLOW_NIL | GB_ALLOW_PAST_ACCESSIBLE);
4202
4203   me_flags = decode_map_extents_flags (flags);
4204
4205   if (!NILP (property))
4206     {
4207       if (!NILP (value))
4208         value = canonicalize_extent_property (property, value);
4209     }
4210
4211   GCPRO5 (function, maparg, object, property, value);
4212
4213   closure.map_arg = maparg;
4214   closure.map_routine = function;
4215   closure.result = Qnil;
4216   closure.property = property;
4217   closure.value = value;
4218   closure.start_min = start;
4219   closure.prev_start = -1;
4220   closure.prev_end = -1;
4221   map_extents_bytind (start, end, slow_map_extent_children_function,
4222                       (void *) &closure, object, after,
4223                       /* You never know what the user might do ... */
4224                       me_flags | ME_MIGHT_CALL_ELISP);
4225
4226   UNGCPRO;
4227   return closure.result;
4228 }
4229
4230 /* ------------------------------- */
4231 /*             extent-at           */
4232 /* ------------------------------- */
4233
4234 /* find "smallest" matching extent containing pos -- (flag == 0) means
4235    all extents match, else (EXTENT_FLAGS (extent) & flag) must be true;
4236    for more than one matching extent with precisely the same endpoints,
4237    we choose the last extent in the extents_list.
4238    The search stops just before "before", if that is non-null.
4239    */
4240
4241 struct extent_at_arg
4242 {
4243   Lisp_Object best_match; /* or list of extents */
4244   Memind best_start;
4245   Memind best_end;
4246   Lisp_Object prop;
4247   EXTENT before;
4248   int all_extents;
4249 };
4250
4251 enum extent_at_flag
4252 {
4253   EXTENT_AT_AFTER,
4254   EXTENT_AT_BEFORE,
4255   EXTENT_AT_AT
4256 };
4257
4258 static enum extent_at_flag
4259 decode_extent_at_flag (Lisp_Object at_flag)
4260 {
4261   if (NILP (at_flag))
4262     return EXTENT_AT_AFTER;
4263
4264   CHECK_SYMBOL (at_flag);
4265   if (EQ (at_flag, Qafter))  return EXTENT_AT_AFTER;
4266   if (EQ (at_flag, Qbefore)) return EXTENT_AT_BEFORE;
4267   if (EQ (at_flag, Qat))     return EXTENT_AT_AT;
4268
4269   invalid_argument ("Invalid AT-FLAG in `extent-at'", at_flag);
4270   return EXTENT_AT_AFTER; /* unreached */
4271 }
4272
4273 static int
4274 extent_at_mapper (EXTENT e, void *arg)
4275 {
4276   struct extent_at_arg *closure = (struct extent_at_arg *) arg;
4277
4278   if (e == closure->before)
4279     return 1;
4280
4281   /* If closure->prop is non-nil, then the extent is only acceptable
4282      if it has a non-nil value for that property. */
4283   if (!NILP (closure->prop))
4284     {
4285       Lisp_Object extent;
4286       XSETEXTENT (extent, e);
4287       if (NILP (Fextent_property (extent, closure->prop, Qnil)))
4288         return 0;
4289     }
4290
4291   if (!closure->all_extents)
4292     {
4293       EXTENT current;
4294
4295       if (NILP (closure->best_match))
4296         goto accept;
4297       current = XEXTENT (closure->best_match);
4298       /* redundant but quick test */
4299       if (extent_start (current) > extent_start (e))
4300         return 0;
4301
4302       /* we return the "last" best fit, instead of the first --
4303          this is because then the glyph closest to two equivalent
4304          extents corresponds to the "extent-at" the text just past
4305          that same glyph */
4306       else if (!EXTENT_LESS_VALS (e, closure->best_start,
4307                                   closure->best_end))
4308         goto accept;
4309       else
4310         return 0;
4311     accept:
4312       XSETEXTENT (closure->best_match, e);
4313       closure->best_start = extent_start (e);
4314       closure->best_end = extent_end (e);
4315     }
4316   else
4317     {
4318       Lisp_Object extent;
4319
4320       XSETEXTENT (extent, e);
4321       closure->best_match = Fcons (extent, closure->best_match);
4322     }
4323
4324   return 0;
4325 }
4326
4327 static Lisp_Object
4328 extent_at_bytind (Bytind position, Lisp_Object object, Lisp_Object property,
4329                   EXTENT before, enum extent_at_flag at_flag, int all_extents)
4330 {
4331   struct extent_at_arg closure;
4332   struct gcpro gcpro1;
4333
4334   /* it might be argued that invalid positions should cause
4335      errors, but the principle of least surprise dictates that
4336      nil should be returned (extent-at is often used in
4337      response to a mouse event, and in many cases previous events
4338      have changed the buffer contents).
4339
4340      Also, the openness stuff in the text-property code currently
4341      does not check its limits and might go off the end. */
4342   if ((at_flag == EXTENT_AT_BEFORE
4343        ? position <= buffer_or_string_absolute_begin_byte (object)
4344        : position < buffer_or_string_absolute_begin_byte (object))
4345       || (at_flag == EXTENT_AT_AFTER
4346           ? position >= buffer_or_string_absolute_end_byte (object)
4347           : position > buffer_or_string_absolute_end_byte (object)))
4348     return Qnil;
4349
4350   closure.best_match = Qnil;
4351   closure.prop = property;
4352   closure.before = before;
4353   closure.all_extents = all_extents;
4354
4355   GCPRO1 (closure.best_match);
4356   map_extents_bytind (at_flag == EXTENT_AT_BEFORE ? position - 1 : position,
4357                       at_flag == EXTENT_AT_AFTER ? position + 1 : position,
4358                       extent_at_mapper, (void *) &closure, object, 0,
4359                       ME_START_OPEN | ME_ALL_EXTENTS_CLOSED);
4360   if (all_extents)
4361     closure.best_match = Fnreverse (closure.best_match);
4362   UNGCPRO;
4363
4364   return closure.best_match;
4365 }
4366
4367 DEFUN ("extent-at", Fextent_at, 1, 5, 0, /*
4368 Find "smallest" extent at POS in OBJECT having PROPERTY set.
4369 Normally, an extent is "at" POS if it overlaps the region (POS, POS+1);
4370  i.e. if it covers the character after POS. (However, see the definition
4371  of AT-FLAG.) "Smallest" means the extent that comes last in the display
4372  order; this normally means the extent whose start position is closest to
4373  POS.  See `next-extent' for more information.
4374 OBJECT specifies a buffer or string and defaults to the current buffer.
4375 PROPERTY defaults to nil, meaning that any extent will do.
4376 Properties are attached to extents with `set-extent-property', which see.
4377 Returns nil if POS is invalid or there is no matching extent at POS.
4378 If the fourth argument BEFORE is not nil, it must be an extent; any returned
4379  extent will precede that extent.  This feature allows `extent-at' to be
4380  used by a loop over extents.
4381 AT-FLAG controls how end cases are handled, and should be one of:
4382
4383 nil or `after'          An extent is at POS if it covers the character
4384                         after POS.  This is consistent with the way
4385                         that text properties work.
4386 `before'                An extent is at POS if it covers the character
4387                         before POS.
4388 `at'                    An extent is at POS if it overlaps or abuts POS.
4389                         This includes all zero-length extents at POS.
4390
4391 Note that in all cases, the start-openness and end-openness of the extents
4392 considered is ignored.  If you want to pay attention to those properties,
4393 you should use `map-extents', which gives you more control.
4394 */
4395      (pos, object, property, before, at_flag))
4396 {
4397   Bytind position;
4398   EXTENT before_extent;
4399   enum extent_at_flag fl;
4400
4401   object = decode_buffer_or_string (object);
4402   position = get_buffer_or_string_pos_byte (object, pos, GB_NO_ERROR_IF_BAD);
4403   if (NILP (before))
4404     before_extent = 0;
4405   else
4406     before_extent = decode_extent (before, DE_MUST_BE_ATTACHED);
4407   if (before_extent && !EQ (object, extent_object (before_extent)))
4408     invalid_argument ("extent not in specified buffer or string", object);
4409   fl = decode_extent_at_flag (at_flag);
4410
4411   return extent_at_bytind (position, object, property, before_extent, fl, 0);
4412 }
4413
4414 DEFUN ("extents-at", Fextents_at, 1, 5, 0, /*
4415 Find all extents at POS in OBJECT having PROPERTY set.
4416 Normally, an extent is "at" POS if it overlaps the region (POS, POS+1);
4417  i.e. if it covers the character after POS. (However, see the definition
4418  of AT-FLAG.)
4419 This provides similar functionality to `extent-list', but does so in a way
4420  that is compatible with `extent-at'. (For example, errors due to POS out of
4421  range are ignored; this makes it safer to use this function in response to
4422  a mouse event, because in many cases previous events have changed the buffer
4423  contents.)
4424 OBJECT specifies a buffer or string and defaults to the current buffer.
4425 PROPERTY defaults to nil, meaning that any extent will do.
4426 Properties are attached to extents with `set-extent-property', which see.
4427 Returns nil if POS is invalid or there is no matching extent at POS.
4428 If the fourth argument BEFORE is not nil, it must be an extent; any returned
4429  extent will precede that extent.  This feature allows `extents-at' to be
4430  used by a loop over extents.
4431 AT-FLAG controls how end cases are handled, and should be one of:
4432
4433 nil or `after'          An extent is at POS if it covers the character
4434                         after POS.  This is consistent with the way
4435                         that text properties work.
4436 `before'                An extent is at POS if it covers the character
4437                         before POS.
4438 `at'                    An extent is at POS if it overlaps or abuts POS.
4439                         This includes all zero-length extents at POS.
4440
4441 Note that in all cases, the start-openness and end-openness of the extents
4442 considered is ignored.  If you want to pay attention to those properties,
4443 you should use `map-extents', which gives you more control.
4444 */
4445      (pos, object, property, before, at_flag))
4446 {
4447   Bytind position;
4448   EXTENT before_extent;
4449   enum extent_at_flag fl;
4450
4451   object = decode_buffer_or_string (object);
4452   position = get_buffer_or_string_pos_byte (object, pos, GB_NO_ERROR_IF_BAD);
4453   if (NILP (before))
4454     before_extent = 0;
4455   else
4456     before_extent = decode_extent (before, DE_MUST_BE_ATTACHED);
4457   if (before_extent && !EQ (object, extent_object (before_extent)))
4458     invalid_argument ("extent not in specified buffer or string", object);
4459   fl = decode_extent_at_flag (at_flag);
4460
4461   return extent_at_bytind (position, object, property, before_extent, fl, 1);
4462 }
4463
4464 /* ------------------------------- */
4465 /*   verify_extent_modification()  */
4466 /* ------------------------------- */
4467
4468 /* verify_extent_modification() is called when a buffer or string is
4469    modified to check whether the modification is occuring inside a
4470    read-only extent.
4471  */
4472
4473 struct verify_extents_arg
4474 {
4475   Lisp_Object object;
4476   Memind start;
4477   Memind end;
4478   Lisp_Object iro; /* value of inhibit-read-only */
4479 };
4480
4481 static int
4482 verify_extent_mapper (EXTENT extent, void *arg)
4483 {
4484   struct verify_extents_arg *closure = (struct verify_extents_arg *) arg;
4485   Lisp_Object prop = extent_read_only (extent);
4486
4487   if (NILP (prop))
4488     return 0;
4489
4490   if (CONSP (closure->iro) && !NILP (Fmemq (prop, closure->iro)))
4491     return 0;
4492
4493 #if 0 /* Nobody seems to care for this any more -sb */
4494   /* Allow deletion if the extent is completely contained in
4495      the region being deleted.
4496      This is important for supporting tokens which are internally
4497      write-protected, but which can be killed and yanked as a whole.
4498      Ignore open/closed distinctions at this point.
4499      -- Rose
4500      */
4501   if (closure->start != closure->end &&
4502       extent_start (extent) >= closure->start &&
4503       extent_end (extent) <= closure->end)
4504     return 0;
4505 #endif
4506
4507   while (1)
4508     Fsignal (Qbuffer_read_only, (list1 (closure->object)));
4509
4510   RETURN_NOT_REACHED(0)
4511 }
4512
4513 /* Value of Vinhibit_read_only is precomputed and passed in for
4514    efficiency */
4515
4516 void
4517 verify_extent_modification (Lisp_Object object, Bytind from, Bytind to,
4518                             Lisp_Object inhibit_read_only_value)
4519 {
4520   int closed;
4521   struct verify_extents_arg closure;
4522
4523   /* If insertion, visit closed-endpoint extents touching the insertion
4524      point because the text would go inside those extents.  If deletion,
4525      treat the range as open on both ends so that touching extents are not
4526      visited.  Note that we assume that an insertion is occurring if the
4527      changed range has zero length, and a deletion otherwise.  This
4528      fails if a change (i.e. non-insertion, non-deletion) is happening.
4529      As far as I know, this doesn't currently occur in XEmacs. --ben */
4530   closed = (from==to);
4531   closure.object = object;
4532   closure.start = buffer_or_string_bytind_to_memind (object, from);
4533   closure.end = buffer_or_string_bytind_to_memind (object, to);
4534   closure.iro = inhibit_read_only_value;
4535
4536   map_extents_bytind (from, to, verify_extent_mapper, (void *) &closure,
4537                       object, 0, closed ? ME_END_CLOSED : ME_START_OPEN);
4538 }
4539
4540 /* ------------------------------------ */
4541 /*    process_extents_for_insertion()   */
4542 /* ------------------------------------ */
4543
4544 struct process_extents_for_insertion_arg
4545 {
4546   Bytind opoint;
4547   int length;
4548   Lisp_Object object;
4549 };
4550
4551 /*   A region of length LENGTH was just inserted at OPOINT.  Modify all
4552      of the extents as required for the insertion, based on their
4553      start-open/end-open properties.
4554  */
4555
4556 static int
4557 process_extents_for_insertion_mapper (EXTENT extent, void *arg)
4558 {
4559   struct process_extents_for_insertion_arg *closure =
4560     (struct process_extents_for_insertion_arg *) arg;
4561   Memind indice = buffer_or_string_bytind_to_memind (closure->object,
4562                                                       closure->opoint);
4563
4564   /* When this function is called, one end of the newly-inserted text should
4565      be adjacent to some endpoint of the extent, or disjoint from it.  If
4566      the insertion overlaps any existing extent, something is wrong.
4567    */
4568 #ifdef ERROR_CHECK_EXTENTS
4569   if (extent_start (extent) > indice &&
4570       extent_start (extent) < indice + closure->length)
4571     abort ();
4572   if (extent_end (extent) > indice &&
4573       extent_end (extent) < indice + closure->length)
4574     abort ();
4575 #endif
4576
4577   /* The extent-adjustment code adjusted the extent's endpoints as if
4578      all extents were closed-open -- endpoints at the insertion point
4579      remain unchanged.  We need to fix the other kinds of extents:
4580
4581      1. Start position of start-open extents needs to be moved.
4582
4583      2. End position of end-closed extents needs to be moved.
4584
4585      Note that both conditions hold for zero-length (] extents at the
4586      insertion point.  But under these rules, zero-length () extents
4587      would get adjusted such that their start is greater than their
4588      end; instead of allowing that, we treat them as [) extents by
4589      modifying condition #1 to not fire nothing when dealing with a
4590      zero-length open-open extent.
4591
4592      Existence of zero-length open-open extents is unfortunately an
4593      inelegant part of the extent model, but there is no way around
4594      it. */
4595
4596   {
4597     Memind new_start = extent_start (extent);
4598     Memind new_end   = extent_end (extent);
4599
4600     if (indice == extent_start (extent) && extent_start_open_p (extent)
4601         /* zero-length () extents are exempt; see comment above. */
4602         && !(new_start == new_end && extent_end_open_p (extent))
4603         )
4604       new_start += closure->length;
4605     if (indice == extent_end (extent) && !extent_end_open_p (extent))
4606       new_end += closure->length;
4607
4608     set_extent_endpoints_1 (extent, new_start, new_end);
4609   }
4610
4611   return 0;
4612 }
4613
4614 void
4615 process_extents_for_insertion (Lisp_Object object, Bytind opoint,
4616                                Bytecount length)
4617 {
4618   struct process_extents_for_insertion_arg closure;
4619
4620   closure.opoint = opoint;
4621   closure.length = length;
4622   closure.object = object;
4623
4624   map_extents_bytind (opoint, opoint + length,
4625                       process_extents_for_insertion_mapper,
4626                       (void *) &closure, object, 0,
4627                       ME_END_CLOSED | ME_MIGHT_MODIFY_EXTENTS |
4628                       ME_INCLUDE_INTERNAL);
4629 }
4630
4631 /* ------------------------------------ */
4632 /*    process_extents_for_deletion()    */
4633 /* ------------------------------------ */
4634
4635 struct process_extents_for_deletion_arg
4636 {
4637   Memind start, end;
4638   int destroy_included_extents;
4639 };
4640
4641 /* This function is called when we're about to delete the range [from, to].
4642    Detach all of the extents that are completely inside the range [from, to],
4643    if they're detachable or open-open. */
4644
4645 static int
4646 process_extents_for_deletion_mapper (EXTENT extent, void *arg)
4647 {
4648   struct process_extents_for_deletion_arg *closure =
4649     (struct process_extents_for_deletion_arg *) arg;
4650
4651   /* If the extent lies completely within the range that
4652      is being deleted, then nuke the extent if it's detachable
4653      (otherwise, it will become a zero-length extent). */
4654
4655   if (closure->start <= extent_start (extent) &&
4656       extent_end (extent) <= closure->end)
4657     {
4658       if (extent_detachable_p (extent))
4659         {
4660           if (closure->destroy_included_extents)
4661             destroy_extent (extent);
4662           else
4663             extent_detach (extent);
4664         }
4665     }
4666
4667   return 0;
4668 }
4669
4670 /* DESTROY_THEM means destroy the extents instead of just deleting them.
4671    It is unused currently, but perhaps might be used (there used to
4672    be a function process_extents_for_destruction(), #if 0'd out,
4673    that did the equivalent). */
4674 void
4675 process_extents_for_deletion (Lisp_Object object, Bytind from,
4676                               Bytind to, int destroy_them)
4677 {
4678   struct process_extents_for_deletion_arg closure;
4679
4680   closure.start = buffer_or_string_bytind_to_memind (object, from);
4681   closure.end = buffer_or_string_bytind_to_memind (object, to);
4682   closure.destroy_included_extents = destroy_them;
4683
4684   map_extents_bytind (from, to, process_extents_for_deletion_mapper,
4685                       (void *) &closure, object, 0,
4686                       ME_END_CLOSED | ME_MIGHT_MODIFY_EXTENTS);
4687 }
4688
4689 /* ------------------------------- */
4690 /*   report_extent_modification()  */
4691 /* ------------------------------- */
4692 struct report_extent_modification_closure {
4693   Lisp_Object buffer;
4694   Bufpos start, end;
4695   int afterp;
4696   int speccount;
4697 };
4698
4699 static Lisp_Object
4700 report_extent_modification_restore (Lisp_Object buffer)
4701 {
4702   if (current_buffer != XBUFFER (buffer))
4703     Fset_buffer (buffer);
4704   return Qnil;
4705 }
4706
4707 static int
4708 report_extent_modification_mapper (EXTENT extent, void *arg)
4709 {
4710   struct report_extent_modification_closure *closure =
4711     (struct report_extent_modification_closure *)arg;
4712   Lisp_Object exobj, startobj, endobj;
4713   Lisp_Object hook = (closure->afterp
4714                       ? extent_after_change_functions (extent)
4715                       : extent_before_change_functions (extent));
4716   if (NILP (hook))
4717     return 0;
4718
4719   XSETEXTENT (exobj, extent);
4720   XSETINT (startobj, closure->start);
4721   XSETINT (endobj, closure->end);
4722
4723   /* Now that we are sure to call elisp, set up an unwind-protect so
4724      inside_change_hook gets restored in case we throw.  Also record
4725      the current buffer, in case we change it.  Do the recording only
4726      once.
4727
4728      One confusing thing here is that our caller never actually calls
4729      unbind_to (closure.speccount, Qnil).  This is because
4730      map_extents_bytind() unbinds before, and with a smaller
4731      speccount.  The additional unbind_to() in
4732      report_extent_modification() would cause XEmacs to abort.  */
4733   if (closure->speccount == -1)
4734     {
4735       closure->speccount = specpdl_depth ();
4736       record_unwind_protect (report_extent_modification_restore,
4737                              Fcurrent_buffer ());
4738     }
4739
4740   /* The functions will expect closure->buffer to be the current
4741      buffer, so change it if it isn't.  */
4742   if (current_buffer != XBUFFER (closure->buffer))
4743     Fset_buffer (closure->buffer);
4744
4745   /* #### It's a shame that we can't use any of the existing run_hook*
4746      functions here.  This is so because all of them work with
4747      symbols, to be able to retrieve default values of local hooks.
4748      <sigh>
4749
4750      #### Idea: we could set up a dummy symbol, and call the hook
4751      functions on *that*.  */
4752
4753   if (!CONSP (hook) || EQ (XCAR (hook), Qlambda))
4754     call3 (hook, exobj, startobj, endobj);
4755   else
4756     {
4757       Lisp_Object tail;
4758       EXTERNAL_LIST_LOOP (tail, hook)
4759         /* #### Shouldn't this perform the same Fset_buffer() check as
4760            above?  */
4761         call3 (XCAR (tail), exobj, startobj, endobj);
4762     }
4763   return 0;
4764 }
4765
4766 void
4767 report_extent_modification (Lisp_Object buffer, Bufpos start, Bufpos end,
4768                             int afterp)
4769 {
4770   struct report_extent_modification_closure closure;
4771
4772   closure.buffer = buffer;
4773   closure.start = start;
4774   closure.end = end;
4775   closure.afterp = afterp;
4776   closure.speccount = -1;
4777
4778   map_extents (start, end, report_extent_modification_mapper, (void *)&closure,
4779                buffer, NULL, ME_MIGHT_CALL_ELISP);
4780 }
4781
4782 \f
4783 /************************************************************************/
4784 /*                      extent properties                               */
4785 /************************************************************************/
4786
4787 static void
4788 set_extent_invisible (EXTENT extent, Lisp_Object value)
4789 {
4790   if (!EQ (extent_invisible (extent), value))
4791     {
4792       set_extent_invisible_1 (extent, value);
4793       extent_changed_for_redisplay (extent, 1, 1);
4794     }
4795 }
4796
4797 /* This function does "memoization" -- similar to the interning
4798    that happens with symbols.  Given a list of faces, an equivalent
4799    list is returned such that if this function is called twice with
4800    input that is `equal', the resulting outputs will be `eq'.
4801
4802    Note that the inputs and outputs are in general *not* `equal' --
4803    faces in symbol form become actual face objects in the output.
4804    This is necessary so that temporary faces stay around. */
4805
4806 static Lisp_Object
4807 memoize_extent_face_internal (Lisp_Object list)
4808 {
4809   int len;
4810   int thelen;
4811   Lisp_Object cons, thecons;
4812   Lisp_Object oldtail, tail;
4813   struct gcpro gcpro1;
4814
4815   if (NILP (list))
4816     return Qnil;
4817   if (!CONSP (list))
4818     return Fget_face (list);
4819
4820   /* To do the memoization, we use a hash table mapping from
4821      external lists to internal lists.  We do `equal' comparisons
4822      on the keys so the memoization works correctly.
4823
4824      Note that we canonicalize things so that the keys in the
4825      hash table (the external lists) always contain symbols and
4826      the values (the internal lists) always contain face objects.
4827
4828      We also maintain a "reverse" table that maps from the internal
4829      lists to the external equivalents.  The idea here is twofold:
4830
4831      1) `extent-face' wants to return a list containing face symbols
4832         rather than face objects.
4833      2) We don't want things to get quite so messed up if the user
4834         maliciously side-effects the returned lists.
4835      */
4836
4837   len = XINT (Flength (list));
4838   thelen = XINT (Flength (Vextent_face_reusable_list));
4839   oldtail = Qnil;
4840   tail = Qnil;
4841   GCPRO1 (oldtail);
4842
4843   /* We canonicalize the given list into another list.
4844      We try to avoid consing except when necessary, so we have
4845      a reusable list.
4846   */
4847
4848   if (thelen < len)
4849     {
4850       cons = Vextent_face_reusable_list;
4851       while (!NILP (XCDR (cons)))
4852         cons = XCDR (cons);
4853       XCDR (cons) = Fmake_list (make_int (len - thelen), Qnil);
4854     }
4855   else if (thelen > len)
4856     {
4857       int i;
4858
4859       /* Truncate the list temporarily so it's the right length;
4860          remember the old tail. */
4861       cons = Vextent_face_reusable_list;
4862       for (i = 0; i < len - 1; i++)
4863         cons = XCDR (cons);
4864       tail = cons;
4865       oldtail = XCDR (cons);
4866       XCDR (cons) = Qnil;
4867     }
4868
4869   thecons = Vextent_face_reusable_list;
4870   EXTERNAL_LIST_LOOP (cons, list)
4871     {
4872       Lisp_Object face = Fget_face (XCAR (cons));
4873
4874       XCAR (thecons) = Fface_name (face);
4875       thecons = XCDR (thecons);
4876     }
4877
4878   list = Fgethash (Vextent_face_reusable_list, Vextent_face_memoize_hash_table,
4879                    Qnil);
4880   if (NILP (list))
4881     {
4882       Lisp_Object symlist = Fcopy_sequence (Vextent_face_reusable_list);
4883       Lisp_Object facelist = Fcopy_sequence (Vextent_face_reusable_list);
4884
4885       LIST_LOOP (cons, facelist)
4886         {
4887           XCAR (cons) = Fget_face (XCAR (cons));
4888         }
4889       Fputhash (symlist, facelist, Vextent_face_memoize_hash_table);
4890       Fputhash (facelist, symlist, Vextent_face_reverse_memoize_hash_table);
4891       list = facelist;
4892     }
4893
4894   /* Now restore the truncated tail of the reusable list, if necessary. */
4895   if (!NILP (tail))
4896     XCDR (tail) = oldtail;
4897
4898   UNGCPRO;
4899   return list;
4900 }
4901
4902 static Lisp_Object
4903 external_of_internal_memoized_face (Lisp_Object face)
4904 {
4905   if (NILP (face))
4906     return Qnil;
4907   else if (!CONSP (face))
4908     return XFACE (face)->name;
4909   else
4910     {
4911       face = Fgethash (face, Vextent_face_reverse_memoize_hash_table,
4912                        Qunbound);
4913       assert (!UNBOUNDP (face));
4914       return face;
4915     }
4916 }
4917
4918 static Lisp_Object
4919 canonicalize_extent_property (Lisp_Object prop, Lisp_Object value)
4920 {
4921   if (EQ (prop, Qface) || EQ (prop, Qmouse_face))
4922     value = (external_of_internal_memoized_face
4923              (memoize_extent_face_internal (value)));
4924   return value;
4925 }
4926
4927 /* Do we need a lisp-level function ? */
4928 DEFUN ("set-extent-initial-redisplay-function", Fset_extent_initial_redisplay_function,
4929        2,2,0, /*
4930 Note: This feature is experimental!
4931
4932 Set initial-redisplay-function of EXTENT to the function
4933 FUNCTION.
4934
4935 The first time the EXTENT is (re)displayed, an eval event will be
4936 dispatched calling FUNCTION with EXTENT as its only argument.
4937 */
4938        (extent, function))
4939 {
4940   EXTENT e = decode_extent(extent, DE_MUST_BE_ATTACHED);
4941
4942   e = extent_ancestor (e);  /* Is this needed? Macro also does chasing!*/
4943   set_extent_initial_redisplay_function(e,function);
4944   extent_in_red_event_p(e) = 0;  /* If the function changed we can spawn
4945                                     new events */
4946   extent_changed_for_redisplay(e,1,0); /* Do we need to mark children too ?*/
4947
4948   return function;
4949 }
4950
4951 DEFUN ("extent-face", Fextent_face, 1, 1, 0, /*
4952 Return the name of the face in which EXTENT is displayed, or nil
4953 if the extent's face is unspecified.  This might also return a list
4954 of face names.
4955 */
4956        (extent))
4957 {
4958   Lisp_Object face;
4959
4960   CHECK_EXTENT (extent);
4961   face = extent_face (XEXTENT (extent));
4962
4963   return external_of_internal_memoized_face (face);
4964 }
4965
4966 DEFUN ("set-extent-face", Fset_extent_face, 2, 2, 0, /*
4967 Make the given EXTENT have the graphic attributes specified by FACE.
4968 FACE can also be a list of faces, and all faces listed will apply,
4969 with faces earlier in the list taking priority over those later in the
4970 list.
4971 */
4972        (extent, face))
4973 {
4974   EXTENT e = decode_extent(extent, 0);
4975   Lisp_Object orig_face = face;
4976
4977   /* retrieve the ancestor for efficiency and proper redisplay noting. */
4978   e = extent_ancestor (e);
4979
4980   face = memoize_extent_face_internal (face);
4981
4982   extent_face (e) = face;
4983   extent_changed_for_redisplay (e, 1, 0);
4984
4985   return orig_face;
4986 }
4987
4988
4989 DEFUN ("extent-mouse-face", Fextent_mouse_face, 1, 1, 0, /*
4990 Return the face used to highlight EXTENT when the mouse passes over it.
4991 The return value will be a face name, a list of face names, or nil
4992 if the extent's mouse face is unspecified.
4993 */
4994        (extent))
4995 {
4996   Lisp_Object face;
4997
4998   CHECK_EXTENT (extent);
4999   face = extent_mouse_face (XEXTENT (extent));
5000
5001   return external_of_internal_memoized_face (face);
5002 }
5003
5004 DEFUN ("set-extent-mouse-face", Fset_extent_mouse_face, 2, 2, 0, /*
5005 Set the face used to highlight EXTENT when the mouse passes over it.
5006 FACE can also be a list of faces, and all faces listed will apply,
5007 with faces earlier in the list taking priority over those later in the
5008 list.
5009 */
5010        (extent, face))
5011 {
5012   EXTENT e;
5013   Lisp_Object orig_face = face;
5014
5015   CHECK_EXTENT (extent);
5016   e = XEXTENT (extent);
5017   /* retrieve the ancestor for efficiency and proper redisplay noting. */
5018   e = extent_ancestor (e);
5019
5020   face = memoize_extent_face_internal (face);
5021
5022   set_extent_mouse_face (e, face);
5023   extent_changed_for_redisplay (e, 1, 0);
5024
5025   return orig_face;
5026 }
5027
5028 void
5029 set_extent_glyph (EXTENT extent, Lisp_Object glyph, int endp,
5030                   glyph_layout layout)
5031 {
5032   extent = extent_ancestor (extent);
5033
5034   if (!endp)
5035     {
5036       set_extent_begin_glyph (extent, glyph);
5037       extent_begin_glyph_layout (extent) = layout;
5038     }
5039   else
5040     {
5041       set_extent_end_glyph (extent, glyph);
5042       extent_end_glyph_layout (extent) = layout;
5043     }
5044
5045   extent_changed_for_redisplay (extent, 1, 0);
5046 }
5047
5048 static Lisp_Object
5049 glyph_layout_to_symbol (glyph_layout layout)
5050 {
5051   switch (layout)
5052     {
5053     case GL_TEXT:           return Qtext;
5054     case GL_OUTSIDE_MARGIN: return Qoutside_margin;
5055     case GL_INSIDE_MARGIN:  return Qinside_margin;
5056     case GL_WHITESPACE:     return Qwhitespace;
5057     default:
5058       abort ();
5059       return Qnil; /* unreached */
5060     }
5061 }
5062
5063 static glyph_layout
5064 symbol_to_glyph_layout (Lisp_Object layout_obj)
5065 {
5066   if (NILP (layout_obj))
5067     return GL_TEXT;
5068
5069   CHECK_SYMBOL (layout_obj);
5070   if (EQ (layout_obj, Qoutside_margin)) return GL_OUTSIDE_MARGIN;
5071   if (EQ (layout_obj, Qinside_margin))  return GL_INSIDE_MARGIN;
5072   if (EQ (layout_obj, Qwhitespace))     return GL_WHITESPACE;
5073   if (EQ (layout_obj, Qtext))           return GL_TEXT;
5074
5075   invalid_argument ("Unknown glyph layout type", layout_obj);
5076   return GL_TEXT; /* unreached */
5077 }
5078
5079 static Lisp_Object
5080 set_extent_glyph_1 (Lisp_Object extent_obj, Lisp_Object glyph, int endp,
5081                     Lisp_Object layout_obj)
5082 {
5083   EXTENT extent = decode_extent (extent_obj, 0);
5084   glyph_layout layout = symbol_to_glyph_layout (layout_obj);
5085
5086   /* Make sure we've actually been given a valid glyph or it's nil
5087      (meaning we're deleting a glyph from an extent). */
5088   if (!NILP (glyph))
5089     CHECK_BUFFER_GLYPH (glyph);
5090
5091   set_extent_glyph (extent, glyph, endp, layout);
5092   return glyph;
5093 }
5094
5095 DEFUN ("set-extent-begin-glyph", Fset_extent_begin_glyph, 2, 3, 0, /*
5096 Display a bitmap, subwindow or string at the beginning of EXTENT.
5097 BEGIN-GLYPH must be a glyph object.  The layout policy defaults to `text'.
5098 */
5099        (extent, begin_glyph, layout))
5100 {
5101   return set_extent_glyph_1 (extent, begin_glyph, 0, layout);
5102 }
5103
5104 DEFUN ("set-extent-end-glyph", Fset_extent_end_glyph, 2, 3, 0, /*
5105 Display a bitmap, subwindow or string at the end of EXTENT.
5106 END-GLYPH must be a glyph object.  The layout policy defaults to `text'.
5107 */
5108        (extent, end_glyph, layout))
5109 {
5110   return set_extent_glyph_1 (extent, end_glyph, 1, layout);
5111 }
5112
5113 DEFUN ("extent-begin-glyph", Fextent_begin_glyph, 1, 1, 0, /*
5114 Return the glyph object displayed at the beginning of EXTENT.
5115 If there is none, nil is returned.
5116 */
5117        (extent))
5118 {
5119   return extent_begin_glyph (decode_extent (extent, 0));
5120 }
5121
5122 DEFUN ("extent-end-glyph", Fextent_end_glyph, 1, 1, 0, /*
5123 Return the glyph object displayed at the end of EXTENT.
5124 If there is none, nil is returned.
5125 */
5126        (extent))
5127 {
5128   return extent_end_glyph (decode_extent (extent, 0));
5129 }
5130
5131 DEFUN ("set-extent-begin-glyph-layout", Fset_extent_begin_glyph_layout, 2, 2, 0, /*
5132 Set the layout policy of EXTENT's begin glyph.
5133 Access this using the `extent-begin-glyph-layout' function.
5134 */
5135        (extent, layout))
5136 {
5137   EXTENT e = decode_extent (extent, 0);
5138   e = extent_ancestor (e);
5139   extent_begin_glyph_layout (e) = symbol_to_glyph_layout (layout);
5140   extent_maybe_changed_for_redisplay (e, 1, 0);
5141   return layout;
5142 }
5143
5144 DEFUN ("set-extent-end-glyph-layout", Fset_extent_end_glyph_layout, 2, 2, 0, /*
5145 Set the layout policy of EXTENT's end glyph.
5146 Access this using the `extent-end-glyph-layout' function.
5147 */
5148        (extent, layout))
5149 {
5150   EXTENT e = decode_extent (extent, 0);
5151   e = extent_ancestor (e);
5152   extent_end_glyph_layout (e) = symbol_to_glyph_layout (layout);
5153   extent_maybe_changed_for_redisplay (e, 1, 0);
5154   return layout;
5155 }
5156
5157 DEFUN ("extent-begin-glyph-layout", Fextent_begin_glyph_layout, 1, 1, 0, /*
5158 Return the layout policy associated with EXTENT's begin glyph.
5159 Set this using the `set-extent-begin-glyph-layout' function.
5160 */
5161        (extent))
5162 {
5163   EXTENT e = decode_extent (extent, 0);
5164   return glyph_layout_to_symbol ((glyph_layout) extent_begin_glyph_layout (e));
5165 }
5166
5167 DEFUN ("extent-end-glyph-layout", Fextent_end_glyph_layout, 1, 1, 0, /*
5168 Return the layout policy associated with EXTENT's end glyph.
5169 Set this using the `set-extent-end-glyph-layout' function.
5170 */
5171        (extent))
5172 {
5173   EXTENT e = decode_extent (extent, 0);
5174   return glyph_layout_to_symbol ((glyph_layout) extent_end_glyph_layout (e));
5175 }
5176
5177 DEFUN ("set-extent-priority", Fset_extent_priority, 2, 2, 0, /*
5178 Set the display priority of EXTENT to PRIORITY (an integer).
5179 When the extent attributes are being merged for display, the priority
5180 is used to determine which extent takes precedence in the event of a
5181 conflict (two extents whose faces both specify font, for example: the
5182 font of the extent with the higher priority will be used).
5183 Extents are created with priority 0; priorities may be negative.
5184 */
5185        (extent, priority))
5186 {
5187   EXTENT e = decode_extent (extent, 0);
5188
5189   CHECK_INT (priority);
5190   e = extent_ancestor (e);
5191   set_extent_priority (e, XINT (priority));
5192   extent_maybe_changed_for_redisplay (e, 1, 0);
5193   return priority;
5194 }
5195
5196 DEFUN ("extent-priority", Fextent_priority, 1, 1, 0, /*
5197 Return the display priority of EXTENT; see `set-extent-priority'.
5198 */
5199        (extent))
5200 {
5201   EXTENT e = decode_extent (extent, 0);
5202   return make_int (extent_priority (e));
5203 }
5204
5205 DEFUN ("set-extent-property", Fset_extent_property, 3, 3, 0, /*
5206 Change a property of an extent.
5207 PROPERTY may be any symbol; the value stored may be accessed with
5208  the `extent-property' function.
5209 The following symbols have predefined meanings:
5210
5211  detached           Removes the extent from its buffer; setting this is
5212                     the same as calling `detach-extent'.
5213
5214  destroyed          Removes the extent from its buffer, and makes it
5215                     unusable in the future; this is the same calling
5216                     `delete-extent'.
5217
5218  priority           Change redisplay priority; same as `set-extent-priority'.
5219
5220  start-open         Whether the set of characters within the extent is
5221                     treated being open on the left, that is, whether
5222                     the start position is an exclusive, rather than
5223                     inclusive, boundary.  If true, then characters
5224                     inserted exactly at the beginning of the extent
5225                     will remain outside of the extent; otherwise they
5226                     will go into the extent, extending it.
5227
5228  end-open           Whether the set of characters within the extent is
5229                     treated being open on the right, that is, whether
5230                     the end position is an exclusive, rather than
5231                     inclusive, boundary.  If true, then characters
5232                     inserted exactly at the end of the extent will
5233                     remain outside of the extent; otherwise they will
5234                     go into the extent, extending it.
5235
5236                     By default, extents have the `end-open' but not the
5237                     `start-open' property set.
5238
5239  read-only          Text within this extent will be unmodifiable.
5240
5241  initial-redisplay-function (EXPERIMENTAL)
5242                     function to be called the first time (part of) the extent
5243                     is redisplayed. It will be called with the extent as its
5244                     first argument.
5245                     Note: The function will not be called immediately
5246                     during redisplay, an eval event will be dispatched.
5247
5248  detachable         Whether the extent gets detached (as with
5249                     `detach-extent') when all the text within the
5250                     extent is deleted.  This is true by default.  If
5251                     this property is not set, the extent becomes a
5252                     zero-length extent when its text is deleted. (In
5253                     such a case, the `start-open' property is
5254                     automatically removed if both the `start-open' and
5255                     `end-open' properties are set, since zero-length
5256                     extents open on both ends are not allowed.)
5257
5258  face               The face in which to display the text.  Setting
5259                     this is the same as calling `set-extent-face'.
5260
5261  mouse-face         If non-nil, the extent will be highlighted in this
5262                     face when the mouse moves over it.
5263
5264  pointer            If non-nil, and a valid pointer glyph, this specifies
5265                     the shape of the mouse pointer while over the extent.
5266
5267  highlight          Obsolete: Setting this property is equivalent to
5268                     setting a `mouse-face' property of `highlight'.
5269                     Reading this property returns non-nil if
5270                     the extent has a non-nil `mouse-face' property.
5271
5272  duplicable         Whether this extent should be copied into strings,
5273                     so that kill, yank, and undo commands will restore
5274                     or copy it.  `duplicable' extents are copied from
5275                     an extent into a string when `buffer-substring' or
5276                     a similar function creates a string.  The extents
5277                     in a string are copied into other strings created
5278                     from the string using `concat' or `substring'.
5279                     When `insert' or a similar function inserts the
5280                     string into a buffer, the extents are copied back
5281                     into the buffer.
5282
5283  unique             Meaningful only in conjunction with `duplicable'.
5284                     When this is set, there may be only one instance
5285                     of this extent attached at a time: if it is copied
5286                     to the kill ring and then yanked, the extent is
5287                     not copied.  If, however, it is killed (removed
5288                     from the buffer) and then yanked, it will be
5289                     re-attached at the new position.
5290
5291  invisible          If the value is non-nil, text under this extent
5292                     may be treated as not present for the purpose of
5293                     redisplay, or may be displayed using an ellipsis
5294                     or other marker; see `buffer-invisibility-spec'
5295                     and `invisible-text-glyph'.  In all cases,
5296                     however, the text is still visible to other
5297                     functions that examine a buffer's text.
5298
5299  keymap             This keymap is consulted for mouse clicks on this
5300                     extent, or keypresses made while point is within the
5301                     extent.
5302
5303  copy-function      This is a hook that is run when a duplicable extent
5304                     is about to be copied from a buffer to a string (or
5305                     the kill ring).  It is called with three arguments,
5306                     the extent, and the buffer-positions within it
5307                     which are being copied.  If this function returns
5308                     nil, then the extent will not be copied; otherwise
5309                     it will.
5310
5311  paste-function     This is a hook that is run when a duplicable extent is
5312                     about to be copied from a string (or the kill ring)
5313                     into a buffer.  It is called with three arguments,
5314                     the original extent, and the buffer positions which
5315                     the copied extent will occupy.  (This hook is run
5316                     after the corresponding text has already been
5317                     inserted into the buffer.)  Note that the extent
5318                     argument may be detached when this function is run.
5319                     If this function returns nil, no extent will be
5320                     inserted.  Otherwise, there will be an extent
5321                     covering the range in question.
5322
5323                     If the original extent is not attached to a buffer,
5324                     then it will be re-attached at this range.
5325                     Otherwise, a copy will be made, and that copy
5326                     attached here.
5327
5328                     The copy-function and paste-function are meaningful
5329                     only for extents with the `duplicable' flag set,
5330                     and if they are not specified, behave as if `t' was
5331                     the returned value.  When these hooks are invoked,
5332                     the current buffer is the buffer which the extent
5333                     is being copied from/to, respectively.
5334
5335  begin-glyph        A glyph to be displayed at the beginning of the extent,
5336                     or nil.
5337
5338  end-glyph          A glyph to be displayed at the end of the extent,
5339                     or nil.
5340
5341  begin-glyph-layout The layout policy (one of `text', `whitespace',
5342                     `inside-margin', or `outside-margin') of the extent's
5343                     begin glyph.
5344
5345  end-glyph-layout The layout policy of the extent's end glyph.
5346 */
5347        (extent, property, value))
5348 {
5349   /* This function can GC if property is `keymap' */
5350   EXTENT e = decode_extent (extent, 0);
5351
5352   if (EQ (property, Qread_only))
5353     set_extent_read_only (e, value);
5354   else if (EQ (property, Qunique))
5355     extent_unique_p (e) = !NILP (value);
5356   else if (EQ (property, Qduplicable))
5357     extent_duplicable_p (e) = !NILP (value);
5358   else if (EQ (property, Qinvisible))
5359     set_extent_invisible (e, value);
5360   else if (EQ (property, Qdetachable))
5361     extent_detachable_p (e) = !NILP (value);
5362
5363   else if (EQ (property, Qdetached))
5364     {
5365       if (NILP (value))
5366         error ("can only set `detached' to t");
5367       Fdetach_extent (extent);
5368     }
5369   else if (EQ (property, Qdestroyed))
5370     {
5371       if (NILP (value))
5372         error ("can only set `destroyed' to t");
5373       Fdelete_extent (extent);
5374     }
5375   else if (EQ (property, Qpriority))
5376     Fset_extent_priority (extent, value);
5377   else if (EQ (property, Qface))
5378     Fset_extent_face (extent, value);
5379   else if (EQ (property, Qinitial_redisplay_function))
5380     Fset_extent_initial_redisplay_function (extent, value);
5381   else if (EQ (property, Qbefore_change_functions))
5382     set_extent_before_change_functions (e, value);
5383   else if (EQ (property, Qafter_change_functions))
5384     set_extent_after_change_functions (e, value);
5385   else if (EQ (property, Qmouse_face))
5386     Fset_extent_mouse_face (extent, value);
5387   /* Obsolete: */
5388   else if (EQ (property, Qhighlight))
5389     Fset_extent_mouse_face (extent, Qhighlight);
5390   else if (EQ (property, Qbegin_glyph_layout))
5391     Fset_extent_begin_glyph_layout (extent, value);
5392   else if (EQ (property, Qend_glyph_layout))
5393     Fset_extent_end_glyph_layout (extent, value);
5394   /* For backwards compatibility.  We use begin glyph because it is by
5395      far the more used of the two. */
5396   else if (EQ (property, Qglyph_layout))
5397     Fset_extent_begin_glyph_layout (extent, value);
5398   else if (EQ (property, Qbegin_glyph))
5399     Fset_extent_begin_glyph (extent, value, Qnil);
5400   else if (EQ (property, Qend_glyph))
5401     Fset_extent_end_glyph (extent, value, Qnil);
5402   else if (EQ (property, Qstart_open))
5403     set_extent_openness (e, !NILP (value), -1);
5404   else if (EQ (property, Qend_open))
5405     set_extent_openness (e, -1, !NILP (value));
5406   /* Support (but don't document...) the obvious *_closed antonyms. */
5407   else if (EQ (property, Qstart_closed))
5408     set_extent_openness (e, NILP (value), -1);
5409   else if (EQ (property, Qend_closed))
5410     set_extent_openness (e, -1, NILP (value));
5411   else
5412     {
5413       if (EQ (property, Qkeymap))
5414         while (!NILP (value) && NILP (Fkeymapp (value)))
5415           value = wrong_type_argument (Qkeymapp, value);
5416
5417       external_plist_put (extent_plist_addr (e), property, value, 0, ERROR_ME);
5418     }
5419
5420   return value;
5421 }
5422
5423 DEFUN ("set-extent-properties", Fset_extent_properties, 2, 2, 0, /*
5424 Change some properties of EXTENT.
5425 PLIST is a property list.
5426 For a list of built-in properties, see `set-extent-property'.
5427 */
5428        (extent, plist))
5429 {
5430   /* This function can GC, if one of the properties is `keymap' */
5431   Lisp_Object property, value;
5432   struct gcpro gcpro1;
5433   GCPRO1 (plist);
5434
5435   plist = Fcopy_sequence (plist);
5436   Fcanonicalize_plist (plist, Qnil);
5437
5438   while (!NILP (plist))
5439     {
5440       property = Fcar (plist); plist = Fcdr (plist);
5441       value    = Fcar (plist); plist = Fcdr (plist);
5442       Fset_extent_property (extent, property, value);
5443     }
5444   UNGCPRO;
5445   return Qnil;
5446 }
5447
5448 DEFUN ("extent-property", Fextent_property, 2, 3, 0, /*
5449 Return EXTENT's value for property PROPERTY.
5450 If no such property exists, DEFAULT is returned.
5451 See `set-extent-property' for the built-in property names.
5452 */
5453        (extent, property, default_))
5454 {
5455   EXTENT e = decode_extent (extent, 0);
5456
5457   if (EQ (property, Qdetached))
5458     return extent_detached_p (e) ? Qt : Qnil;
5459   else if (EQ (property, Qdestroyed))
5460     return !EXTENT_LIVE_P (e) ? Qt : Qnil;
5461   else if (EQ (property, Qstart_open))
5462     return extent_normal_field (e, start_open) ? Qt : Qnil;
5463   else if (EQ (property, Qend_open))
5464     return extent_normal_field (e, end_open) ? Qt : Qnil;
5465   else if (EQ (property, Qunique))
5466     return extent_normal_field (e, unique) ? Qt : Qnil;
5467   else if (EQ (property, Qduplicable))
5468     return extent_normal_field (e, duplicable) ? Qt : Qnil;
5469   else if (EQ (property, Qdetachable))
5470     return extent_normal_field (e, detachable) ? Qt : Qnil;
5471   /* Support (but don't document...) the obvious *_closed antonyms. */
5472   else if (EQ (property, Qstart_closed))
5473     return extent_start_open_p (e) ? Qnil : Qt;
5474   else if (EQ (property, Qend_closed))
5475     return extent_end_open_p (e) ? Qnil : Qt;
5476   else if (EQ (property, Qpriority))
5477     return make_int (extent_priority (e));
5478   else if (EQ (property, Qread_only))
5479     return extent_read_only (e);
5480   else if (EQ (property, Qinvisible))
5481     return extent_invisible (e);
5482   else if (EQ (property, Qface))
5483     return Fextent_face (extent);
5484   else if (EQ (property, Qinitial_redisplay_function))
5485     return extent_initial_redisplay_function (e);
5486   else if (EQ (property, Qbefore_change_functions))
5487     return extent_before_change_functions (e);
5488   else if (EQ (property, Qafter_change_functions))
5489     return extent_after_change_functions (e);
5490   else if (EQ (property, Qmouse_face))
5491     return Fextent_mouse_face (extent);
5492   /* Obsolete: */
5493   else if (EQ (property, Qhighlight))
5494     return !NILP (Fextent_mouse_face (extent)) ? Qt : Qnil;
5495   else if (EQ (property, Qbegin_glyph_layout))
5496     return Fextent_begin_glyph_layout (extent);
5497   else if (EQ (property, Qend_glyph_layout))
5498     return Fextent_end_glyph_layout (extent);
5499   /* For backwards compatibility.  We use begin glyph because it is by
5500      far the more used of the two. */
5501   else if (EQ (property, Qglyph_layout))
5502     return Fextent_begin_glyph_layout (extent);
5503   else if (EQ (property, Qbegin_glyph))
5504     return extent_begin_glyph (e);
5505   else if (EQ (property, Qend_glyph))
5506     return extent_end_glyph (e);
5507   else
5508     {
5509       Lisp_Object value = external_plist_get (extent_plist_addr (e),
5510                                               property, 0, ERROR_ME);
5511       return UNBOUNDP (value) ? default_ : value;
5512     }
5513 }
5514
5515 DEFUN ("extent-properties", Fextent_properties, 1, 1, 0, /*
5516 Return a property list of the attributes of EXTENT.
5517 Do not modify this list; use `set-extent-property' instead.
5518 */
5519        (extent))
5520 {
5521   EXTENT e, anc;
5522   Lisp_Object result, face, anc_obj;
5523   glyph_layout layout;
5524
5525   CHECK_EXTENT (extent);
5526   e = XEXTENT (extent);
5527   if (!EXTENT_LIVE_P (e))
5528     return cons3 (Qdestroyed, Qt, Qnil);
5529
5530   anc = extent_ancestor (e);
5531   XSETEXTENT (anc_obj, anc);
5532
5533   /* For efficiency, use the ancestor for all properties except detached */
5534
5535   result = extent_plist_slot (anc);
5536
5537   if (!NILP (face = Fextent_face (anc_obj)))
5538     result = cons3 (Qface, face, result);
5539
5540   if (!NILP (face = Fextent_mouse_face (anc_obj)))
5541     result = cons3 (Qmouse_face, face, result);
5542
5543   if ((layout = (glyph_layout) extent_begin_glyph_layout (anc)) != GL_TEXT)
5544     {
5545       Lisp_Object sym = glyph_layout_to_symbol (layout);
5546       result = cons3 (Qglyph_layout,       sym, result); /* compatibility */
5547       result = cons3 (Qbegin_glyph_layout, sym, result);
5548     }
5549
5550   if ((layout = (glyph_layout) extent_end_glyph_layout (anc)) != GL_TEXT)
5551     result = cons3 (Qend_glyph_layout, glyph_layout_to_symbol (layout), result);
5552
5553   if (!NILP (extent_end_glyph (anc)))
5554     result = cons3 (Qend_glyph, extent_end_glyph (anc), result);
5555
5556   if (!NILP (extent_begin_glyph (anc)))
5557     result = cons3 (Qbegin_glyph, extent_begin_glyph (anc), result);
5558
5559   if (extent_priority (anc) != 0)
5560     result = cons3 (Qpriority, make_int (extent_priority (anc)), result);
5561
5562   if (!NILP (extent_initial_redisplay_function (anc)))
5563     result = cons3 (Qinitial_redisplay_function,
5564                     extent_initial_redisplay_function (anc), result);
5565
5566   if (!NILP (extent_before_change_functions (anc)))
5567     result = cons3 (Qbefore_change_functions,
5568                     extent_before_change_functions (anc), result);
5569
5570   if (!NILP (extent_after_change_functions (anc)))
5571     result = cons3 (Qafter_change_functions,
5572                     extent_after_change_functions (anc), result);
5573
5574   if (!NILP (extent_invisible (anc)))
5575     result = cons3 (Qinvisible, extent_invisible (anc), result);
5576
5577   if (!NILP (extent_read_only (anc)))
5578     result = cons3 (Qread_only, extent_read_only (anc), result);
5579
5580   if  (extent_normal_field (anc, end_open))
5581     result = cons3 (Qend_open, Qt, result);
5582
5583   if  (extent_normal_field (anc, start_open))
5584     result = cons3 (Qstart_open, Qt, result);
5585
5586   if  (extent_normal_field (anc, detachable))
5587     result = cons3 (Qdetachable, Qt, result);
5588
5589   if  (extent_normal_field (anc, duplicable))
5590     result = cons3 (Qduplicable, Qt, result);
5591
5592   if  (extent_normal_field (anc, unique))
5593     result = cons3 (Qunique, Qt, result);
5594
5595   /* detached is not an inherited property */
5596   if (extent_detached_p (e))
5597     result = cons3 (Qdetached, Qt, result);
5598
5599   return result;
5600 }
5601
5602 \f
5603 /************************************************************************/
5604 /*                           highlighting                               */
5605 /************************************************************************/
5606
5607 /* The display code looks into the Vlast_highlighted_extent variable to
5608    correctly display highlighted extents.  This updates that variable,
5609    and marks the appropriate buffers as needing some redisplay.
5610  */
5611 static void
5612 do_highlight (Lisp_Object extent_obj, int highlight_p)
5613 {
5614   if (( highlight_p && (EQ (Vlast_highlighted_extent, extent_obj))) ||
5615       (!highlight_p && (EQ (Vlast_highlighted_extent, Qnil))))
5616     return;
5617   if (EXTENTP (Vlast_highlighted_extent) &&
5618       EXTENT_LIVE_P (XEXTENT (Vlast_highlighted_extent)))
5619     {
5620       /* do not recurse on descendants.  Only one extent is highlighted
5621          at a time. */
5622       extent_changed_for_redisplay (XEXTENT (Vlast_highlighted_extent), 0, 0);
5623     }
5624   Vlast_highlighted_extent = Qnil;
5625   if (!NILP (extent_obj)
5626       && BUFFERP (extent_object (XEXTENT (extent_obj)))
5627       && highlight_p)
5628     {
5629       extent_changed_for_redisplay (XEXTENT (extent_obj), 0, 0);
5630       Vlast_highlighted_extent = extent_obj;
5631     }
5632 }
5633
5634 DEFUN ("force-highlight-extent", Fforce_highlight_extent, 1, 2, 0, /*
5635 Highlight or unhighlight the given extent.
5636 If the second arg is non-nil, it will be highlighted, else dehighlighted.
5637 This is the same as `highlight-extent', except that it will work even
5638 on extents without the `mouse-face' property.
5639 */
5640        (extent, highlight_p))
5641 {
5642   if (NILP (extent))
5643     highlight_p = Qnil;
5644   else
5645     XSETEXTENT (extent, decode_extent (extent, DE_MUST_BE_ATTACHED));
5646   do_highlight (extent, !NILP (highlight_p));
5647   return Qnil;
5648 }
5649
5650 DEFUN ("highlight-extent", Fhighlight_extent, 1, 2, 0, /*
5651 Highlight EXTENT, if it is highlightable.
5652 \(that is, if it has the `mouse-face' property).
5653 If the second arg is non-nil, it will be highlighted, else dehighlighted.
5654 Highlighted extents are displayed as if they were merged with the face
5655 or faces specified by the `mouse-face' property.
5656 */
5657        (extent, highlight_p))
5658 {
5659   if (EXTENTP (extent) && NILP (extent_mouse_face (XEXTENT (extent))))
5660     return Qnil;
5661   else
5662     return Fforce_highlight_extent (extent, highlight_p);
5663 }
5664
5665 \f
5666 /************************************************************************/
5667 /*                         strings and extents                          */
5668 /************************************************************************/
5669
5670 /* copy/paste hooks */
5671
5672 static int
5673 run_extent_copy_paste_internal (EXTENT e, Bufpos from, Bufpos to,
5674                                 Lisp_Object object,
5675                                 Lisp_Object prop)
5676 {
5677   /* This function can GC */
5678   Lisp_Object extent;
5679   Lisp_Object copy_fn;
5680   XSETEXTENT (extent, e);
5681   copy_fn = Fextent_property (extent, prop, Qnil);
5682   if (!NILP (copy_fn))
5683     {
5684       Lisp_Object flag;
5685       struct gcpro gcpro1, gcpro2, gcpro3;
5686       GCPRO3 (extent, copy_fn, object);
5687       if (BUFFERP (object))
5688         flag = call3_in_buffer (XBUFFER (object), copy_fn, extent,
5689                                 make_int (from), make_int (to));
5690       else
5691         flag = call3 (copy_fn, extent, make_int (from), make_int (to));
5692       UNGCPRO;
5693       if (NILP (flag) || !EXTENT_LIVE_P (XEXTENT (extent)))
5694         return 0;
5695     }
5696   return 1;
5697 }
5698
5699 static int
5700 run_extent_copy_function (EXTENT e, Bytind from, Bytind to)
5701 {
5702   Lisp_Object object = extent_object (e);
5703   /* This function can GC */
5704   return run_extent_copy_paste_internal
5705     (e, buffer_or_string_bytind_to_bufpos (object, from),
5706      buffer_or_string_bytind_to_bufpos (object, to), object,
5707      Qcopy_function);
5708 }
5709
5710 static int
5711 run_extent_paste_function (EXTENT e, Bytind from, Bytind to,
5712                            Lisp_Object object)
5713 {
5714   /* This function can GC */
5715   return run_extent_copy_paste_internal
5716     (e, buffer_or_string_bytind_to_bufpos (object, from),
5717      buffer_or_string_bytind_to_bufpos (object, to), object,
5718      Qpaste_function);
5719 }
5720
5721 static void
5722 update_extent (EXTENT extent, Bytind from, Bytind to)
5723 {
5724   set_extent_endpoints (extent, from, to, Qnil);
5725 }
5726
5727 /* Insert an extent, usually from the dup_list of a string which
5728    has just been inserted.
5729    This code does not handle the case of undo.
5730    */
5731 static Lisp_Object
5732 insert_extent (EXTENT extent, Bytind new_start, Bytind new_end,
5733                Lisp_Object object, int run_hooks)
5734 {
5735   /* This function can GC */
5736   Lisp_Object tmp;
5737
5738   if (!EQ (extent_object (extent), object))
5739     goto copy_it;
5740
5741   if (extent_detached_p (extent))
5742     {
5743       if (run_hooks &&
5744           !run_extent_paste_function (extent, new_start, new_end, object))
5745         /* The paste-function said don't re-attach this extent here. */
5746         return Qnil;
5747       else
5748         update_extent (extent, new_start, new_end);
5749     }
5750   else
5751     {
5752       Bytind exstart = extent_endpoint_bytind (extent, 0);
5753       Bytind exend = extent_endpoint_bytind (extent, 1);
5754
5755       if (exend < new_start || exstart > new_end)
5756         goto copy_it;
5757       else
5758         {
5759           new_start = min (exstart, new_start);
5760           new_end = max (exend, new_end);
5761           if (exstart != new_start || exend != new_end)
5762             update_extent (extent, new_start, new_end);
5763         }
5764     }
5765
5766   XSETEXTENT (tmp, extent);
5767   return tmp;
5768
5769  copy_it:
5770   if (run_hooks &&
5771       !run_extent_paste_function (extent, new_start, new_end, object))
5772     /* The paste-function said don't attach a copy of the extent here. */
5773     return Qnil;
5774   else
5775     {
5776       XSETEXTENT (tmp, copy_extent (extent, new_start, new_end, object));
5777       return tmp;
5778     }
5779 }
5780
5781 DEFUN ("insert-extent", Finsert_extent, 1, 5, 0, /*
5782 Insert EXTENT from START to END in BUFFER-OR-STRING.
5783 BUFFER-OR-STRING defaults to the current buffer if omitted.
5784 This operation does not insert any characters,
5785 but otherwise acts as if there were a replicating extent whose
5786 parent is EXTENT in some string that was just inserted.
5787 Returns the newly-inserted extent.
5788 The fourth arg, NO-HOOKS, can be used to inhibit the running of the
5789  extent's `paste-function' property if it has one.
5790 See documentation on `detach-extent' for a discussion of undo recording.
5791 */
5792        (extent, start, end, no_hooks, buffer_or_string))
5793 {
5794   EXTENT ext = decode_extent (extent, 0);
5795   Lisp_Object copy;
5796   Bytind s, e;
5797
5798   buffer_or_string = decode_buffer_or_string (buffer_or_string);
5799   get_buffer_or_string_range_byte (buffer_or_string, start, end, &s, &e,
5800                                    GB_ALLOW_PAST_ACCESSIBLE);
5801
5802   copy = insert_extent (ext, s, e, buffer_or_string, NILP (no_hooks));
5803   if (EXTENTP (copy))
5804     {
5805       if (extent_duplicable_p (XEXTENT (copy)))
5806         record_extent (copy, 1);
5807     }
5808   return copy;
5809 }
5810
5811 \f
5812 /* adding buffer extents to a string */
5813
5814 struct add_string_extents_arg
5815 {
5816   Bytind from;
5817   Bytecount length;
5818   Lisp_Object string;
5819 };
5820
5821 static int
5822 add_string_extents_mapper (EXTENT extent, void *arg)
5823 {
5824   /* This function can GC */
5825   struct add_string_extents_arg *closure =
5826     (struct add_string_extents_arg *) arg;
5827   Bytecount start = extent_endpoint_bytind (extent, 0) - closure->from;
5828   Bytecount end   = extent_endpoint_bytind (extent, 1) - closure->from;
5829
5830   if (extent_duplicable_p (extent))
5831     {
5832       start = max (start, 0);
5833       end = min (end, closure->length);
5834
5835       /* Run the copy-function to give an extent the option of
5836          not being copied into the string (or kill ring).
5837          */
5838       if (extent_duplicable_p (extent) &&
5839           !run_extent_copy_function (extent, start + closure->from,
5840                                      end + closure->from))
5841         return 0;
5842       copy_extent (extent, start, end, closure->string);
5843     }
5844
5845   return 0;
5846 }
5847
5848 /* Add the extents in buffer BUF from OPOINT to OPOINT+LENGTH to
5849    the string STRING. */
5850 void
5851 add_string_extents (Lisp_Object string, struct buffer *buf, Bytind opoint,
5852                     Bytecount length)
5853 {
5854   /* This function can GC */
5855   struct add_string_extents_arg closure;
5856   struct gcpro gcpro1, gcpro2;
5857   Lisp_Object buffer;
5858
5859   closure.from = opoint;
5860   closure.length = length;
5861   closure.string = string;
5862   buffer = make_buffer (buf);
5863   GCPRO2 (buffer, string);
5864   map_extents_bytind (opoint, opoint + length, add_string_extents_mapper,
5865                       (void *) &closure, buffer, 0,
5866                       /* ignore extents that just abut the region */
5867                       ME_END_CLOSED | ME_ALL_EXTENTS_OPEN |
5868                       /* we are calling E-Lisp (the extent's copy function)
5869                          so anything might happen */
5870                       ME_MIGHT_CALL_ELISP);
5871   UNGCPRO;
5872 }
5873
5874 struct splice_in_string_extents_arg
5875 {
5876   Bytecount pos;
5877   Bytecount length;
5878   Bytind opoint;
5879   Lisp_Object buffer;
5880 };
5881
5882 static int
5883 splice_in_string_extents_mapper (EXTENT extent, void *arg)
5884 {
5885   /* This function can GC */
5886   struct splice_in_string_extents_arg *closure =
5887     (struct splice_in_string_extents_arg *) arg;
5888   /* BASE_START and BASE_END are the limits in the buffer of the string
5889      that was just inserted.
5890
5891      NEW_START and NEW_END are the prospective buffer positions of the
5892      extent that is going into the buffer. */
5893   Bytind base_start = closure->opoint;
5894   Bytind base_end = base_start + closure->length;
5895   Bytind new_start = (base_start + extent_endpoint_bytind (extent, 0) -
5896                       closure->pos);
5897   Bytind new_end = (base_start + extent_endpoint_bytind (extent, 1) -
5898                     closure->pos);
5899
5900   if (new_start < base_start)
5901     new_start = base_start;
5902   if (new_end > base_end)
5903     new_end = base_end;
5904   if (new_end <= new_start)
5905     return 0;
5906
5907   if (!extent_duplicable_p (extent))
5908     return 0;
5909
5910   if (!inside_undo &&
5911       !run_extent_paste_function (extent, new_start, new_end,
5912                                   closure->buffer))
5913     return 0;
5914   copy_extent (extent, new_start, new_end, closure->buffer);
5915
5916   return 0;
5917 }
5918
5919 /* We have just inserted a section of STRING (starting at POS, of
5920    length LENGTH) into buffer BUF at OPOINT.  Do whatever is necessary
5921    to get the string's extents into the buffer. */
5922
5923 void
5924 splice_in_string_extents (Lisp_Object string, struct buffer *buf,
5925                           Bytind opoint, Bytecount length, Bytecount pos)
5926 {
5927   struct splice_in_string_extents_arg closure;
5928   struct gcpro gcpro1, gcpro2;
5929   Lisp_Object buffer;
5930
5931   buffer = make_buffer (buf);
5932   closure.opoint = opoint;
5933   closure.pos = pos;
5934   closure.length = length;
5935   closure.buffer = buffer;
5936   GCPRO2 (buffer, string);
5937   map_extents_bytind (pos, pos + length,
5938                       splice_in_string_extents_mapper,
5939                       (void *) &closure, string, 0,
5940                       /* ignore extents that just abut the region */
5941                       ME_END_CLOSED | ME_ALL_EXTENTS_OPEN |
5942                       /* we are calling E-Lisp (the extent's copy function)
5943                          so anything might happen */
5944                       ME_MIGHT_CALL_ELISP);
5945   UNGCPRO;
5946 }
5947
5948 struct copy_string_extents_arg
5949 {
5950   Bytecount new_pos;
5951   Bytecount old_pos;
5952   Bytecount length;
5953   Lisp_Object new_string;
5954 };
5955
5956 struct copy_string_extents_1_arg
5957 {
5958   Lisp_Object parent_in_question;
5959   EXTENT found_extent;
5960 };
5961
5962 static int
5963 copy_string_extents_mapper (EXTENT extent, void *arg)
5964 {
5965   struct copy_string_extents_arg *closure =
5966     (struct copy_string_extents_arg *) arg;
5967   Bytecount old_start, old_end, new_start, new_end;
5968
5969   old_start = extent_endpoint_bytind (extent, 0);
5970   old_end   = extent_endpoint_bytind (extent, 1);
5971
5972   old_start = max (closure->old_pos, old_start);
5973   old_end   = min (closure->old_pos + closure->length, old_end);
5974
5975   if (old_start >= old_end)
5976     return 0;
5977
5978   new_start = old_start + closure->new_pos - closure->old_pos;
5979   new_end   = old_end   + closure->new_pos - closure->old_pos;
5980
5981   copy_extent (extent, new_start, new_end, closure->new_string);
5982   return 0;
5983 }
5984
5985 /* The string NEW_STRING was partially constructed from OLD_STRING.
5986    In particular, the section of length LEN starting at NEW_POS in
5987    NEW_STRING came from the section of the same length starting at
5988    OLD_POS in OLD_STRING.  Copy the extents as appropriate. */
5989
5990 void
5991 copy_string_extents (Lisp_Object new_string, Lisp_Object old_string,
5992                      Bytecount new_pos, Bytecount old_pos,
5993                      Bytecount length)
5994 {
5995   struct copy_string_extents_arg closure;
5996   struct gcpro gcpro1, gcpro2;
5997
5998   closure.new_pos = new_pos;
5999   closure.old_pos = old_pos;
6000   closure.new_string = new_string;
6001   closure.length = length;
6002   GCPRO2 (new_string, old_string);
6003   map_extents_bytind (old_pos, old_pos + length,
6004                       copy_string_extents_mapper,
6005                       (void *) &closure, old_string, 0,
6006                       /* ignore extents that just abut the region */
6007                       ME_END_CLOSED | ME_ALL_EXTENTS_OPEN |
6008                       /* we are calling E-Lisp (the extent's copy function)
6009                          so anything might happen */
6010                       ME_MIGHT_CALL_ELISP);
6011   UNGCPRO;
6012 }
6013
6014 /* Checklist for sanity checking:
6015    - {kill, yank, copy} at {open, closed} {start, end} of {writable, read-only} extent
6016    - {kill, copy} & yank {once, repeatedly} duplicable extent in {same, different} buffer
6017  */
6018
6019 \f
6020 /************************************************************************/
6021 /*                              text properties                         */
6022 /************************************************************************/
6023
6024 /* Text properties
6025    Originally this stuff was implemented in lisp (all of the functionality
6026    exists to make that possible) but speed was a problem.
6027  */
6028
6029 Lisp_Object Qtext_prop;
6030 Lisp_Object Qtext_prop_extent_paste_function;
6031
6032 static Lisp_Object
6033 get_text_property_bytind (Bytind position, Lisp_Object prop,
6034                           Lisp_Object object, enum extent_at_flag fl,
6035                           int text_props_only)
6036 {
6037   Lisp_Object extent;
6038
6039   /* text_props_only specifies whether we only consider text-property
6040      extents (those with the 'text-prop property set) or all extents. */
6041   if (!text_props_only)
6042     extent = extent_at_bytind (position, object, prop, 0, fl, 0);
6043   else
6044     {
6045       EXTENT prior = 0;
6046       while (1)
6047         {
6048           extent = extent_at_bytind (position, object, Qtext_prop, prior,
6049                                      fl, 0);
6050           if (NILP (extent))
6051             return Qnil;
6052           if (EQ (prop, Fextent_property (extent, Qtext_prop, Qnil)))
6053             break;
6054           prior = XEXTENT (extent);
6055         }
6056     }
6057
6058   if (!NILP (extent))
6059     return Fextent_property (extent, prop, Qnil);
6060   if (!NILP (Vdefault_text_properties))
6061     return Fplist_get (Vdefault_text_properties, prop, Qnil);
6062   return Qnil;
6063 }
6064
6065 static Lisp_Object
6066 get_text_property_1 (Lisp_Object pos, Lisp_Object prop, Lisp_Object object,
6067                      Lisp_Object at_flag, int text_props_only)
6068 {
6069   Bytind position;
6070   int invert = 0;
6071
6072   object = decode_buffer_or_string (object);
6073   position = get_buffer_or_string_pos_byte (object, pos, GB_NO_ERROR_IF_BAD);
6074
6075   /* We canonicalize the start/end-open/closed properties to the
6076      non-default version -- "adding" the default property really
6077      needs to remove the non-default one.  See below for more
6078      on this. */
6079   if (EQ (prop, Qstart_closed))
6080     {
6081       prop = Qstart_open;
6082       invert = 1;
6083     }
6084
6085   if (EQ (prop, Qend_open))
6086     {
6087       prop = Qend_closed;
6088       invert = 1;
6089     }
6090
6091   {
6092     Lisp_Object val =
6093       get_text_property_bytind (position, prop, object,
6094                                 decode_extent_at_flag (at_flag),
6095                                 text_props_only);
6096     if (invert)
6097       val = NILP (val) ? Qt : Qnil;
6098     return val;
6099   }
6100 }
6101
6102 DEFUN ("get-text-property", Fget_text_property, 2, 4, 0, /*
6103 Return the value of the PROP property at the given position.
6104 Optional arg OBJECT specifies the buffer or string to look in, and
6105  defaults to the current buffer.
6106 Optional arg AT-FLAG controls what it means for a property to be "at"
6107  a position, and has the same meaning as in `extent-at'.
6108 This examines only those properties added with `put-text-property'.
6109 See also `get-char-property'.
6110 */
6111        (pos, prop, object, at_flag))
6112 {
6113   return get_text_property_1 (pos, prop, object, at_flag, 1);
6114 }
6115
6116 DEFUN ("get-char-property", Fget_char_property, 2, 4, 0, /*
6117 Return the value of the PROP property at the given position.
6118 Optional arg OBJECT specifies the buffer or string to look in, and
6119  defaults to the current buffer.
6120 Optional arg AT-FLAG controls what it means for a property to be "at"
6121  a position, and has the same meaning as in `extent-at'.
6122 This examines properties on all extents.
6123 See also `get-text-property'.
6124 */
6125        (pos, prop, object, at_flag))
6126 {
6127   return get_text_property_1 (pos, prop, object, at_flag, 0);
6128 }
6129
6130 /* About start/end-open/closed:
6131
6132    These properties have to be handled specially because of their
6133    strange behavior.  If I put the "start-open" property on a region,
6134    then *all* text-property extents in the region have to have their
6135    start be open.  This is unlike all other properties, which don't
6136    affect the extents of text properties other than their own.
6137
6138    So:
6139
6140    1) We have to map start-closed to (not start-open) and end-open
6141       to (not end-closed) -- i.e. adding the default is really the
6142       same as remove the non-default property.  It won't work, for
6143       example, to have both "start-open" and "start-closed" on
6144       the same region.
6145    2) Whenever we add one of these properties, we go through all
6146       text-property extents in the region and set the appropriate
6147       open/closedness on them.
6148    3) Whenever we change a text-property extent for a property,
6149       we have to make sure we set the open/closedness properly.
6150
6151       (2) and (3) together rely on, and maintain, the invariant
6152       that the open/closedness of text-property extents is correct
6153       at the beginning and end of each operation.
6154    */
6155
6156 struct put_text_prop_arg
6157 {
6158   Lisp_Object prop, value;      /* The property and value we are storing */
6159   Bytind start, end;    /* The region into which we are storing it */
6160   Lisp_Object object;
6161   Lisp_Object the_extent;       /* Our chosen extent; this is used for
6162                                    communication between subsequent passes. */
6163   int changed_p;                /* Output: whether we have modified anything */
6164 };
6165
6166 static int
6167 put_text_prop_mapper (EXTENT e, void *arg)
6168 {
6169   struct put_text_prop_arg *closure = (struct put_text_prop_arg *) arg;
6170
6171   Lisp_Object object = closure->object;
6172   Lisp_Object value = closure->value;
6173   Bytind e_start, e_end;
6174   Bytind start = closure->start;
6175   Bytind end   = closure->end;
6176   Lisp_Object extent, e_val;
6177   int is_eq;
6178
6179   XSETEXTENT (extent, e);
6180
6181   /* Note: in some cases when the property itself is 'start-open
6182      or 'end-closed, the checks to set the openness may do a bit
6183      of extra work; but it won't hurt because we then fix up the
6184      openness later on in put_text_prop_openness_mapper(). */
6185   if (!EQ (Fextent_property (extent, Qtext_prop, Qnil), closure->prop))
6186     /* It's not for this property; do nothing. */
6187     return 0;
6188
6189   e_start = extent_endpoint_bytind (e, 0);
6190   e_end   = extent_endpoint_bytind (e, 1);
6191   e_val = Fextent_property (extent, closure->prop, Qnil);
6192   is_eq = EQ (value, e_val);
6193
6194   if (!NILP (value) && NILP (closure->the_extent) && is_eq)
6195     {
6196       /* We want there to be an extent here at the end, and we haven't picked
6197          one yet, so use this one.  Extend it as necessary.  We only reuse an
6198          extent which has an EQ value for the prop in question to avoid
6199          side-effecting the kill ring (that is, we never change the property
6200          on an extent after it has been created.)
6201        */
6202       if (e_start != start || e_end != end)
6203         {
6204           Bytind new_start = min (e_start, start);
6205           Bytind new_end = max (e_end, end);
6206           set_extent_endpoints (e, new_start, new_end, Qnil);
6207           /* If we changed the endpoint, then we need to set its
6208              openness. */
6209           set_extent_openness (e, new_start != e_start
6210                                ? !NILP (get_text_property_bytind
6211                                         (start, Qstart_open, object,
6212                                          EXTENT_AT_AFTER, 1)) : -1,
6213                                new_end != e_end
6214                                ? NILP (get_text_property_bytind
6215                                        (end - 1, Qend_closed, object,
6216                                         EXTENT_AT_AFTER, 1))
6217                                : -1);
6218           closure->changed_p = 1;
6219         }
6220       closure->the_extent = extent;
6221     }
6222
6223   /* Even if we're adding a prop, at this point, we want all other extents of
6224      this prop to go away (as now they overlap).  So the theory here is that,
6225      when we are adding a prop to a region that has multiple (disjoint)
6226      occurrences of that prop in it already, we pick one of those and extend
6227      it, and remove the others.
6228    */
6229
6230   else if (EQ (extent, closure->the_extent))
6231     {
6232       /* just in case map-extents hits it again (does that happen?) */
6233       ;
6234     }
6235   else if (e_start >= start && e_end <= end)
6236     {
6237       /* Extent is contained in region; remove it.  Don't destroy or modify
6238          it, because we don't want to change the attributes pointed to by the
6239          duplicates in the kill ring.
6240        */
6241       extent_detach (e);
6242       closure->changed_p = 1;
6243     }
6244   else if (!NILP (closure->the_extent) &&
6245            is_eq &&
6246            e_start <= end &&
6247            e_end >= start)
6248     {
6249       EXTENT te = XEXTENT (closure->the_extent);
6250       /* This extent overlaps, and has the same prop/value as the extent we've
6251          decided to reuse, so we can remove this existing extent as well (the
6252          whole thing, even the part outside of the region) and extend
6253          the-extent to cover it, resulting in the minimum number of extents in
6254          the buffer.
6255        */
6256       Bytind the_start = extent_endpoint_bytind (te, 0);
6257       Bytind the_end = extent_endpoint_bytind (te, 1);
6258       if (e_start != the_start &&  /* note AND not OR -- hmm, why is this
6259                                       the case? I think it's because the
6260                                       assumption that the text-property
6261                                       extents don't overlap makes it
6262                                       OK; changing it to an OR would
6263                                       result in changed_p sometimes getting
6264                                       falsely marked.  Is this bad? */
6265           e_end   != the_end)
6266         {
6267           Bytind new_start = min (e_start, the_start);
6268           Bytind new_end = max (e_end, the_end);
6269           set_extent_endpoints (te, new_start, new_end, Qnil);
6270           /* If we changed the endpoint, then we need to set its
6271              openness.  We are setting the endpoint to be the same as
6272              that of the extent we're about to remove, and we assume
6273              (the invariant mentioned above) that extent has the
6274              proper endpoint setting, so we just use it. */
6275           set_extent_openness (te, new_start != e_start ?
6276                                (int) extent_start_open_p (e) : -1,
6277                                new_end != e_end ?
6278                                (int) extent_end_open_p (e) : -1);
6279           closure->changed_p = 1;
6280         }
6281       extent_detach (e);
6282     }
6283   else if (e_end <= end)
6284     {
6285       /* Extent begins before start but ends before end, so we can just
6286          decrease its end position.
6287        */
6288       if (e_end != start)
6289         {
6290           set_extent_endpoints (e, e_start, start, Qnil);
6291           set_extent_openness (e, -1, NILP (get_text_property_bytind
6292                                        (start - 1, Qend_closed, object,
6293                                         EXTENT_AT_AFTER, 1)));
6294           closure->changed_p = 1;
6295         }
6296     }
6297   else if (e_start >= start)
6298     {
6299       /* Extent ends after end but begins after start, so we can just
6300          increase its start position.
6301        */
6302       if (e_start != end)
6303         {
6304           set_extent_endpoints (e, end, e_end, Qnil);
6305           set_extent_openness (e, !NILP (get_text_property_bytind
6306                                         (end, Qstart_open, object,
6307                                          EXTENT_AT_AFTER, 1)), -1);
6308           closure->changed_p = 1;
6309         }
6310     }
6311   else
6312     {
6313       /* Otherwise, `extent' straddles the region.  We need to split it.
6314        */
6315       set_extent_endpoints (e, e_start, start, Qnil);
6316       set_extent_openness (e, -1, NILP (get_text_property_bytind
6317                                         (start - 1, Qend_closed, object,
6318                                          EXTENT_AT_AFTER, 1)));
6319       set_extent_openness (copy_extent (e, end, e_end, extent_object (e)),
6320                            !NILP (get_text_property_bytind
6321                                   (end, Qstart_open, object,
6322                                    EXTENT_AT_AFTER, 1)), -1);
6323       closure->changed_p = 1;
6324     }
6325
6326   return 0;  /* to continue mapping. */
6327 }
6328
6329 static int
6330 put_text_prop_openness_mapper (EXTENT e, void *arg)
6331 {
6332   struct put_text_prop_arg *closure = (struct put_text_prop_arg *) arg;
6333   Bytind e_start, e_end;
6334   Bytind start = closure->start;
6335   Bytind end   = closure->end;
6336   Lisp_Object extent;
6337   XSETEXTENT (extent, e);
6338   e_start = extent_endpoint_bytind (e, 0);
6339   e_end   = extent_endpoint_bytind (e, 1);
6340
6341   if (NILP (Fextent_property (extent, Qtext_prop, Qnil)))
6342     {
6343       /* It's not a text-property extent; do nothing. */
6344       ;
6345     }
6346   /* Note end conditions and NILP/!NILP's carefully. */
6347   else if (EQ (closure->prop, Qstart_open)
6348            && e_start >= start && e_start < end)
6349     set_extent_openness (e, !NILP (closure->value), -1);
6350   else if (EQ (closure->prop, Qend_closed)
6351            && e_end > start && e_end <= end)
6352     set_extent_openness (e, -1, NILP (closure->value));
6353
6354   return 0;  /* to continue mapping. */
6355 }
6356
6357 static int
6358 put_text_prop (Bytind start, Bytind end, Lisp_Object object,
6359                Lisp_Object prop, Lisp_Object value,
6360                int duplicable_p)
6361 {
6362   /* This function can GC */
6363   struct put_text_prop_arg closure;
6364
6365   if (start == end)   /* There are no characters in the region. */
6366     return 0;
6367
6368   /* convert to the non-default versions, since a nil property is
6369      the same as it not being present. */
6370   if (EQ (prop, Qstart_closed))
6371     {
6372       prop = Qstart_open;
6373       value = NILP (value) ? Qt : Qnil;
6374     }
6375   else if (EQ (prop, Qend_open))
6376     {
6377       prop = Qend_closed;
6378       value = NILP (value) ? Qt : Qnil;
6379     }
6380
6381   value = canonicalize_extent_property (prop, value);
6382
6383   closure.prop = prop;
6384   closure.value = value;
6385   closure.start = start;
6386   closure.end = end;
6387   closure.object = object;
6388   closure.changed_p = 0;
6389   closure.the_extent = Qnil;
6390
6391   map_extents_bytind (start, end,
6392                       put_text_prop_mapper,
6393                       (void *) &closure, object, 0,
6394                       /* get all extents that abut the region */
6395                       ME_ALL_EXTENTS_CLOSED | ME_END_CLOSED |
6396                       /* it might QUIT or error if the user has
6397                          fucked with the extent plist. */
6398                       /* #### dmoore - I think this should include
6399                          ME_MIGHT_MOVE_SOE, since the callback function
6400                          might recurse back into map_extents_bytind. */
6401                       ME_MIGHT_THROW |
6402                       ME_MIGHT_MODIFY_EXTENTS);
6403
6404   /* If we made it through the loop without reusing an extent
6405      (and we want there to be one) make it now.
6406    */
6407   if (!NILP (value) && NILP (closure.the_extent))
6408     {
6409       Lisp_Object extent;
6410
6411       XSETEXTENT (extent, make_extent_internal (object, start, end));
6412       closure.changed_p = 1;
6413       Fset_extent_property (extent, Qtext_prop, prop);
6414       Fset_extent_property (extent, prop, value);
6415       if (duplicable_p)
6416         {
6417           extent_duplicable_p (XEXTENT (extent)) = 1;
6418           Fset_extent_property (extent, Qpaste_function,
6419                                 Qtext_prop_extent_paste_function);
6420         }
6421       set_extent_openness (XEXTENT (extent),
6422                            !NILP (get_text_property_bytind
6423                                   (start, Qstart_open, object,
6424                                    EXTENT_AT_AFTER, 1)),
6425                            NILP (get_text_property_bytind
6426                                  (end - 1, Qend_closed, object,
6427                                   EXTENT_AT_AFTER, 1)));
6428     }
6429
6430   if (EQ (prop, Qstart_open) || EQ (prop, Qend_closed))
6431     {
6432       map_extents_bytind (start, end,
6433                           put_text_prop_openness_mapper,
6434                           (void *) &closure, object, 0,
6435                           /* get all extents that abut the region */
6436                           ME_ALL_EXTENTS_CLOSED | ME_END_CLOSED |
6437                           ME_MIGHT_MODIFY_EXTENTS);
6438     }
6439
6440   return closure.changed_p;
6441 }
6442
6443 DEFUN ("put-text-property", Fput_text_property, 4, 5, 0, /*
6444 Adds the given property/value to all characters in the specified region.
6445 The property is conceptually attached to the characters rather than the
6446 region.  The properties are copied when the characters are copied/pasted.
6447 Fifth argument OBJECT is the buffer or string containing the text, and
6448 defaults to the current buffer.
6449 */
6450        (start, end, prop, value, object))
6451 {
6452   /* This function can GC */
6453   Bytind s, e;
6454
6455   object = decode_buffer_or_string (object);
6456   get_buffer_or_string_range_byte (object, start, end, &s, &e, 0);
6457   put_text_prop (s, e, object, prop, value, 1);
6458   return prop;
6459 }
6460
6461 DEFUN ("put-nonduplicable-text-property", Fput_nonduplicable_text_property,
6462        4, 5, 0, /*
6463 Adds the given property/value to all characters in the specified region.
6464 The property is conceptually attached to the characters rather than the
6465 region, however the properties will not be copied when the characters
6466 are copied.
6467 Fifth argument OBJECT is the buffer or string containing the text, and
6468 defaults to the current buffer.
6469 */
6470        (start, end, prop, value, object))
6471 {
6472   /* This function can GC */
6473   Bytind s, e;
6474
6475   object = decode_buffer_or_string (object);
6476   get_buffer_or_string_range_byte (object, start, end, &s, &e, 0);
6477   put_text_prop (s, e, object, prop, value, 0);
6478   return prop;
6479 }
6480
6481 DEFUN ("add-text-properties", Fadd_text_properties, 3, 4, 0, /*
6482 Add properties to the characters from START to END.
6483 The third argument PROPS is a property list specifying the property values
6484 to add.  The optional fourth argument, OBJECT, is the buffer or string
6485 containing the text and defaults to the current buffer.  Returns t if
6486 any property was changed, nil otherwise.
6487 */
6488        (start, end, props, object))
6489 {
6490   /* This function can GC */
6491   int changed = 0;
6492   Bytind s, e;
6493
6494   object = decode_buffer_or_string (object);
6495   get_buffer_or_string_range_byte (object, start, end, &s, &e, 0);
6496   CHECK_LIST (props);
6497   for (; !NILP (props); props = Fcdr (Fcdr (props)))
6498     {
6499       Lisp_Object prop = XCAR (props);
6500       Lisp_Object value = Fcar (XCDR (props));
6501       changed |= put_text_prop (s, e, object, prop, value, 1);
6502     }
6503   return changed ? Qt : Qnil;
6504 }
6505
6506
6507 DEFUN ("add-nonduplicable-text-properties", Fadd_nonduplicable_text_properties,
6508        3, 4, 0, /*
6509 Add nonduplicable properties to the characters from START to END.
6510 \(The properties will not be copied when the characters are copied.)
6511 The third argument PROPS is a property list specifying the property values
6512 to add.  The optional fourth argument, OBJECT, is the buffer or string
6513 containing the text and defaults to the current buffer.  Returns t if
6514 any property was changed, nil otherwise.
6515 */
6516        (start, end, props, object))
6517 {
6518   /* This function can GC */
6519   int changed = 0;
6520   Bytind s, e;
6521
6522   object = decode_buffer_or_string (object);
6523   get_buffer_or_string_range_byte (object, start, end, &s, &e, 0);
6524   CHECK_LIST (props);
6525   for (; !NILP (props); props = Fcdr (Fcdr (props)))
6526     {
6527       Lisp_Object prop = XCAR (props);
6528       Lisp_Object value = Fcar (XCDR (props));
6529       changed |= put_text_prop (s, e, object, prop, value, 0);
6530     }
6531   return changed ? Qt : Qnil;
6532 }
6533
6534 DEFUN ("remove-text-properties", Fremove_text_properties, 3, 4, 0, /*
6535 Remove the given properties from all characters in the specified region.
6536 PROPS should be a plist, but the values in that plist are ignored (treated
6537 as nil).  Returns t if any property was changed, nil otherwise.
6538 Fourth argument OBJECT is the buffer or string containing the text, and
6539 defaults to the current buffer.
6540 */
6541        (start, end, props, object))
6542 {
6543   /* This function can GC */
6544   int changed = 0;
6545   Bytind s, e;
6546
6547   object = decode_buffer_or_string (object);
6548   get_buffer_or_string_range_byte (object, start, end, &s, &e, 0);
6549   CHECK_LIST (props);
6550   for (; !NILP (props); props = Fcdr (Fcdr (props)))
6551     {
6552       Lisp_Object prop = XCAR (props);
6553       changed |= put_text_prop (s, e, object, prop, Qnil, 1);
6554     }
6555   return changed ? Qt : Qnil;
6556 }
6557
6558 /* Whenever a text-prop extent is pasted into a buffer (via `yank' or `insert'
6559    or whatever) we attach the properties to the buffer by calling
6560    `put-text-property' instead of by simply allowing the extent to be copied or
6561    re-attached.  Then we return nil, telling the extents code not to attach it
6562    again.  By handing the insertion hackery in this way, we make kill/yank
6563    behave consistently with put-text-property and not fragment the extents
6564    (since text-prop extents must partition, not overlap).
6565
6566    The lisp implementation of this was probably fast enough, but since I moved
6567    the rest of the put-text-prop code here, I moved this as well for
6568    completeness.
6569  */
6570 DEFUN ("text-prop-extent-paste-function", Ftext_prop_extent_paste_function,
6571        3, 3, 0, /*
6572 Used as the `paste-function' property of `text-prop' extents.
6573 */
6574        (extent, from, to))
6575 {
6576   /* This function can GC */
6577   Lisp_Object prop, val;
6578
6579   prop = Fextent_property (extent, Qtext_prop, Qnil);
6580   if (NILP (prop))
6581     signal_type_error (Qinternal_error,
6582                        "Internal error: no text-prop", extent);
6583   val = Fextent_property (extent, prop, Qnil);
6584 #if 0
6585   /* removed by bill perry, 2/9/97
6586   ** This little bit of code would not allow you to have a text property
6587   ** with a value of Qnil.  This is bad bad bad.
6588   */
6589   if (NILP (val))
6590     signal_type_error_2 (Qinternal_error,
6591                          "Internal error: no text-prop",
6592                          extent, prop);
6593 #endif
6594   Fput_text_property (from, to, prop, val, Qnil);
6595   return Qnil; /* important! */
6596 }
6597
6598 /* This function could easily be written in Lisp but the C code wants
6599    to use it in connection with invisible extents (at least currently).
6600    If this changes, consider moving this back into Lisp. */
6601
6602 DEFUN ("next-single-property-change", Fnext_single_property_change,
6603        2, 4, 0, /*
6604 Return the position of next property change for a specific property.
6605 Scans characters forward from POS till it finds a change in the PROP
6606  property, then returns the position of the change.  The optional third
6607  argument OBJECT is the buffer or string to scan (defaults to the current
6608  buffer).
6609 The property values are compared with `eq'.
6610 Return nil if the property is constant all the way to the end of OBJECT.
6611 If the value is non-nil, it is a position greater than POS, never equal.
6612
6613 If the optional fourth argument LIMIT is non-nil, don't search
6614  past position LIMIT; return LIMIT if nothing is found before LIMIT.
6615 If two or more extents with conflicting non-nil values for PROP overlap
6616  a particular character, it is undefined which value is considered to be
6617  the value of PROP. (Note that this situation will not happen if you always
6618  use the text-property primitives.)
6619 */
6620        (pos, prop, object, limit))
6621 {
6622   Bufpos bpos;
6623   Bufpos blim;
6624   Lisp_Object extent, value;
6625   int limit_was_nil;
6626
6627   object = decode_buffer_or_string (object);
6628   bpos = get_buffer_or_string_pos_char (object, pos, 0);
6629   if (NILP (limit))
6630     {
6631       blim = buffer_or_string_accessible_end_char (object);
6632       limit_was_nil = 1;
6633     }
6634   else
6635     {
6636       blim = get_buffer_or_string_pos_char (object, limit, 0);
6637       limit_was_nil = 0;
6638     }
6639
6640   extent = Fextent_at (make_int (bpos), object, prop, Qnil, Qnil);
6641   if (!NILP (extent))
6642     value = Fextent_property (extent, prop, Qnil);
6643   else
6644     value = Qnil;
6645
6646   while (1)
6647     {
6648       bpos = XINT (Fnext_extent_change (make_int (bpos), object));
6649       if (bpos >= blim)
6650         break; /* property is the same all the way to the end */
6651       extent = Fextent_at (make_int (bpos), object, prop, Qnil, Qnil);
6652       if ((NILP (extent) && !NILP (value)) ||
6653           (!NILP (extent) && !EQ (value,
6654                                   Fextent_property (extent, prop, Qnil))))
6655         return make_int (bpos);
6656     }
6657
6658   /* I think it's more sensible for this function to return nil always
6659      in this situation and it used to do it this way, but it's been changed
6660      for FSF compatibility. */
6661   if (limit_was_nil)
6662     return Qnil;
6663   else
6664     return make_int (blim);
6665 }
6666
6667 /* See comment on previous function about why this is written in C. */
6668
6669 DEFUN ("previous-single-property-change", Fprevious_single_property_change,
6670        2, 4, 0, /*
6671 Return the position of next property change for a specific property.
6672 Scans characters backward from POS till it finds a change in the PROP
6673  property, then returns the position of the change.  The optional third
6674  argument OBJECT is the buffer or string to scan (defaults to the current
6675  buffer).
6676 The property values are compared with `eq'.
6677 Return nil if the property is constant all the way to the start of OBJECT.
6678 If the value is non-nil, it is a position less than POS, never equal.
6679
6680 If the optional fourth argument LIMIT is non-nil, don't search back
6681  past position LIMIT; return LIMIT if nothing is found until LIMIT.
6682 If two or more extents with conflicting non-nil values for PROP overlap
6683  a particular character, it is undefined which value is considered to be
6684  the value of PROP. (Note that this situation will not happen if you always
6685  use the text-property primitives.)
6686 */
6687        (pos, prop, object, limit))
6688 {
6689   Bufpos bpos;
6690   Bufpos blim;
6691   Lisp_Object extent, value;
6692   int limit_was_nil;
6693
6694   object = decode_buffer_or_string (object);
6695   bpos = get_buffer_or_string_pos_char (object, pos, 0);
6696   if (NILP (limit))
6697     {
6698       blim = buffer_or_string_accessible_begin_char (object);
6699       limit_was_nil = 1;
6700     }
6701   else
6702     {
6703       blim = get_buffer_or_string_pos_char (object, limit, 0);
6704       limit_was_nil = 0;
6705     }
6706
6707   /* extent-at refers to the character AFTER bpos, but we want the
6708      character before bpos.  Thus the - 1.  extent-at simply
6709      returns nil on bogus positions, so not to worry. */
6710   extent = Fextent_at (make_int (bpos - 1), object, prop, Qnil, Qnil);
6711   if (!NILP (extent))
6712     value = Fextent_property (extent, prop, Qnil);
6713   else
6714     value = Qnil;
6715
6716   while (1)
6717     {
6718       bpos = XINT (Fprevious_extent_change (make_int (bpos), object));
6719       if (bpos <= blim)
6720         break; /* property is the same all the way to the beginning */
6721       extent = Fextent_at (make_int (bpos - 1), object, prop, Qnil, Qnil);
6722       if ((NILP (extent) && !NILP (value)) ||
6723           (!NILP (extent) && !EQ (value,
6724                                   Fextent_property (extent, prop, Qnil))))
6725         return make_int (bpos);
6726     }
6727
6728   /* I think it's more sensible for this function to return nil always
6729      in this situation and it used to do it this way, but it's been changed
6730      for FSF compatibility. */
6731   if (limit_was_nil)
6732     return Qnil;
6733   else
6734     return make_int (blim);
6735 }
6736
6737 #ifdef MEMORY_USAGE_STATS
6738
6739 int
6740 compute_buffer_extent_usage (struct buffer *b, struct overhead_stats *ovstats)
6741 {
6742   /* #### not yet written */
6743   return 0;
6744 }
6745
6746 #endif /* MEMORY_USAGE_STATS */
6747
6748 \f
6749 /************************************************************************/
6750 /*                              initialization                          */
6751 /************************************************************************/
6752
6753 void
6754 syms_of_extents (void)
6755 {
6756   INIT_LRECORD_IMPLEMENTATION (extent);
6757   INIT_LRECORD_IMPLEMENTATION (extent_info);
6758   INIT_LRECORD_IMPLEMENTATION (extent_auxiliary);
6759
6760   defsymbol (&Qextentp, "extentp");
6761   defsymbol (&Qextent_live_p, "extent-live-p");
6762
6763   defsymbol (&Qall_extents_closed, "all-extents-closed");
6764   defsymbol (&Qall_extents_open, "all-extents-open");
6765   defsymbol (&Qall_extents_closed_open, "all-extents-closed-open");
6766   defsymbol (&Qall_extents_open_closed, "all-extents-open-closed");
6767   defsymbol (&Qstart_in_region, "start-in-region");
6768   defsymbol (&Qend_in_region, "end-in-region");
6769   defsymbol (&Qstart_and_end_in_region, "start-and-end-in-region");
6770   defsymbol (&Qstart_or_end_in_region, "start-or-end-in-region");
6771   defsymbol (&Qnegate_in_region, "negate-in-region");
6772
6773   defsymbol (&Qdetached, "detached");
6774   defsymbol (&Qdestroyed, "destroyed");
6775   defsymbol (&Qbegin_glyph, "begin-glyph");
6776   defsymbol (&Qend_glyph, "end-glyph");
6777   defsymbol (&Qstart_open, "start-open");
6778   defsymbol (&Qend_open, "end-open");
6779   defsymbol (&Qstart_closed, "start-closed");
6780   defsymbol (&Qend_closed, "end-closed");
6781   defsymbol (&Qread_only, "read-only");
6782   /* defsymbol (&Qhighlight, "highlight"); in faces.c */
6783   defsymbol (&Qunique, "unique");
6784   defsymbol (&Qduplicable, "duplicable");
6785   defsymbol (&Qdetachable, "detachable");
6786   defsymbol (&Qpriority, "priority");
6787   defsymbol (&Qmouse_face, "mouse-face");
6788   defsymbol (&Qinitial_redisplay_function,"initial-redisplay-function");
6789
6790
6791   defsymbol (&Qglyph_layout, "glyph-layout");   /* backwards compatibility */
6792   defsymbol (&Qbegin_glyph_layout, "begin-glyph-layout");
6793   defsymbol (&Qend_glyph_layout, "end-glyph-layout");
6794   defsymbol (&Qoutside_margin, "outside-margin");
6795   defsymbol (&Qinside_margin, "inside-margin");
6796   defsymbol (&Qwhitespace, "whitespace");
6797   /* Qtext defined in general.c */
6798
6799   defsymbol (&Qpaste_function, "paste-function");
6800   defsymbol (&Qcopy_function,  "copy-function");
6801
6802   defsymbol (&Qtext_prop, "text-prop");
6803   defsymbol (&Qtext_prop_extent_paste_function,
6804              "text-prop-extent-paste-function");
6805
6806   DEFSUBR (Fextentp);
6807   DEFSUBR (Fextent_live_p);
6808   DEFSUBR (Fextent_detached_p);
6809   DEFSUBR (Fextent_start_position);
6810   DEFSUBR (Fextent_end_position);
6811   DEFSUBR (Fextent_object);
6812   DEFSUBR (Fextent_length);
6813
6814   DEFSUBR (Fmake_extent);
6815   DEFSUBR (Fcopy_extent);
6816   DEFSUBR (Fdelete_extent);
6817   DEFSUBR (Fdetach_extent);
6818   DEFSUBR (Fset_extent_endpoints);
6819   DEFSUBR (Fnext_extent);
6820   DEFSUBR (Fprevious_extent);
6821 #if DEBUG_XEMACS
6822   DEFSUBR (Fnext_e_extent);
6823   DEFSUBR (Fprevious_e_extent);
6824 #endif
6825   DEFSUBR (Fnext_extent_change);
6826   DEFSUBR (Fprevious_extent_change);
6827
6828   DEFSUBR (Fextent_parent);
6829   DEFSUBR (Fextent_children);
6830   DEFSUBR (Fset_extent_parent);
6831
6832   DEFSUBR (Fextent_in_region_p);
6833   DEFSUBR (Fmap_extents);
6834   DEFSUBR (Fmap_extent_children);
6835   DEFSUBR (Fextent_at);
6836   DEFSUBR (Fextents_at);
6837
6838   DEFSUBR (Fset_extent_initial_redisplay_function);
6839   DEFSUBR (Fextent_face);
6840   DEFSUBR (Fset_extent_face);
6841   DEFSUBR (Fextent_mouse_face);
6842   DEFSUBR (Fset_extent_mouse_face);
6843   DEFSUBR (Fset_extent_begin_glyph);
6844   DEFSUBR (Fset_extent_end_glyph);
6845   DEFSUBR (Fextent_begin_glyph);
6846   DEFSUBR (Fextent_end_glyph);
6847   DEFSUBR (Fset_extent_begin_glyph_layout);
6848   DEFSUBR (Fset_extent_end_glyph_layout);
6849   DEFSUBR (Fextent_begin_glyph_layout);
6850   DEFSUBR (Fextent_end_glyph_layout);
6851   DEFSUBR (Fset_extent_priority);
6852   DEFSUBR (Fextent_priority);
6853   DEFSUBR (Fset_extent_property);
6854   DEFSUBR (Fset_extent_properties);
6855   DEFSUBR (Fextent_property);
6856   DEFSUBR (Fextent_properties);
6857
6858   DEFSUBR (Fhighlight_extent);
6859   DEFSUBR (Fforce_highlight_extent);
6860
6861   DEFSUBR (Finsert_extent);
6862
6863   DEFSUBR (Fget_text_property);
6864   DEFSUBR (Fget_char_property);
6865   DEFSUBR (Fput_text_property);
6866   DEFSUBR (Fput_nonduplicable_text_property);
6867   DEFSUBR (Fadd_text_properties);
6868   DEFSUBR (Fadd_nonduplicable_text_properties);
6869   DEFSUBR (Fremove_text_properties);
6870   DEFSUBR (Ftext_prop_extent_paste_function);
6871   DEFSUBR (Fnext_single_property_change);
6872   DEFSUBR (Fprevious_single_property_change);
6873 }
6874
6875 void
6876 reinit_vars_of_extents (void)
6877 {
6878   extent_auxiliary_defaults.begin_glyph = Qnil;
6879   extent_auxiliary_defaults.end_glyph = Qnil;
6880   extent_auxiliary_defaults.parent = Qnil;
6881   extent_auxiliary_defaults.children = Qnil;
6882   extent_auxiliary_defaults.priority = 0;
6883   extent_auxiliary_defaults.invisible = Qnil;
6884   extent_auxiliary_defaults.read_only = Qnil;
6885   extent_auxiliary_defaults.mouse_face = Qnil;
6886   extent_auxiliary_defaults.initial_redisplay_function = Qnil;
6887   extent_auxiliary_defaults.before_change_functions = Qnil;
6888   extent_auxiliary_defaults.after_change_functions = Qnil;
6889 }
6890
6891 void
6892 vars_of_extents (void)
6893 {
6894   reinit_vars_of_extents ();
6895
6896   DEFVAR_INT ("mouse-highlight-priority", &mouse_highlight_priority /*
6897 The priority to use for the mouse-highlighting pseudo-extent
6898 that is used to highlight extents with the `mouse-face' attribute set.
6899 See `set-extent-priority'.
6900 */ );
6901   /* Set mouse-highlight-priority (which ends up being used both for the
6902      mouse-highlighting pseudo-extent and the primary selection extent)
6903      to a very high value because very few extents should override it.
6904      1000 gives lots of room below it for different-prioritized extents.
6905      10 doesn't. ediff, for example, likes to use priorities around 100.
6906      --ben */
6907   mouse_highlight_priority = /* 10 */ 1000;
6908
6909   DEFVAR_LISP ("default-text-properties", &Vdefault_text_properties /*
6910 Property list giving default values for text properties.
6911 Whenever a character does not specify a value for a property, the value
6912 stored in this list is used instead.  This only applies when the
6913 functions `get-text-property' or `get-char-property' are called.
6914 */ );
6915   Vdefault_text_properties = Qnil;
6916
6917   staticpro (&Vlast_highlighted_extent);
6918   Vlast_highlighted_extent = Qnil;
6919
6920   Vextent_face_reusable_list = Fcons (Qnil, Qnil);
6921   staticpro (&Vextent_face_reusable_list);
6922 }
6923
6924 void
6925 complex_vars_of_extents (void)
6926 {
6927   staticpro (&Vextent_face_memoize_hash_table);
6928   /* The memoize hash table maps from lists of symbols to lists of
6929      faces.  It needs to be `equal' to implement the memoization.
6930      The reverse table maps in the other direction and just needs
6931      to do `eq' comparison because the lists of faces are already
6932      memoized. */
6933   Vextent_face_memoize_hash_table =
6934     make_lisp_hash_table (100, HASH_TABLE_VALUE_WEAK, HASH_TABLE_EQUAL);
6935   staticpro (&Vextent_face_reverse_memoize_hash_table);
6936   Vextent_face_reverse_memoize_hash_table =
6937     make_lisp_hash_table (100, HASH_TABLE_KEY_WEAK, HASH_TABLE_EQ);
6938 }