comparison src/extents.c @ 442:abe6d1db359e r21-2-36

Import from CVS: tag r21-2-36
author cvs
date Mon, 13 Aug 2007 11:35:02 +0200
parents 8de8e3f6228a
children 576fb035e263
comparison
equal deleted inserted replaced
441:72a7cfa4a488 442:abe6d1db359e
1 /* Copyright (c) 1994, 1995 Free Software Foundation, Inc. 1 /* Copyright (c) 1994, 1995 Free Software Foundation, Inc.
2 Copyright (c) 1995 Sun Microsystems, Inc. 2 Copyright (c) 1995 Sun Microsystems, Inc.
3 Copyright (c) 1995, 1996 Ben Wing. 3 Copyright (c) 1995, 1996, 2000 Ben Wing.
4 4
5 This file is part of XEmacs. 5 This file is part of XEmacs.
6 6
7 XEmacs is free software; you can redistribute it and/or modify it 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 8 under the terms of the GNU General Public License as published by the
225 #include "insdel.h" 225 #include "insdel.h"
226 #include "keymap.h" 226 #include "keymap.h"
227 #include "opaque.h" 227 #include "opaque.h"
228 #include "process.h" 228 #include "process.h"
229 #include "redisplay.h" 229 #include "redisplay.h"
230 #include "gutter.h"
230 231
231 /* ------------------------------- */ 232 /* ------------------------------- */
232 /* gap array */ 233 /* gap array */
233 /* ------------------------------- */ 234 /* ------------------------------- */
234 235
459 Lisp_Object Vextent_face_reverse_memoize_hash_table; 460 Lisp_Object Vextent_face_reverse_memoize_hash_table;
460 Lisp_Object Vextent_face_reusable_list; 461 Lisp_Object Vextent_face_reusable_list;
461 /* FSFmacs bogosity */ 462 /* FSFmacs bogosity */
462 Lisp_Object Vdefault_text_properties; 463 Lisp_Object Vdefault_text_properties;
463 464
464
465 EXFUN (Fextent_properties, 1); 465 EXFUN (Fextent_properties, 1);
466 EXFUN (Fset_extent_property, 3); 466 EXFUN (Fset_extent_property, 3);
467
468 /* if true, we don't want to set any redisplay flags on modeline extent
469 changes */
470 int in_modeline_generation;
467 471
468 472
469 /************************************************************************/ 473 /************************************************************************/
470 /* Generalized gap array */ 474 /* Generalized gap array */
471 /************************************************************************/ 475 /************************************************************************/
1535 extent_endpoint_bytind (EXTENT extent, int endp) 1539 extent_endpoint_bytind (EXTENT extent, int endp)
1536 { 1540 {
1537 assert (EXTENT_LIVE_P (extent)); 1541 assert (EXTENT_LIVE_P (extent));
1538 assert (!extent_detached_p (extent)); 1542 assert (!extent_detached_p (extent));
1539 { 1543 {
1540 Memind i = (endp) ? (extent_end (extent)) : 1544 Memind i = endp ? extent_end (extent) : extent_start (extent);
1541 (extent_start (extent));
1542 Lisp_Object obj = extent_object (extent); 1545 Lisp_Object obj = extent_object (extent);
1543 return buffer_or_string_memind_to_bytind (obj, i); 1546 return buffer_or_string_memind_to_bytind (obj, i);
1544 } 1547 }
1545 } 1548 }
1546 1549
1548 extent_endpoint_bufpos (EXTENT extent, int endp) 1551 extent_endpoint_bufpos (EXTENT extent, int endp)
1549 { 1552 {
1550 assert (EXTENT_LIVE_P (extent)); 1553 assert (EXTENT_LIVE_P (extent));
1551 assert (!extent_detached_p (extent)); 1554 assert (!extent_detached_p (extent));
1552 { 1555 {
1553 Memind i = (endp) ? (extent_end (extent)) : 1556 Memind i = endp ? extent_end (extent) : extent_start (extent);
1554 (extent_start (extent));
1555 Lisp_Object obj = extent_object (extent); 1557 Lisp_Object obj = extent_object (extent);
1556 return buffer_or_string_memind_to_bufpos (obj, i); 1558 return buffer_or_string_memind_to_bufpos (obj, i);
1557 } 1559 }
1558 } 1560 }
1559 1561
1589 1591
1590 /* now mark the extent itself. */ 1592 /* now mark the extent itself. */
1591 1593
1592 object = extent_object (extent); 1594 object = extent_object (extent);
1593 1595
1594 if (!BUFFERP (object) || extent_detached_p (extent)) 1596 if (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; 1597 return;
1609 1598
1610 { 1599 else if (STRINGP (object))
1611 struct buffer *b; 1600 {
1612 b = XBUFFER (object); 1601 /* #### Changes to string extents can affect redisplay if they are
1613 BUF_FACECHANGE (b)++; 1602 in the modeline or in the gutters.
1614 MARK_EXTENTS_CHANGED; 1603
1615 if (invisibility_change) 1604 If the extent is in some generated-modeline-string: when we
1616 MARK_CLIP_CHANGED; 1605 change an extent in generated-modeline-string, this changes its
1617 buffer_extent_signal_changed_region (b, 1606 parent, which is in `modeline-format', so we should force the
1618 extent_endpoint_bufpos (extent, 0), 1607 modeline to be updated. But how to determine whether a string
1619 extent_endpoint_bufpos (extent, 1)); 1608 is a `generated-modeline-string'? Looping through all buffers
1620 } 1609 is not very efficient. Should we add all
1610 `generated-modeline-string' strings to a hash table? Maybe
1611 efficiency is not the greatest concern here and there's no big
1612 loss in looping over the buffers.
1613
1614 If the extent is in a gutter we mark the gutter as
1615 changed. This means (a) we can update extents in the gutters
1616 when we need it. (b) we don't have to update the gutters when
1617 only extents attached to buffers have changed. */
1618
1619 if (!in_modeline_generation)
1620 MARK_EXTENTS_CHANGED;
1621 gutter_extent_signal_changed_region_maybe (object,
1622 extent_endpoint_bufpos (extent, 0),
1623 extent_endpoint_bufpos (extent, 1));
1624 }
1625 else if (BUFFERP (object))
1626 {
1627 struct buffer *b;
1628 b = XBUFFER (object);
1629 BUF_FACECHANGE (b)++;
1630 MARK_EXTENTS_CHANGED;
1631 if (invisibility_change)
1632 MARK_CLIP_CHANGED;
1633 buffer_extent_signal_changed_region (b,
1634 extent_endpoint_bufpos (extent, 0),
1635 extent_endpoint_bufpos (extent, 1));
1636 }
1621 } 1637 }
1622 1638
1623 /* A change to an extent occurred that might affect redisplay. 1639 /* A change to an extent occurred that might affect redisplay.
1624 This is called when properties such as the endpoints, the layout, 1640 This is called when properties such as the endpoints, the layout,
1625 or the priority changes. Redisplay will be affected only if 1641 or the priority changes. Redisplay will be affected only if
1842 { 1858 {
1843 case ME_ALL_EXTENTS_CLOSED: start_open = 0, end_open = 0; break; 1859 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; 1860 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; 1861 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; 1862 case ME_ALL_EXTENTS_OPEN_CLOSED: start_open = 1, end_open = 0; break;
1847 default: abort(); break; 1863 default: abort(); return 0;
1848 } 1864 }
1849 1865
1850 start = buffer_or_string_bytind_to_startind (obj, from, 1866 start = buffer_or_string_bytind_to_startind (obj, from,
1851 flags & ME_START_OPEN); 1867 flags & ME_START_OPEN);
1852 end = buffer_or_string_bytind_to_endind (obj, to, ! (flags & ME_END_CLOSED)); 1868 end = buffer_or_string_bytind_to_endind (obj, to, ! (flags & ME_END_CLOSED));
1877 retval = start <= exs && exe <= end; break; 1893 retval = start <= exs && exe <= end; break;
1878 case ME_START_OR_END_IN_REGION: 1894 case ME_START_OR_END_IN_REGION:
1879 retval = (start <= exs && exs <= end) || (start <= exe && exe <= end); 1895 retval = (start <= exs && exs <= end) || (start <= exe && exe <= end);
1880 break; 1896 break;
1881 default: 1897 default:
1882 abort(); break; 1898 abort(); return 0;
1883 } 1899 }
1884 return flags & ME_NEGATE_IN_REGION ? !retval : retval; 1900 return flags & ME_NEGATE_IN_REGION ? !retval : retval;
1885 } 1901 }
1886 1902
1887 struct map_extents_struct 1903 struct map_extents_struct
2597 Dynarr_free (ef->begin_glyphs); 2613 Dynarr_free (ef->begin_glyphs);
2598 Dynarr_free (ef->end_glyphs); 2614 Dynarr_free (ef->end_glyphs);
2599 xfree (ef); 2615 xfree (ef);
2600 } 2616 }
2601 2617
2602 /* Note: CONST is losing, but `const' is part of the interface of qsort() */
2603 static int 2618 static int
2604 extent_priority_sort_function (const void *humpty, const void *dumpty) 2619 extent_priority_sort_function (const void *humpty, const void *dumpty)
2605 { 2620 {
2606 CONST EXTENT foo = * (CONST EXTENT *) humpty; 2621 const EXTENT foo = * (const EXTENT *) humpty;
2607 CONST EXTENT bar = * (CONST EXTENT *) dumpty; 2622 const EXTENT bar = * (const EXTENT *) dumpty;
2608 if (extent_priority (foo) < extent_priority (bar)) 2623 if (extent_priority (foo) < extent_priority (bar))
2609 return -1; 2624 return -1;
2610 return extent_priority (foo) > extent_priority (bar); 2625 return extent_priority (foo) > extent_priority (bar);
2611 } 2626 }
2612 2627
2908 2923
2909 /* These are the basic helper functions for handling the allocation of 2924 /* These are the basic helper functions for handling the allocation of
2910 extent objects. They are similar to the functions for other 2925 extent objects. They are similar to the functions for other
2911 lrecord objects. allocate_extent() is in alloc.c, not here. */ 2926 lrecord objects. allocate_extent() is in alloc.c, not here. */
2912 2927
2913 static Lisp_Object mark_extent (Lisp_Object);
2914 static int extent_equal (Lisp_Object, Lisp_Object, int depth);
2915 static unsigned long extent_hash (Lisp_Object obj, int depth);
2916 static void print_extent (Lisp_Object obj, Lisp_Object printcharfun,
2917 int escapeflag);
2918 static Lisp_Object extent_getprop (Lisp_Object obj, Lisp_Object prop);
2919 static int extent_putprop (Lisp_Object obj, Lisp_Object prop,
2920 Lisp_Object value);
2921 static int extent_remprop (Lisp_Object obj, Lisp_Object prop);
2922 static Lisp_Object extent_plist (Lisp_Object obj);
2923
2924 static const struct lrecord_description extent_description[] = {
2925 { XD_LISP_OBJECT, offsetof (struct extent, object) },
2926 { XD_LISP_OBJECT, offsetof (struct extent, flags.face) },
2927 { XD_LISP_OBJECT, offsetof (struct extent, plist) },
2928 { XD_END }
2929 };
2930
2931 DEFINE_BASIC_LRECORD_IMPLEMENTATION_WITH_PROPS ("extent", extent,
2932 mark_extent,
2933 print_extent,
2934 /* NOTE: If you declare a
2935 finalization method here,
2936 it will NOT be called.
2937 Shaft city. */
2938 0,
2939 extent_equal, extent_hash,
2940 extent_description,
2941 extent_getprop, extent_putprop,
2942 extent_remprop, extent_plist,
2943 struct extent);
2944
2945 static Lisp_Object 2928 static Lisp_Object
2946 mark_extent (Lisp_Object obj) 2929 mark_extent (Lisp_Object obj)
2947 { 2930 {
2948 struct extent *extent = XEXTENT (obj); 2931 struct extent *extent = XEXTENT (obj);
2949 2932
3005 static void 2988 static void
3006 print_extent (Lisp_Object obj, Lisp_Object printcharfun, int escapeflag) 2989 print_extent (Lisp_Object obj, Lisp_Object printcharfun, int escapeflag)
3007 { 2990 {
3008 if (escapeflag) 2991 if (escapeflag)
3009 { 2992 {
3010 CONST char *title = ""; 2993 const char *title = "";
3011 CONST char *name = ""; 2994 const char *name = "";
3012 CONST char *posttitle = ""; 2995 const char *posttitle = "";
3013 Lisp_Object obj2 = Qnil; 2996 Lisp_Object obj2 = Qnil;
3014 2997
3015 /* Destroyed extents have 't' in the object field, causing 2998 /* Destroyed extents have 't' in the object field, causing
3016 extent_object() to abort (maybe). */ 2999 extent_object() to abort (maybe). */
3017 if (EXTENT_LIVE_P (XEXTENT (obj))) 3000 if (EXTENT_LIVE_P (XEXTENT (obj)))
3128 /* No need to hash all of the elements; that would take too long. 3111 /* No need to hash all of the elements; that would take too long.
3129 Just hash the most common ones. */ 3112 Just hash the most common ones. */
3130 return HASH3 (extent_start (e), extent_end (e), 3113 return HASH3 (extent_start (e), extent_end (e),
3131 internal_hash (extent_object (e), depth + 1)); 3114 internal_hash (extent_object (e), depth + 1));
3132 } 3115 }
3116
3117 static const struct lrecord_description extent_description[] = {
3118 { XD_LISP_OBJECT, offsetof (struct extent, object) },
3119 { XD_LISP_OBJECT, offsetof (struct extent, flags.face) },
3120 { XD_LISP_OBJECT, offsetof (struct extent, plist) },
3121 { XD_END }
3122 };
3133 3123
3134 static Lisp_Object 3124 static Lisp_Object
3135 extent_getprop (Lisp_Object obj, Lisp_Object prop) 3125 extent_getprop (Lisp_Object obj, Lisp_Object prop)
3136 { 3126 {
3137 return Fextent_property (obj, prop, Qunbound); 3127 return Fextent_property (obj, prop, Qunbound);
3187 extent_plist (Lisp_Object obj) 3177 extent_plist (Lisp_Object obj)
3188 { 3178 {
3189 return Fextent_properties (obj); 3179 return Fextent_properties (obj);
3190 } 3180 }
3191 3181
3182 DEFINE_BASIC_LRECORD_IMPLEMENTATION_WITH_PROPS ("extent", extent,
3183 mark_extent,
3184 print_extent,
3185 /* NOTE: If you declare a
3186 finalization method here,
3187 it will NOT be called.
3188 Shaft city. */
3189 0,
3190 extent_equal, extent_hash,
3191 extent_description,
3192 extent_getprop, extent_putprop,
3193 extent_remprop, extent_plist,
3194 struct extent);
3195
3192 3196
3193 /************************************************************************/ 3197 /************************************************************************/
3194 /* basic extent accessors */ 3198 /* basic extent accessors */
3195 /************************************************************************/ 3199 /************************************************************************/
3196 3200
3239 assert (!NILP (obj) || extent_detached_p (extent)); 3243 assert (!NILP (obj) || extent_detached_p (extent));
3240 3244
3241 if ((NILP (obj) && (flags & DE_MUST_HAVE_BUFFER)) 3245 if ((NILP (obj) && (flags & DE_MUST_HAVE_BUFFER))
3242 || (extent_detached_p (extent) && (flags & DE_MUST_BE_ATTACHED))) 3246 || (extent_detached_p (extent) && (flags & DE_MUST_BE_ATTACHED)))
3243 { 3247 {
3244 signal_simple_error ("extent doesn't belong to a buffer or string", 3248 invalid_argument ("extent doesn't belong to a buffer or string",
3245 extent_obj); 3249 extent_obj);
3246 } 3250 }
3247 3251
3248 return extent; 3252 return extent;
3249 } 3253 }
3250 3254
3530 CHECK_LIVE_EXTENT (parent); 3534 CHECK_LIVE_EXTENT (parent);
3531 if (EQ (parent, cur_parent)) 3535 if (EQ (parent, cur_parent))
3532 return Qnil; 3536 return Qnil;
3533 for (rest = parent; !NILP (rest); rest = extent_parent (XEXTENT (rest))) 3537 for (rest = parent; !NILP (rest); rest = extent_parent (XEXTENT (rest)))
3534 if (EQ (rest, extent)) 3538 if (EQ (rest, extent))
3535 signal_simple_error ("Circular parent chain would result", extent); 3539 signal_type_error (Qinvalid_change,
3540 "Circular parent chain would result",
3541 extent);
3536 if (NILP (parent)) 3542 if (NILP (parent))
3537 { 3543 {
3538 remove_extent_from_children_list (XEXTENT (cur_parent), extent); 3544 remove_extent_from_children_list (XEXTENT (cur_parent), extent);
3539 set_extent_no_chase_aux_field (e, parent, Qnil); 3545 set_extent_no_chase_aux_field (e, parent, Qnil);
3540 e->flags.has_parent = 0; 3546 e->flags.has_parent = 0;
3893 EQ (sym, Qstart_in_region) ? ME_START_IN_REGION : 3899 EQ (sym, Qstart_in_region) ? ME_START_IN_REGION :
3894 EQ (sym, Qend_in_region) ? ME_END_IN_REGION : 3900 EQ (sym, Qend_in_region) ? ME_END_IN_REGION :
3895 EQ (sym, Qstart_and_end_in_region) ? ME_START_AND_END_IN_REGION : 3901 EQ (sym, Qstart_and_end_in_region) ? ME_START_AND_END_IN_REGION :
3896 EQ (sym, Qstart_or_end_in_region) ? ME_START_OR_END_IN_REGION : 3902 EQ (sym, Qstart_or_end_in_region) ? ME_START_OR_END_IN_REGION :
3897 EQ (sym, Qnegate_in_region) ? ME_NEGATE_IN_REGION : 3903 EQ (sym, Qnegate_in_region) ? ME_NEGATE_IN_REGION :
3898 (signal_simple_error ("Invalid `map-extents' flag", sym), 0); 3904 (invalid_argument ("Invalid `map-extents' flag", sym), 0);
3899 3905
3900 flags = XCDR (flags); 3906 flags = XCDR (flags);
3901 } 3907 }
3902 return retval; 3908 return retval;
3903 } 3909 }
4231 The search stops just before "before", if that is non-null. 4237 The search stops just before "before", if that is non-null.
4232 */ 4238 */
4233 4239
4234 struct extent_at_arg 4240 struct extent_at_arg
4235 { 4241 {
4236 EXTENT best_match; 4242 Lisp_Object best_match; /* or list of extents */
4237 Memind best_start; 4243 Memind best_start;
4238 Memind best_end; 4244 Memind best_end;
4239 Lisp_Object prop; 4245 Lisp_Object prop;
4240 EXTENT before; 4246 EXTENT before;
4247 int all_extents;
4241 }; 4248 };
4242 4249
4243 enum extent_at_flag 4250 enum extent_at_flag
4244 { 4251 {
4245 EXTENT_AT_AFTER, 4252 EXTENT_AT_AFTER,
4256 CHECK_SYMBOL (at_flag); 4263 CHECK_SYMBOL (at_flag);
4257 if (EQ (at_flag, Qafter)) return EXTENT_AT_AFTER; 4264 if (EQ (at_flag, Qafter)) return EXTENT_AT_AFTER;
4258 if (EQ (at_flag, Qbefore)) return EXTENT_AT_BEFORE; 4265 if (EQ (at_flag, Qbefore)) return EXTENT_AT_BEFORE;
4259 if (EQ (at_flag, Qat)) return EXTENT_AT_AT; 4266 if (EQ (at_flag, Qat)) return EXTENT_AT_AT;
4260 4267
4261 signal_simple_error ("Invalid AT-FLAG in `extent-at'", at_flag); 4268 invalid_argument ("Invalid AT-FLAG in `extent-at'", at_flag);
4262 return EXTENT_AT_AFTER; /* unreached */ 4269 return EXTENT_AT_AFTER; /* unreached */
4263 } 4270 }
4264 4271
4265 static int 4272 static int
4266 extent_at_mapper (EXTENT e, void *arg) 4273 extent_at_mapper (EXTENT e, void *arg)
4278 XSETEXTENT (extent, e); 4285 XSETEXTENT (extent, e);
4279 if (NILP (Fextent_property (extent, closure->prop, Qnil))) 4286 if (NILP (Fextent_property (extent, closure->prop, Qnil)))
4280 return 0; 4287 return 0;
4281 } 4288 }
4282 4289
4283 { 4290 if (!closure->all_extents)
4284 EXTENT current = closure->best_match; 4291 {
4285 4292 EXTENT current;
4286 if (!current) 4293
4294 if (NILP (closure->best_match))
4287 goto accept; 4295 goto accept;
4296 current = XEXTENT (closure->best_match);
4288 /* redundant but quick test */ 4297 /* redundant but quick test */
4289 else if (extent_start (current) > extent_start (e)) 4298 if (extent_start (current) > extent_start (e))
4290 return 0; 4299 return 0;
4291 4300
4292 /* we return the "last" best fit, instead of the first -- 4301 /* we return the "last" best fit, instead of the first --
4293 this is because then the glyph closest to two equivalent 4302 this is because then the glyph closest to two equivalent
4294 extents corresponds to the "extent-at" the text just past 4303 extents corresponds to the "extent-at" the text just past
4297 closure->best_end)) 4306 closure->best_end))
4298 goto accept; 4307 goto accept;
4299 else 4308 else
4300 return 0; 4309 return 0;
4301 accept: 4310 accept:
4302 closure->best_match = e; 4311 XSETEXTENT (closure->best_match, e);
4303 closure->best_start = extent_start (e); 4312 closure->best_start = extent_start (e);
4304 closure->best_end = extent_end (e); 4313 closure->best_end = extent_end (e);
4305 } 4314 }
4315 else
4316 {
4317 Lisp_Object extent;
4318
4319 XSETEXTENT (extent, e);
4320 closure->best_match = Fcons (extent, closure->best_match);
4321 }
4306 4322
4307 return 0; 4323 return 0;
4308 } 4324 }
4309 4325
4310 static Lisp_Object 4326 static Lisp_Object
4311 extent_at_bytind (Bytind position, Lisp_Object object, Lisp_Object property, 4327 extent_at_bytind (Bytind position, Lisp_Object object, Lisp_Object property,
4312 EXTENT before, enum extent_at_flag at_flag) 4328 EXTENT before, enum extent_at_flag at_flag, int all_extents)
4313 { 4329 {
4314 struct extent_at_arg closure; 4330 struct extent_at_arg closure;
4315 Lisp_Object extent_obj; 4331 struct gcpro gcpro1;
4316 4332
4317 /* it might be argued that invalid positions should cause 4333 /* it might be argued that invalid positions should cause
4318 errors, but the principle of least surprise dictates that 4334 errors, but the principle of least surprise dictates that
4319 nil should be returned (extent-at is often used in 4335 nil should be returned (extent-at is often used in
4320 response to a mouse event, and in many cases previous events 4336 response to a mouse event, and in many cases previous events
4328 || (at_flag == EXTENT_AT_AFTER 4344 || (at_flag == EXTENT_AT_AFTER
4329 ? position >= buffer_or_string_absolute_end_byte (object) 4345 ? position >= buffer_or_string_absolute_end_byte (object)
4330 : position > buffer_or_string_absolute_end_byte (object))) 4346 : position > buffer_or_string_absolute_end_byte (object)))
4331 return Qnil; 4347 return Qnil;
4332 4348
4333 closure.best_match = 0; 4349 closure.best_match = Qnil;
4334 closure.prop = property; 4350 closure.prop = property;
4335 closure.before = before; 4351 closure.before = before;
4336 4352 closure.all_extents = all_extents;
4353
4354 GCPRO1 (closure.best_match);
4337 map_extents_bytind (at_flag == EXTENT_AT_BEFORE ? position - 1 : position, 4355 map_extents_bytind (at_flag == EXTENT_AT_BEFORE ? position - 1 : position,
4338 at_flag == EXTENT_AT_AFTER ? position + 1 : position, 4356 at_flag == EXTENT_AT_AFTER ? position + 1 : position,
4339 extent_at_mapper, (void *) &closure, object, 0, 4357 extent_at_mapper, (void *) &closure, object, 0,
4340 ME_START_OPEN | ME_ALL_EXTENTS_CLOSED); 4358 ME_START_OPEN | ME_ALL_EXTENTS_CLOSED);
4341 4359 if (all_extents)
4342 if (!closure.best_match) 4360 closure.best_match = Fnreverse (closure.best_match);
4343 return Qnil; 4361 UNGCPRO;
4344 4362
4345 XSETEXTENT (extent_obj, closure.best_match); 4363 return closure.best_match;
4346 return extent_obj;
4347 } 4364 }
4348 4365
4349 DEFUN ("extent-at", Fextent_at, 1, 5, 0, /* 4366 DEFUN ("extent-at", Fextent_at, 1, 5, 0, /*
4350 Find "smallest" extent at POS in OBJECT having PROPERTY set. 4367 Find "smallest" extent at POS in OBJECT having PROPERTY set.
4351 Normally, an extent is "at" POS if it overlaps the region (POS, POS+1); 4368 Normally, an extent is "at" POS if it overlaps the region (POS, POS+1);
4385 if (NILP (before)) 4402 if (NILP (before))
4386 before_extent = 0; 4403 before_extent = 0;
4387 else 4404 else
4388 before_extent = decode_extent (before, DE_MUST_BE_ATTACHED); 4405 before_extent = decode_extent (before, DE_MUST_BE_ATTACHED);
4389 if (before_extent && !EQ (object, extent_object (before_extent))) 4406 if (before_extent && !EQ (object, extent_object (before_extent)))
4390 signal_simple_error ("extent not in specified buffer or string", object); 4407 invalid_argument ("extent not in specified buffer or string", object);
4391 fl = decode_extent_at_flag (at_flag); 4408 fl = decode_extent_at_flag (at_flag);
4392 4409
4393 return extent_at_bytind (position, object, property, before_extent, fl); 4410 return extent_at_bytind (position, object, property, before_extent, fl, 0);
4411 }
4412
4413 DEFUN ("extents-at", Fextents_at, 1, 5, 0, /*
4414 Find all extents at POS in OBJECT having PROPERTY set.
4415 Normally, an extent is "at" POS if it overlaps the region (POS, POS+1);
4416 i.e. if it covers the character after POS. (However, see the definition
4417 of AT-FLAG.)
4418 This provides similar functionality to `extent-list', but does so in a way
4419 that is compatible with `extent-at'. (For example, errors due to POS out of
4420 range are ignored; this makes it safer to use this function in response to
4421 a mouse event, because in many cases previous events have changed the buffer
4422 contents.)
4423 OBJECT specifies a buffer or string and defaults to the current buffer.
4424 PROPERTY defaults to nil, meaning that any extent will do.
4425 Properties are attached to extents with `set-extent-property', which see.
4426 Returns nil if POS is invalid or there is no matching extent at POS.
4427 If the fourth argument BEFORE is not nil, it must be an extent; any returned
4428 extent will precede that extent. This feature allows `extents-at' to be
4429 used by a loop over extents.
4430 AT-FLAG controls how end cases are handled, and should be one of:
4431
4432 nil or `after' An extent is at POS if it covers the character
4433 after POS. This is consistent with the way
4434 that text properties work.
4435 `before' An extent is at POS if it covers the character
4436 before POS.
4437 `at' An extent is at POS if it overlaps or abuts POS.
4438 This includes all zero-length extents at POS.
4439
4440 Note that in all cases, the start-openness and end-openness of the extents
4441 considered is ignored. If you want to pay attention to those properties,
4442 you should use `map-extents', which gives you more control.
4443 */
4444 (pos, object, property, before, at_flag))
4445 {
4446 Bytind position;
4447 EXTENT before_extent;
4448 enum extent_at_flag fl;
4449
4450 object = decode_buffer_or_string (object);
4451 position = get_buffer_or_string_pos_byte (object, pos, GB_NO_ERROR_IF_BAD);
4452 if (NILP (before))
4453 before_extent = 0;
4454 else
4455 before_extent = decode_extent (before, DE_MUST_BE_ATTACHED);
4456 if (before_extent && !EQ (object, extent_object (before_extent)))
4457 invalid_argument ("extent not in specified buffer or string", object);
4458 fl = decode_extent_at_flag (at_flag);
4459
4460 return extent_at_bytind (position, object, property, before_extent, fl, 1);
4394 } 4461 }
4395 4462
4396 /* ------------------------------- */ 4463 /* ------------------------------- */
4397 /* verify_extent_modification() */ 4464 /* verify_extent_modification() */
4398 /* ------------------------------- */ 4465 /* ------------------------------- */
4993 if (EQ (layout_obj, Qoutside_margin)) return GL_OUTSIDE_MARGIN; 5060 if (EQ (layout_obj, Qoutside_margin)) return GL_OUTSIDE_MARGIN;
4994 if (EQ (layout_obj, Qinside_margin)) return GL_INSIDE_MARGIN; 5061 if (EQ (layout_obj, Qinside_margin)) return GL_INSIDE_MARGIN;
4995 if (EQ (layout_obj, Qwhitespace)) return GL_WHITESPACE; 5062 if (EQ (layout_obj, Qwhitespace)) return GL_WHITESPACE;
4996 if (EQ (layout_obj, Qtext)) return GL_TEXT; 5063 if (EQ (layout_obj, Qtext)) return GL_TEXT;
4997 5064
4998 signal_simple_error ("Unknown glyph layout type", layout_obj); 5065 invalid_argument ("Unknown glyph layout type", layout_obj);
4999 return GL_TEXT; /* unreached */ 5066 return GL_TEXT; /* unreached */
5000 } 5067 }
5001 5068
5002 static Lisp_Object 5069 static Lisp_Object
5003 set_extent_glyph_1 (Lisp_Object extent_obj, Lisp_Object glyph, int endp, 5070 set_extent_glyph_1 (Lisp_Object extent_obj, Lisp_Object glyph, int endp,
5004 Lisp_Object layout_obj) 5071 Lisp_Object layout_obj)
5005 { 5072 {
5006 EXTENT extent = decode_extent (extent_obj, DE_MUST_HAVE_BUFFER); 5073 EXTENT extent = decode_extent (extent_obj, 0);
5007 glyph_layout layout = symbol_to_glyph_layout (layout_obj); 5074 glyph_layout layout = symbol_to_glyph_layout (layout_obj);
5008 5075
5009 /* Make sure we've actually been given a valid glyph or it's nil 5076 /* Make sure we've actually been given a valid glyph or it's nil
5010 (meaning we're deleting a glyph from an extent). */ 5077 (meaning we're deleting a glyph from an extent). */
5011 if (!NILP (glyph)) 5078 if (!NILP (glyph))
5959 Lisp_Object extent; 6026 Lisp_Object extent;
5960 6027
5961 /* text_props_only specifies whether we only consider text-property 6028 /* text_props_only specifies whether we only consider text-property
5962 extents (those with the 'text-prop property set) or all extents. */ 6029 extents (those with the 'text-prop property set) or all extents. */
5963 if (!text_props_only) 6030 if (!text_props_only)
5964 extent = extent_at_bytind (position, object, prop, 0, fl); 6031 extent = extent_at_bytind (position, object, prop, 0, fl, 0);
5965 else 6032 else
5966 { 6033 {
5967 EXTENT prior = 0; 6034 EXTENT prior = 0;
5968 while (1) 6035 while (1)
5969 { 6036 {
5970 extent = extent_at_bytind (position, object, Qtext_prop, prior, 6037 extent = extent_at_bytind (position, object, Qtext_prop, prior,
5971 fl); 6038 fl, 0);
5972 if (NILP (extent)) 6039 if (NILP (extent))
5973 return Qnil; 6040 return Qnil;
5974 if (EQ (prop, Fextent_property (extent, Qtext_prop, Qnil))) 6041 if (EQ (prop, Fextent_property (extent, Qtext_prop, Qnil)))
5975 break; 6042 break;
5976 prior = XEXTENT (extent); 6043 prior = XEXTENT (extent);
6498 /* This function can GC */ 6565 /* This function can GC */
6499 Lisp_Object prop, val; 6566 Lisp_Object prop, val;
6500 6567
6501 prop = Fextent_property (extent, Qtext_prop, Qnil); 6568 prop = Fextent_property (extent, Qtext_prop, Qnil);
6502 if (NILP (prop)) 6569 if (NILP (prop))
6503 signal_simple_error ("Internal error: no text-prop", extent); 6570 signal_type_error (Qinternal_error,
6571 "Internal error: no text-prop", extent);
6504 val = Fextent_property (extent, prop, Qnil); 6572 val = Fextent_property (extent, prop, Qnil);
6505 #if 0 6573 #if 0
6506 /* removed by bill perry, 2/9/97 6574 /* removed by bill perry, 2/9/97
6507 ** This little bit of code would not allow you to have a text property 6575 ** This little bit of code would not allow you to have a text property
6508 ** with a value of Qnil. This is bad bad bad. 6576 ** with a value of Qnil. This is bad bad bad.
6509 */ 6577 */
6510 if (NILP (val)) 6578 if (NILP (val))
6511 signal_simple_error_2 ("Internal error: no text-prop", 6579 signal_type_error_2 (Qinternal_error,
6512 extent, prop); 6580 "Internal error: no text-prop",
6581 extent, prop);
6513 #endif 6582 #endif
6514 Fput_text_property (from, to, prop, val, Qnil); 6583 Fput_text_property (from, to, prop, val, Qnil);
6515 return Qnil; /* important! */ 6584 return Qnil; /* important! */
6516 } 6585 }
6517 6586
6671 /************************************************************************/ 6740 /************************************************************************/
6672 6741
6673 void 6742 void
6674 syms_of_extents (void) 6743 syms_of_extents (void)
6675 { 6744 {
6745 INIT_LRECORD_IMPLEMENTATION (extent);
6746 INIT_LRECORD_IMPLEMENTATION (extent_info);
6747 INIT_LRECORD_IMPLEMENTATION (extent_auxiliary);
6748
6676 defsymbol (&Qextentp, "extentp"); 6749 defsymbol (&Qextentp, "extentp");
6677 defsymbol (&Qextent_live_p, "extent-live-p"); 6750 defsymbol (&Qextent_live_p, "extent-live-p");
6678 6751
6679 defsymbol (&Qall_extents_closed, "all-extents-closed"); 6752 defsymbol (&Qall_extents_closed, "all-extents-closed");
6680 defsymbol (&Qall_extents_open, "all-extents-open"); 6753 defsymbol (&Qall_extents_open, "all-extents-open");
6747 6820
6748 DEFSUBR (Fextent_in_region_p); 6821 DEFSUBR (Fextent_in_region_p);
6749 DEFSUBR (Fmap_extents); 6822 DEFSUBR (Fmap_extents);
6750 DEFSUBR (Fmap_extent_children); 6823 DEFSUBR (Fmap_extent_children);
6751 DEFSUBR (Fextent_at); 6824 DEFSUBR (Fextent_at);
6825 DEFSUBR (Fextents_at);
6752 6826
6753 DEFSUBR (Fset_extent_initial_redisplay_function); 6827 DEFSUBR (Fset_extent_initial_redisplay_function);
6754 DEFSUBR (Fextent_face); 6828 DEFSUBR (Fextent_face);
6755 DEFSUBR (Fset_extent_face); 6829 DEFSUBR (Fset_extent_face);
6756 DEFSUBR (Fextent_mouse_face); 6830 DEFSUBR (Fextent_mouse_face);