Mercurial > hg > xemacs-beta
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); |