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