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