aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorAndreas Politz2017-02-07 17:56:50 +0100
committerAndreas Politz2017-10-04 22:32:26 +0200
commit8d7bdfa3fca076b34aaf86548d3243bee11872ad (patch)
tree419c7897f336ad206bb9e99824f35819ba9796c1 /src
parentf204e6e1a418073bd1e24a83947f1f3c53581c7f (diff)
downloademacs-8d7bdfa3fca076b34aaf86548d3243bee11872ad.tar.gz
emacs-8d7bdfa3fca076b34aaf86548d3243bee11872ad.zip
Provide a new tree data-structure for overlays.
* src/itree.c (interval_generator_narrow, interval_generator_next) (interval_node_init, interval_node_begin) (interval_node_end, interval_node_set_region) (interval_tree_create, interval_tree_clear) (interval_tree_init, interval_tree_destroy) (interval_tree_size, interval_tree_insert) (interval_tree_contains, interval_tree_remove) (interval_tree_validate, interval_tree_iter_start) (interval_tree_iter_finish, interval_tree_iter_next) (interval_tree_iter_ensure_space, interval_tree_max_height) (interval_tree_insert_gap, interval_tree_delete_gap) (interval_generator_create, interval_generator_reset) (interval_generator_ensure_space, interval_node_intersects) (interval_generator_next, interval_generator_narrow) (interval_generator_destroy, interval_stack_create) (interval_stack_destroy, interval_stack_clear) (interval_stack_ensure_space, interval_stack_push) (interval_stack_push_flagged, interval_stack_pop) (interval_tree_update_limit, interval_tree_inherit_offset) (interval_tree_propagate_limit, interval_tree_rotate_left) (interval_tree_rotate_right, interval_tree_insert_fix) (interval_tree_remove_fix, interval_tree_transplant) (interval_tree_subtree_min): New file and new functions. * src/itree.h: New file. * configure.ac: Create Makefile for manual overlay tests. * src/Makefile.in: Add itree.o target. * src/alloc.c (build_overlay, mark_overlay, mark_buffer) (sweep_misc, sweep_buffers): Adapt to new tree data-structure. * src/buffer.c (overlays_in, overlays_at): Remove unused arguments prev_ptr and change_req, adapt to new data-structure and reuse code. (copy_overlays, drop_overlays, delete_all_overlays) (reset_buffer, kill-buffer, buffer-swap-text, next_overlay_change) (previous_overlay_change, mouse_face_overlay_overlaps) (disable_line_numbers_overlay_at_eob, overlay_touches_p) (overlay_strings, adjust_overlays_for_insert) (adjust_overlays_for_delete, overlayp, make-overlay, move-overlay) (delete-overlay, overlay-start, overlay-end, overlay-buffer) (overlay-properties, overlays-at, overlays-in) (next-overlay-change, previous-overlay-change, overlay-put) (overlay-get, report_overlay_modification, evaporate_overlays) (init_buffer_once): Adapt to changes and tree data-structure. (overlay-lists, overlay-recenter): Funtions are now obsolete, but kept anyway. (set_buffer_overlays_before, set_buffer_overlays_after) (recenter_overlay_lists,fix_start_end_in_overlays,fix_overlays_before) (unchain_overlay,): Removed functions of the old list data-structure. (swap_buffer_overlays, make_sortvec_item): New functions. (sort_overlays): Adapt to changes and tree data-structure. (sortvec): Moved to buffer.h . (make_lispy_interval_node, overlay_tree, overlay-tree) [ITREE_DEBUG]: New debugging functions. * src/buffer.h (overlays_before, overlays_after): Removed struct member of the list data-structure. (overlays): Added tree struct member. (sortvec): Moved here from buffer.c . (GET_OVERLAYS_AT): Adapt to changes. (set_buffer_intervals, OVERLAY_START, OVERLAY_END, OVERLAY_PLIST): Adapt to tree data-structure. (OVERLAY_POSITION): Removed macro of the list data-structure. (OVERLAY_REAR_ADVANCE_P, OVERLAY_FRONT_ADVANCE_P): New macros. (overlay_start, overlay_end) (set_overlay_region, maybe_alloc_buffer_overlays) (free_buffer_overlays, add_buffer_overlay) (remove_buffer_overlay, buffer_overlay_iter_start) (buffer_overlay_iter_next, buffer_overlay_iter_finish) (buffer_overlay_iter_narrow): New functions. (compare_overlays, make_sortvec_item): Export functions. * src/editfns.c (overlays_around): Reuse overlays_in. (get-pos-property): Adapt to tree data-structure. (transpose-regions): Remove call to deleted function. * src/fileio.c: (insert-file-contents): Remove references to deleted struct member. * src/fns.c (internal_equal): Adapt to tree data-structure. * src/indent.c (check_display_width): Adapt to tree data-structure. (skip_invisible): Remove call to deleted function. * src/insdel.c (adjust_markers_for_insert): Remove calls to deleted functions. * src/intervals.c (adjust_for_invis_intang): Adapt to tree data-structure. * src/keyboard.c (adjust_point_for_property): Adapt to tree data-structure. * src/lisp.h (Lisp_Overlay): Modified struct layout. * src/print.c (temp_output_buffer_setup, print_object): Adapt to tree data-structure. * src/textprop.c (get_char_property_and_overlay): Adapt to tree data-structure. Take advantage of the new data-structure. * src/window.h (overlay_matches_window): New function. * src/xdisp.h (next_overlay_change): Removed function. Use next-overlay-change, which does not use xmalloc anymore. (handle_single_display_spec, load_overlay_strings) (back_to_previous_visible_line_start, note_mouse_highlight): Adapt to tree data-structure. (move_it_to, display_line): Remove calls to deleted functions. * src/xfaces.c (face_at_buffer_position): Adapt to changes and tree data-structure. * test/src/buffer-tests.el: Many tests regarding overlays added. * test/manual/noverlay/itree-tests.c: New file with tests of the tree data-structure on the C level. * test/manual/noverlay/Makefile.in: New file. * test/manual/noverlay/check-sanitize.sh: New file. * test/manual/noverlay/emacs-compat.h: New file. * test/manual/noverlay/.gitignore: New file. * test/manual/noverlay/overlay-perf.el: New file providing performance tests. * test/manual/noverlay/many-errors.h: New file.
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.in1
-rw-r--r--src/alloc.c49
-rw-r--r--src/buffer.c1458
-rw-r--r--src/buffer.h161
-rw-r--r--src/editfns.c56
-rw-r--r--src/fileio.c3
-rw-r--r--src/fns.c7
-rw-r--r--src/indent.c5
-rw-r--r--src/insdel.c12
-rw-r--r--src/intervals.c4
-rw-r--r--src/itree.c1138
-rw-r--r--src/itree.h88
-rw-r--r--src/keyboard.c4
-rw-r--r--src/lisp.h19
-rw-r--r--src/print.c12
-rw-r--r--src/textprop.c52
-rw-r--r--src/window.h10
-rw-r--r--src/xdisp.c167
-rw-r--r--src/xfaces.c17
19 files changed, 1916 insertions, 1347 deletions
diff --git a/src/Makefile.in b/src/Makefile.in
index 9a8c9c85f04..8a8df03e49f 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -395,6 +395,7 @@ base_obj = dispnew.o frame.o scroll.o xdisp.o menu.o $(XMENU_OBJ) window.o \
395 $(XWIDGETS_OBJ) \ 395 $(XWIDGETS_OBJ) \
396 profiler.o decompress.o \ 396 profiler.o decompress.o \
397 thread.o systhread.o \ 397 thread.o systhread.o \
398 itree.o \
398 $(if $(HYBRID_MALLOC),sheap.o) \ 399 $(if $(HYBRID_MALLOC),sheap.o) \
399 $(MSDOS_OBJ) $(MSDOS_X_OBJ) $(NS_OBJ) $(CYGWIN_OBJ) $(FONT_OBJ) \ 400 $(MSDOS_OBJ) $(MSDOS_X_OBJ) $(NS_OBJ) $(CYGWIN_OBJ) $(FONT_OBJ) \
400 $(W32_OBJ) $(WINDOW_SYSTEM_OBJ) $(XGSELOBJ) 401 $(W32_OBJ) $(WINDOW_SYSTEM_OBJ) $(XGSELOBJ)
diff --git a/src/alloc.c b/src/alloc.c
index 2e6399e7f8d..15a6fc43b72 100644
--- a/src/alloc.c
+++ b/src/alloc.c
@@ -43,6 +43,7 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
43#include "frame.h" 43#include "frame.h"
44#include "blockinput.h" 44#include "blockinput.h"
45#include "termhooks.h" /* For struct terminal. */ 45#include "termhooks.h" /* For struct terminal. */
46#include "itree.h"
46#ifdef HAVE_WINDOW_SYSTEM 47#ifdef HAVE_WINDOW_SYSTEM
47#include TERM_HEADER 48#include TERM_HEADER
48#endif /* HAVE_WINDOW_SYSTEM */ 49#endif /* HAVE_WINDOW_SYSTEM */
@@ -3835,16 +3836,19 @@ free_save_value (Lisp_Object save)
3835/* Return a Lisp_Misc_Overlay object with specified START, END and PLIST. */ 3836/* Return a Lisp_Misc_Overlay object with specified START, END and PLIST. */
3836 3837
3837Lisp_Object 3838Lisp_Object
3838build_overlay (Lisp_Object start, Lisp_Object end, Lisp_Object plist) 3839build_overlay (ptrdiff_t begin, ptrdiff_t end,
3840 bool front_advance, bool rear_advance,
3841 Lisp_Object plist)
3839{ 3842{
3840 register Lisp_Object overlay; 3843 Lisp_Object ov = allocate_misc (Lisp_Misc_Overlay);
3844 struct interval_node *node = xmalloc (sizeof (*node));
3841 3845
3842 overlay = allocate_misc (Lisp_Misc_Overlay); 3846 interval_node_init (node, begin, end, front_advance,
3843 OVERLAY_START (overlay) = start; 3847 rear_advance, ov);
3844 OVERLAY_END (overlay) = end; 3848 XOVERLAY (ov)->interval = node;
3845 set_overlay_plist (overlay, plist); 3849 XOVERLAY (ov)->buffer = NULL;
3846 XOVERLAY (overlay)->next = NULL; 3850 set_overlay_plist (ov, plist);
3847 return overlay; 3851 return ov;
3848} 3852}
3849 3853
3850DEFUN ("make-marker", Fmake_marker, Smake_marker, 0, 0, 0, 3854DEFUN ("make-marker", Fmake_marker, Smake_marker, 0, 0, 0,
@@ -6280,16 +6284,10 @@ mark_compiled (struct Lisp_Vector *ptr)
6280/* Mark the chain of overlays starting at PTR. */ 6284/* Mark the chain of overlays starting at PTR. */
6281 6285
6282static void 6286static void
6283mark_overlay (struct Lisp_Overlay *ptr) 6287mark_overlay (struct Lisp_Overlay *ov)
6284{ 6288{
6285 for (; ptr && !ptr->gcmarkbit; ptr = ptr->next) 6289 ov->gcmarkbit = 1;
6286 { 6290 mark_object (ov->plist);
6287 ptr->gcmarkbit = 1;
6288 /* These two are always markers and can be marked fast. */
6289 XMARKER (ptr->start)->gcmarkbit = 1;
6290 XMARKER (ptr->end)->gcmarkbit = 1;
6291 mark_object (ptr->plist);
6292 }
6293} 6291}
6294 6292
6295/* Mark Lisp_Objects and special pointers in BUFFER. */ 6293/* Mark Lisp_Objects and special pointers in BUFFER. */
@@ -6308,8 +6306,15 @@ mark_buffer (struct buffer *buffer)
6308 a special way just before the sweep phase, and after stripping 6306 a special way just before the sweep phase, and after stripping
6309 some of its elements that are not needed any more. */ 6307 some of its elements that are not needed any more. */
6310 6308
6311 mark_overlay (buffer->overlays_before); 6309 if (buffer->overlays)
6312 mark_overlay (buffer->overlays_after); 6310 {
6311 struct interval_node *node;
6312 buffer_overlay_iter_start (buffer, PTRDIFF_MIN, PTRDIFF_MAX, ITREE_ASCENDING);
6313
6314 while ((node = buffer_overlay_iter_next (buffer)))
6315 mark_overlay (XOVERLAY (node->data));
6316 buffer_overlay_iter_finish (buffer);
6317 }
6313 6318
6314 /* If this is an indirect buffer, mark its base buffer. */ 6319 /* If this is an indirect buffer, mark its base buffer. */
6315 if (buffer->base_buffer && !VECTOR_MARKED_P (buffer->base_buffer)) 6320 if (buffer->base_buffer && !VECTOR_MARKED_P (buffer->base_buffer))
@@ -7090,6 +7095,11 @@ sweep_misc (void)
7090 unchain_marker (&mblk->markers[i].m.u_marker); 7095 unchain_marker (&mblk->markers[i].m.u_marker);
7091 else if (mblk->markers[i].m.u_any.type == Lisp_Misc_Finalizer) 7096 else if (mblk->markers[i].m.u_any.type == Lisp_Misc_Finalizer)
7092 unchain_finalizer (&mblk->markers[i].m.u_finalizer); 7097 unchain_finalizer (&mblk->markers[i].m.u_finalizer);
7098 else if (mblk->markers[i].m.u_any.type == Lisp_Misc_Overlay)
7099 {
7100 xfree (mblk->markers[i].m.u_overlay.interval);
7101 mblk->markers[i].m.u_overlay.interval = NULL;
7102 }
7093#ifdef HAVE_MODULES 7103#ifdef HAVE_MODULES
7094 else if (mblk->markers[i].m.u_any.type == Lisp_Misc_User_Ptr) 7104 else if (mblk->markers[i].m.u_any.type == Lisp_Misc_User_Ptr)
7095 { 7105 {
@@ -7145,6 +7155,7 @@ sweep_buffers (void)
7145 if (!VECTOR_MARKED_P (buffer)) 7155 if (!VECTOR_MARKED_P (buffer))
7146 { 7156 {
7147 *bprev = buffer->next; 7157 *bprev = buffer->next;
7158 free_buffer_overlays (buffer);
7148 lisp_free (buffer); 7159 lisp_free (buffer);
7149 } 7160 }
7150 else 7161 else
diff --git a/src/buffer.c b/src/buffer.c
index 76670b89545..21c040ad0e1 100644
--- a/src/buffer.c
+++ b/src/buffer.c
@@ -44,6 +44,7 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
44#include "keymap.h" 44#include "keymap.h"
45#include "frame.h" 45#include "frame.h"
46#include "xwidget.h" 46#include "xwidget.h"
47#include "itree.h"
47 48
48#ifdef WINDOWSNT 49#ifdef WINDOWSNT
49#include "w32heap.h" /* for mmap_* */ 50#include "w32heap.h" /* for mmap_* */
@@ -120,7 +121,7 @@ static Lisp_Object QSFundamental; /* A string "Fundamental". */
120 121
121static void alloc_buffer_text (struct buffer *, ptrdiff_t); 122static void alloc_buffer_text (struct buffer *, ptrdiff_t);
122static void free_buffer_text (struct buffer *b); 123static void free_buffer_text (struct buffer *b);
123static struct Lisp_Overlay * copy_overlays (struct buffer *, struct Lisp_Overlay *); 124static void copy_overlays (struct buffer *, struct buffer *);
124static void modify_overlay (struct buffer *, ptrdiff_t, ptrdiff_t); 125static void modify_overlay (struct buffer *, ptrdiff_t, ptrdiff_t);
125static Lisp_Object buffer_lisp_local_variables (struct buffer *, bool); 126static Lisp_Object buffer_lisp_local_variables (struct buffer *, bool);
126 127
@@ -600,51 +601,30 @@ even if it is dead. The return value is never nil. */)
600} 601}
601 602
602 603
603/* Return a list of overlays which is a copy of the overlay list 604/* Copy overlays of buffer FROM to buffer TO. */
604 LIST, but for buffer B. */
605 605
606static struct Lisp_Overlay * 606static void
607copy_overlays (struct buffer *b, struct Lisp_Overlay *list) 607copy_overlays (struct buffer *from, struct buffer *to)
608{ 608{
609 struct Lisp_Overlay *result = NULL, *tail = NULL; 609 eassert (to && ! to->overlays);
610 610
611 for (; list; list = list->next) 611 struct interval_node *node;
612 {
613 Lisp_Object overlay, start, end;
614 struct Lisp_Marker *m;
615
616 eassert (MARKERP (list->start));
617 m = XMARKER (list->start);
618 start = build_marker (b, m->charpos, m->bytepos);
619 XMARKER (start)->insertion_type = m->insertion_type;
620
621 eassert (MARKERP (list->end));
622 m = XMARKER (list->end);
623 end = build_marker (b, m->charpos, m->bytepos);
624 XMARKER (end)->insertion_type = m->insertion_type;
625
626 overlay = build_overlay (start, end, Fcopy_sequence (list->plist));
627 if (tail)
628 tail = tail->next = XOVERLAY (overlay);
629 else
630 result = tail = XOVERLAY (overlay);
631 }
632
633 return result;
634}
635 612
636/* Set an appropriate overlay of B. */ 613 if (! from->overlays)
614 return;
637 615
638static void 616 buffer_overlay_iter_start (from, PTRDIFF_MIN, PTRDIFF_MAX, ITREE_ASCENDING);
639set_buffer_overlays_before (struct buffer *b, struct Lisp_Overlay *o)
640{
641 b->overlays_before = o;
642}
643 617
644static void 618 while ((node = buffer_overlay_iter_next (from)))
645set_buffer_overlays_after (struct buffer *b, struct Lisp_Overlay *o) 619 {
646{ 620 Lisp_Object ov = node->data;
647 b->overlays_after = o; 621 Lisp_Object copy = build_overlay (node->begin, node->end,
622 node->front_advance,
623 node->rear_advance,
624 Fcopy_sequence (OVERLAY_PLIST (ov)));
625 add_buffer_overlay (to, XOVERLAY (copy));
626 }
627 buffer_overlay_iter_finish (from);
648} 628}
649 629
650/* Clone per-buffer values of buffer FROM. 630/* Clone per-buffer values of buffer FROM.
@@ -681,8 +661,7 @@ clone_per_buffer_values (struct buffer *from, struct buffer *to)
681 661
682 memcpy (to->local_flags, from->local_flags, sizeof to->local_flags); 662 memcpy (to->local_flags, from->local_flags, sizeof to->local_flags);
683 663
684 set_buffer_overlays_before (to, copy_overlays (to, from->overlays_before)); 664 copy_overlays (from, to);
685 set_buffer_overlays_after (to, copy_overlays (to, from->overlays_after));
686 665
687 /* Get (a copy of) the alist of Lisp-level local variables of FROM 666 /* Get (a copy of) the alist of Lisp-level local variables of FROM
688 and install that in TO. */ 667 and install that in TO. */
@@ -867,17 +846,16 @@ CLONE nil means the indirect buffer's state is reset to default values. */)
867 return buf; 846 return buf;
868} 847}
869 848
870/* Mark OV as no longer associated with B. */ 849/* Mark OV as no longer associated with its buffer. */
871 850
872static void 851static void
873drop_overlay (struct buffer *b, struct Lisp_Overlay *ov) 852drop_overlay (struct Lisp_Overlay *ov)
874{ 853{
875 eassert (b == XBUFFER (Fmarker_buffer (ov->start))); 854 if (! ov->buffer)
876 modify_overlay (b, marker_position (ov->start), 855 return;
877 marker_position (ov->end));
878 unchain_marker (XMARKER (ov->start));
879 unchain_marker (XMARKER (ov->end));
880 856
857 modify_overlay (ov->buffer, overlay_start (ov), overlay_end (ov));
858 remove_buffer_overlay (ov->buffer, ov);
881} 859}
882 860
883/* Delete all overlays of B and reset its overlay lists. */ 861/* Delete all overlays of B and reset its overlay lists. */
@@ -885,26 +863,20 @@ drop_overlay (struct buffer *b, struct Lisp_Overlay *ov)
885void 863void
886delete_all_overlays (struct buffer *b) 864delete_all_overlays (struct buffer *b)
887{ 865{
888 struct Lisp_Overlay *ov, *next; 866 struct interval_node *node;
889 867
890 /* FIXME: Since each drop_overlay will scan BUF_MARKERS to unlink its 868 if (! b->overlays)
891 markers, we have an unneeded O(N^2) behavior here. */ 869 return;
892 for (ov = b->overlays_before; ov; ov = next)
893 {
894 drop_overlay (b, ov);
895 next = ov->next;
896 ov->next = NULL;
897 }
898 870
899 for (ov = b->overlays_after; ov; ov = next) 871 buffer_overlay_iter_start (b, PTRDIFF_MIN, PTRDIFF_MAX, ITREE_ASCENDING);
872 while ((node = buffer_overlay_iter_next (b)))
900 { 873 {
901 drop_overlay (b, ov); 874 modify_overlay (b, node->begin, node->end);
902 next = ov->next; 875 /* Where are the nodes freed ? --ap */
903 ov->next = NULL; 876 XOVERLAY (node->data)->buffer = NULL;
904 } 877 }
905 878 buffer_overlay_iter_finish (b);
906 set_buffer_overlays_before (b, NULL); 879 interval_tree_clear (b->overlays);
907 set_buffer_overlays_after (b, NULL);
908} 880}
909 881
910/* Reinitialize everything about a buffer except its name and contents 882/* Reinitialize everything about a buffer except its name and contents
@@ -932,9 +904,7 @@ reset_buffer (register struct buffer *b)
932 b->auto_save_failure_time = 0; 904 b->auto_save_failure_time = 0;
933 bset_auto_save_file_name (b, Qnil); 905 bset_auto_save_file_name (b, Qnil);
934 bset_read_only (b, Qnil); 906 bset_read_only (b, Qnil);
935 set_buffer_overlays_before (b, NULL); 907 b->overlays = NULL;
936 set_buffer_overlays_after (b, NULL);
937 b->overlay_center = BEG;
938 bset_mark_active (b, Qnil); 908 bset_mark_active (b, Qnil);
939 bset_point_before_scroll (b, Qnil); 909 bset_point_before_scroll (b, Qnil);
940 bset_file_format (b, Qnil); 910 bset_file_format (b, Qnil);
@@ -1843,10 +1813,8 @@ cleaning up all windows currently displaying the buffer to be killed. */)
1843 1813
1844 /* Perhaps we should explicitly free the interval tree here... */ 1814 /* Perhaps we should explicitly free the interval tree here... */
1845 } 1815 }
1846 /* Since we've unlinked the markers, the overlays can't be here any more 1816 delete_all_overlays (b);
1847 either. */ 1817 free_buffer_overlays (b);
1848 b->overlays_before = NULL;
1849 b->overlays_after = NULL;
1850 1818
1851 /* Reset the local variables, so that this buffer's local values 1819 /* Reset the local variables, so that this buffer's local values
1852 won't be protected from GC. They would be protected 1820 won't be protected from GC. They would be protected
@@ -2254,6 +2222,31 @@ advance_to_char_boundary (ptrdiff_t byte_pos)
2254 return byte_pos; 2222 return byte_pos;
2255} 2223}
2256 2224
2225static void
2226swap_buffer_overlays (struct buffer *buffer, struct buffer *other)
2227{
2228 struct interval_node *node;
2229
2230 if (buffer->overlays)
2231 {
2232 buffer_overlay_iter_start (buffer, PTRDIFF_MIN, PTRDIFF_MAX, ITREE_ASCENDING);
2233 while ((node = buffer_overlay_iter_next (buffer)))
2234 XOVERLAY (node->data)->buffer = other;
2235 buffer_overlay_iter_finish (buffer);
2236 }
2237 if (other->overlays)
2238 {
2239 buffer_overlay_iter_start (other, PTRDIFF_MIN, PTRDIFF_MAX, ITREE_ASCENDING);
2240 while ((node = buffer_overlay_iter_next (other)))
2241 XOVERLAY (node->data)->buffer = buffer;
2242 buffer_overlay_iter_finish (other);
2243 }
2244 /* Swap the interval trees. */
2245 void *tmp = buffer->overlays;
2246 buffer->overlays = other->overlays;
2247 other->overlays = tmp;
2248}
2249
2257DEFUN ("buffer-swap-text", Fbuffer_swap_text, Sbuffer_swap_text, 2250DEFUN ("buffer-swap-text", Fbuffer_swap_text, Sbuffer_swap_text,
2258 1, 1, 0, 2251 1, 1, 0,
2259 doc: /* Swap the text between current buffer and BUFFER. 2252 doc: /* Swap the text between current buffer and BUFFER.
@@ -2324,9 +2317,6 @@ results, see Info node `(elisp)Swapping Text'. */)
2324 swapfield (bidi_paragraph_cache, struct region_cache *); 2317 swapfield (bidi_paragraph_cache, struct region_cache *);
2325 current_buffer->prevent_redisplay_optimizations_p = 1; 2318 current_buffer->prevent_redisplay_optimizations_p = 1;
2326 other_buffer->prevent_redisplay_optimizations_p = 1; 2319 other_buffer->prevent_redisplay_optimizations_p = 1;
2327 swapfield (overlays_before, struct Lisp_Overlay *);
2328 swapfield (overlays_after, struct Lisp_Overlay *);
2329 swapfield (overlay_center, ptrdiff_t);
2330 swapfield_ (undo_list, Lisp_Object); 2320 swapfield_ (undo_list, Lisp_Object);
2331 swapfield_ (mark, Lisp_Object); 2321 swapfield_ (mark, Lisp_Object);
2332 swapfield_ (enable_multibyte_characters, Lisp_Object); 2322 swapfield_ (enable_multibyte_characters, Lisp_Object);
@@ -2349,6 +2339,7 @@ results, see Info node `(elisp)Swapping Text'. */)
2349 current_buffer->text->end_unchanged = current_buffer->text->gpt; 2339 current_buffer->text->end_unchanged = current_buffer->text->gpt;
2350 other_buffer->text->beg_unchanged = other_buffer->text->gpt; 2340 other_buffer->text->beg_unchanged = other_buffer->text->gpt;
2351 other_buffer->text->end_unchanged = other_buffer->text->gpt; 2341 other_buffer->text->end_unchanged = other_buffer->text->gpt;
2342 swap_buffer_overlays (current_buffer, other_buffer);
2352 { 2343 {
2353 struct Lisp_Marker *m; 2344 struct Lisp_Marker *m;
2354 for (m = BUF_MARKERS (current_buffer); m; m = m->next) 2345 for (m = BUF_MARKERS (current_buffer); m; m = m->next)
@@ -2763,285 +2754,160 @@ swap_out_buffer_local_variables (struct buffer *b)
2763 } 2754 }
2764 } 2755 }
2765} 2756}
2757
2766 2758
2767/* Find all the overlays in the current buffer that contain position POS. 2759/* Find all the overlays in the current buffer that overlap the range
2760 [BEG, END).
2761
2762 If EMPTY is true, include empty overlays in that range and also at
2763 END, provided END denotes the position at the end of the buffer.
2764
2768 Return the number found, and store them in a vector in *VEC_PTR. 2765 Return the number found, and store them in a vector in *VEC_PTR.
2769 Store in *LEN_PTR the size allocated for the vector. 2766 Store in *LEN_PTR the size allocated for the vector.
2770 Store in *NEXT_PTR the next position after POS where an overlay starts, 2767 Store in *NEXT_PTR the next position after POS where an overlay starts,
2771 or ZV if there are no more overlays between POS and ZV. 2768 or ZV if there are no more overlays.
2772 Store in *PREV_PTR the previous position before POS where an overlay ends, 2769 NEXT_PTR may be 0, meaning don't store that info.
2773 or where an overlay starts which ends at or after POS;
2774 or BEGV if there are no such overlays from BEGV to POS.
2775 NEXT_PTR and/or PREV_PTR may be 0, meaning don't store that info.
2776 2770
2777 *VEC_PTR and *LEN_PTR should contain a valid vector and size 2771 *VEC_PTR and *LEN_PTR should contain a valid vector and size
2778 when this function is called. 2772 when this function is called.
2779 2773
2780 If EXTEND, make the vector bigger if necessary. 2774 If EXTEND, make the vector bigger if necessary. If not, never
2781 If not, never extend the vector, 2775 extend the vector, and store only as many overlays as will fit.
2782 and store only as many overlays as will fit.
2783 But still return the total number of overlays. 2776 But still return the total number of overlays.
2784 2777*/
2785 If CHANGE_REQ, any position written into *PREV_PTR or
2786 *NEXT_PTR is guaranteed to be not equal to POS, unless it is the
2787 default (BEGV or ZV). */
2788 2778
2789ptrdiff_t 2779ptrdiff_t
2790overlays_at (EMACS_INT pos, bool extend, Lisp_Object **vec_ptr, 2780overlays_in (ptrdiff_t beg, ptrdiff_t end, bool extend,
2791 ptrdiff_t *len_ptr, 2781 Lisp_Object **vec_ptr, ptrdiff_t *len_ptr, bool empty,
2792 ptrdiff_t *next_ptr, ptrdiff_t *prev_ptr, bool change_req) 2782 ptrdiff_t *next_ptr)
2793{ 2783{
2794 Lisp_Object overlay, start, end;
2795 struct Lisp_Overlay *tail;
2796 ptrdiff_t idx = 0; 2784 ptrdiff_t idx = 0;
2797 ptrdiff_t len = *len_ptr; 2785 ptrdiff_t len = *len_ptr;
2798 Lisp_Object *vec = *vec_ptr;
2799 ptrdiff_t next = ZV; 2786 ptrdiff_t next = ZV;
2800 ptrdiff_t prev = BEGV; 2787 Lisp_Object *vec = *vec_ptr;
2801 bool inhibit_storing = 0;
2802
2803 for (tail = current_buffer->overlays_before; tail; tail = tail->next)
2804 {
2805 ptrdiff_t startpos, endpos;
2806 2788
2807 XSETMISC (overlay, tail); 2789 struct interval_node *node;
2808 2790
2809 start = OVERLAY_START (overlay); 2791 if (! current_buffer->overlays)
2810 end = OVERLAY_END (overlay); 2792 return idx;
2811 endpos = OVERLAY_POSITION (end);
2812 if (endpos < pos)
2813 {
2814 if (prev < endpos)
2815 prev = endpos;
2816 break;
2817 }
2818 startpos = OVERLAY_POSITION (start);
2819 /* This one ends at or after POS
2820 so its start counts for PREV_PTR if it's before POS. */
2821 if (prev < startpos && startpos < pos)
2822 prev = startpos;
2823 if (endpos == pos)
2824 continue;
2825 if (startpos <= pos)
2826 {
2827 if (idx == len)
2828 {
2829 /* The supplied vector is full.
2830 Either make it bigger, or don't store any more in it. */
2831 if (extend)
2832 {
2833 vec = xpalloc (vec, len_ptr, 1, OVERLAY_COUNT_MAX,
2834 sizeof *vec);
2835 *vec_ptr = vec;
2836 len = *len_ptr;
2837 }
2838 else
2839 inhibit_storing = 1;
2840 }
2841 2793
2842 if (!inhibit_storing) 2794 buffer_overlay_iter_start (current_buffer, beg,
2843 vec[idx] = overlay; 2795 /* Find empty OV at Z ? */
2844 /* Keep counting overlays even if we can't return them all. */ 2796 (end >= Z && empty) ? Z + 1 : ZV,
2845 idx++; 2797 ITREE_ASCENDING);
2846 }
2847 else if (startpos < next)
2848 next = startpos;
2849 }
2850 2798
2851 for (tail = current_buffer->overlays_after; tail; tail = tail->next) 2799 while ((node = buffer_overlay_iter_next (current_buffer)))
2852 { 2800 {
2853 ptrdiff_t startpos, endpos; 2801 if (node->begin > end)
2854 2802 {
2855 XSETMISC (overlay, tail); 2803 next = min (next, node->begin);
2856 2804 break;
2857 start = OVERLAY_START (overlay); 2805 }
2858 end = OVERLAY_END (overlay); 2806 else if (node->begin == end)
2859 startpos = OVERLAY_POSITION (start); 2807 {
2860 if (pos < startpos) 2808 next = node->begin;
2861 { 2809 if ((! empty || end < Z) && beg < end)
2862 if (startpos < next) 2810 break;
2863 next = startpos; 2811 }
2864 break;
2865 }
2866 endpos = OVERLAY_POSITION (end);
2867 if (pos < endpos)
2868 {
2869 if (idx == len)
2870 {
2871 if (extend)
2872 {
2873 vec = xpalloc (vec, len_ptr, 1, OVERLAY_COUNT_MAX,
2874 sizeof *vec);
2875 *vec_ptr = vec;
2876 len = *len_ptr;
2877 }
2878 else
2879 inhibit_storing = 1;
2880 }
2881 2812
2882 if (!inhibit_storing) 2813 if (! empty && node->begin == node->end)
2883 vec[idx] = overlay; 2814 continue;
2884 idx++;
2885 2815
2886 if (startpos < pos && startpos > prev) 2816 if (extend && idx == len)
2887 prev = startpos; 2817 {
2888 } 2818 vec = xpalloc (vec, len_ptr, 1, OVERLAY_COUNT_MAX,
2889 else if (endpos < pos && endpos > prev) 2819 sizeof *vec);
2890 prev = endpos; 2820 *vec_ptr = vec;
2891 else if (endpos == pos && startpos > prev 2821 len = *len_ptr;
2892 && (!change_req || startpos < pos)) 2822 }
2893 prev = startpos; 2823 if (idx < len)
2824 vec[idx] = node->data;
2825 /* Keep counting overlays even if we can't return them all. */
2826 idx++;
2894 } 2827 }
2895 2828 buffer_overlay_iter_finish (current_buffer);
2896 if (next_ptr) 2829 if (next_ptr)
2897 *next_ptr = next; 2830 *next_ptr = next ? next : ZV;
2898 if (prev_ptr) 2831
2899 *prev_ptr = prev;
2900 return idx; 2832 return idx;
2901} 2833}
2902
2903/* Find all the overlays in the current buffer that overlap the range
2904 BEG-END, or are empty at BEG, or are empty at END provided END
2905 denotes the position at the end of the current buffer.
2906 2834
2907 Return the number found, and store them in a vector in *VEC_PTR. 2835/* Find all non-empty overlays in the current buffer that contain
2908 Store in *LEN_PTR the size allocated for the vector. 2836 position POS.
2909 Store in *NEXT_PTR the next position after POS where an overlay starts,
2910 or ZV if there are no more overlays.
2911 Store in *PREV_PTR the previous position before POS where an overlay ends,
2912 or BEGV if there are no previous overlays.
2913 NEXT_PTR and/or PREV_PTR may be 0, meaning don't store that info.
2914 2837
2915 *VEC_PTR and *LEN_PTR should contain a valid vector and size 2838 See overlays_in for the meaning of the arguments.
2916 when this function is called. 2839 */
2917 2840
2918 If EXTEND, make the vector bigger if necessary. 2841ptrdiff_t
2919 If not, never extend the vector, 2842overlays_at (ptrdiff_t pos, bool extend,
2920 and store only as many overlays as will fit. 2843 Lisp_Object **vec_ptr, ptrdiff_t *len_ptr,
2921 But still return the total number of overlays. */ 2844 ptrdiff_t *next_ptr)
2845{
2846 return overlays_in (pos, pos + 1, extend, vec_ptr, len_ptr, false, next_ptr);
2847}
2922 2848
2923static ptrdiff_t 2849ptrdiff_t
2924overlays_in (EMACS_INT beg, EMACS_INT end, bool extend, 2850next_overlay_change (ptrdiff_t pos)
2925 Lisp_Object **vec_ptr, ptrdiff_t *len_ptr,
2926 ptrdiff_t *next_ptr, ptrdiff_t *prev_ptr)
2927{ 2851{
2928 Lisp_Object overlay, ostart, oend;
2929 struct Lisp_Overlay *tail;
2930 ptrdiff_t idx = 0;
2931 ptrdiff_t len = *len_ptr;
2932 Lisp_Object *vec = *vec_ptr;
2933 ptrdiff_t next = ZV; 2852 ptrdiff_t next = ZV;
2934 ptrdiff_t prev = BEGV; 2853 struct interval_node *node;
2935 bool inhibit_storing = 0;
2936 bool end_is_Z = end == Z;
2937 2854
2938 for (tail = current_buffer->overlays_before; tail; tail = tail->next) 2855 if (! current_buffer->overlays)
2939 { 2856 return next;
2940 ptrdiff_t startpos, endpos;
2941 2857
2942 XSETMISC (overlay, tail); 2858 buffer_overlay_iter_start (current_buffer, pos, ZV, ITREE_ASCENDING);
2943 2859 while ((node = buffer_overlay_iter_next (current_buffer)))
2944 ostart = OVERLAY_START (overlay); 2860 {
2945 oend = OVERLAY_END (overlay); 2861 if (node->begin > pos)
2946 endpos = OVERLAY_POSITION (oend); 2862 {
2947 if (endpos < beg) 2863 /* If we reach this branch, node->begin must be the least upper bound
2948 { 2864 of pos, because the search is limited to [pos,next) . */
2949 if (prev < endpos) 2865 eassert (node->begin < next);
2950 prev = endpos; 2866 next = node->begin;
2951 break; 2867 break;
2952 } 2868 }
2953 startpos = OVERLAY_POSITION (ostart); 2869 else if (node->begin < node->end && node->end < next)
2954 /* Count an interval if it overlaps the range, is empty at the 2870 {
2955 start of the range, or is empty at END provided END denotes the 2871 next = node->end;
2956 end of the buffer. */ 2872 buffer_overlay_iter_narrow (current_buffer, pos, next);
2957 if ((beg < endpos && startpos < end) 2873 }
2958 || (startpos == endpos
2959 && (beg == endpos || (end_is_Z && endpos == end))))
2960 {
2961 if (idx == len)
2962 {
2963 /* The supplied vector is full.
2964 Either make it bigger, or don't store any more in it. */
2965 if (extend)
2966 {
2967 vec = xpalloc (vec, len_ptr, 1, OVERLAY_COUNT_MAX,
2968 sizeof *vec);
2969 *vec_ptr = vec;
2970 len = *len_ptr;
2971 }
2972 else
2973 inhibit_storing = 1;
2974 }
2975
2976 if (!inhibit_storing)
2977 vec[idx] = overlay;
2978 /* Keep counting overlays even if we can't return them all. */
2979 idx++;
2980 }
2981 else if (startpos < next)
2982 next = startpos;
2983 } 2874 }
2875 buffer_overlay_iter_finish (current_buffer);
2984 2876
2985 for (tail = current_buffer->overlays_after; tail; tail = tail->next) 2877 return next;
2986 { 2878}
2987 ptrdiff_t startpos, endpos;
2988 2879
2989 XSETMISC (overlay, tail); 2880ptrdiff_t
2881previous_overlay_change (ptrdiff_t pos)
2882{
2883 struct interval_node *node;
2884 ptrdiff_t prev = BEGV;
2990 2885
2991 ostart = OVERLAY_START (overlay); 2886 if (! current_buffer->overlays)
2992 oend = OVERLAY_END (overlay); 2887 return prev;
2993 startpos = OVERLAY_POSITION (ostart);
2994 if (end < startpos)
2995 {
2996 if (startpos < next)
2997 next = startpos;
2998 break;
2999 }
3000 endpos = OVERLAY_POSITION (oend);
3001 /* Count an interval if it overlaps the range, is empty at the
3002 start of the range, or is empty at END provided END denotes the
3003 end of the buffer. */
3004 if ((beg < endpos && startpos < end)
3005 || (startpos == endpos
3006 && (beg == endpos || (end_is_Z && endpos == end))))
3007 {
3008 if (idx == len)
3009 {
3010 if (extend)
3011 {
3012 vec = xpalloc (vec, len_ptr, 1, OVERLAY_COUNT_MAX,
3013 sizeof *vec);
3014 *vec_ptr = vec;
3015 len = *len_ptr;
3016 }
3017 else
3018 inhibit_storing = 1;
3019 }
3020 2888
3021 if (!inhibit_storing) 2889 buffer_overlay_iter_start (current_buffer, BEGV, pos, ITREE_DESCENDING);
3022 vec[idx] = overlay; 2890 while ((node = buffer_overlay_iter_next (current_buffer)))
3023 idx++; 2891 {
3024 } 2892 if (node->end < pos)
3025 else if (endpos < beg && endpos > prev) 2893 prev = node->end;
3026 prev = endpos; 2894 else
2895 prev = max (prev, node->begin);
2896 buffer_overlay_iter_narrow (current_buffer, prev, pos);
3027 } 2897 }
2898 buffer_overlay_iter_finish (current_buffer);
3028 2899
3029 if (next_ptr) 2900 return prev;
3030 *next_ptr = next;
3031 if (prev_ptr)
3032 *prev_ptr = prev;
3033 return idx;
3034} 2901}
3035 2902
3036
3037/* Return true if there exists an overlay with a non-nil 2903/* Return true if there exists an overlay with a non-nil
3038 `mouse-face' property overlapping OVERLAY. */ 2904 `mouse-face' property overlapping OVERLAY. */
3039 2905
3040bool 2906bool
3041mouse_face_overlay_overlaps (Lisp_Object overlay) 2907mouse_face_overlay_overlaps (Lisp_Object overlay)
3042{ 2908{
3043 ptrdiff_t start = OVERLAY_POSITION (OVERLAY_START (overlay)); 2909 ptrdiff_t start = OVERLAY_START (overlay);
3044 ptrdiff_t end = OVERLAY_POSITION (OVERLAY_END (overlay)); 2910 ptrdiff_t end = OVERLAY_END (overlay);
3045 ptrdiff_t n, i, size; 2911 ptrdiff_t n, i, size;
3046 Lisp_Object *v, tem; 2912 Lisp_Object *v, tem;
3047 Lisp_Object vbuf[10]; 2913 Lisp_Object vbuf[10];
@@ -3049,11 +2915,11 @@ mouse_face_overlay_overlaps (Lisp_Object overlay)
3049 2915
3050 size = ARRAYELTS (vbuf); 2916 size = ARRAYELTS (vbuf);
3051 v = vbuf; 2917 v = vbuf;
3052 n = overlays_in (start, end, 0, &v, &size, NULL, NULL); 2918 n = overlays_in (start, end, 0, &v, &size, true, NULL);
3053 if (n > size) 2919 if (n > size)
3054 { 2920 {
3055 SAFE_NALLOCA (v, 1, n); 2921 SAFE_NALLOCA (v, 1, n);
3056 overlays_in (start, end, 0, &v, &n, NULL, NULL); 2922 overlays_in (start, end, 0, &v, &n, true, NULL);
3057 } 2923 }
3058 2924
3059 for (i = 0; i < n; ++i) 2925 for (i = 0; i < n; ++i)
@@ -3095,52 +2961,34 @@ disable_line_numbers_overlay_at_eob (void)
3095} 2961}
3096 2962
3097 2963
3098/* Fast function to just test if we're at an overlay boundary. */ 2964/* Fast function to just test if we're at an overlay boundary.
2965
2966 Returns true if some overlay starts or ends (or both) at POS,
2967*/
3099bool 2968bool
3100overlay_touches_p (ptrdiff_t pos) 2969overlay_touches_p (ptrdiff_t pos)
3101{ 2970{
3102 Lisp_Object overlay; 2971 struct interval_node *node;
3103 struct Lisp_Overlay *tail; 2972 bool result = false;
3104
3105 for (tail = current_buffer->overlays_before; tail; tail = tail->next)
3106 {
3107 ptrdiff_t endpos;
3108 2973
3109 XSETMISC (overlay ,tail); 2974 if (! current_buffer->overlays)
3110 eassert (OVERLAYP (overlay)); 2975 return false;
3111 2976
3112 endpos = OVERLAY_POSITION (OVERLAY_END (overlay)); 2977 /* We need to find overlays ending in pos, as well as empty ones at
3113 if (endpos < pos) 2978 pos. */
3114 break; 2979 buffer_overlay_iter_start (current_buffer,
3115 if (endpos == pos || OVERLAY_POSITION (OVERLAY_START (overlay)) == pos) 2980 pos - 1, pos + 1, ITREE_DESCENDING);
3116 return 1;
3117 }
3118 2981
3119 for (tail = current_buffer->overlays_after; tail; tail = tail->next) 2982 while (! result && (node = buffer_overlay_iter_next (current_buffer)))
3120 { 2983 result = (node->begin == pos || node->end == pos);
3121 ptrdiff_t startpos;
3122 2984
3123 XSETMISC (overlay, tail); 2985 buffer_overlay_iter_finish (current_buffer);
3124 eassert (OVERLAYP (overlay));
3125 2986
3126 startpos = OVERLAY_POSITION (OVERLAY_START (overlay)); 2987 return result;
3127 if (pos < startpos)
3128 break;
3129 if (startpos == pos || OVERLAY_POSITION (OVERLAY_END (overlay)) == pos)
3130 return 1;
3131 }
3132 return 0;
3133} 2988}
3134
3135struct sortvec
3136{
3137 Lisp_Object overlay;
3138 ptrdiff_t beg, end;
3139 EMACS_INT priority;
3140 EMACS_INT spriority; /* Secondary priority. */
3141};
3142 2989
3143static int 2990
2991int
3144compare_overlays (const void *v1, const void *v2) 2992compare_overlays (const void *v1, const void *v2)
3145{ 2993{
3146 const struct sortvec *s1 = v1; 2994 const struct sortvec *s1 = v1;
@@ -3169,6 +3017,33 @@ compare_overlays (const void *v1, const void *v2)
3169 return XLI (s1->overlay) < XLI (s2->overlay) ? -1 : 1; 3017 return XLI (s1->overlay) < XLI (s2->overlay) ? -1 : 1;
3170} 3018}
3171 3019
3020void
3021make_sortvec_item (struct sortvec *item, Lisp_Object overlay)
3022{
3023 Lisp_Object tem;
3024 /* This overlay is good and counts: put it into sortvec. */
3025 item->overlay = overlay;
3026 item->beg = OVERLAY_START (overlay);
3027 item->end = OVERLAY_END (overlay);
3028 tem = Foverlay_get (overlay, Qpriority);
3029 if (NILP (tem))
3030 {
3031 item->priority = 0;
3032 item->spriority = 0;
3033 }
3034 else if (INTEGERP (tem))
3035 {
3036 item->priority = XINT (tem);
3037 item->spriority = 0;
3038 }
3039 else if (CONSP (tem))
3040 {
3041 Lisp_Object car = XCAR (tem);
3042 Lisp_Object cdr = XCDR (tem);
3043 item->priority = INTEGERP (car) ? XINT (car) : 0;
3044 item->spriority = INTEGERP (cdr) ? XINT (cdr) : 0;
3045 }
3046}
3172/* Sort an array of overlays by priority. The array is modified in place. 3047/* Sort an array of overlays by priority. The array is modified in place.
3173 The return value is the new size; this may be smaller than the original 3048 The return value is the new size; this may be smaller than the original
3174 size if some of the overlays were invalid or were window-specific. */ 3049 size if some of the overlays were invalid or were window-specific. */
@@ -3185,47 +3060,18 @@ sort_overlays (Lisp_Object *overlay_vec, ptrdiff_t noverlays, struct window *w)
3185 3060
3186 for (i = 0, j = 0; i < noverlays; i++) 3061 for (i = 0, j = 0; i < noverlays; i++)
3187 { 3062 {
3188 Lisp_Object tem;
3189 Lisp_Object overlay; 3063 Lisp_Object overlay;
3190 3064
3191 overlay = overlay_vec[i]; 3065 overlay = overlay_vec[i];
3192 if (OVERLAYP (overlay) 3066 if (OVERLAYP (overlay)
3193 && OVERLAY_POSITION (OVERLAY_START (overlay)) > 0 3067 && OVERLAY_START (overlay) > 0
3194 && OVERLAY_POSITION (OVERLAY_END (overlay)) > 0) 3068 && OVERLAY_END (overlay) > 0)
3195 { 3069 {
3196 /* If we're interested in a specific window, then ignore 3070 /* If we're interested in a specific window, then ignore
3197 overlays that are limited to some other window. */ 3071 overlays that are limited to some other window. */
3198 if (w) 3072 if (w && ! overlay_matches_window (w, overlay))
3199 { 3073 continue;
3200 Lisp_Object window; 3074 make_sortvec_item (sortvec + j, overlay);
3201
3202 window = Foverlay_get (overlay, Qwindow);
3203 if (WINDOWP (window) && XWINDOW (window) != w)
3204 continue;
3205 }
3206
3207 /* This overlay is good and counts: put it into sortvec. */
3208 sortvec[j].overlay = overlay;
3209 sortvec[j].beg = OVERLAY_POSITION (OVERLAY_START (overlay));
3210 sortvec[j].end = OVERLAY_POSITION (OVERLAY_END (overlay));
3211 tem = Foverlay_get (overlay, Qpriority);
3212 if (NILP (tem))
3213 {
3214 sortvec[j].priority = 0;
3215 sortvec[j].spriority = 0;
3216 }
3217 else if (INTEGERP (tem))
3218 {
3219 sortvec[j].priority = XINT (tem);
3220 sortvec[j].spriority = 0;
3221 }
3222 else if (CONSP (tem))
3223 {
3224 Lisp_Object car = XCAR (tem);
3225 Lisp_Object cdr = XCDR (tem);
3226 sortvec[j].priority = INTEGERP (car) ? XINT (car) : 0;
3227 sortvec[j].spriority = INTEGERP (cdr) ? XINT (cdr) : 0;
3228 }
3229 j++; 3075 j++;
3230 } 3076 }
3231 } 3077 }
@@ -3340,68 +3186,44 @@ ptrdiff_t
3340overlay_strings (ptrdiff_t pos, struct window *w, unsigned char **pstr) 3186overlay_strings (ptrdiff_t pos, struct window *w, unsigned char **pstr)
3341{ 3187{
3342 Lisp_Object overlay, window, str; 3188 Lisp_Object overlay, window, str;
3343 struct Lisp_Overlay *ov; 3189 ptrdiff_t obegin, oend;
3344 ptrdiff_t startpos, endpos;
3345 bool multibyte = ! NILP (BVAR (current_buffer, enable_multibyte_characters)); 3190 bool multibyte = ! NILP (BVAR (current_buffer, enable_multibyte_characters));
3191 struct interval_node *node;
3346 3192
3347 overlay_heads.used = overlay_heads.bytes = 0; 3193 overlay_heads.used = overlay_heads.bytes = 0;
3348 overlay_tails.used = overlay_tails.bytes = 0; 3194 overlay_tails.used = overlay_tails.bytes = 0;
3349 for (ov = current_buffer->overlays_before; ov; ov = ov->next) 3195
3196 buffer_overlay_iter_start (current_buffer,
3197 pos - 1, pos + 1, ITREE_DESCENDING);
3198 while ((node = buffer_overlay_iter_next (current_buffer)))
3350 { 3199 {
3351 XSETMISC (overlay, ov); 3200 overlay = node->data;
3352 eassert (OVERLAYP (overlay)); 3201 eassert (OVERLAYP (overlay));
3353 3202
3354 startpos = OVERLAY_POSITION (OVERLAY_START (overlay)); 3203 obegin = node->begin;
3355 endpos = OVERLAY_POSITION (OVERLAY_END (overlay)); 3204 oend = node->end;
3356 if (endpos < pos) 3205
3357 break; 3206 if (oend != pos && obegin != pos)
3358 if (endpos != pos && startpos != pos)
3359 continue; 3207 continue;
3360 window = Foverlay_get (overlay, Qwindow); 3208 window = Foverlay_get (overlay, Qwindow);
3361 if (WINDOWP (window) && XWINDOW (window) != w) 3209 if (WINDOWP (window) && XWINDOW (window) != w)
3362 continue; 3210 continue;
3363 if (startpos == pos 3211 if (obegin == pos
3364 && (str = Foverlay_get (overlay, Qbefore_string), STRINGP (str))) 3212 && (str = Foverlay_get (overlay, Qbefore_string), STRINGP (str)))
3365 record_overlay_string (&overlay_heads, str, 3213 record_overlay_string (&overlay_heads, str,
3366 (startpos == endpos 3214 (obegin == oend
3367 ? Foverlay_get (overlay, Qafter_string) 3215 ? Foverlay_get (overlay, Qafter_string)
3368 : Qnil), 3216 : Qnil),
3369 Foverlay_get (overlay, Qpriority), 3217 Foverlay_get (overlay, Qpriority),
3370 endpos - startpos); 3218 oend - obegin);
3371 else if (endpos == pos 3219 else if (oend == pos
3372 && (str = Foverlay_get (overlay, Qafter_string), STRINGP (str))) 3220 && (str = Foverlay_get (overlay, Qafter_string), STRINGP (str)))
3373 record_overlay_string (&overlay_tails, str, Qnil, 3221 record_overlay_string (&overlay_tails, str, Qnil,
3374 Foverlay_get (overlay, Qpriority), 3222 Foverlay_get (overlay, Qpriority),
3375 endpos - startpos); 3223 oend - obegin);
3376 } 3224 }
3377 for (ov = current_buffer->overlays_after; ov; ov = ov->next) 3225 buffer_overlay_iter_finish (current_buffer);
3378 {
3379 XSETMISC (overlay, ov);
3380 eassert (OVERLAYP (overlay));
3381 3226
3382 startpos = OVERLAY_POSITION (OVERLAY_START (overlay));
3383 endpos = OVERLAY_POSITION (OVERLAY_END (overlay));
3384 if (startpos > pos)
3385 break;
3386 if (endpos != pos && startpos != pos)
3387 continue;
3388 window = Foverlay_get (overlay, Qwindow);
3389 if (WINDOWP (window) && XWINDOW (window) != w)
3390 continue;
3391 if (startpos == pos
3392 && (str = Foverlay_get (overlay, Qbefore_string), STRINGP (str)))
3393 record_overlay_string (&overlay_heads, str,
3394 (startpos == endpos
3395 ? Foverlay_get (overlay, Qafter_string)
3396 : Qnil),
3397 Foverlay_get (overlay, Qpriority),
3398 endpos - startpos);
3399 else if (endpos == pos
3400 && (str = Foverlay_get (overlay, Qafter_string), STRINGP (str)))
3401 record_overlay_string (&overlay_tails, str, Qnil,
3402 Foverlay_get (overlay, Qpriority),
3403 endpos - startpos);
3404 }
3405 if (overlay_tails.used > 1) 3227 if (overlay_tails.used > 1)
3406 qsort (overlay_tails.buf, overlay_tails.used, sizeof (struct sortstr), 3228 qsort (overlay_tails.buf, overlay_tails.used, sizeof (struct sortstr),
3407 cmp_for_strings); 3229 cmp_for_strings);
@@ -3456,385 +3278,26 @@ overlay_strings (ptrdiff_t pos, struct window *w, unsigned char **pstr)
3456 } 3278 }
3457 return 0; 3279 return 0;
3458} 3280}
3459
3460/* Shift overlays in BUF's overlay lists, to center the lists at POS. */
3461
3462void
3463recenter_overlay_lists (struct buffer *buf, ptrdiff_t pos)
3464{
3465 Lisp_Object overlay, beg, end;
3466 struct Lisp_Overlay *prev, *tail, *next;
3467
3468 /* See if anything in overlays_before should move to overlays_after. */
3469
3470 /* We don't strictly need prev in this loop; it should always be nil.
3471 But we use it for symmetry and in case that should cease to be true
3472 with some future change. */
3473 prev = NULL;
3474 for (tail = buf->overlays_before; tail; prev = tail, tail = next)
3475 {
3476 next = tail->next;
3477 XSETMISC (overlay, tail);
3478 eassert (OVERLAYP (overlay));
3479
3480 beg = OVERLAY_START (overlay);
3481 end = OVERLAY_END (overlay);
3482
3483 if (OVERLAY_POSITION (end) > pos)
3484 {
3485 /* OVERLAY needs to be moved. */
3486 ptrdiff_t where = OVERLAY_POSITION (beg);
3487 struct Lisp_Overlay *other, *other_prev;
3488
3489 /* Splice the cons cell TAIL out of overlays_before. */
3490 if (prev)
3491 prev->next = next;
3492 else
3493 set_buffer_overlays_before (buf, next);
3494
3495 /* Search thru overlays_after for where to put it. */
3496 other_prev = NULL;
3497 for (other = buf->overlays_after; other;
3498 other_prev = other, other = other->next)
3499 {
3500 Lisp_Object otherbeg, otheroverlay;
3501
3502 XSETMISC (otheroverlay, other);
3503 eassert (OVERLAYP (otheroverlay));
3504
3505 otherbeg = OVERLAY_START (otheroverlay);
3506 if (OVERLAY_POSITION (otherbeg) >= where)
3507 break;
3508 }
3509
3510 /* Add TAIL to overlays_after before OTHER. */
3511 tail->next = other;
3512 if (other_prev)
3513 other_prev->next = tail;
3514 else
3515 set_buffer_overlays_after (buf, tail);
3516 tail = prev;
3517 }
3518 else
3519 /* We've reached the things that should stay in overlays_before.
3520 All the rest of overlays_before must end even earlier,
3521 so stop now. */
3522 break;
3523 }
3524
3525 /* See if anything in overlays_after should be in overlays_before. */
3526 prev = NULL;
3527 for (tail = buf->overlays_after; tail; prev = tail, tail = next)
3528 {
3529 next = tail->next;
3530 XSETMISC (overlay, tail);
3531 eassert (OVERLAYP (overlay));
3532
3533 beg = OVERLAY_START (overlay);
3534 end = OVERLAY_END (overlay);
3535
3536 /* Stop looking, when we know that nothing further
3537 can possibly end before POS. */
3538 if (OVERLAY_POSITION (beg) > pos)
3539 break;
3540
3541 if (OVERLAY_POSITION (end) <= pos)
3542 {
3543 /* OVERLAY needs to be moved. */
3544 ptrdiff_t where = OVERLAY_POSITION (end);
3545 struct Lisp_Overlay *other, *other_prev;
3546
3547 /* Splice the cons cell TAIL out of overlays_after. */
3548 if (prev)
3549 prev->next = next;
3550 else
3551 set_buffer_overlays_after (buf, next);
3552
3553 /* Search thru overlays_before for where to put it. */
3554 other_prev = NULL;
3555 for (other = buf->overlays_before; other;
3556 other_prev = other, other = other->next)
3557 {
3558 Lisp_Object otherend, otheroverlay;
3559
3560 XSETMISC (otheroverlay, other);
3561 eassert (OVERLAYP (otheroverlay));
3562
3563 otherend = OVERLAY_END (otheroverlay);
3564 if (OVERLAY_POSITION (otherend) <= where)
3565 break;
3566 }
3567
3568 /* Add TAIL to overlays_before before OTHER. */
3569 tail->next = other;
3570 if (other_prev)
3571 other_prev->next = tail;
3572 else
3573 set_buffer_overlays_before (buf, tail);
3574 tail = prev;
3575 }
3576 }
3577
3578 buf->overlay_center = pos;
3579}
3580 3281
3282
3581void 3283void
3582adjust_overlays_for_insert (ptrdiff_t pos, ptrdiff_t length) 3284adjust_overlays_for_insert (ptrdiff_t pos, ptrdiff_t length)
3583{ 3285{
3584 /* After an insertion, the lists are still sorted properly, 3286 /* After an insertion, the lists are still sorted properly,
3585 but we may need to update the value of the overlay center. */ 3287 but we may need to update the value of the overlay center. */
3586 if (current_buffer->overlay_center >= pos) 3288 if (! current_buffer->overlays)
3587 current_buffer->overlay_center += length; 3289 return;
3290 interval_tree_insert_gap (current_buffer->overlays, pos, length);
3588} 3291}
3589 3292
3590void 3293void
3591adjust_overlays_for_delete (ptrdiff_t pos, ptrdiff_t length) 3294adjust_overlays_for_delete (ptrdiff_t pos, ptrdiff_t length)
3592{ 3295{
3593 if (current_buffer->overlay_center < pos) 3296 if (! current_buffer->overlays)
3594 /* The deletion was to our right. No change needed; the before- and
3595 after-lists are still consistent. */
3596 ;
3597 else if (current_buffer->overlay_center - pos > length)
3598 /* The deletion was to our left. We need to adjust the center value
3599 to account for the change in position, but the lists are consistent
3600 given the new value. */
3601 current_buffer->overlay_center -= length;
3602 else
3603 /* We're right in the middle. There might be things on the after-list
3604 that now belong on the before-list. Recentering will move them,
3605 and also update the center point. */
3606 recenter_overlay_lists (current_buffer, pos);
3607}
3608
3609/* Fix up overlays that were garbled as a result of permuting markers
3610 in the range START through END. Any overlay with at least one
3611 endpoint in this range will need to be unlinked from the overlay
3612 list and reinserted in its proper place.
3613 Such an overlay might even have negative size at this point.
3614 If so, we'll make the overlay empty. */
3615void
3616fix_start_end_in_overlays (register ptrdiff_t start, register ptrdiff_t end)
3617{
3618 Lisp_Object overlay;
3619 struct Lisp_Overlay *before_list;
3620 struct Lisp_Overlay *after_list;
3621 /* These are either nil, indicating that before_list or after_list
3622 should be assigned, or the cons cell the cdr of which should be
3623 assigned. */
3624 struct Lisp_Overlay *beforep = NULL, *afterp = NULL;
3625 /* 'Parent', likewise, indicates a cons cell or
3626 current_buffer->overlays_before or overlays_after, depending
3627 which loop we're in. */
3628 struct Lisp_Overlay *tail, *parent;
3629 ptrdiff_t startpos, endpos;
3630
3631 /* This algorithm shifts links around instead of consing and GCing.
3632 The loop invariant is that before_list (resp. after_list) is a
3633 well-formed list except that its last element, the CDR of beforep
3634 (resp. afterp) if beforep (afterp) isn't nil or before_list
3635 (after_list) if it is, is still uninitialized. So it's not a bug
3636 that before_list isn't initialized, although it may look
3637 strange. */
3638 for (parent = NULL, tail = current_buffer->overlays_before; tail;)
3639 {
3640 XSETMISC (overlay, tail);
3641
3642 endpos = OVERLAY_POSITION (OVERLAY_END (overlay));
3643 startpos = OVERLAY_POSITION (OVERLAY_START (overlay));
3644
3645 /* If the overlay is backwards, make it empty. */
3646 if (endpos < startpos)
3647 {
3648 startpos = endpos;
3649 Fset_marker (OVERLAY_START (overlay), make_number (startpos),
3650 Qnil);
3651 }
3652
3653 if (endpos < start)
3654 break;
3655
3656 if (endpos < end
3657 || (startpos >= start && startpos < end))
3658 {
3659 /* Add it to the end of the wrong list. Later on,
3660 recenter_overlay_lists will move it to the right place. */
3661 if (endpos < current_buffer->overlay_center)
3662 {
3663 if (!afterp)
3664 after_list = tail;
3665 else
3666 afterp->next = tail;
3667 afterp = tail;
3668 }
3669 else
3670 {
3671 if (!beforep)
3672 before_list = tail;
3673 else
3674 beforep->next = tail;
3675 beforep = tail;
3676 }
3677 if (!parent)
3678 set_buffer_overlays_before (current_buffer, tail->next);
3679 else
3680 parent->next = tail->next;
3681 tail = tail->next;
3682 }
3683 else
3684 parent = tail, tail = parent->next;
3685 }
3686 for (parent = NULL, tail = current_buffer->overlays_after; tail;)
3687 {
3688 XSETMISC (overlay, tail);
3689
3690 startpos = OVERLAY_POSITION (OVERLAY_START (overlay));
3691 endpos = OVERLAY_POSITION (OVERLAY_END (overlay));
3692
3693 /* If the overlay is backwards, make it empty. */
3694 if (endpos < startpos)
3695 {
3696 startpos = endpos;
3697 Fset_marker (OVERLAY_START (overlay), make_number (startpos),
3698 Qnil);
3699 }
3700
3701 if (startpos >= end)
3702 break;
3703
3704 if (startpos >= start
3705 || (endpos >= start && endpos < end))
3706 {
3707 if (endpos < current_buffer->overlay_center)
3708 {
3709 if (!afterp)
3710 after_list = tail;
3711 else
3712 afterp->next = tail;
3713 afterp = tail;
3714 }
3715 else
3716 {
3717 if (!beforep)
3718 before_list = tail;
3719 else
3720 beforep->next = tail;
3721 beforep = tail;
3722 }
3723 if (!parent)
3724 set_buffer_overlays_after (current_buffer, tail->next);
3725 else
3726 parent->next = tail->next;
3727 tail = tail->next;
3728 }
3729 else
3730 parent = tail, tail = parent->next;
3731 }
3732
3733 /* Splice the constructed (wrong) lists into the buffer's lists,
3734 and let the recenter function make it sane again. */
3735 if (beforep)
3736 {
3737 beforep->next = current_buffer->overlays_before;
3738 set_buffer_overlays_before (current_buffer, before_list);
3739 }
3740
3741 if (afterp)
3742 {
3743 afterp->next = current_buffer->overlays_after;
3744 set_buffer_overlays_after (current_buffer, after_list);
3745 }
3746 recenter_overlay_lists (current_buffer, current_buffer->overlay_center);
3747}
3748
3749/* We have two types of overlay: the one whose ending marker is
3750 after-insertion-marker (this is the usual case) and the one whose
3751 ending marker is before-insertion-marker. When `overlays_before'
3752 contains overlays of the latter type and the former type in this
3753 order and both overlays end at inserting position, inserting a text
3754 increases only the ending marker of the latter type, which results
3755 in incorrect ordering of `overlays_before'.
3756
3757 This function fixes ordering of overlays in the slot
3758 `overlays_before' of the buffer *BP. Before the insertion, `point'
3759 was at PREV, and now is at POS. */
3760
3761void
3762fix_overlays_before (struct buffer *bp, ptrdiff_t prev, ptrdiff_t pos)
3763{
3764 /* If parent is nil, replace overlays_before; otherwise, parent->next. */
3765 struct Lisp_Overlay *tail = bp->overlays_before, *parent = NULL, *right_pair;
3766 Lisp_Object tem;
3767 ptrdiff_t end UNINIT;
3768
3769 /* After the insertion, the several overlays may be in incorrect
3770 order. The possibility is that, in the list `overlays_before',
3771 an overlay which ends at POS appears after an overlay which ends
3772 at PREV. Since POS is greater than PREV, we must fix the
3773 ordering of these overlays, by moving overlays ends at POS before
3774 the overlays ends at PREV. */
3775
3776 /* At first, find a place where disordered overlays should be linked
3777 in. It is where an overlay which end before POS exists. (i.e. an
3778 overlay whose ending marker is after-insertion-marker if disorder
3779 exists). */
3780 while (tail
3781 && (XSETMISC (tem, tail),
3782 (end = OVERLAY_POSITION (OVERLAY_END (tem))) >= pos))
3783 {
3784 parent = tail;
3785 tail = tail->next;
3786 }
3787
3788 /* If we don't find such an overlay,
3789 or the found one ends before PREV,
3790 or the found one is the last one in the list,
3791 we don't have to fix anything. */
3792 if (!tail || end < prev || !tail->next)
3793 return; 3297 return;
3794 3298 interval_tree_delete_gap (current_buffer->overlays, pos, length);
3795 right_pair = parent;
3796 parent = tail;
3797 tail = tail->next;
3798
3799 /* Now, end position of overlays in the list TAIL should be before
3800 or equal to PREV. In the loop, an overlay which ends at POS is
3801 moved ahead to the place indicated by the CDR of RIGHT_PAIR. If
3802 we found an overlay which ends before PREV, the remaining
3803 overlays are in correct order. */
3804 while (tail)
3805 {
3806 XSETMISC (tem, tail);
3807 end = OVERLAY_POSITION (OVERLAY_END (tem));
3808
3809 if (end == pos)
3810 { /* This overlay is disordered. */
3811 struct Lisp_Overlay *found = tail;
3812
3813 /* Unlink the found overlay. */
3814 tail = found->next;
3815 parent->next = tail;
3816 /* Move an overlay at RIGHT_PLACE to the next of the found one,
3817 and link it into the right place. */
3818 if (!right_pair)
3819 {
3820 found->next = bp->overlays_before;
3821 set_buffer_overlays_before (bp, found);
3822 }
3823 else
3824 {
3825 found->next = right_pair->next;
3826 right_pair->next = found;
3827 }
3828 }
3829 else if (end == prev)
3830 {
3831 parent = tail;
3832 tail = tail->next;
3833 }
3834 else /* No more disordered overlay. */
3835 break;
3836 }
3837} 3299}
3300
3838 3301
3839DEFUN ("overlayp", Foverlayp, Soverlayp, 1, 1, 0, 3302DEFUN ("overlayp", Foverlayp, Soverlayp, 1, 1, 0,
3840 doc: /* Return t if OBJECT is an overlay. */) 3303 doc: /* Return t if OBJECT is an overlay. */)
@@ -3853,10 +3316,11 @@ for the front of the overlay advance when text is inserted there
3853The fifth arg REAR-ADVANCE, if non-nil, makes the marker 3316The fifth arg REAR-ADVANCE, if non-nil, makes the marker
3854for the rear of the overlay advance when text is inserted there 3317for the rear of the overlay advance when text is inserted there
3855\(which means the text *is* included in the overlay). */) 3318\(which means the text *is* included in the overlay). */)
3856 (Lisp_Object beg, Lisp_Object end, Lisp_Object buffer, 3319 (Lisp_Object begin, Lisp_Object end, Lisp_Object buffer,
3857 Lisp_Object front_advance, Lisp_Object rear_advance) 3320 Lisp_Object front_advance, Lisp_Object rear_advance)
3858{ 3321{
3859 Lisp_Object overlay; 3322 Lisp_Object ov;
3323 ptrdiff_t obegin, oend;
3860 struct buffer *b; 3324 struct buffer *b;
3861 3325
3862 if (NILP (buffer)) 3326 if (NILP (buffer))
@@ -3864,53 +3328,35 @@ for the rear of the overlay advance when text is inserted there
3864 else 3328 else
3865 CHECK_BUFFER (buffer); 3329 CHECK_BUFFER (buffer);
3866 3330
3867 if (MARKERP (beg) && !EQ (Fmarker_buffer (beg), buffer)) 3331 b = XBUFFER (buffer);
3868 signal_error ("Marker points into wrong buffer", beg); 3332 if (! BUFFER_LIVE_P (b))
3333 error ("Attempt to create overlay in a dead buffer");
3334
3335 if (MARKERP (begin) && !EQ (Fmarker_buffer (begin), buffer))
3336 signal_error ("Marker points into wrong buffer", begin);
3869 if (MARKERP (end) && !EQ (Fmarker_buffer (end), buffer)) 3337 if (MARKERP (end) && !EQ (Fmarker_buffer (end), buffer))
3870 signal_error ("Marker points into wrong buffer", end); 3338 signal_error ("Marker points into wrong buffer", end);
3871 3339
3872 CHECK_NUMBER_COERCE_MARKER (beg); 3340 CHECK_NUMBER_COERCE_MARKER (begin);
3873 CHECK_NUMBER_COERCE_MARKER (end); 3341 CHECK_NUMBER_COERCE_MARKER (end);
3874 3342
3875 if (XINT (beg) > XINT (end)) 3343 if (XINT (begin) > XINT (end))
3876 { 3344 {
3877 Lisp_Object temp; 3345 Lisp_Object temp;
3878 temp = beg; beg = end; end = temp; 3346 temp = begin; begin = end; end = temp;
3879 } 3347 }
3880 3348
3881 b = XBUFFER (buffer); 3349 obegin = clip_to_bounds (BEG, XINT (begin), b->text->z);
3882 3350 oend = clip_to_bounds (obegin, XINT (end), b->text->z);
3883 beg = Fset_marker (Fmake_marker (), beg, buffer); 3351 ov = build_overlay (obegin, oend,
3884 end = Fset_marker (Fmake_marker (), end, buffer); 3352 ! NILP (front_advance),
3885 3353 ! NILP (rear_advance), Qnil);
3886 if (!NILP (front_advance)) 3354 add_buffer_overlay (b, XOVERLAY (ov));
3887 XMARKER (beg)->insertion_type = 1;
3888 if (!NILP (rear_advance))
3889 XMARKER (end)->insertion_type = 1;
3890
3891 overlay = build_overlay (beg, end, Qnil);
3892
3893 /* Put the new overlay on the wrong list. */
3894 end = OVERLAY_END (overlay);
3895 if (OVERLAY_POSITION (end) < b->overlay_center)
3896 {
3897 eassert (b->overlays_after || (XOVERLAY (overlay)->next == NULL));
3898 XOVERLAY (overlay)->next = b->overlays_after;
3899 set_buffer_overlays_after (b, XOVERLAY (overlay));
3900 }
3901 else
3902 {
3903 eassert (b->overlays_before || (XOVERLAY (overlay)->next == NULL));
3904 XOVERLAY (overlay)->next = b->overlays_before;
3905 set_buffer_overlays_before (b, XOVERLAY (overlay));
3906 }
3907 /* This puts it in the right list, and in the right order. */
3908 recenter_overlay_lists (b, b->overlay_center);
3909 3355
3910 /* We don't need to redisplay the region covered by the overlay, because 3356 /* We don't need to redisplay the region covered by the overlay, because
3911 the overlay has no properties at the moment. */ 3357 the overlay has no properties at the moment. */
3912 3358
3913 return overlay; 3359 return ov;
3914} 3360}
3915 3361
3916/* Mark a section of BUF as needing redisplay because of overlays changes. */ 3362/* Mark a section of BUF as needing redisplay because of overlays changes. */
@@ -3932,35 +3378,6 @@ modify_overlay (struct buffer *buf, ptrdiff_t start, ptrdiff_t end)
3932 ++BUF_OVERLAY_MODIFF (buf); 3378 ++BUF_OVERLAY_MODIFF (buf);
3933} 3379}
3934 3380
3935/* Remove OVERLAY from LIST. */
3936
3937static struct Lisp_Overlay *
3938unchain_overlay (struct Lisp_Overlay *list, struct Lisp_Overlay *overlay)
3939{
3940 register struct Lisp_Overlay *tail, **prev = &list;
3941
3942 for (tail = list; tail; prev = &tail->next, tail = *prev)
3943 if (tail == overlay)
3944 {
3945 *prev = overlay->next;
3946 overlay->next = NULL;
3947 break;
3948 }
3949 return list;
3950}
3951
3952/* Remove OVERLAY from both overlay lists of B. */
3953
3954static void
3955unchain_both (struct buffer *b, Lisp_Object overlay)
3956{
3957 struct Lisp_Overlay *ov = XOVERLAY (overlay);
3958
3959 set_buffer_overlays_before (b, unchain_overlay (b->overlays_before, ov));
3960 set_buffer_overlays_after (b, unchain_overlay (b->overlays_after, ov));
3961 eassert (XOVERLAY (overlay)->next == NULL);
3962}
3963
3964DEFUN ("move-overlay", Fmove_overlay, Smove_overlay, 3, 4, 0, 3381DEFUN ("move-overlay", Fmove_overlay, Smove_overlay, 3, 4, 0,
3965 doc: /* Set the endpoints of OVERLAY to BEG and END in BUFFER. 3382 doc: /* Set the endpoints of OVERLAY to BEG and END in BUFFER.
3966If BUFFER is omitted, leave OVERLAY in the same buffer it inhabits now. 3383If BUFFER is omitted, leave OVERLAY in the same buffer it inhabits now.
@@ -3976,7 +3393,7 @@ buffer. */)
3976 3393
3977 CHECK_OVERLAY (overlay); 3394 CHECK_OVERLAY (overlay);
3978 if (NILP (buffer)) 3395 if (NILP (buffer))
3979 buffer = Fmarker_buffer (OVERLAY_START (overlay)); 3396 buffer = Foverlay_buffer (overlay);
3980 if (NILP (buffer)) 3397 if (NILP (buffer))
3981 XSETBUFFER (buffer, current_buffer); 3398 XSETBUFFER (buffer, current_buffer);
3982 CHECK_BUFFER (buffer); 3399 CHECK_BUFFER (buffer);
@@ -4000,25 +3417,28 @@ buffer. */)
4000 3417
4001 specbind (Qinhibit_quit, Qt); 3418 specbind (Qinhibit_quit, Qt);
4002 3419
4003 obuffer = Fmarker_buffer (OVERLAY_START (overlay)); 3420 obuffer = Foverlay_buffer (overlay);
4004 b = XBUFFER (buffer); 3421 b = XBUFFER (buffer);
4005 3422
4006 if (!NILP (obuffer)) 3423 if (!NILP (obuffer))
4007 { 3424 {
4008 ob = XBUFFER (obuffer); 3425 ob = XBUFFER (obuffer);
4009 3426
4010 o_beg = OVERLAY_POSITION (OVERLAY_START (overlay)); 3427 o_beg = OVERLAY_START (overlay);
4011 o_end = OVERLAY_POSITION (OVERLAY_END (overlay)); 3428 o_end = OVERLAY_END (overlay);
4012
4013 unchain_both (ob, overlay);
4014 } 3429 }
4015 3430
3431 if (! EQ (buffer, obuffer))
3432 {
3433 if (! NILP (obuffer))
3434 remove_buffer_overlay (XBUFFER (obuffer), XOVERLAY (overlay));
3435 add_buffer_overlay (XBUFFER (buffer), XOVERLAY (overlay));
3436 }
4016 /* Set the overlay boundaries, which may clip them. */ 3437 /* Set the overlay boundaries, which may clip them. */
4017 Fset_marker (OVERLAY_START (overlay), beg, buffer); 3438 set_overlay_region (XOVERLAY (overlay), XINT (beg), XINT (end));
4018 Fset_marker (OVERLAY_END (overlay), end, buffer);
4019 3439
4020 n_beg = marker_position (OVERLAY_START (overlay)); 3440 n_beg = OVERLAY_START (overlay);
4021 n_end = marker_position (OVERLAY_END (overlay)); 3441 n_end = OVERLAY_END (overlay);
4022 3442
4023 /* If the overlay has changed buffers, do a thorough redisplay. */ 3443 /* If the overlay has changed buffers, do a thorough redisplay. */
4024 if (!EQ (buffer, obuffer)) 3444 if (!EQ (buffer, obuffer))
@@ -4046,22 +3466,6 @@ buffer. */)
4046 if (n_beg == n_end && !NILP (Foverlay_get (overlay, Qevaporate))) 3466 if (n_beg == n_end && !NILP (Foverlay_get (overlay, Qevaporate)))
4047 return unbind_to (count, Fdelete_overlay (overlay)); 3467 return unbind_to (count, Fdelete_overlay (overlay));
4048 3468
4049 /* Put the overlay into the new buffer's overlay lists, first on the
4050 wrong list. */
4051 if (n_end < b->overlay_center)
4052 {
4053 XOVERLAY (overlay)->next = b->overlays_after;
4054 set_buffer_overlays_after (b, XOVERLAY (overlay));
4055 }
4056 else
4057 {
4058 XOVERLAY (overlay)->next = b->overlays_before;
4059 set_buffer_overlays_before (b, XOVERLAY (overlay));
4060 }
4061
4062 /* This puts it in the right list, and in the right order. */
4063 recenter_overlay_lists (b, b->overlay_center);
4064
4065 return unbind_to (count, overlay); 3469 return unbind_to (count, overlay);
4066} 3470}
4067 3471
@@ -4069,21 +3473,18 @@ DEFUN ("delete-overlay", Fdelete_overlay, Sdelete_overlay, 1, 1, 0,
4069 doc: /* Delete the overlay OVERLAY from its buffer. */) 3473 doc: /* Delete the overlay OVERLAY from its buffer. */)
4070 (Lisp_Object overlay) 3474 (Lisp_Object overlay)
4071{ 3475{
4072 Lisp_Object buffer;
4073 struct buffer *b; 3476 struct buffer *b;
4074 ptrdiff_t count = SPECPDL_INDEX (); 3477 ptrdiff_t count = SPECPDL_INDEX ();
4075 3478
4076 CHECK_OVERLAY (overlay); 3479 CHECK_OVERLAY (overlay);
4077 3480
4078 buffer = Fmarker_buffer (OVERLAY_START (overlay)); 3481 b = OVERLAY_BUFFER (overlay);
4079 if (NILP (buffer)) 3482 if (! b)
4080 return Qnil; 3483 return Qnil;
4081 3484
4082 b = XBUFFER (buffer);
4083 specbind (Qinhibit_quit, Qt); 3485 specbind (Qinhibit_quit, Qt);
4084 3486
4085 unchain_both (b, overlay); 3487 drop_overlay (XOVERLAY (overlay));
4086 drop_overlay (b, XOVERLAY (overlay));
4087 3488
4088 /* When deleting an overlay with before or after strings, turn off 3489 /* When deleting an overlay with before or after strings, turn off
4089 display optimizations for the affected buffer, on the basis that 3490 display optimizations for the affected buffer, on the basis that
@@ -4114,8 +3515,10 @@ DEFUN ("overlay-start", Foverlay_start, Soverlay_start, 1, 1, 0,
4114 (Lisp_Object overlay) 3515 (Lisp_Object overlay)
4115{ 3516{
4116 CHECK_OVERLAY (overlay); 3517 CHECK_OVERLAY (overlay);
3518 if (! OVERLAY_BUFFER (overlay))
3519 return Qnil;
4117 3520
4118 return (Fmarker_position (OVERLAY_START (overlay))); 3521 return make_number (OVERLAY_START (overlay));
4119} 3522}
4120 3523
4121DEFUN ("overlay-end", Foverlay_end, Soverlay_end, 1, 1, 0, 3524DEFUN ("overlay-end", Foverlay_end, Soverlay_end, 1, 1, 0,
@@ -4123,8 +3526,10 @@ DEFUN ("overlay-end", Foverlay_end, Soverlay_end, 1, 1, 0,
4123 (Lisp_Object overlay) 3526 (Lisp_Object overlay)
4124{ 3527{
4125 CHECK_OVERLAY (overlay); 3528 CHECK_OVERLAY (overlay);
3529 if (! OVERLAY_BUFFER (overlay))
3530 return Qnil;
4126 3531
4127 return (Fmarker_position (OVERLAY_END (overlay))); 3532 return make_number (OVERLAY_END (overlay));
4128} 3533}
4129 3534
4130DEFUN ("overlay-buffer", Foverlay_buffer, Soverlay_buffer, 1, 1, 0, 3535DEFUN ("overlay-buffer", Foverlay_buffer, Soverlay_buffer, 1, 1, 0,
@@ -4132,9 +3537,16 @@ DEFUN ("overlay-buffer", Foverlay_buffer, Soverlay_buffer, 1, 1, 0,
4132Return nil if OVERLAY has been deleted. */) 3537Return nil if OVERLAY has been deleted. */)
4133 (Lisp_Object overlay) 3538 (Lisp_Object overlay)
4134{ 3539{
3540 Lisp_Object buffer;
3541
4135 CHECK_OVERLAY (overlay); 3542 CHECK_OVERLAY (overlay);
4136 3543
4137 return Fmarker_buffer (OVERLAY_START (overlay)); 3544 if (! OVERLAY_BUFFER (overlay))
3545 return Qnil;
3546
3547 XSETBUFFER (buffer, OVERLAY_BUFFER (overlay));
3548
3549 return buffer;
4138} 3550}
4139 3551
4140DEFUN ("overlay-properties", Foverlay_properties, Soverlay_properties, 1, 1, 0, 3552DEFUN ("overlay-properties", Foverlay_properties, Soverlay_properties, 1, 1, 0,
@@ -4145,7 +3557,7 @@ OVERLAY. */)
4145{ 3557{
4146 CHECK_OVERLAY (overlay); 3558 CHECK_OVERLAY (overlay);
4147 3559
4148 return Fcopy_sequence (XOVERLAY (overlay)->plist); 3560 return Fcopy_sequence (OVERLAY_PLIST (overlay));
4149} 3561}
4150 3562
4151 3563
@@ -4169,8 +3581,7 @@ If SORTED is non-nil, then sort them by decreasing priority. */)
4169 3581
4170 /* Put all the overlays we want in a vector in overlay_vec. 3582 /* Put all the overlays we want in a vector in overlay_vec.
4171 Store the length in len. */ 3583 Store the length in len. */
4172 noverlays = overlays_at (XINT (pos), 1, &overlay_vec, &len, 3584 noverlays = overlays_at (XINT (pos), 1, &overlay_vec, &len, NULL);
4173 NULL, NULL, 0);
4174 3585
4175 if (!NILP (sorted)) 3586 if (!NILP (sorted))
4176 noverlays = sort_overlays (overlay_vec, noverlays, 3587 noverlays = sort_overlays (overlay_vec, noverlays,
@@ -4213,8 +3624,7 @@ end of the buffer. */)
4213 3624
4214 /* Put all the overlays we want in a vector in overlay_vec. 3625 /* Put all the overlays we want in a vector in overlay_vec.
4215 Store the length in len. */ 3626 Store the length in len. */
4216 noverlays = overlays_in (XINT (beg), XINT (end), 1, &overlay_vec, &len, 3627 noverlays = overlays_in (XINT (beg), XINT (end), 1, &overlay_vec, &len, true, NULL);
4217 NULL, NULL);
4218 3628
4219 /* Make a list of them all. */ 3629 /* Make a list of them all. */
4220 result = Flist (noverlays, overlay_vec); 3630 result = Flist (noverlays, overlay_vec);
@@ -4230,39 +3640,12 @@ If there are no overlay boundaries from POS to (point-max),
4230the value is (point-max). */) 3640the value is (point-max). */)
4231 (Lisp_Object pos) 3641 (Lisp_Object pos)
4232{ 3642{
4233 ptrdiff_t i, len, noverlays;
4234 ptrdiff_t endpos;
4235 Lisp_Object *overlay_vec;
4236
4237 CHECK_NUMBER_COERCE_MARKER (pos); 3643 CHECK_NUMBER_COERCE_MARKER (pos);
4238 3644
4239 if (!buffer_has_overlays ()) 3645 if (!buffer_has_overlays ())
4240 return make_number (ZV); 3646 return make_number (ZV);
4241 3647
4242 len = 10; 3648 return make_number (next_overlay_change (XINT (pos)));
4243 overlay_vec = xmalloc (len * sizeof *overlay_vec);
4244
4245 /* Put all the overlays we want in a vector in overlay_vec.
4246 Store the length in len.
4247 endpos gets the position where the next overlay starts. */
4248 noverlays = overlays_at (XINT (pos), 1, &overlay_vec, &len,
4249 &endpos, 0, 1);
4250
4251 /* If any of these overlays ends before endpos,
4252 use its ending point instead. */
4253 for (i = 0; i < noverlays; i++)
4254 {
4255 Lisp_Object oend;
4256 ptrdiff_t oendpos;
4257
4258 oend = OVERLAY_END (overlay_vec[i]);
4259 oendpos = OVERLAY_POSITION (oend);
4260 if (oendpos < endpos)
4261 endpos = oendpos;
4262 }
4263
4264 xfree (overlay_vec);
4265 return make_number (endpos);
4266} 3649}
4267 3650
4268DEFUN ("previous-overlay-change", Fprevious_overlay_change, 3651DEFUN ("previous-overlay-change", Fprevious_overlay_change,
@@ -4272,32 +3655,15 @@ If there are no overlay boundaries from (point-min) to POS,
4272the value is (point-min). */) 3655the value is (point-min). */)
4273 (Lisp_Object pos) 3656 (Lisp_Object pos)
4274{ 3657{
4275 ptrdiff_t prevpos;
4276 Lisp_Object *overlay_vec;
4277 ptrdiff_t len;
4278 3658
4279 CHECK_NUMBER_COERCE_MARKER (pos); 3659 CHECK_NUMBER_COERCE_MARKER (pos);
4280 3660
4281 if (!buffer_has_overlays ()) 3661 if (!buffer_has_overlays ())
4282 return make_number (BEGV); 3662 return make_number (BEGV);
4283 3663
4284 /* At beginning of buffer, we know the answer; 3664 return make_number (previous_overlay_change (XINT (pos)));
4285 avoid bug subtracting 1 below. */
4286 if (XINT (pos) == BEGV)
4287 return pos;
4288
4289 len = 10;
4290 overlay_vec = xmalloc (len * sizeof *overlay_vec);
4291
4292 /* Put all the overlays we want in a vector in overlay_vec.
4293 Store the length in len.
4294 prevpos gets the position of the previous change. */
4295 overlays_at (XINT (pos), 1, &overlay_vec, &len,
4296 0, &prevpos, 1);
4297
4298 xfree (overlay_vec);
4299 return make_number (prevpos);
4300} 3665}
3666
4301 3667
4302/* These functions are for debugging overlays. */ 3668/* These functions are for debugging overlays. */
4303 3669
@@ -4307,24 +3673,21 @@ The car has all the overlays before the overlay center;
4307the cdr has all the overlays after the overlay center. 3673the cdr has all the overlays after the overlay center.
4308Recentering overlays moves overlays between these lists. 3674Recentering overlays moves overlays between these lists.
4309The lists you get are copies, so that changing them has no effect. 3675The lists you get are copies, so that changing them has no effect.
4310However, the overlays you get are the real objects that the buffer uses. */) 3676However, the overlays you get are the real objects that the buffer uses. */)
4311 (void) 3677 (void)
4312{ 3678{
4313 struct Lisp_Overlay *ol; 3679 Lisp_Object overlays = Qnil;
4314 Lisp_Object before = Qnil, after = Qnil, tmp;
4315 3680
4316 for (ol = current_buffer->overlays_before; ol; ol = ol->next) 3681 if (current_buffer->overlays)
4317 {
4318 XSETMISC (tmp, ol);
4319 before = Fcons (tmp, before);
4320 }
4321 for (ol = current_buffer->overlays_after; ol; ol = ol->next)
4322 { 3682 {
4323 XSETMISC (tmp, ol); 3683 struct interval_node *node;
4324 after = Fcons (tmp, after);
4325 }
4326 3684
4327 return Fcons (Fnreverse (before), Fnreverse (after)); 3685 buffer_overlay_iter_start (current_buffer, BEG, Z, ITREE_DESCENDING);
3686 while ((node = buffer_overlay_iter_next (current_buffer)))
3687 overlays = Fcons (node->data, overlays);
3688 buffer_overlay_iter_finish (current_buffer);
3689 }
3690 return Fcons (overlays, Qnil);
4328} 3691}
4329 3692
4330DEFUN ("overlay-recenter", Foverlay_recenter, Soverlay_recenter, 1, 1, 0, 3693DEFUN ("overlay-recenter", Foverlay_recenter, Soverlay_recenter, 1, 1, 0,
@@ -4333,11 +3696,8 @@ That makes overlay lookup faster for positions near POS (but perhaps slower
4333for positions far away from POS). */) 3696for positions far away from POS). */)
4334 (Lisp_Object pos) 3697 (Lisp_Object pos)
4335{ 3698{
4336 ptrdiff_t p;
4337 CHECK_NUMBER_COERCE_MARKER (pos); 3699 CHECK_NUMBER_COERCE_MARKER (pos);
4338 3700 /* Noop */
4339 p = clip_to_bounds (PTRDIFF_MIN, XINT (pos), PTRDIFF_MAX);
4340 recenter_overlay_lists (current_buffer, p);
4341 return Qnil; 3701 return Qnil;
4342} 3702}
4343 3703
@@ -4354,12 +3714,13 @@ DEFUN ("overlay-put", Foverlay_put, Soverlay_put, 3, 3, 0,
4354VALUE will be returned.*/) 3714VALUE will be returned.*/)
4355 (Lisp_Object overlay, Lisp_Object prop, Lisp_Object value) 3715 (Lisp_Object overlay, Lisp_Object prop, Lisp_Object value)
4356{ 3716{
4357 Lisp_Object tail, buffer; 3717 Lisp_Object tail;
3718 struct buffer *b;
4358 bool changed; 3719 bool changed;
4359 3720
4360 CHECK_OVERLAY (overlay); 3721 CHECK_OVERLAY (overlay);
4361 3722
4362 buffer = Fmarker_buffer (OVERLAY_START (overlay)); 3723 b = OVERLAY_BUFFER (overlay);
4363 3724
4364 for (tail = XOVERLAY (overlay)->plist; 3725 for (tail = XOVERLAY (overlay)->plist;
4365 CONSP (tail) && CONSP (XCDR (tail)); 3726 CONSP (tail) && CONSP (XCDR (tail));
@@ -4375,15 +3736,14 @@ VALUE will be returned.*/)
4375 set_overlay_plist 3736 set_overlay_plist
4376 (overlay, Fcons (prop, Fcons (value, XOVERLAY (overlay)->plist))); 3737 (overlay, Fcons (prop, Fcons (value, XOVERLAY (overlay)->plist)));
4377 found: 3738 found:
4378 if (! NILP (buffer)) 3739 if (b)
4379 { 3740 {
4380 if (changed) 3741 if (changed)
4381 modify_overlay (XBUFFER (buffer), 3742 modify_overlay (b, OVERLAY_START (overlay),
4382 marker_position (OVERLAY_START (overlay)), 3743 OVERLAY_END (overlay));
4383 marker_position (OVERLAY_END (overlay)));
4384 if (EQ (prop, Qevaporate) && ! NILP (value) 3744 if (EQ (prop, Qevaporate) && ! NILP (value)
4385 && (OVERLAY_POSITION (OVERLAY_START (overlay)) 3745 && (OVERLAY_START (overlay)
4386 == OVERLAY_POSITION (OVERLAY_END (overlay)))) 3746 == OVERLAY_END (overlay)))
4387 Fdelete_overlay (overlay); 3747 Fdelete_overlay (overlay);
4388 } 3748 }
4389 3749
@@ -4441,14 +3801,9 @@ void
4441report_overlay_modification (Lisp_Object start, Lisp_Object end, bool after, 3801report_overlay_modification (Lisp_Object start, Lisp_Object end, bool after,
4442 Lisp_Object arg1, Lisp_Object arg2, Lisp_Object arg3) 3802 Lisp_Object arg1, Lisp_Object arg2, Lisp_Object arg3)
4443{ 3803{
4444 Lisp_Object prop, overlay;
4445 struct Lisp_Overlay *tail;
4446 /* True if this change is an insertion. */ 3804 /* True if this change is an insertion. */
4447 bool insertion = (after ? XFASTINT (arg3) == 0 : EQ (start, end)); 3805 bool insertion = (after ? XFASTINT (arg3) == 0 : EQ (start, end));
4448 3806
4449 overlay = Qnil;
4450 tail = NULL;
4451
4452 /* We used to run the functions as soon as we found them and only register 3807 /* We used to run the functions as soon as we found them and only register
4453 them in last_overlay_modification_hooks for the purpose of the `after' 3808 them in last_overlay_modification_hooks for the purpose of the `after'
4454 case. But running elisp code as we traverse the list of overlays is 3809 case. But running elisp code as we traverse the list of overlays is
@@ -4459,68 +3814,35 @@ report_overlay_modification (Lisp_Object start, Lisp_Object end, bool after,
4459 3814
4460 if (!after) 3815 if (!after)
4461 { 3816 {
3817 struct interval_node *node;
3818 EMACS_INT begin_arg = XFASTINT (start);
3819 EMACS_INT end_arg = XFASTINT (end);
4462 /* We are being called before a change. 3820 /* We are being called before a change.
4463 Scan the overlays to find the functions to call. */ 3821 Scan the overlays to find the functions to call. */
4464 last_overlay_modification_hooks_used = 0; 3822 last_overlay_modification_hooks_used = 0;
4465 for (tail = current_buffer->overlays_before; tail; tail = tail->next)
4466 {
4467 ptrdiff_t startpos, endpos;
4468 Lisp_Object ostart, oend;
4469
4470 XSETMISC (overlay, tail);
4471
4472 ostart = OVERLAY_START (overlay);
4473 oend = OVERLAY_END (overlay);
4474 endpos = OVERLAY_POSITION (oend);
4475 if (XFASTINT (start) > endpos)
4476 break;
4477 startpos = OVERLAY_POSITION (ostart);
4478 if (insertion && (XFASTINT (start) == startpos
4479 || XFASTINT (end) == startpos))
4480 {
4481 prop = Foverlay_get (overlay, Qinsert_in_front_hooks);
4482 if (!NILP (prop))
4483 add_overlay_mod_hooklist (prop, overlay);
4484 }
4485 if (insertion && (XFASTINT (start) == endpos
4486 || XFASTINT (end) == endpos))
4487 {
4488 prop = Foverlay_get (overlay, Qinsert_behind_hooks);
4489 if (!NILP (prop))
4490 add_overlay_mod_hooklist (prop, overlay);
4491 }
4492 /* Test for intersecting intervals. This does the right thing
4493 for both insertion and deletion. */
4494 if (XFASTINT (end) > startpos && XFASTINT (start) < endpos)
4495 {
4496 prop = Foverlay_get (overlay, Qmodification_hooks);
4497 if (!NILP (prop))
4498 add_overlay_mod_hooklist (prop, overlay);
4499 }
4500 }
4501 3823
4502 for (tail = current_buffer->overlays_after; tail; tail = tail->next) 3824 if (! current_buffer->overlays)
3825 return;
3826 buffer_overlay_iter_start (current_buffer,
3827 begin_arg - (insertion ? 1 : 0),
3828 end_arg + (insertion ? 1 : 0),
3829 ITREE_ASCENDING);
3830 while ((node = buffer_overlay_iter_next (current_buffer)))
4503 { 3831 {
4504 ptrdiff_t startpos, endpos; 3832 Lisp_Object overlay = node->data;
4505 Lisp_Object ostart, oend; 3833 ptrdiff_t obegin = OVERLAY_START (overlay);
4506 3834 ptrdiff_t oend = OVERLAY_END (overlay);
4507 XSETMISC (overlay, tail); 3835 Lisp_Object prop;
4508 3836
4509 ostart = OVERLAY_START (overlay); 3837 if (insertion && (begin_arg == obegin
4510 oend = OVERLAY_END (overlay); 3838 || end_arg == obegin))
4511 startpos = OVERLAY_POSITION (ostart);
4512 endpos = OVERLAY_POSITION (oend);
4513 if (XFASTINT (end) < startpos)
4514 break;
4515 if (insertion && (XFASTINT (start) == startpos
4516 || XFASTINT (end) == startpos))
4517 { 3839 {
4518 prop = Foverlay_get (overlay, Qinsert_in_front_hooks); 3840 prop = Foverlay_get (overlay, Qinsert_in_front_hooks);
4519 if (!NILP (prop)) 3841 if (!NILP (prop))
4520 add_overlay_mod_hooklist (prop, overlay); 3842 add_overlay_mod_hooklist (prop, overlay);
4521 } 3843 }
4522 if (insertion && (XFASTINT (start) == endpos 3844 if (insertion && (begin_arg == oend
4523 || XFASTINT (end) == endpos)) 3845 || end_arg == oend))
4524 { 3846 {
4525 prop = Foverlay_get (overlay, Qinsert_behind_hooks); 3847 prop = Foverlay_get (overlay, Qinsert_behind_hooks);
4526 if (!NILP (prop)) 3848 if (!NILP (prop))
@@ -4528,15 +3850,15 @@ report_overlay_modification (Lisp_Object start, Lisp_Object end, bool after,
4528 } 3850 }
4529 /* Test for intersecting intervals. This does the right thing 3851 /* Test for intersecting intervals. This does the right thing
4530 for both insertion and deletion. */ 3852 for both insertion and deletion. */
4531 if (XFASTINT (end) > startpos && XFASTINT (start) < endpos) 3853 if (! insertion || (end_arg > obegin && begin_arg < oend))
4532 { 3854 {
4533 prop = Foverlay_get (overlay, Qmodification_hooks); 3855 prop = Foverlay_get (overlay, Qmodification_hooks);
4534 if (!NILP (prop)) 3856 if (!NILP (prop))
4535 add_overlay_mod_hooklist (prop, overlay); 3857 add_overlay_mod_hooklist (prop, overlay);
4536 } 3858 }
4537 } 3859 }
3860 buffer_overlay_iter_finish (current_buffer);
4538 } 3861 }
4539
4540 { 3862 {
4541 /* Call the functions recorded in last_overlay_modification_hooks. 3863 /* Call the functions recorded in last_overlay_modification_hooks.
4542 First copy the vector contents, in case some of these hooks 3864 First copy the vector contents, in case some of these hooks
@@ -4558,7 +3880,7 @@ report_overlay_modification (Lisp_Object start, Lisp_Object end, bool after,
4558 function is never called to record the overlay modification 3880 function is never called to record the overlay modification
4559 hook functions in the last_overlay_modification_hooks 3881 hook functions in the last_overlay_modification_hooks
4560 array, so anything we find there is not ours. */ 3882 array, so anything we find there is not ours. */
4561 if (XMARKER (OVERLAY_START (ovl))->buffer != current_buffer) 3883 if (OVERLAY_BUFFER (ovl) != current_buffer)
4562 return; 3884 return;
4563 } 3885 }
4564 3886
@@ -4598,34 +3920,22 @@ call_overlay_mod_hooks (Lisp_Object list, Lisp_Object overlay, bool after,
4598void 3920void
4599evaporate_overlays (ptrdiff_t pos) 3921evaporate_overlays (ptrdiff_t pos)
4600{ 3922{
4601 Lisp_Object overlay, hit_list; 3923 Lisp_Object hit_list;
4602 struct Lisp_Overlay *tail; 3924 struct interval_node *node;
3925
3926 if (! current_buffer->overlays)
3927 return;
4603 3928
4604 hit_list = Qnil; 3929 hit_list = Qnil;
4605 if (pos <= current_buffer->overlay_center) 3930 buffer_overlay_iter_start (current_buffer, pos, pos, ITREE_ASCENDING);
4606 for (tail = current_buffer->overlays_before; tail; tail = tail->next) 3931
4607 { 3932 while ((node = buffer_overlay_iter_next (current_buffer)))
4608 ptrdiff_t endpos; 3933 {
4609 XSETMISC (overlay, tail); 3934 if (node->end == pos
4610 endpos = OVERLAY_POSITION (OVERLAY_END (overlay)); 3935 && ! NILP (Foverlay_get (node->data, Qevaporate)))
4611 if (endpos < pos) 3936 hit_list = Fcons (node->data, hit_list);
4612 break; 3937 }
4613 if (endpos == pos && OVERLAY_POSITION (OVERLAY_START (overlay)) == pos 3938 buffer_overlay_iter_finish (current_buffer);
4614 && ! NILP (Foverlay_get (overlay, Qevaporate)))
4615 hit_list = Fcons (overlay, hit_list);
4616 }
4617 else
4618 for (tail = current_buffer->overlays_after; tail; tail = tail->next)
4619 {
4620 ptrdiff_t startpos;
4621 XSETMISC (overlay, tail);
4622 startpos = OVERLAY_POSITION (OVERLAY_START (overlay));
4623 if (startpos > pos)
4624 break;
4625 if (startpos == pos && OVERLAY_POSITION (OVERLAY_END (overlay)) == pos
4626 && ! NILP (Foverlay_get (overlay, Qevaporate)))
4627 hit_list = Fcons (overlay, hit_list);
4628 }
4629 for (; CONSP (hit_list); hit_list = XCDR (hit_list)) 3939 for (; CONSP (hit_list); hit_list = XCDR (hit_list))
4630 Fdelete_overlay (XCAR (hit_list)); 3940 Fdelete_overlay (XCAR (hit_list));
4631} 3941}
@@ -5212,9 +4522,7 @@ init_buffer_once (void)
5212 bset_mark_active (&buffer_defaults, Qnil); 4522 bset_mark_active (&buffer_defaults, Qnil);
5213 bset_file_format (&buffer_defaults, Qnil); 4523 bset_file_format (&buffer_defaults, Qnil);
5214 bset_auto_save_file_format (&buffer_defaults, Qt); 4524 bset_auto_save_file_format (&buffer_defaults, Qt);
5215 set_buffer_overlays_before (&buffer_defaults, NULL); 4525 buffer_defaults.overlays = NULL;
5216 set_buffer_overlays_after (&buffer_defaults, NULL);
5217 buffer_defaults.overlay_center = BEG;
5218 4526
5219 XSETFASTINT (BVAR (&buffer_defaults, tab_width), 8); 4527 XSETFASTINT (BVAR (&buffer_defaults, tab_width), 8);
5220 bset_truncate_lines (&buffer_defaults, Qnil); 4528 bset_truncate_lines (&buffer_defaults, Qnil);
@@ -5434,6 +4742,48 @@ defvar_per_buffer (struct Lisp_Buffer_Objfwd *bo_fwd, const char *namestring,
5434 emacs_abort (); 4742 emacs_abort ();
5435} 4743}
5436 4744
4745#ifdef ITREE_DEBUG
4746static Lisp_Object
4747make_lispy_interval_node (const struct interval_node *node)
4748{
4749 return listn (CONSTYPE_HEAP, 12,
4750 intern (":begin"),
4751 make_number (node->begin),
4752 intern (":end"),
4753 make_number (node->end),
4754 intern (":limit"),
4755 make_number (node->limit),
4756 intern (":offset"),
4757 make_number (node->offset),
4758 intern (":rear-advance"),
4759 node->rear_advance ? Qt : Qnil,
4760 intern (":front-advance"),
4761 node->front_advance ? Qt : Qnil);
4762}
4763
4764static Lisp_Object
4765overlay_tree (const struct interval_tree *tree,
4766 const struct interval_node *node)
4767{
4768 if (node == &tree->nil)
4769 return Qnil;
4770 return list3 (make_lispy_interval_node (node),
4771 overlay_tree (tree, node->left),
4772 overlay_tree (tree, node->right));
4773}
4774
4775DEFUN ("overlay-tree", Foverlay_tree, Soverlay_tree, 0, 1, 0,
4776 doc: /* Get the overlay tree for BUFFER. */)
4777 (Lisp_Object buffer)
4778{
4779 struct buffer *b = decode_buffer (buffer);
4780 if (! b->overlays)
4781 return Qnil;
4782 return overlay_tree (b->overlays, b->overlays->root);
4783}
4784#endif
4785
4786
5437 4787
5438/* Initialize the buffer routines. */ 4788/* Initialize the buffer routines. */
5439void 4789void
@@ -6303,6 +5653,10 @@ Functions running this hook are, `get-buffer-create',
6303 defsubr (&Srestore_buffer_modified_p); 5653 defsubr (&Srestore_buffer_modified_p);
6304 5654
6305 Fput (intern_c_string ("erase-buffer"), Qdisabled, Qt); 5655 Fput (intern_c_string ("erase-buffer"), Qdisabled, Qt);
5656
5657#ifdef ITREE_DEBUG
5658 defsubr (&Soverlay_tree);
5659#endif
6306} 5660}
6307 5661
6308void 5662void
diff --git a/src/buffer.h b/src/buffer.h
index ac7c5a54679..ef31ad1ed9d 100644
--- a/src/buffer.h
+++ b/src/buffer.h
@@ -26,6 +26,7 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
26 26
27#include "character.h" 27#include "character.h"
28#include "lisp.h" 28#include "lisp.h"
29#include "itree.h"
29 30
30INLINE_HEADER_BEGIN 31INLINE_HEADER_BEGIN
31 32
@@ -877,16 +878,8 @@ struct buffer
877 /* Non-zero whenever the narrowing is changed in this buffer. */ 878 /* Non-zero whenever the narrowing is changed in this buffer. */
878 bool_bf clip_changed : 1; 879 bool_bf clip_changed : 1;
879 880
880 /* List of overlays that end at or before the current center, 881 /* The inveral tree containing this buffer's overlays. */
881 in order of end-position. */ 882 struct interval_tree *overlays;
882 struct Lisp_Overlay *overlays_before;
883
884 /* List of overlays that end after the current center,
885 in order of start-position. */
886 struct Lisp_Overlay *overlays_after;
887
888 /* Position where the overlay lists are centered. */
889 ptrdiff_t overlay_center;
890 883
891 /* Changes in the buffer are recorded here for undo, and t means 884 /* Changes in the buffer are recorded here for undo, and t means
892 don't record anything. This information belongs to the base 885 don't record anything. This information belongs to the base
@@ -896,6 +889,14 @@ struct buffer
896 Lisp_Object undo_list_; 889 Lisp_Object undo_list_;
897}; 890};
898 891
892struct sortvec
893{
894 Lisp_Object overlay;
895 ptrdiff_t beg, end;
896 EMACS_INT priority;
897 EMACS_INT spriority; /* Secondary priority. */
898};
899
899INLINE bool 900INLINE bool
900BUFFERP (Lisp_Object a) 901BUFFERP (Lisp_Object a)
901{ 902{
@@ -1109,8 +1110,11 @@ extern void delete_all_overlays (struct buffer *);
1109extern void reset_buffer (struct buffer *); 1110extern void reset_buffer (struct buffer *);
1110extern void compact_buffer (struct buffer *); 1111extern void compact_buffer (struct buffer *);
1111extern void evaporate_overlays (ptrdiff_t); 1112extern void evaporate_overlays (ptrdiff_t);
1112extern ptrdiff_t overlays_at (EMACS_INT, bool, Lisp_Object **, 1113extern ptrdiff_t overlays_at (ptrdiff_t, bool, Lisp_Object **, ptrdiff_t *, ptrdiff_t *);
1113 ptrdiff_t *, ptrdiff_t *, ptrdiff_t *, bool); 1114extern ptrdiff_t overlays_in (ptrdiff_t, ptrdiff_t, bool, Lisp_Object **,
1115 ptrdiff_t *, bool, ptrdiff_t *);
1116extern ptrdiff_t previous_overlay_change (ptrdiff_t);
1117extern ptrdiff_t next_overlay_change (ptrdiff_t);
1114extern ptrdiff_t sort_overlays (Lisp_Object *, ptrdiff_t, struct window *); 1118extern ptrdiff_t sort_overlays (Lisp_Object *, ptrdiff_t, struct window *);
1115extern void recenter_overlay_lists (struct buffer *, ptrdiff_t); 1119extern void recenter_overlay_lists (struct buffer *, ptrdiff_t);
1116extern ptrdiff_t overlay_strings (ptrdiff_t, struct window *, unsigned char **); 1120extern ptrdiff_t overlay_strings (ptrdiff_t, struct window *, unsigned char **);
@@ -1162,18 +1166,16 @@ record_unwind_current_buffer (void)
1162 If NEXTP is non-NULL, return next overlay there. 1166 If NEXTP is non-NULL, return next overlay there.
1163 See overlay_at arg CHANGE_REQ for meaning of CHRQ arg. */ 1167 See overlay_at arg CHANGE_REQ for meaning of CHRQ arg. */
1164 1168
1165#define GET_OVERLAYS_AT(posn, overlays, noverlays, nextp, chrq) \ 1169#define GET_OVERLAYS_AT(posn, overlays, noverlays, next) \
1166 do { \ 1170 do { \
1167 ptrdiff_t maxlen = 40; \ 1171 ptrdiff_t maxlen = 40; \
1168 SAFE_NALLOCA (overlays, 1, maxlen); \ 1172 SAFE_NALLOCA (overlays, 1, maxlen); \
1169 (noverlays) = overlays_at (posn, false, &(overlays), &maxlen, \ 1173 (noverlays) = overlays_at (posn, false, &(overlays), &maxlen, next); \
1170 nextp, NULL, chrq); \
1171 if ((noverlays) > maxlen) \ 1174 if ((noverlays) > maxlen) \
1172 { \ 1175 { \
1173 maxlen = noverlays; \ 1176 maxlen = noverlays; \
1174 SAFE_NALLOCA (overlays, 1, maxlen); \ 1177 SAFE_NALLOCA (overlays, 1, maxlen); \
1175 (noverlays) = overlays_at (posn, false, &(overlays), &maxlen, \ 1178 (noverlays) = overlays_at (posn, false, &(overlays), &maxlen, next); \
1176 nextp, NULL, chrq); \
1177 } \ 1179 } \
1178 } while (false) 1180 } while (false)
1179 1181
@@ -1208,7 +1210,8 @@ set_buffer_intervals (struct buffer *b, INTERVAL i)
1208INLINE bool 1210INLINE bool
1209buffer_has_overlays (void) 1211buffer_has_overlays (void)
1210{ 1212{
1211 return current_buffer->overlays_before || current_buffer->overlays_after; 1213 return current_buffer->overlays
1214 && (interval_tree_size (current_buffer->overlays) > 0);
1212} 1215}
1213 1216
1214/* Return character code of multi-byte form at byte position POS. If POS 1217/* Return character code of multi-byte form at byte position POS. If POS
@@ -1248,23 +1251,124 @@ buffer_window_count (struct buffer *b)
1248 1251
1249/* Overlays */ 1252/* Overlays */
1250 1253
1251/* Return the marker that stands for where OV starts in the buffer. */ 1254INLINE ptrdiff_t
1255overlay_start (struct Lisp_Overlay *ov)
1256{
1257 if (! ov->buffer)
1258 return -1;
1259 return interval_node_begin (ov->buffer->overlays, ov->interval);
1260}
1261
1262INLINE ptrdiff_t
1263overlay_end (struct Lisp_Overlay *ov)
1264{
1265 if (! ov->buffer)
1266 return -1;
1267 return interval_node_end (ov->buffer->overlays, ov->interval);
1268}
1269
1270INLINE void
1271set_overlay_region (struct Lisp_Overlay *ov, ptrdiff_t begin, ptrdiff_t end)
1272{
1273 eassert (ov->buffer);
1274 begin = clip_to_bounds (BEG, begin, ov->buffer->text->z);
1275 end = clip_to_bounds (begin, end, ov->buffer->text->z);
1276 interval_node_set_region (ov->buffer->overlays, ov->interval, begin, end);
1277}
1278
1279INLINE void
1280maybe_alloc_buffer_overlays (struct buffer *b)
1281{
1282 if (! b->overlays)
1283 b->overlays = interval_tree_create ();
1284}
1285
1286/* FIXME: Actually this does not free any overlay, but the tree
1287 only. --ap */
1288
1289INLINE void
1290free_buffer_overlays (struct buffer *b)
1291{
1292 eassert (! b->overlays || 0 == interval_tree_size (b->overlays));
1293 if (b->overlays)
1294 {
1295 interval_tree_destroy (b->overlays);
1296 b->overlays = NULL;
1297 }
1298}
1299
1300INLINE void
1301add_buffer_overlay (struct buffer *b, struct Lisp_Overlay *ov)
1302{
1303 eassert (! ov->buffer);
1304 maybe_alloc_buffer_overlays (b);
1305 ov->buffer = b;
1306 interval_tree_insert (b->overlays, ov->interval);
1307}
1308
1309INLINE void
1310remove_buffer_overlay (struct buffer *b, struct Lisp_Overlay *ov)
1311{
1312 eassert (b->overlays);
1313 eassert (ov->buffer == b);
1314 interval_tree_remove (ov->buffer->overlays, ov->interval);
1315 ov->buffer = NULL;
1316}
1317
1318INLINE void
1319buffer_overlay_iter_start (struct buffer *b, ptrdiff_t begin, ptrdiff_t end,
1320 enum interval_tree_order order)
1321{
1322 if (b->overlays)
1323 interval_tree_iter_start (b->overlays, begin, end, order);
1324}
1325
1326INLINE struct interval_node*
1327buffer_overlay_iter_next (struct buffer *b)
1328{
1329 if (! b->overlays)
1330 return NULL;
1331 return interval_tree_iter_next (b->overlays);
1332}
1333
1334INLINE void
1335buffer_overlay_iter_finish (struct buffer *b)
1336{
1337 if (b->overlays)
1338 interval_tree_iter_finish (b->overlays);
1339}
1340
1341INLINE void
1342buffer_overlay_iter_narrow (struct buffer *b, ptrdiff_t begin, ptrdiff_t end)
1343{
1344 if (b->overlays)
1345 interval_tree_iter_narrow (b->overlays, begin, end);
1346}
1252 1347
1253#define OVERLAY_START(OV) XOVERLAY (OV)->start 1348/* Return the start of OV in its buffer, or -1 if OV is not associated
1349 with any buffer. */
1254 1350
1255/* Return the marker that stands for where OV ends in the buffer. */ 1351#define OVERLAY_START(OV) (overlay_start (XOVERLAY (OV)))
1256 1352
1257#define OVERLAY_END(OV) XOVERLAY (OV)->end 1353/* Return the end of OV in its buffer, or -1. */
1354
1355#define OVERLAY_END(OV) (overlay_end (XOVERLAY (OV)))
1258 1356
1259/* Return the plist of overlay OV. */ 1357/* Return the plist of overlay OV. */
1260 1358
1261#define OVERLAY_PLIST(OV) XOVERLAY (OV)->plist 1359#define OVERLAY_PLIST(OV) (XOVERLAY (OV)->plist)
1360
1361/* Return the buffer of overlay OV. */
1362
1363#define OVERLAY_BUFFER(OV) (XOVERLAY (OV)->buffer)
1262 1364
1263/* Return the actual buffer position for the marker P. 1365/* Return true, if OV's rear-advance is set. */
1264 We assume you know which buffer it's pointing into. */
1265 1366
1266#define OVERLAY_POSITION(P) \ 1367#define OVERLAY_REAR_ADVANCE_P(OV) (XOVERLAY (OV)->interval->rear_advance)
1267 (MARKERP (P) ? marker_position (P) : (emacs_abort (), 0)) 1368
1369/* Return true, if OV's front-advance is set. */
1370
1371#define OVERLAY_FRONT_ADVANCE_P(OV) (XOVERLAY (OV)->interval->front_advance)
1268 1372
1269 1373
1270/*********************************************************************** 1374/***********************************************************************
@@ -1405,4 +1509,7 @@ lowercasep (int c)
1405 1509
1406INLINE_HEADER_END 1510INLINE_HEADER_END
1407 1511
1512int compare_overlays (const void *v1, const void *v2);
1513void make_sortvec_item (struct sortvec *item, Lisp_Object overlay);
1514
1408#endif /* EMACS_BUFFER_H */ 1515#endif /* EMACS_BUFFER_H */
diff --git a/src/editfns.c b/src/editfns.c
index 4dcf7cbe6ef..8628b1b2d49 100644
--- a/src/editfns.c
+++ b/src/editfns.c
@@ -457,51 +457,9 @@ If you set the marker not to point anywhere, the buffer will have no mark. */)
457 of length LEN. */ 457 of length LEN. */
458 458
459static ptrdiff_t 459static ptrdiff_t
460overlays_around (EMACS_INT pos, Lisp_Object *vec, ptrdiff_t len) 460overlays_around (ptrdiff_t pos, Lisp_Object *vec, ptrdiff_t len)
461{ 461{
462 Lisp_Object overlay, start, end; 462 return overlays_in (pos - 1, pos, false, &vec, &len, false, NULL);
463 struct Lisp_Overlay *tail;
464 ptrdiff_t startpos, endpos;
465 ptrdiff_t idx = 0;
466
467 for (tail = current_buffer->overlays_before; tail; tail = tail->next)
468 {
469 XSETMISC (overlay, tail);
470
471 end = OVERLAY_END (overlay);
472 endpos = OVERLAY_POSITION (end);
473 if (endpos < pos)
474 break;
475 start = OVERLAY_START (overlay);
476 startpos = OVERLAY_POSITION (start);
477 if (startpos <= pos)
478 {
479 if (idx < len)
480 vec[idx] = overlay;
481 /* Keep counting overlays even if we can't return them all. */
482 idx++;
483 }
484 }
485
486 for (tail = current_buffer->overlays_after; tail; tail = tail->next)
487 {
488 XSETMISC (overlay, tail);
489
490 start = OVERLAY_START (overlay);
491 startpos = OVERLAY_POSITION (start);
492 if (pos < startpos)
493 break;
494 end = OVERLAY_END (overlay);
495 endpos = OVERLAY_POSITION (end);
496 if (pos <= endpos)
497 {
498 if (idx < len)
499 vec[idx] = overlay;
500 idx++;
501 }
502 }
503
504 return idx;
505} 463}
506 464
507DEFUN ("get-pos-property", Fget_pos_property, Sget_pos_property, 2, 3, 0, 465DEFUN ("get-pos-property", Fget_pos_property, Sget_pos_property, 2, 3, 0,
@@ -561,11 +519,10 @@ at POSITION. */)
561 if (!NILP (tem)) 519 if (!NILP (tem))
562 { 520 {
563 /* Check the overlay is indeed active at point. */ 521 /* Check the overlay is indeed active at point. */
564 Lisp_Object start = OVERLAY_START (ol), finish = OVERLAY_END (ol); 522 if ((OVERLAY_START (ol) == posn
565 if ((OVERLAY_POSITION (start) == posn 523 && OVERLAY_FRONT_ADVANCE_P (ol))
566 && XMARKER (start)->insertion_type == 1) 524 || (OVERLAY_END (ol) == posn
567 || (OVERLAY_POSITION (finish) == posn 525 && ! OVERLAY_REAR_ADVANCE_P (ol)))
568 && XMARKER (finish)->insertion_type == 0))
569 ; /* The overlay will not cover a char inserted at point. */ 526 ; /* The overlay will not cover a char inserted at point. */
570 else 527 else
571 { 528 {
@@ -5385,7 +5342,6 @@ Transposing beyond buffer boundaries is an error. */)
5385 transpose_markers (start1, end1, start2, end2, 5342 transpose_markers (start1, end1, start2, end2,
5386 start1_byte, start1_byte + len1_byte, 5343 start1_byte, start1_byte + len1_byte,
5387 start2_byte, start2_byte + len2_byte); 5344 start2_byte, start2_byte + len2_byte);
5388 fix_start_end_in_overlays (start1, end2);
5389 } 5345 }
5390 else 5346 else
5391 { 5347 {
diff --git a/src/fileio.c b/src/fileio.c
index 11370279d1b..6b22b29aa70 100644
--- a/src/fileio.c
+++ b/src/fileio.c
@@ -3656,8 +3656,7 @@ by calling `format-decode', which see. */)
3656 bset_read_only (buf, Qnil); 3656 bset_read_only (buf, Qnil);
3657 bset_filename (buf, Qnil); 3657 bset_filename (buf, Qnil);
3658 bset_undo_list (buf, Qt); 3658 bset_undo_list (buf, Qt);
3659 eassert (buf->overlays_before == NULL); 3659 eassert (buf->overlays == NULL);
3660 eassert (buf->overlays_after == NULL);
3661 3660
3662 set_buffer_internal (buf); 3661 set_buffer_internal (buf);
3663 Ferase_buffer (); 3662 Ferase_buffer ();
diff --git a/src/fns.c b/src/fns.c
index 2311a6e041b..9f411036825 100644
--- a/src/fns.c
+++ b/src/fns.c
@@ -2240,10 +2240,9 @@ internal_equal (Lisp_Object o1, Lisp_Object o2, enum equal_kind equal_kind,
2240 return false; 2240 return false;
2241 if (OVERLAYP (o1)) 2241 if (OVERLAYP (o1))
2242 { 2242 {
2243 if (!internal_equal (OVERLAY_START (o1), OVERLAY_START (o2), 2243 if (OVERLAY_START (o1) != OVERLAY_START (o2)
2244 equal_kind, depth + 1, ht) 2244 || OVERLAY_END (o1) != OVERLAY_END (o2)
2245 || !internal_equal (OVERLAY_END (o1), OVERLAY_END (o2), 2245 || OVERLAY_BUFFER (o1) != OVERLAY_BUFFER (o2))
2246 equal_kind, depth + 1, ht))
2247 return false; 2246 return false;
2248 o1 = XOVERLAY (o1)->plist; 2247 o1 = XOVERLAY (o1)->plist;
2249 o2 = XOVERLAY (o2)->plist; 2248 o2 = XOVERLAY (o2)->plist;
diff --git a/src/indent.c b/src/indent.c
index 26507b5eb5b..8ac7c6ef109 100644
--- a/src/indent.c
+++ b/src/indent.c
@@ -225,9 +225,6 @@ skip_invisible (ptrdiff_t pos, ptrdiff_t *next_boundary_p, ptrdiff_t to, Lisp_Ob
225 XSETFASTINT (position, pos); 225 XSETFASTINT (position, pos);
226 XSETBUFFER (buffer, current_buffer); 226 XSETBUFFER (buffer, current_buffer);
227 227
228 /* Give faster response for overlay lookup near POS. */
229 recenter_overlay_lists (current_buffer, pos);
230
231 /* We must not advance farther than the next overlay change. 228 /* We must not advance farther than the next overlay change.
232 The overlay change might change the invisible property; 229 The overlay change might change the invisible property;
233 or there might be overlay strings to be displayed there. */ 230 or there might be overlay strings to be displayed there. */
@@ -501,7 +498,7 @@ check_display_width (ptrdiff_t pos, ptrdiff_t col, ptrdiff_t *endpos)
501 { 498 {
502 ptrdiff_t start; 499 ptrdiff_t start;
503 if (OVERLAYP (overlay)) 500 if (OVERLAYP (overlay))
504 *endpos = OVERLAY_POSITION (OVERLAY_END (overlay)); 501 *endpos = OVERLAY_END (overlay);
505 else 502 else
506 get_property_and_range (pos, Qdisplay, &val, &start, endpos, Qnil); 503 get_property_and_range (pos, Qdisplay, &val, &start, endpos, Qnil);
507 504
diff --git a/src/insdel.c b/src/insdel.c
index 5dfc62843a7..3e9f0c90e34 100644
--- a/src/insdel.c
+++ b/src/insdel.c
@@ -276,7 +276,6 @@ adjust_markers_for_insert (ptrdiff_t from, ptrdiff_t from_byte,
276 ptrdiff_t to, ptrdiff_t to_byte, bool before_markers) 276 ptrdiff_t to, ptrdiff_t to_byte, bool before_markers)
277{ 277{
278 struct Lisp_Marker *m; 278 struct Lisp_Marker *m;
279 bool adjusted = 0;
280 ptrdiff_t nchars = to - from; 279 ptrdiff_t nchars = to - from;
281 ptrdiff_t nbytes = to_byte - from_byte; 280 ptrdiff_t nbytes = to_byte - from_byte;
282 281
@@ -292,8 +291,6 @@ adjust_markers_for_insert (ptrdiff_t from, ptrdiff_t from_byte,
292 { 291 {
293 m->bytepos = to_byte; 292 m->bytepos = to_byte;
294 m->charpos = to; 293 m->charpos = to;
295 if (m->insertion_type)
296 adjusted = 1;
297 } 294 }
298 } 295 }
299 else if (m->bytepos > from_byte) 296 else if (m->bytepos > from_byte)
@@ -302,15 +299,6 @@ adjust_markers_for_insert (ptrdiff_t from, ptrdiff_t from_byte,
302 m->charpos += nchars; 299 m->charpos += nchars;
303 } 300 }
304 } 301 }
305
306 /* Adjusting only markers whose insertion-type is t may result in
307 - disordered start and end in overlays, and
308 - disordered overlays in the slot `overlays_before' of current_buffer. */
309 if (adjusted)
310 {
311 fix_start_end_in_overlays (from, to);
312 fix_overlays_before (current_buffer, from, to);
313 }
314} 302}
315 303
316/* Adjust point for an insertion of NBYTES bytes, which are NCHARS characters. 304/* Adjust point for an insertion of NBYTES bytes, which are NCHARS characters.
diff --git a/src/intervals.c b/src/intervals.c
index e711212d744..3db80ebed4a 100644
--- a/src/intervals.c
+++ b/src/intervals.c
@@ -1810,8 +1810,8 @@ adjust_for_invis_intang (ptrdiff_t pos, ptrdiff_t test_offs, ptrdiff_t adj,
1810 == (test_offs == 0 ? 1 : -1)) 1810 == (test_offs == 0 ? 1 : -1))
1811 /* Invisible property is from an overlay. */ 1811 /* Invisible property is from an overlay. */
1812 : (test_offs == 0 1812 : (test_offs == 0
1813 ? XMARKER (OVERLAY_START (invis_overlay))->insertion_type == 0 1813 ? ! OVERLAY_FRONT_ADVANCE_P (invis_overlay)
1814 : XMARKER (OVERLAY_END (invis_overlay))->insertion_type == 1))) 1814 : OVERLAY_REAR_ADVANCE_P (invis_overlay))))
1815 pos += adj; 1815 pos += adj;
1816 1816
1817 return pos; 1817 return pos;
diff --git a/src/itree.c b/src/itree.c
new file mode 100644
index 00000000000..0c10100eef7
--- /dev/null
+++ b/src/itree.c
@@ -0,0 +1,1138 @@
1/* This file implements an efficient interval data-structure.
2
3Copyright (C) 2017 Andreas Politz (politza@hochschule-trier.de)
4
5This file is not part of GNU Emacs.
6
7GNU Emacs is free software: you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
9the Free Software Foundation, either version 3 of the License, or (at
10your option) any later version.
11
12GNU Emacs is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
19
20#include <config.h>
21#include <math.h>
22#include "lisp.h"
23#include "itree.h"
24
25/*
26 Intervals of the form [BEGIN, END), are stored as nodes inside a RB
27 tree, sorted by BEGIN . The core operation of this tree (besides
28 insert, remove, etc.) is finding all intervals intersecting with
29 some given interval. In order to perform this operation
30 efficiently, every node stores a third value called LIMIT. (See
31 https://en.wikipedia.org/wiki/Interval_tree#Augmented_tree and its
32 source Introduction to Algorithms (Section 14.3), Cormen et al. .)
33
34 ==== Finding intervals ====
35
36 If we search for all intervals intersecting with (X, Y], we look at
37 some node and test whether
38
39 NODE.BEGIN > Y
40
41 Due to the invariant of the search tree, we know, that we may
42 safely prune NODE's right subtree if this test succeeds, since all
43 intervals begin strictly after Y.
44
45 But we can not make such an assumptions about the left tree, since
46 all we know is that the intervals in this subtree must start before
47 or at NODE.BEGIN. So we can't tell, whether they end before X or
48 not. To solve this problem we add another attribute to each node,
49 called LIMIT.
50
51 The LIMIT of a node is the largest END value occurring in the nodes
52 subtree (including the node itself). Thus, we may look at the left
53 child of some NODE and test whether
54
55 NODE.left.LIMIT < X
56
57 and this tells us, if all intervals in the left subtree of NODE end
58 before X and if they can be pruned.
59
60 Conversely, if this inequality is false, the left subtree must
61 contain at least one intersecting interval, giving a resulting time
62 complexity of O(K*log(N)) for this operation, where K is the size
63 of the result set and N the size of the tree.
64
65 ==== Adjusting intervals ====
66
67 Since this data-structure will be used for overlays in an Emacs
68 buffer, a second core operation implements the ability to insert or
69 delete gaps in resp. from the tree. This models the insertion
70 resp. deletion of text in a buffer and the effects it may have on
71 the positions of overlays.
72
73 Consider this: Something gets inserted at position P into a buffer
74 and assume that all overlays occur strictly after P. Ordinarily,
75 we would have to iterate all overlays and increment their BEGIN and
76 END values accordingly (the insertion of text pushes them back).
77 In order to avoid this, we introduce yet another node attribute,
78 called OFFSET.
79
80 The OFFSET of some some subtree, represented by its root, is the
81 amount of shift that needs to be applied to its BEGIN, END and
82 LIMIT values, in order to get to the real values. Coming back to
83 the example, all we would need to do in this case, is to increment
84 the OFFSET of the tree's root, without any traversal of the tree
85 itself.
86
87 As a consequence, the real values of BEGIN, END and LIMIT of some
88 NODE need to be computed by incrementing them by the sum of NODE's
89 OFFSET and all of its ancestors offsets. Therefore, we store a
90 counter (otick) inside every node and also the tree, by which we
91 remember the fact, that a node's path to the root has no offsets
92 applied (i.e. its values are up to date). This is the case if some
93 node's value differs from the tree's one, the later of which is
94 incremented whenever some node's offset has changed.
95*/
96
97static struct interval_node *interval_tree_validate(struct interval_tree *, struct interval_node *);
98static void interval_generator_ensure_space(struct interval_generator *);
99static bool interval_node_intersects(const struct interval_node *, ptrdiff_t, ptrdiff_t);
100static int interval_tree_max_height(const struct interval_tree *);
101static struct interval_stack *interval_stack_create(intmax_t);
102static void interval_stack_destroy(struct interval_stack *);
103static void interval_stack_clear(struct interval_stack *);
104static void interval_stack_ensure_space(struct interval_stack *, intmax_t);
105static void interval_stack_push(struct interval_stack *, struct interval_node *);
106static void interval_stack_push_flagged(struct interval_stack *, struct interval_node *, bool);
107static struct interval_node *interval_stack_pop(struct interval_stack *);
108static void interval_tree_update_limit(const struct interval_tree *, struct interval_node *);
109static void interval_tree_inherit_offset(const struct interval_tree *, struct interval_node *);
110static void interval_tree_propagate_limit(const struct interval_tree *, struct interval_node *);
111static void interval_tree_rotate_left(struct interval_tree *, struct interval_node *);
112static void interval_tree_rotate_right(struct interval_tree *, struct interval_node *);
113static void interval_tree_insert_fix(struct interval_tree *, struct interval_node *);
114static void interval_tree_remove_fix(struct interval_tree *, struct interval_node *);
115static void interval_tree_transplant(struct interval_tree *, struct interval_node *, struct interval_node *);
116static struct interval_node *interval_tree_subtree_min(const struct interval_tree *, struct interval_node *);
117static struct interval_generator* interval_generator_create (struct interval_tree *);
118static void interval_generator_destroy (struct interval_generator *);
119static void interval_generator_reset (struct interval_generator *,
120 ptrdiff_t, ptrdiff_t,
121 enum interval_tree_order);
122static void
123interval_generator_narrow (struct interval_generator *g,
124 ptrdiff_t begin, ptrdiff_t end);
125static inline struct interval_node*
126interval_generator_next (struct interval_generator *g);
127static inline void interval_tree_iter_ensure_space(struct interval_tree *);
128
129
130
131/* +------------------------------------------------------------------------------------+ */
132
133/* Simple dynamic array. */
134struct interval_stack
135{
136 struct interval_node **nodes;
137 size_t size;
138 size_t length;
139};
140
141/* State used when iterating interval. */
142struct interval_generator
143{
144 struct interval_tree *tree;
145 struct interval_stack *stack;
146 ptrdiff_t begin;
147 ptrdiff_t end;
148 enum interval_tree_order order;
149};
150
151
152
153/* +===================================================================================+
154 * | Tree operations
155 * +===================================================================================+ */
156
157/* Initialize an allocated node. */
158
159void
160interval_node_init (struct interval_node *node,
161 ptrdiff_t begin, ptrdiff_t end,
162 bool front_advance, bool rear_advance,
163 Lisp_Object data)
164{
165 node->begin = begin;
166 node->end = max (begin, end);
167 node->front_advance = front_advance;
168 node->rear_advance = rear_advance;
169 node->data = data;
170}
171
172/* Return NODE's begin value, computing it if necessary. */
173
174ptrdiff_t
175interval_node_begin (struct interval_tree *tree,
176 struct interval_node *node)
177{
178 interval_tree_validate (tree, node);
179 return node->begin;
180}
181
182/* Return NODE's end value, computing it if necessary. */
183
184ptrdiff_t
185interval_node_end (struct interval_tree *tree,
186 struct interval_node *node)
187{
188 interval_tree_validate (tree, node);
189 return node->end;
190}
191
192/* Safely modify a node's interval. */
193
194void
195interval_node_set_region (struct interval_tree *tree,
196 struct interval_node *node,
197 ptrdiff_t begin, ptrdiff_t end)
198{
199 interval_tree_validate (tree, node);
200 if (begin != node->begin)
201 {
202 interval_tree_remove (tree, node);
203 node->begin = min (begin, PTRDIFF_MAX - 1);
204 node->end = max (node->begin, end);
205 interval_tree_insert (tree, node);
206 }
207 else if (end != node->end)
208 {
209 node->end = max (node->begin, end);
210 interval_tree_propagate_limit (tree, node);
211 }
212}
213
214/* Allocate an interval_tree. Free with interval_tree_destroy. */
215
216struct interval_tree*
217interval_tree_create (void)
218{
219 struct interval_tree *tree = xmalloc (sizeof (*tree));
220 interval_tree_clear (tree);
221 tree->iter = interval_generator_create (tree);
222 return tree;
223}
224
225/* Reset the tree TREE to its empty state. */
226
227void
228interval_tree_clear (struct interval_tree *tree)
229{
230 struct interval_node *nil = &tree->nil;
231 nil->left = nil->right = nil->parent = nil;
232 nil->offset = nil->otick = 0;
233 nil->begin = PTRDIFF_MIN;
234 nil->end = PTRDIFF_MIN;
235 nil->limit = PTRDIFF_MIN; /* => max(x, nil.limit) = x */
236 nil->color = ITREE_BLACK;
237 tree->root = nil;
238 tree->otick = 1;
239 tree->size = 0;
240 tree->iter_running = 0;
241}
242
243#ifdef ITREE_TESTING
244/* Initialize a pre-allocated tree (presumably on the stack). */
245
246static void
247interval_tree_init (struct interval_tree *tree)
248{
249 interval_tree_clear (tree);
250 tree->iter = interval_generator_create (tree);
251}
252#endif
253
254/* Release a tree, freeing its allocated memory. */
255void
256interval_tree_destroy (struct interval_tree *tree)
257{
258 if (! tree)
259 return;
260 if (tree->iter)
261 interval_generator_destroy (tree->iter);
262 xfree (tree);
263}
264
265/* Return the number of nodes in TREE. */
266
267intmax_t
268interval_tree_size (struct interval_tree *tree)
269{
270 return tree->size;
271}
272
273/* Insert a NODE into the TREE.
274
275 Note, that inserting a node twice results in undefined behaviour.
276*/
277
278void
279interval_tree_insert (struct interval_tree *tree, struct interval_node *node)
280{
281 eassert (node && node->begin <= node->end && node != &tree->nil);
282
283 struct interval_node *parent = &tree->nil;
284 struct interval_node *child = tree->root;
285 ptrdiff_t offset = 0;
286
287 /* Find the insertion point, accumulate node's offset and update
288 ancestors limit values. */
289 while (child != &tree->nil)
290 {
291 parent = child;
292 offset += child->offset;
293 child->limit = max (child->limit, node->end - offset);
294 /* This suggests that nodes in the right subtree are strictly
295 greater. But this is not true due to later rotations. */
296 child = node->begin <= child->begin ? child->left : child->right;
297 }
298
299 /* Insert the node */
300 if (parent == &tree->nil)
301 tree->root = node;
302 else if (node->begin <= parent->begin)
303 parent->left = node;
304 else
305 parent->right = node;
306
307 /* Init the node */
308 node->parent = parent;
309 node->left = &tree->nil;
310 node->right = &tree->nil;
311 node->color = ITREE_RED;
312 node->offset = offset;
313 node->limit = node->end;
314 node->otick = tree->otick - 1;
315
316 /* Fix/update the tree */
317 ++tree->size;
318 interval_tree_insert_fix (tree, node);
319 interval_tree_iter_ensure_space (tree);
320}
321
322/* Return true, if NODE is a member of TREE. */
323
324bool
325interval_tree_contains (struct interval_tree *tree, struct interval_node *node)
326{
327 struct interval_node *other;
328
329 interval_tree_iter_start (tree, node->begin, PTRDIFF_MAX, ITREE_ASCENDING);
330 while ((other = interval_tree_iter_next (tree)))
331 if (other == node)
332 break;
333
334 interval_tree_iter_finish (tree);
335 return other == node;
336}
337
338/* Remove NODE from TREE and return it. NODE must exist in TREE.*/
339
340struct interval_node*
341interval_tree_remove (struct interval_tree *tree, struct interval_node *node)
342{
343 eassert (interval_tree_contains (tree, node));
344
345 struct interval_node *broken = NULL;
346
347 interval_tree_inherit_offset (tree, node);
348 if (node->left == &tree->nil || node->right == &tree->nil)
349 {
350 struct interval_node *subst =
351 (node->right == &tree->nil) ? node->left : node->right;
352 if (node->color == ITREE_BLACK)
353 broken = subst;
354 interval_tree_transplant (tree, subst, node);
355 interval_tree_propagate_limit (tree, subst);
356 }
357 else
358 {
359 struct interval_node *min = interval_tree_subtree_min (tree, node->right);
360 struct interval_node *min_right = min->right;
361
362 if (min->color == ITREE_BLACK)
363 broken = min->right;
364 if (min->parent == node)
365 min_right->parent = min; /* set parent, if min_right = nil */
366 else
367 {
368 interval_tree_transplant (tree, min->right, min);
369 min->right = node->right;
370 min->right->parent = min;
371 }
372 interval_tree_inherit_offset (tree, min);
373 interval_tree_transplant (tree, min, node);
374 min->left = node->left;
375 min->left->parent = min;
376 min->color = node->color;
377 interval_tree_propagate_limit (tree, min_right);
378 interval_tree_propagate_limit (tree, min);
379 }
380
381 if (broken)
382 interval_tree_remove_fix (tree, broken);
383
384 node->right = node->left = node->parent = NULL;
385 --tree->size;
386
387 eassert (tree->size == 0 || (tree->size > 0 && tree->root != &tree->nil));
388
389 return node;
390}
391
392static struct interval_node*
393interval_tree_validate (struct interval_tree *tree, struct interval_node *node)
394{
395
396 if (tree->otick == node->otick || node == &tree->nil)
397 return node;
398 if (node != tree->root)
399 interval_tree_validate (tree, node->parent);
400
401 interval_tree_inherit_offset (tree, node);
402 return node;
403}
404
405/* Start a generator iterating all intervals in [BEGIN,END) in the
406 given ORDER. Only one iterator per tree can be running at any
407 time.
408*/
409
410void
411interval_tree_iter_start (struct interval_tree *tree,
412 ptrdiff_t begin, ptrdiff_t end,
413 enum interval_tree_order order)
414{
415 if (tree->iter_running)
416 emacs_abort ();
417 interval_generator_reset (tree->iter, begin, end, order);
418 tree->iter_running = 1;
419}
420
421/* Limit the search interval of the iterator to the given values. The
422 interval can only shrink, but never grow.*/
423
424inline void
425interval_tree_iter_narrow(struct interval_tree *tree,
426 ptrdiff_t begin, ptrdiff_t end)
427{
428 if (! tree->iter_running)
429 emacs_abort ();
430 interval_generator_narrow (tree->iter, begin, end);
431}
432
433/* Stop using the iterator. */
434
435void
436interval_tree_iter_finish (struct interval_tree *tree)
437{
438 if (! tree->iter_running)
439 emacs_abort ();
440 tree->iter_running = 0;
441}
442
443/* Return the next node of the iterator in the order given when it was
444 started; or NULL if there are no more nodes. */
445
446inline struct interval_node*
447interval_tree_iter_next (struct interval_tree *tree)
448{
449 if (! tree->iter_running)
450 emacs_abort ();
451 return interval_generator_next (tree->iter);
452}
453
454/* Ensure that the tree's iterator does not need to allocate space
455 until the tree grows in size. */
456
457static inline void
458interval_tree_iter_ensure_space (struct interval_tree *tree)
459{
460 interval_generator_ensure_space (tree->iter);
461}
462
463static int
464interval_tree_max_height (const struct interval_tree *tree)
465{
466 return 2 * log (tree->size + 1) / log (2) + 0.5;
467}
468
469
470/* +===================================================================================+
471 * | Insert/Delete Gaps
472 * +===================================================================================+ */
473
474/* Insert a gap at POS of length LENGTH expanding all intervals
475 intersecting it, while respecting their rear_advance and
476 front_advance setting. */
477
478void
479interval_tree_insert_gap (struct interval_tree *tree, ptrdiff_t pos, ptrdiff_t length)
480{
481 if (length <= 0 || tree->size == 0)
482 return;
483
484 /* FIXME: Don't allocate generator/stack anew every time. */
485
486 /* Nodes with front_advance starting at pos may mess up the tree
487 order, so we need to remove them first. */
488 struct interval_stack *saved = interval_stack_create (0);
489 struct interval_node *node = NULL;
490 interval_tree_iter_start (tree, pos, pos + 1, ITREE_PRE_ORDER);
491 while ((node = interval_tree_iter_next (tree)))
492 {
493 if (node->begin == pos && node->front_advance
494 && (node->begin != node->end || node->rear_advance))
495 interval_stack_push (saved, node);
496 }
497 interval_tree_iter_finish (tree);
498 for (int i = 0; i < saved->length; ++i)
499 interval_tree_remove (tree, saved->nodes[i]);
500
501
502 /* We can't use a generator here, because we can't effectively
503 narrow AND shift some subtree at the same time. */
504 const int size = interval_tree_max_height (tree) + 1;
505 struct interval_stack *stack = interval_stack_create (size);
506 interval_stack_push (stack, tree->root);
507 while ((node = interval_stack_pop (stack)))
508 {
509 /* Process in pre-order. */
510 interval_tree_inherit_offset (tree, node);
511 if (node->right != &tree->nil)
512 {
513 if (node->begin > pos)
514 {
515 /* All nodes in this subtree are shifted by length. */
516 node->right->offset += length;
517 ++tree->otick;
518 }
519 else
520 interval_stack_push (stack, node->right);
521 }
522 if (node->left != &tree->nil && pos <= node->left->limit)
523 interval_stack_push (stack, node->left);
524
525 /* node->begin == pos implies no front-advance. */
526 if (node->begin > pos)
527 node->begin += length;
528 if (node->end > pos || (node->end == pos && node->rear_advance))
529 {
530 node->end += length;
531 interval_tree_propagate_limit (tree, node);
532 }
533 }
534 interval_stack_destroy (stack);
535
536 /* Reinsert nodes starting at POS having front-advance. */
537 while ((node = interval_stack_pop (saved)))
538 {
539 node->begin += length;
540 if (node->end != pos || node->rear_advance)
541 node->end += length;
542 interval_tree_insert (tree, node);
543 }
544
545 interval_stack_destroy (saved);
546}
547
548/* Delete a gap at POS of length LENGTH, contracting all intervals
549 intersecting it. */
550
551void
552interval_tree_delete_gap (struct interval_tree *tree, ptrdiff_t pos, ptrdiff_t length)
553{
554 if (length <= 0 || tree->size == 0)
555 return;
556
557 /* FIXME: Don't allocate stack anew every time. */
558
559 /* Can't use the generator here, because by decrementing begin, we
560 might unintentionally bring shifted nodes back into our search
561 space. */
562 const int size = interval_tree_max_height (tree) + 1;
563 struct interval_stack *stack = interval_stack_create (size);
564 struct interval_node *node;
565
566 interval_stack_push (stack, tree->root);
567 while ((node = interval_stack_pop (stack)))
568 {
569 interval_tree_inherit_offset (tree, node);
570 if (node->right != &tree->nil)
571 {
572 if (node->begin > pos + length)
573 {
574 /* Shift right subtree to the left. */
575 node->right->offset -= length;
576 ++tree->otick;
577 }
578 else
579 interval_stack_push (stack, node->right);
580 }
581 if (node->left != &tree->nil && pos <= node->left->limit)
582 interval_stack_push (stack, node->left);
583
584 if (pos < node->begin)
585 node->begin = max (pos, node->begin - length);
586 if (node->end > pos)
587 {
588 node->end = max (pos , node->end - length);
589 interval_tree_propagate_limit (tree, node);
590 }
591 }
592 interval_stack_destroy (stack);
593}
594
595
596
597/* +===================================================================================+
598 * | Generator
599 * +===================================================================================+ */
600
601/* Allocate a new generator for TREE. */
602
603static struct interval_generator*
604interval_generator_create (struct interval_tree *tree)
605{
606 struct interval_generator *g = xmalloc (sizeof *g);
607 const int size = interval_tree_max_height (tree) + 1;
608
609 g->stack = interval_stack_create (size);
610 g->tree = tree;
611 interval_generator_reset (g, 1, 0, 0);
612 return g;
613}
614
615/* Reset generator G such that it iterates over intervals intersecting
616 with [BEGIN, END) in the given ORDER. */
617
618void
619interval_generator_reset (struct interval_generator *g,
620 ptrdiff_t begin, ptrdiff_t end,
621 enum interval_tree_order order)
622{
623 if (! g) return;
624
625 g->begin = begin;
626 g->end = end;
627 g->order = order;
628 interval_stack_clear (g->stack);
629 if (begin <= end && g->tree->size > 0)
630 interval_stack_push_flagged (g->stack, g->tree->root, false);
631}
632
633/* Allocate enough space for the tree of G in its current shape. */
634
635static inline void
636interval_generator_ensure_space (struct interval_generator *g)
637{
638 interval_stack_ensure_space (g->stack, interval_tree_max_height (g->tree) + 1);
639}
640
641/* Return true, if NODE's interval intersects with [BEGIN, END). */
642
643static inline bool
644interval_node_intersects (const struct interval_node *node,
645 ptrdiff_t begin, ptrdiff_t end)
646{
647 return (begin < node->end && node->begin < end)
648 || (node->begin == node->end && begin == node->begin);
649}
650
651/* Return the next node of G, or NULL if there is none. */
652
653inline struct interval_node*
654interval_generator_next (struct interval_generator *g)
655{
656 if (! g) return NULL;
657
658 struct interval_node * const nil = &g->tree->nil;
659 struct interval_node *node;
660
661 do {
662 node = interval_stack_pop (g->stack);
663
664 while (node && ! node->visited)
665 {
666 struct interval_node * const left = node->left;
667 struct interval_node * const right = node->right;
668
669 interval_tree_inherit_offset (g->tree, node);
670 switch (g->order)
671 {
672 case ITREE_ASCENDING:
673 if (right != nil && node->begin <= g->end)
674 interval_stack_push_flagged (g->stack, right, false);
675 if (interval_node_intersects (node, g->begin, g->end))
676 interval_stack_push_flagged (g->stack, node, true);
677 /* Node's children may still be off-set and we need to add it. */
678 if (left != nil && g->begin <= left->limit + left->offset)
679 interval_stack_push_flagged (g->stack, left, false);
680 break;
681 case ITREE_DESCENDING:
682 if (left != nil && g->begin <= left->limit + left->offset)
683 interval_stack_push_flagged (g->stack, left, false);
684 if (interval_node_intersects (node, g->begin, g->end))
685 interval_stack_push_flagged (g->stack, node, true);
686 if (right != nil && node->begin <= g->end)
687 interval_stack_push_flagged (g->stack, right, false);
688 break;
689 case ITREE_PRE_ORDER:
690 if (right != nil && node->begin <= g->end)
691 interval_stack_push_flagged (g->stack, right, false);
692 if (left != nil && g->begin <= left->limit + left->offset)
693 interval_stack_push_flagged (g->stack, left, false);
694 if (interval_node_intersects (node, g->begin, g->end))
695 interval_stack_push_flagged (g->stack, node, true);
696 break;
697 }
698 node = interval_stack_pop (g->stack);
699 }
700 /* Node may have been invalidated by interval_generator_narrow
701 after it was pushed: Check if it still intersects. */
702 } while (node && ! interval_node_intersects (node, g->begin, g->end));
703
704 return node;
705}
706
707/* Limit G to the new interval [BEGIN, END), which must be a subset of
708 the current one. I.E. it can't grow on either side. */
709
710static inline void
711interval_generator_narrow (struct interval_generator *g,
712 ptrdiff_t begin, ptrdiff_t end)
713{
714 g->begin = max (begin, g->begin);
715 g->end = min (end, g->end);
716}
717
718/* Free the memory allocated for G. */
719
720void
721interval_generator_destroy (struct interval_generator *g)
722{
723 if (! g) return;
724 if (g->stack)
725 interval_stack_destroy (g->stack);
726 xfree (g);
727}
728
729
730/* +===================================================================================+
731 * | Stack
732 * +===================================================================================+ */
733
734/* This is just a simple dynamic array with stack semantics. */
735
736static struct interval_stack*
737interval_stack_create (intmax_t initial_size)
738{
739 struct interval_stack *stack = xmalloc (sizeof (struct interval_stack));
740 stack->size = max (0, initial_size);
741 stack->nodes = xmalloc (stack->size * sizeof (struct interval_node*));
742 stack->length = 0;
743 return stack;
744}
745
746static void
747interval_stack_destroy (struct interval_stack *stack)
748{
749 if (! stack)
750 return;
751 if (stack->nodes)
752 xfree (stack->nodes);
753 xfree (stack);
754}
755
756static void
757interval_stack_clear (struct interval_stack *stack)
758{
759 stack->length = 0;
760}
761
762static inline void
763interval_stack_ensure_space (struct interval_stack *stack, intmax_t nelements)
764{
765 if (nelements > stack->size)
766 {
767 stack->size = (nelements + 1) * 2;
768 stack->nodes = xrealloc (stack->nodes, stack->size * sizeof (*stack->nodes));
769 }
770}
771
772static inline void
773interval_stack_push (struct interval_stack *stack, struct interval_node *node)
774{
775 interval_stack_ensure_space (stack, stack->length + 1);
776 stack->nodes[stack->length] = node;
777 stack->length++;
778}
779
780/* Push NODE on the STACK, while settings its visited flag to FLAG. */
781
782static inline void
783interval_stack_push_flagged (struct interval_stack *stack,
784 struct interval_node *node, bool flag)
785{
786 interval_stack_push (stack, node);
787 node->visited = flag;
788}
789
790static inline struct interval_node*
791interval_stack_pop (struct interval_stack *stack)
792{
793 if (stack->length == 0)
794 return NULL;
795 return stack->nodes[--stack->length];
796}
797
798
799/* +===================================================================================+
800 * | Internal Functions
801 * +===================================================================================+ */
802
803/* Update NODE's limit attribute according to its children. */
804
805static void
806interval_tree_update_limit (const struct interval_tree *tree,
807 struct interval_node *node)
808{
809 if (node == &tree->nil)
810 return;
811
812 node->limit = max (node->end, max (node->left->limit + node->left->offset,
813 node->right->limit + node->right->offset));
814}
815
816/* Apply NODE's offset to its begin, end and limit values and
817 propagate it to its children.
818
819 Does nothing, if NODE is clean, i.e. NODE.otick = tree.otick .
820*/
821
822static void
823interval_tree_inherit_offset (const struct interval_tree *tree,
824 struct interval_node *node)
825{
826
827 if (node->otick == tree->otick)
828 return;
829
830 node->begin += node->offset;
831 node->end += node->offset;
832 node->limit += node->offset;
833 if (node->left != &tree->nil)
834 node->left->offset += node->offset;
835 if (node->right != &tree->nil)
836 node->right->offset += node->offset;
837 node->offset = 0;
838 if (node == tree->root || node->parent->otick == tree->otick)
839 node->otick = tree->otick;
840}
841
842/* Update limit of NODE and its ancestors. Stop when it becomes
843 stable, i.e. new_limit = old_limit.
844
845 NODE may also be the nil node, in which case its parent is
846 used. (This feature is due to the RB algorithm.)
847*/
848
849static void
850interval_tree_propagate_limit (const struct interval_tree *tree,
851 struct interval_node *node)
852{
853 if (node == &tree->nil)
854 node = node->parent;
855 if (node == &tree->nil)
856 return;
857
858 while (1) {
859 ptrdiff_t newlimit = max (node->end, max (node->left->limit + node->left->offset,
860 node->right->limit + node->right->offset));
861 if (newlimit == node->limit)
862 break;
863 node->limit = newlimit;
864 if (node == tree->root)
865 break;
866 node = node->parent;
867 }
868}
869
870/* Perform the familiar left-rotation on node NODE. */
871
872static void
873interval_tree_rotate_left (struct interval_tree *tree, struct interval_node *node)
874{
875 eassert (node->right != &tree->nil);
876
877 struct interval_node *right = node->right;
878
879 interval_tree_inherit_offset (tree, node);
880 interval_tree_inherit_offset (tree, right);
881
882 /* Turn right's left subtree into node's right subtree. */
883 node->right = right->left;
884 if (right->left != &tree->nil)
885 right->left->parent = node;
886
887 /* right's parent was node's parent. */
888 if (right != &tree->nil)
889 right->parent = node->parent;
890
891 /* Get the parent to point to right instead of node. */
892 if (node != tree->root)
893 {
894 if (node == node->parent->left)
895 node->parent->left = right;
896 else
897 node->parent->right = right;
898 }
899 else
900 tree->root = right;
901
902 /* Put node on right's left. */
903 right->left = node;
904 if (node != &tree->nil)
905 node->parent = right;
906
907 /* Order matters here. */
908 interval_tree_update_limit (tree, node);
909 interval_tree_update_limit (tree, right);
910}
911
912/* Perform the familiar right-rotation on node NODE. */
913
914static void
915interval_tree_rotate_right (struct interval_tree *tree, struct interval_node *node)
916{
917 eassert (tree && node && node->left != &tree->nil);
918
919 struct interval_node *left = node->left;
920
921 interval_tree_inherit_offset (tree, node);
922 interval_tree_inherit_offset (tree, left);
923
924 node->left = left->right;
925 if (left->right != &tree->nil)
926 left->right->parent = node;
927
928 if (left != &tree->nil)
929 left->parent = node->parent;
930 if (node != tree->root)
931 {
932 if (node == node->parent->right)
933 node->parent->right = left;
934 else
935 node->parent->left = left;
936 }
937 else
938 tree->root = left;
939
940 left->right = node;
941 if (node != &tree->nil)
942 node->parent = left;
943
944 interval_tree_update_limit (tree, left);
945 interval_tree_update_limit (tree, node);
946}
947
948/* Repair the tree after an insertion. Part of the RB-Tree
949 algorithm. */
950
951static void
952interval_tree_insert_fix (struct interval_tree *tree, struct interval_node *node)
953{
954 while (node->parent->color == ITREE_RED)
955 {
956 /* NODE is red and its parent is red. This is a violation of
957 red-black tree property #3. */
958
959 if (node->parent == node->parent->parent->left)
960 {
961 /* We're on the left side of our grandparent, and OTHER is
962 our "uncle". */
963 struct interval_node *uncle = node->parent->parent->right;
964
965 if (uncle->color == ITREE_RED) /* case 1.a */
966 {
967 /* Uncle and parent are red but should be black because
968 NODE is red. Change the colors accordingly and
969 proceed with the grandparent. */
970 node->parent->color = ITREE_BLACK;
971 uncle->color = ITREE_BLACK;
972 node->parent->parent->color = ITREE_RED;
973 node = node->parent->parent;
974 }
975 else
976 {
977 /* Parent and uncle have different colors; parent is
978 red, uncle is black. */
979 if (node == node->parent->right) /* case 2.a */
980 {
981 node = node->parent;
982 interval_tree_rotate_left (tree, node);
983 }
984 /* case 3.a */
985 node->parent->color = ITREE_BLACK;
986 node->parent->parent->color = ITREE_RED;
987 interval_tree_rotate_right (tree, node->parent->parent);
988 }
989 }
990 else
991 {
992 /* This is the symmetrical case of above. */
993 struct interval_node *uncle = node->parent->parent->left;
994
995 if (uncle->color == ITREE_RED) /* case 1.b */
996 {
997 node->parent->color = ITREE_BLACK;
998 uncle->color = ITREE_BLACK;
999 node->parent->parent->color = ITREE_RED;
1000 node = node->parent->parent;
1001 }
1002 else
1003 {
1004 if (node == node->parent->left) /* case 2.b */
1005 {
1006 node = node->parent;
1007 interval_tree_rotate_right (tree, node);
1008 }
1009 /* case 3.b */
1010 node->parent->color = ITREE_BLACK;
1011 node->parent->parent->color = ITREE_RED;
1012 interval_tree_rotate_left (tree, node->parent->parent);
1013 }
1014 }
1015 }
1016
1017 /* The root may have been changed to red due to the algorithm. Set
1018 it to black so that property #5 is satisfied. */
1019 tree->root->color = ITREE_BLACK;
1020}
1021
1022/* Repair the tree after a deletion. Part of the RB-Tree
1023 algorithm. */
1024
1025static void
1026interval_tree_remove_fix (struct interval_tree *tree, struct interval_node *node)
1027{
1028 while (node != tree->root && node->color == ITREE_BLACK)
1029 {
1030 if (node == node->parent->left)
1031 {
1032 struct interval_node *other = node->parent->right;
1033
1034 if (other->color == ITREE_RED) /* case 1.a */
1035 {
1036 other->color = ITREE_BLACK;
1037 node->parent->color = ITREE_RED;
1038 interval_tree_rotate_left (tree, node->parent);
1039 other = node->parent->right;
1040 }
1041
1042 if (other->left->color == ITREE_BLACK /* 2.a */
1043 && other->right->color == ITREE_BLACK)
1044 {
1045 other->color = ITREE_RED;
1046 node = node->parent;
1047 }
1048 else
1049 {
1050 if (other->right->color == ITREE_BLACK) /* 3.a */
1051 {
1052 other->left->color = ITREE_BLACK;
1053 other->color = ITREE_RED;
1054 interval_tree_rotate_right (tree, other);
1055 other = node->parent->right;
1056 }
1057 other->color = node->parent->color; /* 4.a */
1058 node->parent->color = ITREE_BLACK;
1059 other->right->color = ITREE_BLACK;
1060 interval_tree_rotate_left (tree, node->parent);
1061 node = tree->root;
1062 }
1063 }
1064 else
1065 {
1066 struct interval_node *other = node->parent->left;
1067
1068 if (other->color == ITREE_RED) /* 1.b */
1069 {
1070 other->color = ITREE_BLACK;
1071 node->parent->color = ITREE_RED;
1072 interval_tree_rotate_right (tree, node->parent);
1073 other = node->parent->left;
1074 }
1075
1076 if (other->right->color == ITREE_BLACK /* 2.b */
1077 && other->left->color == ITREE_BLACK)
1078 {
1079 other->color = ITREE_RED;
1080 node = node->parent;
1081 }
1082 else
1083 {
1084 if (other->left->color == ITREE_BLACK) /* 3.b */
1085 {
1086 other->right->color = ITREE_BLACK;
1087 other->color = ITREE_RED;
1088 interval_tree_rotate_left (tree, other);
1089 other = node->parent->left;
1090 }
1091
1092 other->color = node->parent->color; /* 4.b */
1093 node->parent->color = ITREE_BLACK;
1094 other->left->color = ITREE_BLACK;
1095 interval_tree_rotate_right (tree, node->parent);
1096 node = tree->root;
1097 }
1098 }
1099 }
1100
1101 node->color = ITREE_BLACK;
1102}
1103
1104/* Link node SOURCE in DEST's place. */
1105
1106static void
1107interval_tree_transplant (struct interval_tree *tree, struct interval_node *source,
1108 struct interval_node *dest)
1109{
1110 eassert (tree && source && dest && dest != &tree->nil);
1111
1112 if (dest == tree->root)
1113 tree->root = source;
1114 else if (dest == dest->parent->left)
1115 dest->parent->left = source;
1116 else
1117 dest->parent->right = source;
1118
1119 source->parent = dest->parent;
1120}
1121
1122
1123static struct interval_node*
1124interval_tree_subtree_min (const struct interval_tree *tree, struct interval_node *node)
1125{
1126 if (node == &tree->nil)
1127 return node;
1128 while (node->left != &tree->nil)
1129 node = node->left;
1130 return node;
1131}
1132
1133
1134/* +===================================================================================+
1135 * | Debugging
1136 * +===================================================================================+ */
1137
1138/* See Foverlay_tree in buffer.c */
diff --git a/src/itree.h b/src/itree.h
new file mode 100644
index 00000000000..d35c5afc24c
--- /dev/null
+++ b/src/itree.h
@@ -0,0 +1,88 @@
1/* This file implements an efficient interval data-structure.
2
3Copyright (C) 2017 Andreas Politz (politza@hochschule-trier.de)
4
5This file is not part of GNU Emacs.
6
7GNU Emacs is free software: you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
9the Free Software Foundation, either version 3 of the License, or (at
10your option) any later version.
11
12GNU Emacs is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
19
20#ifndef ITREE_H
21#define ITREE_H
22#include <config.h>
23#include <stddef.h>
24#include <inttypes.h>
25
26/* The tree and node structs are mainly here, so they can be allocated.
27
28 NOTE: The only time where it is safe to modify node.begin and
29 node.end directly, is while the node is not part of any tree.
30
31 NOTE: It is safe to read node.begin and node.end directly, if the
32 node came from a generator, because it validates the nodes it
33 returns as a side-effect.
34*/
35
36struct interval_node;
37struct interval_node
38{
39 enum { ITREE_RED, ITREE_BLACK } color;
40 struct interval_node *parent;
41 struct interval_node *left;
42 struct interval_node *right;
43 ptrdiff_t begin; /* The beginning of this interval. */
44 ptrdiff_t end; /* The end of the interval. */
45 ptrdiff_t limit; /* The maximum end in this subtree. */
46 ptrdiff_t offset; /* The amount of shift to apply to this subtree. */
47 uintmax_t otick; /* offset modified tick */
48 Lisp_Object data; /* Exclusively used by the client. */
49 bool_bf visited; /* For traversal via generator. */
50 bool_bf rear_advance : 1; /* Same as for marker and overlays. */
51 bool_bf front_advance : 1; /* Same as for marker and overlays. */
52};
53
54struct interval_tree
55{
56 struct interval_node *root;
57 struct interval_node nil; /* The tree's version of NULL. */
58 uintmax_t otick; /* offset tick, compared with node's otick. */
59 intmax_t size; /* Number of nodes in the tree. */
60 struct interval_generator *iter;
61 bool_bf iter_running;
62};
63
64enum interval_tree_order {
65 ITREE_ASCENDING = 0,
66 ITREE_DEFLT_ORDER = 0,
67 ITREE_DESCENDING,
68 ITREE_PRE_ORDER,
69};
70
71void interval_node_init(struct interval_node *, ptrdiff_t, ptrdiff_t, bool, bool, Lisp_Object);
72ptrdiff_t interval_node_begin(struct interval_tree *, struct interval_node *);
73ptrdiff_t interval_node_end(struct interval_tree *, struct interval_node *);
74void interval_node_set_region(struct interval_tree *, struct interval_node *, ptrdiff_t, ptrdiff_t);
75struct interval_tree *interval_tree_create(void);
76void interval_tree_destroy(struct interval_tree *);
77intmax_t interval_tree_size(struct interval_tree *);
78void interval_tree_clear(struct interval_tree *);
79void interval_tree_insert(struct interval_tree *, struct interval_node *);
80bool interval_tree_contains(struct interval_tree *, struct interval_node *);
81struct interval_node *interval_tree_remove(struct interval_tree *, struct interval_node *);
82void interval_tree_iter_start(struct interval_tree *, ptrdiff_t, ptrdiff_t, enum interval_tree_order);
83void interval_tree_iter_narrow(struct interval_tree *, ptrdiff_t, ptrdiff_t);
84void interval_tree_iter_finish(struct interval_tree *);
85struct interval_node *interval_tree_iter_next(struct interval_tree *);
86void interval_tree_insert_gap(struct interval_tree *, ptrdiff_t, ptrdiff_t);
87void interval_tree_delete_gap(struct interval_tree *, ptrdiff_t, ptrdiff_t);
88#endif
diff --git a/src/keyboard.c b/src/keyboard.c
index e8701b88708..60cdaba9f0b 100644
--- a/src/keyboard.c
+++ b/src/keyboard.c
@@ -1668,8 +1668,8 @@ adjust_point_for_property (ptrdiff_t last_pt, bool modified)
1668 && display_prop_intangible_p (val, overlay, PT, PT_BYTE) 1668 && display_prop_intangible_p (val, overlay, PT, PT_BYTE)
1669 && (!OVERLAYP (overlay) 1669 && (!OVERLAYP (overlay)
1670 ? get_property_and_range (PT, Qdisplay, &val, &beg, &end, Qnil) 1670 ? get_property_and_range (PT, Qdisplay, &val, &beg, &end, Qnil)
1671 : (beg = OVERLAY_POSITION (OVERLAY_START (overlay)), 1671 : (beg = OVERLAY_START (overlay),
1672 end = OVERLAY_POSITION (OVERLAY_END (overlay)))) 1672 end = OVERLAY_END (overlay)))
1673 && (beg < PT /* && end > PT <- It's always the case. */ 1673 && (beg < PT /* && end > PT <- It's always the case. */
1674 || (beg <= PT && STRINGP (val) && SCHARS (val) == 0))) 1674 || (beg <= PT && STRINGP (val) && SCHARS (val) == 0)))
1675 { 1675 {
diff --git a/src/lisp.h b/src/lisp.h
index 680c25d4c49..222a99950a8 100644
--- a/src/lisp.h
+++ b/src/lisp.h
@@ -2217,15 +2217,14 @@ struct Lisp_Overlay
2217 - next fields of start and end markers (singly linked list of markers). 2217 - next fields of start and end markers (singly linked list of markers).
2218 I.e. 9words plus 2 bits, 3words of which are for external linked lists. 2218 I.e. 9words plus 2 bits, 3words of which are for external linked lists.
2219*/ 2219*/
2220 { 2220{
2221 ENUM_BF (Lisp_Misc_Type) type : 16; /* = Lisp_Misc_Overlay */ 2221 ENUM_BF (Lisp_Misc_Type) type : 16; /* = Lisp_Misc_Overlay */
2222 bool_bf gcmarkbit : 1; 2222 bool_bf gcmarkbit : 1;
2223 unsigned spacer : 15; 2223 unsigned spacer : 15;
2224 struct Lisp_Overlay *next; 2224 Lisp_Object plist;
2225 Lisp_Object start; 2225 struct buffer *buffer; /* eassert (live buffer || NULL). */
2226 Lisp_Object end; 2226 struct interval_node *interval;
2227 Lisp_Object plist; 2227};
2228 };
2229 2228
2230/* Number of bits needed to store one of the values 2229/* Number of bits needed to store one of the values
2231 SAVE_UNUSED..SAVE_OBJECT. */ 2230 SAVE_UNUSED..SAVE_OBJECT. */
@@ -3704,7 +3703,7 @@ extern Lisp_Object make_save_funcptr_ptr_obj (void (*) (void), void *,
3704 Lisp_Object); 3703 Lisp_Object);
3705extern Lisp_Object make_save_memory (Lisp_Object *, ptrdiff_t); 3704extern Lisp_Object make_save_memory (Lisp_Object *, ptrdiff_t);
3706extern void free_save_value (Lisp_Object); 3705extern void free_save_value (Lisp_Object);
3707extern Lisp_Object build_overlay (Lisp_Object, Lisp_Object, Lisp_Object); 3706extern Lisp_Object build_overlay (ptrdiff_t, ptrdiff_t, bool, bool, Lisp_Object);
3708extern void free_marker (Lisp_Object); 3707extern void free_marker (Lisp_Object);
3709extern void free_cons (struct Lisp_Cons *); 3708extern void free_cons (struct Lisp_Cons *);
3710extern void init_alloc_once (void); 3709extern void init_alloc_once (void);
diff --git a/src/print.c b/src/print.c
index f280616af8a..a07baa3067a 100644
--- a/src/print.c
+++ b/src/print.c
@@ -548,8 +548,7 @@ temp_output_buffer_setup (const char *bufname)
548 bset_read_only (current_buffer, Qnil); 548 bset_read_only (current_buffer, Qnil);
549 bset_filename (current_buffer, Qnil); 549 bset_filename (current_buffer, Qnil);
550 bset_undo_list (current_buffer, Qt); 550 bset_undo_list (current_buffer, Qt);
551 eassert (current_buffer->overlays_before == NULL); 551 eassert (current_buffer->overlays == NULL);
552 eassert (current_buffer->overlays_after == NULL);
553 bset_enable_multibyte_characters 552 bset_enable_multibyte_characters
554 (current_buffer, BVAR (&buffer_defaults, enable_multibyte_characters)); 553 (current_buffer, BVAR (&buffer_defaults, enable_multibyte_characters));
555 specbind (Qinhibit_read_only, Qt); 554 specbind (Qinhibit_read_only, Qt);
@@ -2074,7 +2073,7 @@ print_object (Lisp_Object obj, Lisp_Object printcharfun, bool escapeflag)
2074 obj = XCDR (obj); 2073 obj = XCDR (obj);
2075 if (!(i & 1)) 2074 if (!(i & 1))
2076 halftail = XCDR (halftail); 2075 halftail = XCDR (halftail);
2077 } 2076 }
2078 2077
2079 /* OBJ non-nil here means it's the end of a dotted list. */ 2078 /* OBJ non-nil here means it's the end of a dotted list. */
2080 if (!NILP (obj)) 2079 if (!NILP (obj))
@@ -2114,15 +2113,14 @@ print_object (Lisp_Object obj, Lisp_Object printcharfun, bool escapeflag)
2114 2113
2115 case Lisp_Misc_Overlay: 2114 case Lisp_Misc_Overlay:
2116 print_c_string ("#<overlay ", printcharfun); 2115 print_c_string ("#<overlay ", printcharfun);
2117 if (! XMARKER (OVERLAY_START (obj))->buffer) 2116 if (! OVERLAY_BUFFER (obj))
2118 print_c_string ("in no buffer", printcharfun); 2117 print_c_string ("in no buffer", printcharfun);
2119 else 2118 else
2120 { 2119 {
2121 int len = sprintf (buf, "from %"pD"d to %"pD"d in ", 2120 int len = sprintf (buf, "from %"pD"d to %"pD"d in ",
2122 marker_position (OVERLAY_START (obj)), 2121 OVERLAY_START (obj), OVERLAY_END (obj));
2123 marker_position (OVERLAY_END (obj)));
2124 strout (buf, len, len, printcharfun); 2122 strout (buf, len, len, printcharfun);
2125 print_string (BVAR (XMARKER (OVERLAY_START (obj))->buffer, name), 2123 print_string (BVAR (OVERLAY_BUFFER (obj), name),
2126 printcharfun); 2124 printcharfun);
2127 } 2125 }
2128 printchar ('>', printcharfun); 2126 printchar ('>', printcharfun);
diff --git a/src/textprop.c b/src/textprop.c
index 513780c3009..aebb6524e68 100644
--- a/src/textprop.c
+++ b/src/textprop.c
@@ -617,36 +617,42 @@ get_char_property_and_overlay (Lisp_Object position, register Lisp_Object prop,
617 } 617 }
618 if (BUFFERP (object)) 618 if (BUFFERP (object))
619 { 619 {
620 ptrdiff_t noverlays; 620 struct buffer *b = XBUFFER (object);
621 Lisp_Object *overlay_vec; 621 struct interval_node *node;
622 struct buffer *obuf = current_buffer; 622 struct sortvec items[2];
623 struct sortvec *result = NULL;
624 Lisp_Object result_tem = Qnil;
623 625
624 if (XINT (position) < BUF_BEGV (XBUFFER (object)) 626 if (XINT (position) < BUF_BEGV (b) || XINT (position) > BUF_ZV (b))
625 || XINT (position) > BUF_ZV (XBUFFER (object)))
626 xsignal1 (Qargs_out_of_range, position); 627 xsignal1 (Qargs_out_of_range, position);
627 628
628 set_buffer_temp (XBUFFER (object)); 629 buffer_overlay_iter_start(b, XINT (position), XINT (position) + 1,
629 630 ITREE_ASCENDING);
630 USE_SAFE_ALLOCA;
631 GET_OVERLAYS_AT (XINT (position), overlay_vec, noverlays, NULL, false);
632 noverlays = sort_overlays (overlay_vec, noverlays, w);
633
634 set_buffer_temp (obuf);
635 631
636 /* Now check the overlays in order of decreasing priority. */ 632 /* Now check the overlays in order of decreasing priority. */
637 while (--noverlays >= 0) 633 while ((node = buffer_overlay_iter_next (b)))
638 { 634 {
639 Lisp_Object tem = Foverlay_get (overlay_vec[noverlays], prop); 635 Lisp_Object tem = Foverlay_get (node->data, prop);
640 if (!NILP (tem)) 636 struct sortvec *this;
641 { 637
642 if (overlay) 638 if (NILP (tem) || (w && ! overlay_matches_window (w, node->data)))
643 /* Return the overlay we got the property from. */ 639 continue;
644 *overlay = overlay_vec[noverlays]; 640
645 SAFE_FREE (); 641 this = (result == items ? items + 1 : items);
646 return tem; 642 make_sortvec_item (this, node->data);
647 } 643 if (! result || (compare_overlays (result, this) < 0))
644 {
645 result = this;
646 result_tem = tem;
647 }
648 } 648 }
649 SAFE_FREE (); 649 buffer_overlay_iter_finish (b);
650 if (result)
651 {
652 if (overlay)
653 *overlay = result->overlay;
654 return result_tem;
655 }
650 } 656 }
651 657
652 if (overlay) 658 if (overlay)
diff --git a/src/window.h b/src/window.h
index df7c23f824b..324d30b57f9 100644
--- a/src/window.h
+++ b/src/window.h
@@ -1128,6 +1128,16 @@ output_cursor_to (struct window *w, int vpos, int hpos, int y, int x)
1128 w->output_cursor.y = y; 1128 w->output_cursor.y = y;
1129} 1129}
1130 1130
1131/* Return true, if overlay OV's properties should have an effect in
1132 window W. */
1133INLINE bool
1134overlay_matches_window (const struct window *w, Lisp_Object ov)
1135{
1136 eassert (OVERLAYP (ov));
1137 Lisp_Object window = Foverlay_get (ov, Qwindow);
1138 return (! WINDOWP (window) || XWINDOW (window) == w);
1139}
1140
1131INLINE_HEADER_END 1141INLINE_HEADER_END
1132 1142
1133#endif /* not WINDOW_H_INCLUDED */ 1143#endif /* not WINDOW_H_INCLUDED */
diff --git a/src/xdisp.c b/src/xdisp.c
index 86164eb9f6f..b3b9ecae377 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -873,7 +873,6 @@ static enum move_it_result
873static void get_visually_first_element (struct it *); 873static void get_visually_first_element (struct it *);
874static void compute_stop_pos (struct it *); 874static void compute_stop_pos (struct it *);
875static int face_before_or_after_it_pos (struct it *, bool); 875static int face_before_or_after_it_pos (struct it *, bool);
876static ptrdiff_t next_overlay_change (ptrdiff_t);
877static int handle_display_spec (struct it *, Lisp_Object, Lisp_Object, 876static int handle_display_spec (struct it *, Lisp_Object, Lisp_Object,
878 Lisp_Object, struct text_pos *, ptrdiff_t, bool); 877 Lisp_Object, struct text_pos *, ptrdiff_t, bool);
879static int handle_single_display_spec (struct it *, Lisp_Object, Lisp_Object, 878static int handle_single_display_spec (struct it *, Lisp_Object, Lisp_Object,
@@ -3606,39 +3605,6 @@ compute_stop_pos (struct it *it)
3606 && it->stop_charpos >= IT_CHARPOS (*it))); 3605 && it->stop_charpos >= IT_CHARPOS (*it)));
3607} 3606}
3608 3607
3609
3610/* Return the position of the next overlay change after POS in
3611 current_buffer. Value is point-max if no overlay change
3612 follows. This is like `next-overlay-change' but doesn't use
3613 xmalloc. */
3614
3615static ptrdiff_t
3616next_overlay_change (ptrdiff_t pos)
3617{
3618 ptrdiff_t i, noverlays;
3619 ptrdiff_t endpos;
3620 Lisp_Object *overlays;
3621 USE_SAFE_ALLOCA;
3622
3623 /* Get all overlays at the given position. */
3624 GET_OVERLAYS_AT (pos, overlays, noverlays, &endpos, true);
3625
3626 /* If any of these overlays ends before endpos,
3627 use its ending point instead. */
3628 for (i = 0; i < noverlays; ++i)
3629 {
3630 Lisp_Object oend;
3631 ptrdiff_t oendpos;
3632
3633 oend = OVERLAY_END (overlays[i]);
3634 oendpos = OVERLAY_POSITION (oend);
3635 endpos = min (endpos, oendpos);
3636 }
3637
3638 SAFE_FREE ();
3639 return endpos;
3640}
3641
3642/* How many characters forward to search for a display property or 3608/* How many characters forward to search for a display property or
3643 display string. Searching too far forward makes the bidi display 3609 display string. Searching too far forward makes the bidi display
3644 sluggish, especially in small windows. */ 3610 sluggish, especially in small windows. */
@@ -5071,7 +5037,7 @@ handle_single_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object,
5071 overlay's display string/image twice. */ 5037 overlay's display string/image twice. */
5072 if (!NILP (overlay)) 5038 if (!NILP (overlay))
5073 { 5039 {
5074 ptrdiff_t ovendpos = OVERLAY_POSITION (OVERLAY_END (overlay)); 5040 ptrdiff_t ovendpos = OVERLAY_END (overlay);
5075 5041
5076 /* Some borderline-sane Lisp might call us with the current 5042 /* Some borderline-sane Lisp might call us with the current
5077 buffer narrowed so that overlay-end is outside the 5043 buffer narrowed so that overlay-end is outside the
@@ -5785,13 +5751,14 @@ static void
5785load_overlay_strings (struct it *it, ptrdiff_t charpos) 5751load_overlay_strings (struct it *it, ptrdiff_t charpos)
5786{ 5752{
5787 Lisp_Object overlay, window, str, invisible; 5753 Lisp_Object overlay, window, str, invisible;
5788 struct Lisp_Overlay *ov;
5789 ptrdiff_t start, end; 5754 ptrdiff_t start, end;
5790 ptrdiff_t n = 0, i, j; 5755 ptrdiff_t n = 0, i, j;
5791 int invis; 5756 int invis;
5792 struct overlay_entry entriesbuf[20]; 5757 struct overlay_entry entriesbuf[20];
5793 ptrdiff_t size = ARRAYELTS (entriesbuf); 5758 ptrdiff_t size = ARRAYELTS (entriesbuf);
5794 struct overlay_entry *entries = entriesbuf; 5759 struct overlay_entry *entries = entriesbuf;
5760 struct interval_node *node;
5761
5795 USE_SAFE_ALLOCA; 5762 USE_SAFE_ALLOCA;
5796 5763
5797 if (charpos <= 0) 5764 if (charpos <= 0)
@@ -5823,83 +5790,47 @@ load_overlay_strings (struct it *it, ptrdiff_t charpos)
5823 } \ 5790 } \
5824 while (false) 5791 while (false)
5825 5792
5826 /* Process overlay before the overlay center. */ 5793 if (current_buffer->overlays)
5827 for (ov = current_buffer->overlays_before; ov; ov = ov->next)
5828 { 5794 {
5829 XSETMISC (overlay, ov); 5795 buffer_overlay_iter_start (current_buffer,
5830 eassert (OVERLAYP (overlay)); 5796 charpos - 1, charpos + 1, ITREE_DESCENDING);
5831 start = OVERLAY_POSITION (OVERLAY_START (overlay)); 5797 /* Process overlays. */
5832 end = OVERLAY_POSITION (OVERLAY_END (overlay)); 5798 while ((node = buffer_overlay_iter_next (current_buffer)))
5833 5799 {
5834 if (end < charpos) 5800 overlay = node->data;
5835 break; 5801 eassert (OVERLAYP (overlay));
5836 5802 start = node->begin;
5837 /* Skip this overlay if it doesn't start or end at IT's current 5803 end = node->end;
5838 position. */ 5804
5839 if (end != charpos && start != charpos) 5805 /* Skip this overlay if it doesn't start or end at IT's current
5840 continue; 5806 position. */
5841 5807 if (end != charpos && start != charpos)
5842 /* Skip this overlay if it doesn't apply to IT->w. */ 5808 continue;
5843 window = Foverlay_get (overlay, Qwindow); 5809
5844 if (WINDOWP (window) && XWINDOW (window) != it->w) 5810 /* Skip this overlay if it doesn't apply to IT->w. */
5845 continue; 5811 window = Foverlay_get (overlay, Qwindow);
5846 5812 if (WINDOWP (window) && XWINDOW (window) != it->w)
5847 /* If the text ``under'' the overlay is invisible, both before- 5813 continue;
5848 and after-strings from this overlay are visible; start and 5814
5849 end position are indistinguishable. */ 5815 /* If the text ``under'' the overlay is invisible, both before-
5850 invisible = Foverlay_get (overlay, Qinvisible); 5816 and after-strings from this overlay are visible; start and
5851 invis = TEXT_PROP_MEANS_INVISIBLE (invisible); 5817 end position are indistinguishable. */
5852 5818 invisible = Foverlay_get (overlay, Qinvisible);
5853 /* If overlay has a non-empty before-string, record it. */ 5819 invis = TEXT_PROP_MEANS_INVISIBLE (invisible);
5854 if ((start == charpos || (end == charpos && invis != 0)) 5820
5855 && (str = Foverlay_get (overlay, Qbefore_string), STRINGP (str)) 5821 /* If overlay has a non-empty before-string, record it. */
5856 && SCHARS (str)) 5822 if ((start == charpos || (end == charpos && invis != 0))
5857 RECORD_OVERLAY_STRING (overlay, str, false); 5823 && (str = Foverlay_get (overlay, Qbefore_string), STRINGP (str))
5858 5824 && SCHARS (str))
5859 /* If overlay has a non-empty after-string, record it. */ 5825 RECORD_OVERLAY_STRING (overlay, str, false);
5860 if ((end == charpos || (start == charpos && invis != 0)) 5826
5861 && (str = Foverlay_get (overlay, Qafter_string), STRINGP (str)) 5827 /* If overlay has a non-empty after-string, record it. */
5862 && SCHARS (str)) 5828 if ((end == charpos || (start == charpos && invis != 0))
5863 RECORD_OVERLAY_STRING (overlay, str, true); 5829 && (str = Foverlay_get (overlay, Qafter_string), STRINGP (str))
5864 } 5830 && SCHARS (str))
5865 5831 RECORD_OVERLAY_STRING (overlay, str, true);
5866 /* Process overlays after the overlay center. */ 5832 }
5867 for (ov = current_buffer->overlays_after; ov; ov = ov->next) 5833 buffer_overlay_iter_finish (current_buffer);
5868 {
5869 XSETMISC (overlay, ov);
5870 eassert (OVERLAYP (overlay));
5871 start = OVERLAY_POSITION (OVERLAY_START (overlay));
5872 end = OVERLAY_POSITION (OVERLAY_END (overlay));
5873
5874 if (start > charpos)
5875 break;
5876
5877 /* Skip this overlay if it doesn't start or end at IT's current
5878 position. */
5879 if (end != charpos && start != charpos)
5880 continue;
5881
5882 /* Skip this overlay if it doesn't apply to IT->w. */
5883 window = Foverlay_get (overlay, Qwindow);
5884 if (WINDOWP (window) && XWINDOW (window) != it->w)
5885 continue;
5886
5887 /* If the text ``under'' the overlay is invisible, it has a zero
5888 dimension, and both before- and after-strings apply. */
5889 invisible = Foverlay_get (overlay, Qinvisible);
5890 invis = TEXT_PROP_MEANS_INVISIBLE (invisible);
5891
5892 /* If overlay has a non-empty before-string, record it. */
5893 if ((start == charpos || (end == charpos && invis != 0))
5894 && (str = Foverlay_get (overlay, Qbefore_string), STRINGP (str))
5895 && SCHARS (str))
5896 RECORD_OVERLAY_STRING (overlay, str, false);
5897
5898 /* If overlay has a non-empty after-string, record it. */
5899 if ((end == charpos || (start == charpos && invis != 0))
5900 && (str = Foverlay_get (overlay, Qafter_string), STRINGP (str))
5901 && SCHARS (str))
5902 RECORD_OVERLAY_STRING (overlay, str, true);
5903 } 5834 }
5904 5835
5905#undef RECORD_OVERLAY_STRING 5836#undef RECORD_OVERLAY_STRING
@@ -6463,7 +6394,7 @@ back_to_previous_visible_line_start (struct it *it)
6463 && !NILP (val = get_char_property_and_overlay 6394 && !NILP (val = get_char_property_and_overlay
6464 (make_number (pos), Qdisplay, Qnil, &overlay)) 6395 (make_number (pos), Qdisplay, Qnil, &overlay))
6465 && (OVERLAYP (overlay) 6396 && (OVERLAYP (overlay)
6466 ? (beg = OVERLAY_POSITION (OVERLAY_START (overlay))) 6397 ? (beg = OVERLAY_START (overlay))
6467 : get_property_and_range (pos, Qdisplay, &val, &beg, &end, Qnil))) 6398 : get_property_and_range (pos, Qdisplay, &val, &beg, &end, Qnil)))
6468 { 6399 {
6469 RESTORE_IT (it, it, it2data); 6400 RESTORE_IT (it, it, it2data);
@@ -9568,7 +9499,6 @@ move_it_to (struct it *it, ptrdiff_t to_charpos, int to_x, int to_y, int to_vpos
9568 } 9499 }
9569 9500
9570 /* Reset/increment for the next run. */ 9501 /* Reset/increment for the next run. */
9571 recenter_overlay_lists (current_buffer, IT_CHARPOS (*it));
9572 it->current_x = line_start_x; 9502 it->current_x = line_start_x;
9573 line_start_x = 0; 9503 line_start_x = 0;
9574 it->hpos = 0; 9504 it->hpos = 0;
@@ -21212,13 +21142,6 @@ display_line (struct it *it, int cursor_vpos)
21212 row->starts_in_middle_of_char_p = it->starts_in_middle_of_char_p; 21142 row->starts_in_middle_of_char_p = it->starts_in_middle_of_char_p;
21213 it->starts_in_middle_of_char_p = false; 21143 it->starts_in_middle_of_char_p = false;
21214 21144
21215 /* Arrange the overlays nicely for our purposes. Usually, we call
21216 display_line on only one line at a time, in which case this
21217 can't really hurt too much, or we call it on lines which appear
21218 one after another in the buffer, in which case all calls to
21219 recenter_overlay_lists but the first will be pretty cheap. */
21220 recenter_overlay_lists (current_buffer, IT_CHARPOS (*it));
21221
21222 /* If we are going to display the cursor's line, account for the 21145 /* If we are going to display the cursor's line, account for the
21223 hscroll of that line. We subtract the window's min_hscroll, 21146 hscroll of that line. We subtract the window's min_hscroll,
21224 because that was already accounted for in init_iterator. */ 21147 because that was already accounted for in init_iterator. */
@@ -31212,7 +31135,7 @@ note_mouse_highlight (struct frame *f, int x, int y)
31212 if (BUFFERP (object)) 31135 if (BUFFERP (object))
31213 { 31136 {
31214 /* Put all the overlays we want in a vector in overlay_vec. */ 31137 /* Put all the overlays we want in a vector in overlay_vec. */
31215 GET_OVERLAYS_AT (pos, overlay_vec, noverlays, NULL, false); 31138 GET_OVERLAYS_AT (pos, overlay_vec, noverlays, NULL);
31216 /* Sort overlays into increasing priority order. */ 31139 /* Sort overlays into increasing priority order. */
31217 noverlays = sort_overlays (overlay_vec, noverlays, w); 31140 noverlays = sort_overlays (overlay_vec, noverlays, w);
31218 } 31141 }
diff --git a/src/xfaces.c b/src/xfaces.c
index b309c161278..b1788725eb7 100644
--- a/src/xfaces.c
+++ b/src/xfaces.c
@@ -5931,8 +5931,7 @@ face_at_buffer_position (struct window *w, ptrdiff_t pos,
5931 USE_SAFE_ALLOCA; 5931 USE_SAFE_ALLOCA;
5932 { 5932 {
5933 ptrdiff_t next_overlay; 5933 ptrdiff_t next_overlay;
5934 5934 GET_OVERLAYS_AT (pos, overlay_vec, noverlays, &next_overlay);
5935 GET_OVERLAYS_AT (pos, overlay_vec, noverlays, &next_overlay, false);
5936 if (next_overlay < endpos) 5935 if (next_overlay < endpos)
5937 endpos = next_overlay; 5936 endpos = next_overlay;
5938 } 5937 }
@@ -5975,7 +5974,6 @@ face_at_buffer_position (struct window *w, ptrdiff_t pos,
5975 { 5974 {
5976 for (prop = Qnil, i = noverlays - 1; i >= 0 && NILP (prop); --i) 5975 for (prop = Qnil, i = noverlays - 1; i >= 0 && NILP (prop); --i)
5977 { 5976 {
5978 Lisp_Object oend;
5979 ptrdiff_t oendpos; 5977 ptrdiff_t oendpos;
5980 5978
5981 prop = Foverlay_get (overlay_vec[i], propname); 5979 prop = Foverlay_get (overlay_vec[i], propname);
@@ -5988,8 +5986,7 @@ face_at_buffer_position (struct window *w, ptrdiff_t pos,
5988 merge_face_ref (f, prop, attrs, true, 0); 5986 merge_face_ref (f, prop, attrs, true, 0);
5989 } 5987 }
5990 5988
5991 oend = OVERLAY_END (overlay_vec[i]); 5989 oendpos = OVERLAY_END (overlay_vec[i]);
5992 oendpos = OVERLAY_POSITION (oend);
5993 if (oendpos < endpos) 5990 if (oendpos < endpos)
5994 endpos = oendpos; 5991 endpos = oendpos;
5995 } 5992 }
@@ -5998,18 +5995,16 @@ face_at_buffer_position (struct window *w, ptrdiff_t pos,
5998 { 5995 {
5999 for (i = 0; i < noverlays; i++) 5996 for (i = 0; i < noverlays; i++)
6000 { 5997 {
6001 Lisp_Object oend;
6002 ptrdiff_t oendpos; 5998 ptrdiff_t oendpos;
6003 5999
6004 prop = Foverlay_get (overlay_vec[i], propname); 6000 prop = Foverlay_get (overlay_vec[i], propname);
6005 if (!NILP (prop)) 6001 if (!NILP (prop))
6006 merge_face_ref (f, prop, attrs, true, 0); 6002 merge_face_ref (f, prop, attrs, true, 0);
6007 6003
6008 oend = OVERLAY_END (overlay_vec[i]); 6004 oendpos = OVERLAY_END (overlay_vec[i]);
6009 oendpos = OVERLAY_POSITION (oend); 6005 if (oendpos < endpos)
6010 if (oendpos < endpos) 6006 endpos = oendpos;
6011 endpos = oendpos; 6007 }
6012 }
6013 } 6008 }
6014 6009
6015 *endptr = endpos; 6010 *endptr = endpos;