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