aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorStefan Monnier2022-10-28 17:44:44 -0400
committerStefan Monnier2022-10-28 17:44:44 -0400
commit71589b101ccbec67fa2741856ee0add5752dea72 (patch)
tree63aeb9f5617c3e7e9b87c04f10bfa938f495736c /src
parent69121c33e4a11805bf6438131c8aec72411a0e5d (diff)
parent9d7ba2b1998afc3664c37d9d1b6f6ca2d68356e9 (diff)
downloademacs-71589b101ccbec67fa2741856ee0add5752dea72.tar.gz
emacs-71589b101ccbec67fa2741856ee0add5752dea72.zip
Merge remote-tracking branch 'origin/feature/noverlay'
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.in39
-rw-r--r--src/alloc.c60
-rw-r--r--src/buffer.c1505
-rw-r--r--src/buffer.h110
-rw-r--r--src/editfns.c67
-rw-r--r--src/eval.c1
-rw-r--r--src/fileio.c3
-rw-r--r--src/fns.c15
-rw-r--r--src/indent.c5
-rw-r--r--src/insdel.c12
-rw-r--r--src/intervals.c4
-rw-r--r--src/itree.c1421
-rw-r--r--src/itree.h181
-rw-r--r--src/keyboard.c4
-rw-r--r--src/lisp.h9
-rw-r--r--src/pdumper.c68
-rw-r--r--src/print.c14
-rw-r--r--src/textprop.c57
-rw-r--r--src/window.h10
-rw-r--r--src/xdisp.c195
-rw-r--r--src/xfaces.c17
21 files changed, 2387 insertions, 1410 deletions
diff --git a/src/Makefile.in b/src/Makefile.in
index 1f941874ea8..059e6c717b4 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -426,25 +426,26 @@ ALL_CXX_CFLAGS = $(EMACS_CFLAGS) \
426 426
427## lastfile must follow all files whose initialized data areas should 427## lastfile must follow all files whose initialized data areas should
428## be dumped as pure by dump-emacs. 428## be dumped as pure by dump-emacs.
429base_obj = dispnew.o frame.o scroll.o xdisp.o menu.o $(XMENU_OBJ) window.o \ 429base_obj = dispnew.o frame.o scroll.o xdisp.o menu.o $(XMENU_OBJ) window.o \
430 charset.o coding.o category.o ccl.o character.o chartab.o bidi.o \ 430 charset.o coding.o category.o ccl.o character.o chartab.o bidi.o \
431 $(CM_OBJ) term.o terminal.o xfaces.o $(XOBJ) $(GTK_OBJ) $(DBUS_OBJ) \ 431 $(CM_OBJ) term.o terminal.o xfaces.o $(XOBJ) $(GTK_OBJ) $(DBUS_OBJ) \
432 emacs.o keyboard.o macros.o keymap.o sysdep.o \ 432 emacs.o keyboard.o macros.o keymap.o sysdep.o \
433 bignum.o buffer.o filelock.o insdel.o marker.o \ 433 bignum.o buffer.o filelock.o insdel.o marker.o \
434 minibuf.o fileio.o dired.o \ 434 minibuf.o fileio.o dired.o \
435 cmds.o casetab.o casefiddle.o indent.o search.o regex-emacs.o undo.o \ 435 cmds.o casetab.o casefiddle.o indent.o search.o regex-emacs.o undo.o \
436 alloc.o pdumper.o data.o doc.o editfns.o callint.o \ 436 alloc.o pdumper.o data.o doc.o editfns.o callint.o \
437 eval.o floatfns.o fns.o sort.o font.o print.o lread.o $(MODULES_OBJ) \ 437 eval.o floatfns.o fns.o sort.o font.o print.o lread.o $(MODULES_OBJ) \
438 syntax.o $(UNEXEC_OBJ) bytecode.o comp.o $(DYNLIB_OBJ) \ 438 syntax.o $(UNEXEC_OBJ) bytecode.o comp.o $(DYNLIB_OBJ) \
439 process.o gnutls.o callproc.o \ 439 process.o gnutls.o callproc.o \
440 region-cache.o sound.o timefns.o atimer.o \ 440 region-cache.o sound.o timefns.o atimer.o \
441 doprnt.o intervals.o textprop.o composite.o xml.o lcms.o $(NOTIFY_OBJ) \ 441 doprnt.o intervals.o textprop.o composite.o xml.o lcms.o $(NOTIFY_OBJ) \
442 $(XWIDGETS_OBJ) \ 442 $(XWIDGETS_OBJ) \
443 profiler.o decompress.o \ 443 profiler.o decompress.o \
444 thread.o systhread.o sqlite.o \ 444 thread.o systhread.o sqlite.o \
445 $(if $(HYBRID_MALLOC),sheap.o) \ 445 itree.o \
446 $(MSDOS_OBJ) $(MSDOS_X_OBJ) $(NS_OBJ) $(CYGWIN_OBJ) $(FONT_OBJ) \ 446 $(if $(HYBRID_MALLOC),sheap.o) \
447 $(W32_OBJ) $(WINDOW_SYSTEM_OBJ) $(XGSELOBJ) $(JSON_OBJ) \ 447 $(MSDOS_OBJ) $(MSDOS_X_OBJ) $(NS_OBJ) $(CYGWIN_OBJ) $(FONT_OBJ) \
448 $(W32_OBJ) $(WINDOW_SYSTEM_OBJ) $(XGSELOBJ) $(JSON_OBJ) \
448 $(HAIKU_OBJ) $(PGTK_OBJ) 449 $(HAIKU_OBJ) $(PGTK_OBJ)
449doc_obj = $(base_obj) $(NS_OBJC_OBJ) 450doc_obj = $(base_obj) $(NS_OBJC_OBJ)
450obj = $(doc_obj) $(HAIKU_CXX_OBJ) 451obj = $(doc_obj) $(HAIKU_CXX_OBJ)
@@ -498,7 +499,7 @@ all: ../native-lisp
498endif 499endif
499.PHONY: all 500.PHONY: all
500 501
501dmpstruct_headers=$(srcdir)/lisp.h $(srcdir)/buffer.h \ 502dmpstruct_headers=$(srcdir)/lisp.h $(srcdir)/buffer.h $(srcdir)/itree.h \
502 $(srcdir)/intervals.h $(srcdir)/charset.h $(srcdir)/bignum.h 503 $(srcdir)/intervals.h $(srcdir)/charset.h $(srcdir)/bignum.h
503ifeq ($(CHECK_STRUCTS),true) 504ifeq ($(CHECK_STRUCTS),true)
504pdumper.o: dmpstruct.h 505pdumper.o: dmpstruct.h
diff --git a/src/alloc.c b/src/alloc.c
index 419c5e558b4..f69c65dedc1 100644
--- a/src/alloc.c
+++ b/src/alloc.c
@@ -1,7 +1,6 @@
1/* Storage allocation and gc for GNU Emacs Lisp interpreter. 1/* Storage allocation and gc for GNU Emacs Lisp interpreter.
2 2
3Copyright (C) 1985-1986, 1988, 1993-1995, 1997-2022 Free Software 3Copyright (C) 1985-2022 Free Software Foundation, Inc.
4Foundation, Inc.
5 4
6This file is part of GNU Emacs. 5This file is part of GNU Emacs.
7 6
@@ -46,6 +45,7 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
46#include "blockinput.h" 45#include "blockinput.h"
47#include "pdumper.h" 46#include "pdumper.h"
48#include "termhooks.h" /* For struct terminal. */ 47#include "termhooks.h" /* For struct terminal. */
48#include "itree.h"
49#ifdef HAVE_WINDOW_SYSTEM 49#ifdef HAVE_WINDOW_SYSTEM
50#include TERM_HEADER 50#include TERM_HEADER
51#endif /* HAVE_WINDOW_SYSTEM */ 51#endif /* HAVE_WINDOW_SYSTEM */
@@ -3129,6 +3129,11 @@ cleanup_vector (struct Lisp_Vector *vector)
3129 3129
3130 if (PSEUDOVECTOR_TYPEP (&vector->header, PVEC_BIGNUM)) 3130 if (PSEUDOVECTOR_TYPEP (&vector->header, PVEC_BIGNUM))
3131 mpz_clear (PSEUDOVEC_STRUCT (vector, Lisp_Bignum)->value); 3131 mpz_clear (PSEUDOVEC_STRUCT (vector, Lisp_Bignum)->value);
3132 else if (PSEUDOVECTOR_TYPEP (&vector->header, PVEC_OVERLAY))
3133 {
3134 struct Lisp_Overlay *ol = PSEUDOVEC_STRUCT (vector, Lisp_Overlay);
3135 xfree (ol->interval);
3136 }
3132 else if (PSEUDOVECTOR_TYPEP (&vector->header, PVEC_FINALIZER)) 3137 else if (PSEUDOVECTOR_TYPEP (&vector->header, PVEC_FINALIZER))
3133 unchain_finalizer (PSEUDOVEC_STRUCT (vector, Lisp_Finalizer)); 3138 unchain_finalizer (PSEUDOVEC_STRUCT (vector, Lisp_Finalizer));
3134 else if (PSEUDOVECTOR_TYPEP (&vector->header, PVEC_FONT)) 3139 else if (PSEUDOVECTOR_TYPEP (&vector->header, PVEC_FONT))
@@ -3697,18 +3702,20 @@ build_symbol_with_pos (Lisp_Object symbol, Lisp_Object position)
3697 return val; 3702 return val;
3698} 3703}
3699 3704
3700/* Return a new overlay with specified START, END and PLIST. */ 3705/* Return a new (deleted) overlay with PLIST. */
3701 3706
3702Lisp_Object 3707Lisp_Object
3703build_overlay (Lisp_Object start, Lisp_Object end, Lisp_Object plist) 3708build_overlay (bool front_advance, bool rear_advance,
3709 Lisp_Object plist)
3704{ 3710{
3705 struct Lisp_Overlay *p = ALLOCATE_PSEUDOVECTOR (struct Lisp_Overlay, plist, 3711 struct Lisp_Overlay *p = ALLOCATE_PSEUDOVECTOR (struct Lisp_Overlay, plist,
3706 PVEC_OVERLAY); 3712 PVEC_OVERLAY);
3707 Lisp_Object overlay = make_lisp_ptr (p, Lisp_Vectorlike); 3713 Lisp_Object overlay = make_lisp_ptr (p, Lisp_Vectorlike);
3708 OVERLAY_START (overlay) = start; 3714 struct itree_node *node = xmalloc (sizeof (*node));
3709 OVERLAY_END (overlay) = end; 3715 itree_node_init (node, front_advance, rear_advance, overlay);
3716 p->interval = node;
3717 p->buffer = NULL;
3710 set_overlay_plist (overlay, plist); 3718 set_overlay_plist (overlay, plist);
3711 p->next = NULL;
3712 return overlay; 3719 return overlay;
3713} 3720}
3714 3721
@@ -5938,8 +5945,7 @@ visit_buffer_root (struct gc_root_visitor visitor,
5938 /* Buffers that are roots don't have intervals, an undo list, or 5945 /* Buffers that are roots don't have intervals, an undo list, or
5939 other constructs that real buffers have. */ 5946 other constructs that real buffers have. */
5940 eassert (buffer->base_buffer == NULL); 5947 eassert (buffer->base_buffer == NULL);
5941 eassert (buffer->overlays_before == NULL); 5948 eassert (buffer->overlays == NULL);
5942 eassert (buffer->overlays_after == NULL);
5943 5949
5944 /* Visit the buffer-locals. */ 5950 /* Visit the buffer-locals. */
5945 visit_vectorlike_root (visitor, (struct Lisp_Vector *) buffer, type); 5951 visit_vectorlike_root (visitor, (struct Lisp_Vector *) buffer, type);
@@ -6273,6 +6279,11 @@ garbage_collect (void)
6273 image_prune_animation_caches (false); 6279 image_prune_animation_caches (false);
6274#endif 6280#endif
6275 6281
6282 /* ELisp code run by `gc-post-hook' could result in itree iteration,
6283 which must not happen while the itree is already busy. See
6284 bug#58639. */
6285 eassert (!itree_iterator_busy_p ());
6286
6276 if (!NILP (Vpost_gc_hook)) 6287 if (!NILP (Vpost_gc_hook))
6277 { 6288 {
6278 specpdl_ref gc_count = inhibit_garbage_collection (); 6289 specpdl_ref gc_count = inhibit_garbage_collection ();
@@ -6495,16 +6506,25 @@ mark_char_table (struct Lisp_Vector *ptr, enum pvec_type pvectype)
6495/* Mark the chain of overlays starting at PTR. */ 6506/* Mark the chain of overlays starting at PTR. */
6496 6507
6497static void 6508static void
6498mark_overlay (struct Lisp_Overlay *ptr) 6509mark_overlay (struct Lisp_Overlay *ov)
6499{ 6510{
6500 for (; ptr && !vectorlike_marked_p (&ptr->header); ptr = ptr->next) 6511 /* We don't mark the `interval_node` object, because it is managed manually
6501 { 6512 rather than by the GC. */
6502 set_vectorlike_marked (&ptr->header); 6513 eassert (BASE_EQ (ov->interval->data, make_lisp_ptr (ov, Lisp_Vectorlike)));
6503 /* These two are always markers and can be marked fast. */ 6514 set_vectorlike_marked (&ov->header);
6504 set_vectorlike_marked (&XMARKER (ptr->start)->header); 6515 mark_object (ov->plist);
6505 set_vectorlike_marked (&XMARKER (ptr->end)->header); 6516}
6506 mark_object (ptr->plist); 6517
6507 } 6518/* Mark the overlay subtree rooted at NODE. */
6519
6520static void
6521mark_overlays (struct itree_node *node)
6522{
6523 if (node == NULL)
6524 return;
6525 mark_object (node->data);
6526 mark_overlays (node->left);
6527 mark_overlays (node->right);
6508} 6528}
6509 6529
6510/* Mark Lisp_Objects and special pointers in BUFFER. */ 6530/* Mark Lisp_Objects and special pointers in BUFFER. */
@@ -6528,8 +6548,8 @@ mark_buffer (struct buffer *buffer)
6528 if (!BUFFER_LIVE_P (buffer)) 6548 if (!BUFFER_LIVE_P (buffer))
6529 mark_object (BVAR (buffer, undo_list)); 6549 mark_object (BVAR (buffer, undo_list));
6530 6550
6531 mark_overlay (buffer->overlays_before); 6551 if (buffer->overlays)
6532 mark_overlay (buffer->overlays_after); 6552 mark_overlays (buffer->overlays->root);
6533 6553
6534 /* If this is an indirect buffer, mark its base buffer. */ 6554 /* If this is an indirect buffer, mark its base buffer. */
6535 if (buffer->base_buffer && 6555 if (buffer->base_buffer &&
diff --git a/src/buffer.c b/src/buffer.c
index d4a0c37bed5..b67b989326e 100644
--- a/src/buffer.c
+++ b/src/buffer.c
@@ -1,7 +1,6 @@
1/* Buffer manipulation primitives for GNU Emacs. 1/* Buffer manipulation primitives for GNU Emacs.
2 2
3Copyright (C) 1985-1989, 1993-1995, 1997-2022 Free Software Foundation, 3Copyright (C) 1985-2022 Free Software Foundation, Inc.
4Inc.
5 4
6This file is part of GNU Emacs. 5This file is part of GNU Emacs.
7 6
@@ -44,6 +43,7 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
44#include "keymap.h" 43#include "keymap.h"
45#include "frame.h" 44#include "frame.h"
46#include "xwidget.h" 45#include "xwidget.h"
46#include "itree.h"
47#include "pdumper.h" 47#include "pdumper.h"
48 48
49#ifdef WINDOWSNT 49#ifdef WINDOWSNT
@@ -116,7 +116,7 @@ static Lisp_Object QSFundamental; /* A string "Fundamental". */
116 116
117static void alloc_buffer_text (struct buffer *, ptrdiff_t); 117static void alloc_buffer_text (struct buffer *, ptrdiff_t);
118static void free_buffer_text (struct buffer *b); 118static void free_buffer_text (struct buffer *b);
119static struct Lisp_Overlay * copy_overlays (struct buffer *, struct Lisp_Overlay *); 119static void copy_overlays (struct buffer *, struct buffer *);
120static void modify_overlay (struct buffer *, ptrdiff_t, ptrdiff_t); 120static void modify_overlay (struct buffer *, ptrdiff_t, ptrdiff_t);
121static Lisp_Object buffer_lisp_local_variables (struct buffer *, bool); 121static Lisp_Object buffer_lisp_local_variables (struct buffer *, bool);
122static Lisp_Object buffer_local_variables_1 (struct buffer *buf, int offset, Lisp_Object sym); 122static Lisp_Object buffer_local_variables_1 (struct buffer *buf, int offset, Lisp_Object sym);
@@ -638,52 +638,33 @@ even if it is dead. The return value is never nil. */)
638 return buffer; 638 return buffer;
639} 639}
640 640
641 641static void
642/* Return a list of overlays which is a copy of the overlay list 642add_buffer_overlay (struct buffer *b, struct Lisp_Overlay *ov,
643 LIST, but for buffer B. */ 643 ptrdiff_t begin, ptrdiff_t end)
644
645static struct Lisp_Overlay *
646copy_overlays (struct buffer *b, struct Lisp_Overlay *list)
647{ 644{
648 struct Lisp_Overlay *result = NULL, *tail = NULL; 645 eassert (! ov->buffer);
649 646 if (! b->overlays)
650 for (; list; list = list->next) 647 b->overlays = itree_create ();
651 { 648 ov->buffer = b;
652 Lisp_Object overlay, start, end; 649 itree_insert (b->overlays, ov->interval, begin, end);
653 struct Lisp_Marker *m;
654
655 eassert (MARKERP (list->start));
656 m = XMARKER (list->start);
657 start = build_marker (b, m->charpos, m->bytepos);
658 XMARKER (start)->insertion_type = m->insertion_type;
659
660 eassert (MARKERP (list->end));
661 m = XMARKER (list->end);
662 end = build_marker (b, m->charpos, m->bytepos);
663 XMARKER (end)->insertion_type = m->insertion_type;
664
665 overlay = build_overlay (start, end, Fcopy_sequence (list->plist));
666 if (tail)
667 tail = tail->next = XOVERLAY (overlay);
668 else
669 result = tail = XOVERLAY (overlay);
670 }
671
672 return result;
673} 650}
674 651
675/* Set an appropriate overlay of B. */ 652/* Copy overlays of buffer FROM to buffer TO. */
676 653
677static void 654static void
678set_buffer_overlays_before (struct buffer *b, struct Lisp_Overlay *o) 655copy_overlays (struct buffer *from, struct buffer *to)
679{ 656{
680 b->overlays_before = o; 657 eassert (to && ! to->overlays);
681} 658 struct itree_node *node;
682 659
683static void 660 ITREE_FOREACH (node, from->overlays, PTRDIFF_MIN, PTRDIFF_MAX, ASCENDING)
684set_buffer_overlays_after (struct buffer *b, struct Lisp_Overlay *o) 661 {
685{ 662 Lisp_Object ov = node->data;
686 b->overlays_after = o; 663 Lisp_Object copy = build_overlay (node->front_advance,
664 node->rear_advance,
665 Fcopy_sequence (OVERLAY_PLIST (ov)));
666 add_buffer_overlay (to, XOVERLAY (copy), node->begin, node->end);
667 }
687} 668}
688 669
689bool 670bool
@@ -726,8 +707,7 @@ clone_per_buffer_values (struct buffer *from, struct buffer *to)
726 707
727 memcpy (to->local_flags, from->local_flags, sizeof to->local_flags); 708 memcpy (to->local_flags, from->local_flags, sizeof to->local_flags);
728 709
729 set_buffer_overlays_before (to, copy_overlays (to, from->overlays_before)); 710 copy_overlays (from, to);
730 set_buffer_overlays_after (to, copy_overlays (to, from->overlays_after));
731 711
732 /* Get (a copy of) the alist of Lisp-level local variables of FROM 712 /* Get (a copy of) the alist of Lisp-level local variables of FROM
733 and install that in TO. */ 713 and install that in TO. */
@@ -926,17 +906,25 @@ does not run the hooks `kill-buffer-hook',
926 return buf; 906 return buf;
927} 907}
928 908
929/* Mark OV as no longer associated with B. */ 909static void
910remove_buffer_overlay (struct buffer *b, struct Lisp_Overlay *ov)
911{
912 eassert (b->overlays);
913 eassert (ov->buffer == b);
914 itree_remove (ov->buffer->overlays, ov->interval);
915 ov->buffer = NULL;
916}
917
918/* Mark OV as no longer associated with its buffer. */
930 919
931static void 920static void
932drop_overlay (struct buffer *b, struct Lisp_Overlay *ov) 921drop_overlay (struct Lisp_Overlay *ov)
933{ 922{
934 eassert (b == XBUFFER (Fmarker_buffer (ov->start))); 923 if (! ov->buffer)
935 modify_overlay (b, marker_position (ov->start), 924 return;
936 marker_position (ov->end));
937 unchain_marker (XMARKER (ov->start));
938 unchain_marker (XMARKER (ov->end));
939 925
926 modify_overlay (ov->buffer, overlay_start (ov), overlay_end (ov));
927 remove_buffer_overlay (ov->buffer, ov);
940} 928}
941 929
942/* Delete all overlays of B and reset its overlay lists. */ 930/* Delete all overlays of B and reset its overlay lists. */
@@ -944,26 +932,94 @@ drop_overlay (struct buffer *b, struct Lisp_Overlay *ov)
944void 932void
945delete_all_overlays (struct buffer *b) 933delete_all_overlays (struct buffer *b)
946{ 934{
947 struct Lisp_Overlay *ov, *next; 935 struct itree_node *node;
936
937 if (! b->overlays)
938 return;
948 939
949 /* FIXME: Since each drop_overlay will scan BUF_MARKERS to unlink its 940 /* FIXME: This loop sets the overlays' `buffer` field to NULL but
950 markers, we have an unneeded O(N^2) behavior here. */ 941 doesn't set the itree_nodes' `parent`, `left` and `right`
951 for (ov = b->overlays_before; ov; ov = next) 942 fields accordingly. I believe it's harmless, but a bit untidy since
943 other parts of the code are careful to set those fields to NULL when
944 the overlay is deleted.
945 Of course, we can't set them to NULL from within the iteration
946 because the iterator may need them (tho we could if we added
947 an ITREE_POST_ORDER iteration order). */
948 ITREE_FOREACH (node, b->overlays, PTRDIFF_MIN, PTRDIFF_MAX, ASCENDING)
952 { 949 {
953 drop_overlay (b, ov); 950 modify_overlay (b, node->begin, node->end);
954 next = ov->next; 951 /* Where are the nodes freed ? --ap */
955 ov->next = NULL; 952 XOVERLAY (node->data)->buffer = NULL;
956 } 953 }
954 itree_clear (b->overlays);
955}
957 956
958 for (ov = b->overlays_after; ov; ov = next) 957static void
958free_buffer_overlays (struct buffer *b)
959{
960 /* Actually this does not free any overlay, but the tree only. --ap */
961 if (b->overlays)
959 { 962 {
960 drop_overlay (b, ov); 963 itree_destroy (b->overlays);
961 next = ov->next; 964 b->overlays = NULL;
962 ov->next = NULL;
963 } 965 }
966}
964 967
965 set_buffer_overlays_before (b, NULL); 968/* Adjust the position of overlays in the current buffer according to
966 set_buffer_overlays_after (b, NULL); 969 MULTIBYTE.
970
971 Assume that positions currently correspond to byte positions, if
972 MULTIBYTE is true and to character positions if not.
973*/
974
975static void
976set_overlays_multibyte (bool multibyte)
977{
978 if (! current_buffer->overlays || Z == Z_BYTE)
979 return;
980
981 struct itree_node **nodes = NULL;
982 struct itree_tree *tree = current_buffer->overlays;
983 const intmax_t size = itree_size (tree);
984
985 /* We can't use `interval_node_set_region` at the same time
986 as we iterate over the itree, so we need an auxiliary storage
987 to keep the list of nodes. */
988 USE_SAFE_ALLOCA;
989 SAFE_NALLOCA (nodes, 1, size);
990 {
991 struct itree_node *node, **cursor = nodes;
992 ITREE_FOREACH (node, tree, PTRDIFF_MIN, PTRDIFF_MAX, ASCENDING)
993 *(cursor++) = node;
994 }
995
996 for (int i = 0; i < size; ++i, ++nodes)
997 {
998 struct itree_node * const node = *nodes;
999
1000 if (multibyte)
1001 {
1002 ptrdiff_t begin = itree_node_begin (tree, node);
1003 ptrdiff_t end = itree_node_end (tree, node);
1004
1005 /* This models the behavior of markers. (The behavior of
1006 text-intervals differs slightly.) */
1007 while (begin < Z_BYTE
1008 && !CHAR_HEAD_P (FETCH_BYTE (begin)))
1009 begin++;
1010 while (end < Z_BYTE
1011 && !CHAR_HEAD_P (FETCH_BYTE (end)))
1012 end++;
1013 itree_node_set_region (tree, node, BYTE_TO_CHAR (begin),
1014 BYTE_TO_CHAR (end));
1015 }
1016 else
1017 {
1018 itree_node_set_region (tree, node, CHAR_TO_BYTE (node->begin),
1019 CHAR_TO_BYTE (node->end));
1020 }
1021 }
1022 SAFE_FREE ();
967} 1023}
968 1024
969/* Reinitialize everything about a buffer except its name and contents 1025/* Reinitialize everything about a buffer except its name and contents
@@ -993,9 +1049,7 @@ reset_buffer (register struct buffer *b)
993 b->auto_save_failure_time = 0; 1049 b->auto_save_failure_time = 0;
994 bset_auto_save_file_name (b, Qnil); 1050 bset_auto_save_file_name (b, Qnil);
995 bset_read_only (b, Qnil); 1051 bset_read_only (b, Qnil);
996 set_buffer_overlays_before (b, NULL); 1052 b->overlays = NULL;
997 set_buffer_overlays_after (b, NULL);
998 b->overlay_center = BEG;
999 bset_mark_active (b, Qnil); 1053 bset_mark_active (b, Qnil);
1000 bset_point_before_scroll (b, Qnil); 1054 bset_point_before_scroll (b, Qnil);
1001 bset_file_format (b, Qnil); 1055 bset_file_format (b, Qnil);
@@ -1978,10 +2032,8 @@ cleaning up all windows currently displaying the buffer to be killed. */)
1978 2032
1979 /* Perhaps we should explicitly free the interval tree here... */ 2033 /* Perhaps we should explicitly free the interval tree here... */
1980 } 2034 }
1981 /* Since we've unlinked the markers, the overlays can't be here any more 2035 delete_all_overlays (b);
1982 either. */ 2036 free_buffer_overlays (b);
1983 set_buffer_overlays_before (b, NULL);
1984 set_buffer_overlays_after (b, NULL);
1985 2037
1986 /* Reset the local variables, so that this buffer's local values 2038 /* Reset the local variables, so that this buffer's local values
1987 won't be protected from GC. They would be protected 2039 won't be protected from GC. They would be protected
@@ -2381,6 +2433,23 @@ advance_to_char_boundary (ptrdiff_t byte_pos)
2381 return byte_pos; 2433 return byte_pos;
2382} 2434}
2383 2435
2436static void
2437swap_buffer_overlays (struct buffer *buffer, struct buffer *other)
2438{
2439 struct itree_node *node;
2440
2441 ITREE_FOREACH (node, buffer->overlays, PTRDIFF_MIN, PTRDIFF_MAX, ASCENDING)
2442 XOVERLAY (node->data)->buffer = other;
2443
2444 ITREE_FOREACH (node, other->overlays, PTRDIFF_MIN, PTRDIFF_MAX, ASCENDING)
2445 XOVERLAY (node->data)->buffer = buffer;
2446
2447 /* Swap the interval trees. */
2448 void *tmp = buffer->overlays;
2449 buffer->overlays = other->overlays;
2450 other->overlays = tmp;
2451}
2452
2384DEFUN ("buffer-swap-text", Fbuffer_swap_text, Sbuffer_swap_text, 2453DEFUN ("buffer-swap-text", Fbuffer_swap_text, Sbuffer_swap_text,
2385 1, 1, 0, 2454 1, 1, 0,
2386 doc: /* Swap the text between current buffer and BUFFER. 2455 doc: /* Swap the text between current buffer and BUFFER.
@@ -2452,9 +2521,6 @@ results, see Info node `(elisp)Swapping Text'. */)
2452 current_buffer->prevent_redisplay_optimizations_p = 1; 2521 current_buffer->prevent_redisplay_optimizations_p = 1;
2453 other_buffer->prevent_redisplay_optimizations_p = 1; 2522 other_buffer->prevent_redisplay_optimizations_p = 1;
2454 swapfield (long_line_optimizations_p, bool_bf); 2523 swapfield (long_line_optimizations_p, bool_bf);
2455 swapfield (overlays_before, struct Lisp_Overlay *);
2456 swapfield (overlays_after, struct Lisp_Overlay *);
2457 swapfield (overlay_center, ptrdiff_t);
2458 swapfield_ (undo_list, Lisp_Object); 2524 swapfield_ (undo_list, Lisp_Object);
2459 swapfield_ (mark, Lisp_Object); 2525 swapfield_ (mark, Lisp_Object);
2460 swapfield_ (mark_active, Lisp_Object); /* Belongs with the `mark'. */ 2526 swapfield_ (mark_active, Lisp_Object); /* Belongs with the `mark'. */
@@ -2481,6 +2547,7 @@ results, see Info node `(elisp)Swapping Text'. */)
2481 current_buffer->text->end_unchanged = current_buffer->text->gpt; 2547 current_buffer->text->end_unchanged = current_buffer->text->gpt;
2482 other_buffer->text->beg_unchanged = other_buffer->text->gpt; 2548 other_buffer->text->beg_unchanged = other_buffer->text->gpt;
2483 other_buffer->text->end_unchanged = other_buffer->text->gpt; 2549 other_buffer->text->end_unchanged = other_buffer->text->gpt;
2550 swap_buffer_overlays (current_buffer, other_buffer);
2484 { 2551 {
2485 struct Lisp_Marker *m; 2552 struct Lisp_Marker *m;
2486 for (m = BUF_MARKERS (current_buffer); m; m = m->next) 2553 for (m = BUF_MARKERS (current_buffer); m; m = m->next)
@@ -2597,7 +2664,8 @@ current buffer is cleared. */)
2597 2664
2598 /* Do this first, so it can use CHAR_TO_BYTE 2665 /* Do this first, so it can use CHAR_TO_BYTE
2599 to calculate the old correspondences. */ 2666 to calculate the old correspondences. */
2600 set_intervals_multibyte (0); 2667 set_intervals_multibyte (false);
2668 set_overlays_multibyte (false);
2601 2669
2602 bset_enable_multibyte_characters (current_buffer, Qnil); 2670 bset_enable_multibyte_characters (current_buffer, Qnil);
2603 2671
@@ -2784,7 +2852,8 @@ current buffer is cleared. */)
2784 /* FIXME: Is it worth the trouble, really? Couldn't we just throw 2852 /* FIXME: Is it worth the trouble, really? Couldn't we just throw
2785 away all the text-properties instead of trying to guess how 2853 away all the text-properties instead of trying to guess how
2786 to adjust them? AFAICT the result is not reliable anyway. */ 2854 to adjust them? AFAICT the result is not reliable anyway. */
2787 set_intervals_multibyte (1); 2855 set_intervals_multibyte (true);
2856 set_overlays_multibyte (true);
2788 } 2857 }
2789 2858
2790 if (!EQ (old_undo, Qt)) 2859 if (!EQ (old_undo, Qt))
@@ -2867,272 +2936,159 @@ the normal hook `change-major-mode-hook'. */)
2867} 2936}
2868 2937
2869 2938
2870/* Find all the overlays in the current buffer that contain position POS. 2939/* Find all the overlays in the current buffer that overlap the range
2940 [BEG, END).
2941
2942 If EMPTY is true, include empty overlays in that range and also at
2943 END, provided END denotes the position at the end of the accessible
2944 part of the buffer.
2945
2946 If TRAILING is true, include overlays that begin at END, provided
2947 END denotes the position at the end of the accessible part of the
2948 buffer.
2949
2871 Return the number found, and store them in a vector in *VEC_PTR. 2950 Return the number found, and store them in a vector in *VEC_PTR.
2872 Store in *LEN_PTR the size allocated for the vector. 2951 Store in *LEN_PTR the size allocated for the vector.
2873 Store in *NEXT_PTR the next position after POS where an overlay starts, 2952 Store in *NEXT_PTR the next position after POS where an overlay starts,
2874 or ZV if there are no more overlays between POS and ZV. 2953 or ZV if there are no more overlays.
2875 Store in *PREV_PTR the previous position before POS where an overlay ends, 2954 NEXT_PTR may be 0, meaning don't store that info.
2876 or where an overlay starts which ends at or after POS;
2877 or BEGV if there are no such overlays from BEGV to POS.
2878 NEXT_PTR and/or PREV_PTR may be 0, meaning don't store that info.
2879 2955
2880 *VEC_PTR and *LEN_PTR should contain a valid vector and size 2956 *VEC_PTR and *LEN_PTR should contain a valid vector and size
2881 when this function is called. 2957 when this function is called.
2882 2958
2883 If EXTEND, make the vector bigger if necessary. 2959 If EXTEND, make the vector bigger if necessary. If not, never
2884 If not, never extend the vector, 2960 extend the vector, and store only as many overlays as will fit.
2885 and store only as many overlays as will fit.
2886 But still return the total number of overlays. 2961 But still return the total number of overlays.
2887 2962*/
2888 If CHANGE_REQ, any position written into *PREV_PTR or
2889 *NEXT_PTR is guaranteed to be not equal to POS, unless it is the
2890 default (BEGV or ZV). */
2891 2963
2892ptrdiff_t 2964ptrdiff_t
2893overlays_at (EMACS_INT pos, bool extend, Lisp_Object **vec_ptr, 2965overlays_in (ptrdiff_t beg, ptrdiff_t end, bool extend,
2894 ptrdiff_t *len_ptr, 2966 Lisp_Object **vec_ptr, ptrdiff_t *len_ptr,
2895 ptrdiff_t *next_ptr, ptrdiff_t *prev_ptr, bool change_req) 2967 bool empty, bool trailing,
2968 ptrdiff_t *next_ptr)
2896{ 2969{
2897 ptrdiff_t idx = 0; 2970 ptrdiff_t idx = 0;
2898 ptrdiff_t len = *len_ptr; 2971 ptrdiff_t len = *len_ptr;
2899 Lisp_Object *vec = *vec_ptr;
2900 ptrdiff_t next = ZV; 2972 ptrdiff_t next = ZV;
2901 ptrdiff_t prev = BEGV; 2973 Lisp_Object *vec = *vec_ptr;
2902 bool inhibit_storing = 0; 2974 struct itree_node *node;
2903
2904 for (struct Lisp_Overlay *tail = current_buffer->overlays_before;
2905 tail; tail = tail->next)
2906 {
2907 Lisp_Object overlay = make_lisp_ptr (tail, Lisp_Vectorlike);
2908 Lisp_Object start = OVERLAY_START (overlay);
2909 Lisp_Object end = OVERLAY_END (overlay);
2910 ptrdiff_t endpos = OVERLAY_POSITION (end);
2911 if (endpos < pos)
2912 {
2913 if (prev < endpos)
2914 prev = endpos;
2915 break;
2916 }
2917 ptrdiff_t startpos = OVERLAY_POSITION (start);
2918 /* This one ends at or after POS
2919 so its start counts for PREV_PTR if it's before POS. */
2920 if (prev < startpos && startpos < pos)
2921 prev = startpos;
2922 if (endpos == pos)
2923 continue;
2924 if (startpos <= pos)
2925 {
2926 if (idx == len)
2927 {
2928 /* The supplied vector is full.
2929 Either make it bigger, or don't store any more in it. */
2930 if (extend)
2931 {
2932 vec = xpalloc (vec, len_ptr, 1, OVERLAY_COUNT_MAX,
2933 sizeof *vec);
2934 *vec_ptr = vec;
2935 len = *len_ptr;
2936 }
2937 else
2938 inhibit_storing = 1;
2939 }
2940 2975
2941 if (!inhibit_storing) 2976 /* Extend the search range if overlays beginning at ZV are
2942 vec[idx] = overlay; 2977 wanted. */
2943 /* Keep counting overlays even if we can't return them all. */ 2978 ptrdiff_t search_end = ZV;
2944 idx++; 2979 if (end >= ZV && (empty || trailing))
2945 } 2980 ++search_end;
2946 else if (startpos < next)
2947 next = startpos;
2948 }
2949 2981
2950 for (struct Lisp_Overlay *tail = current_buffer->overlays_after; 2982 ITREE_FOREACH (node, current_buffer->overlays, beg, search_end,
2951 tail; tail = tail->next) 2983 ASCENDING)
2952 { 2984 {
2953 Lisp_Object overlay = make_lisp_ptr (tail, Lisp_Vectorlike); 2985 if (node->begin > end)
2954 Lisp_Object start = OVERLAY_START (overlay); 2986 {
2955 Lisp_Object end = OVERLAY_END (overlay); 2987 next = min (next, node->begin);
2956 ptrdiff_t startpos = OVERLAY_POSITION (start); 2988 ITREE_FOREACH_ABORT ();
2957 if (pos < startpos) 2989 break;
2958 { 2990 }
2959 if (startpos < next) 2991 else if (node->begin == end)
2960 next = startpos; 2992 {
2961 break; 2993 next = node->begin;
2962 } 2994 if ((! empty || end < ZV) && beg < end)
2963 ptrdiff_t endpos = OVERLAY_POSITION (end); 2995 {
2964 if (pos < endpos) 2996 ITREE_FOREACH_ABORT ();
2965 { 2997 break;
2966 if (idx == len) 2998 }
2967 { 2999 if (empty && node->begin != node->end)
2968 if (extend) 3000 continue;
2969 { 3001 }
2970 vec = xpalloc (vec, len_ptr, 1, OVERLAY_COUNT_MAX,
2971 sizeof *vec);
2972 *vec_ptr = vec;
2973 len = *len_ptr;
2974 }
2975 else
2976 inhibit_storing = 1;
2977 }
2978 3002
2979 if (!inhibit_storing) 3003 if (! empty && node->begin == node->end)
2980 vec[idx] = overlay; 3004 continue;
2981 idx++;
2982 3005
2983 if (startpos < pos && startpos > prev) 3006 if (extend && idx == len)
2984 prev = startpos; 3007 {
2985 } 3008 vec = xpalloc (vec, len_ptr, 1, OVERLAY_COUNT_MAX,
2986 else if (endpos < pos && endpos > prev) 3009 sizeof *vec);
2987 prev = endpos; 3010 *vec_ptr = vec;
2988 else if (endpos == pos && startpos > prev 3011 len = *len_ptr;
2989 && (!change_req || startpos < pos)) 3012 }
2990 prev = startpos; 3013 if (idx < len)
3014 vec[idx] = node->data;
3015 /* Keep counting overlays even if we can't return them all. */
3016 idx++;
2991 } 3017 }
2992
2993 if (next_ptr) 3018 if (next_ptr)
2994 *next_ptr = next; 3019 *next_ptr = next ? next : ZV;
2995 if (prev_ptr) 3020
2996 *prev_ptr = prev;
2997 return idx; 3021 return idx;
2998} 3022}
2999
3000/* Find all the overlays in the current buffer that overlap the range
3001 BEG-END, or are empty at BEG, or are empty at END provided END
3002 denotes the position at the end of the current buffer.
3003 3023
3004 Return the number found, and store them in a vector in *VEC_PTR. 3024/* Find all non-empty overlays in the current buffer that contain
3005 Store in *LEN_PTR the size allocated for the vector. 3025 position POS.
3006 Store in *NEXT_PTR the next position after POS where an overlay starts,
3007 or ZV if there are no more overlays.
3008 Store in *PREV_PTR the previous position before POS where an overlay ends,
3009 or BEGV if there are no previous overlays.
3010 NEXT_PTR and/or PREV_PTR may be 0, meaning don't store that info.
3011 3026
3012 *VEC_PTR and *LEN_PTR should contain a valid vector and size 3027 See overlays_in for the meaning of the arguments.
3013 when this function is called. 3028 */
3014 3029
3015 If EXTEND, make the vector bigger if necessary. 3030ptrdiff_t
3016 If not, never extend the vector, 3031overlays_at (ptrdiff_t pos, bool extend,
3017 and store only as many overlays as will fit. 3032 Lisp_Object **vec_ptr, ptrdiff_t *len_ptr,
3018 But still return the total number of overlays. */ 3033 ptrdiff_t *next_ptr)
3034{
3035 return overlays_in (pos, pos + 1, extend, vec_ptr, len_ptr,
3036 false, true, next_ptr);
3037}
3019 3038
3020static ptrdiff_t 3039ptrdiff_t
3021overlays_in (EMACS_INT beg, EMACS_INT end, bool extend, 3040next_overlay_change (ptrdiff_t pos)
3022 Lisp_Object **vec_ptr, ptrdiff_t *len_ptr,
3023 ptrdiff_t *next_ptr, ptrdiff_t *prev_ptr)
3024{ 3041{
3025 ptrdiff_t idx = 0;
3026 ptrdiff_t len = *len_ptr;
3027 Lisp_Object *vec = *vec_ptr;
3028 ptrdiff_t next = ZV; 3042 ptrdiff_t next = ZV;
3029 ptrdiff_t prev = BEGV; 3043 struct itree_node *node;
3030 bool inhibit_storing = 0;
3031 bool end_is_Z = end == ZV;
3032 3044
3033 for (struct Lisp_Overlay *tail = current_buffer->overlays_before; 3045 ITREE_FOREACH (node, current_buffer->overlays, pos, next, ASCENDING)
3034 tail; tail = tail->next)
3035 { 3046 {
3036 Lisp_Object overlay = make_lisp_ptr (tail, Lisp_Vectorlike); 3047 if (node->begin > pos)
3037 Lisp_Object ostart = OVERLAY_START (overlay); 3048 {
3038 Lisp_Object oend = OVERLAY_END (overlay); 3049 /* If we reach this branch, node->begin must be the least upper bound
3039 ptrdiff_t endpos = OVERLAY_POSITION (oend); 3050 of pos, because the search is limited to [pos,next) . */
3040 if (endpos < beg) 3051 eassert (node->begin < next);
3041 { 3052 next = node->begin;
3042 if (prev < endpos) 3053 ITREE_FOREACH_ABORT ();
3043 prev = endpos; 3054 break;
3044 break; 3055 }
3045 } 3056 else if (node->begin < node->end && node->end < next)
3046 ptrdiff_t startpos = OVERLAY_POSITION (ostart); 3057 {
3047 /* Count an interval if it overlaps the range, is empty at the 3058 next = node->end;
3048 start of the range, or is empty at END provided END denotes the 3059 ITREE_FOREACH_NARROW (pos, next);
3049 end of the buffer. */ 3060 }
3050 if ((beg < endpos && startpos < end)
3051 || (startpos == endpos
3052 && (beg == endpos || (end_is_Z && endpos == end))))
3053 {
3054 if (idx == len)
3055 {
3056 /* The supplied vector is full.
3057 Either make it bigger, or don't store any more in it. */
3058 if (extend)
3059 {
3060 vec = xpalloc (vec, len_ptr, 1, OVERLAY_COUNT_MAX,
3061 sizeof *vec);
3062 *vec_ptr = vec;
3063 len = *len_ptr;
3064 }
3065 else
3066 inhibit_storing = 1;
3067 }
3068
3069 if (!inhibit_storing)
3070 vec[idx] = overlay;
3071 /* Keep counting overlays even if we can't return them all. */
3072 idx++;
3073 }
3074 else if (startpos < next)
3075 next = startpos;
3076 } 3061 }
3077 3062
3078 for (struct Lisp_Overlay *tail = current_buffer->overlays_after; 3063 return next;
3079 tail; tail = tail->next) 3064}
3080 {
3081 Lisp_Object overlay = make_lisp_ptr (tail, Lisp_Vectorlike);
3082 Lisp_Object ostart = OVERLAY_START (overlay);
3083 Lisp_Object oend = OVERLAY_END (overlay);
3084 ptrdiff_t startpos = OVERLAY_POSITION (ostart);
3085 if (end < startpos)
3086 {
3087 if (startpos < next)
3088 next = startpos;
3089 break;
3090 }
3091 ptrdiff_t endpos = OVERLAY_POSITION (oend);
3092 /* Count an interval if it overlaps the range, is empty at the
3093 start of the range, or is empty at END provided END denotes the
3094 end of the buffer. */
3095 if ((beg < endpos && startpos < end)
3096 || (startpos == endpos
3097 && (beg == endpos || (end_is_Z && endpos == end))))
3098 {
3099 if (idx == len)
3100 {
3101 if (extend)
3102 {
3103 vec = xpalloc (vec, len_ptr, 1, OVERLAY_COUNT_MAX,
3104 sizeof *vec);
3105 *vec_ptr = vec;
3106 len = *len_ptr;
3107 }
3108 else
3109 inhibit_storing = 1;
3110 }
3111 3065
3112 if (!inhibit_storing) 3066ptrdiff_t
3113 vec[idx] = overlay; 3067previous_overlay_change (ptrdiff_t pos)
3114 idx++; 3068{
3115 } 3069 struct itree_node *node;
3116 else if (endpos < beg && endpos > prev) 3070 ptrdiff_t prev = BEGV;
3117 prev = endpos; 3071
3072 ITREE_FOREACH (node, current_buffer->overlays, prev, pos, DESCENDING)
3073 {
3074 if (node->end < pos)
3075 prev = node->end;
3076 else
3077 prev = max (prev, node->begin);
3078 ITREE_FOREACH_NARROW (prev, pos);
3118 } 3079 }
3119 3080
3120 if (next_ptr) 3081 return prev;
3121 *next_ptr = next;
3122 if (prev_ptr)
3123 *prev_ptr = prev;
3124 return idx;
3125} 3082}
3126 3083
3127
3128/* Return true if there exists an overlay with a non-nil 3084/* Return true if there exists an overlay with a non-nil
3129 `mouse-face' property overlapping OVERLAY. */ 3085 `mouse-face' property overlapping OVERLAY. */
3130 3086
3131bool 3087bool
3132mouse_face_overlay_overlaps (Lisp_Object overlay) 3088mouse_face_overlay_overlaps (Lisp_Object overlay)
3133{ 3089{
3134 ptrdiff_t start = OVERLAY_POSITION (OVERLAY_START (overlay)); 3090 ptrdiff_t start = OVERLAY_START (overlay);
3135 ptrdiff_t end = OVERLAY_POSITION (OVERLAY_END (overlay)); 3091 ptrdiff_t end = OVERLAY_END (overlay);
3136 ptrdiff_t n, i, size; 3092 ptrdiff_t n, i, size;
3137 Lisp_Object *v, tem; 3093 Lisp_Object *v, tem;
3138 Lisp_Object vbuf[10]; 3094 Lisp_Object vbuf[10];
@@ -3140,11 +3096,11 @@ mouse_face_overlay_overlaps (Lisp_Object overlay)
3140 3096
3141 size = ARRAYELTS (vbuf); 3097 size = ARRAYELTS (vbuf);
3142 v = vbuf; 3098 v = vbuf;
3143 n = overlays_in (start, end, 0, &v, &size, NULL, NULL); 3099 n = overlays_in (start, end, 0, &v, &size, true, false, NULL);
3144 if (n > size) 3100 if (n > size)
3145 { 3101 {
3146 SAFE_NALLOCA (v, 1, n); 3102 SAFE_NALLOCA (v, 1, n);
3147 overlays_in (start, end, 0, &v, &n, NULL, NULL); 3103 overlays_in (start, end, 0, &v, &n, true, false, NULL);
3148 } 3104 }
3149 3105
3150 for (i = 0; i < n; ++i) 3106 for (i = 0; i < n; ++i)
@@ -3169,11 +3125,11 @@ disable_line_numbers_overlay_at_eob (void)
3169 3125
3170 size = ARRAYELTS (vbuf); 3126 size = ARRAYELTS (vbuf);
3171 v = vbuf; 3127 v = vbuf;
3172 n = overlays_in (ZV, ZV, 0, &v, &size, NULL, NULL); 3128 n = overlays_in (ZV, ZV, 0, &v, &size, false, false, NULL);
3173 if (n > size) 3129 if (n > size)
3174 { 3130 {
3175 SAFE_NALLOCA (v, 1, n); 3131 SAFE_NALLOCA (v, 1, n);
3176 overlays_in (ZV, ZV, 0, &v, &n, NULL, NULL); 3132 overlays_in (ZV, ZV, 0, &v, &n, false, false, NULL);
3177 } 3133 }
3178 3134
3179 for (i = 0; i < n; ++i) 3135 for (i = 0; i < n; ++i)
@@ -3186,47 +3142,28 @@ disable_line_numbers_overlay_at_eob (void)
3186} 3142}
3187 3143
3188 3144
3189/* Fast function to just test if we're at an overlay boundary. */ 3145/* Fast function to just test if we're at an overlay boundary.
3146
3147 Returns true if some overlay starts or ends (or both) at POS,
3148*/
3190bool 3149bool
3191overlay_touches_p (ptrdiff_t pos) 3150overlay_touches_p (ptrdiff_t pos)
3192{ 3151{
3193 for (struct Lisp_Overlay *tail = current_buffer->overlays_before; 3152 struct itree_node *node;
3194 tail; tail = tail->next)
3195 {
3196 Lisp_Object overlay = make_lisp_ptr (tail, Lisp_Vectorlike);
3197 eassert (OVERLAYP (overlay));
3198 3153
3199 ptrdiff_t endpos = OVERLAY_POSITION (OVERLAY_END (overlay)); 3154 /* We need to find overlays ending in pos, as well as empty ones at
3200 if (endpos < pos) 3155 pos. */
3201 break; 3156 ITREE_FOREACH (node, current_buffer->overlays, pos - 1, pos + 1, DESCENDING)
3202 if (endpos == pos || OVERLAY_POSITION (OVERLAY_START (overlay)) == pos) 3157 if (node->begin == pos || node->end == pos)
3203 return 1; 3158 {
3204 } 3159 ITREE_FOREACH_ABORT ();
3205 3160 return true;
3206 for (struct Lisp_Overlay *tail = current_buffer->overlays_after; 3161 }
3207 tail; tail = tail->next) 3162 return false;
3208 {
3209 Lisp_Object overlay = make_lisp_ptr (tail, Lisp_Vectorlike);
3210 eassert (OVERLAYP (overlay));
3211
3212 ptrdiff_t startpos = OVERLAY_POSITION (OVERLAY_START (overlay));
3213 if (pos < startpos)
3214 break;
3215 if (startpos == pos || OVERLAY_POSITION (OVERLAY_END (overlay)) == pos)
3216 return 1;
3217 }
3218 return 0;
3219} 3163}
3220
3221struct sortvec
3222{
3223 Lisp_Object overlay;
3224 ptrdiff_t beg, end;
3225 EMACS_INT priority;
3226 EMACS_INT spriority; /* Secondary priority. */
3227};
3228 3164
3229static int 3165
3166int
3230compare_overlays (const void *v1, const void *v2) 3167compare_overlays (const void *v1, const void *v2)
3231{ 3168{
3232 const struct sortvec *s1 = v1; 3169 const struct sortvec *s1 = v1;
@@ -3255,6 +3192,33 @@ compare_overlays (const void *v1, const void *v2)
3255 return XLI (s1->overlay) < XLI (s2->overlay) ? -1 : 1; 3192 return XLI (s1->overlay) < XLI (s2->overlay) ? -1 : 1;
3256} 3193}
3257 3194
3195void
3196make_sortvec_item (struct sortvec *item, Lisp_Object overlay)
3197{
3198 Lisp_Object tem;
3199 /* This overlay is good and counts: put it into sortvec. */
3200 item->overlay = overlay;
3201 item->beg = OVERLAY_START (overlay);
3202 item->end = OVERLAY_END (overlay);
3203 tem = Foverlay_get (overlay, Qpriority);
3204 if (NILP (tem))
3205 {
3206 item->priority = 0;
3207 item->spriority = 0;
3208 }
3209 else if (FIXNUMP (tem))
3210 {
3211 item->priority = XFIXNUM (tem);
3212 item->spriority = 0;
3213 }
3214 else if (CONSP (tem))
3215 {
3216 Lisp_Object car = XCAR (tem);
3217 Lisp_Object cdr = XCDR (tem);
3218 item->priority = FIXNUMP (car) ? XFIXNUM (car) : 0;
3219 item->spriority = FIXNUMP (cdr) ? XFIXNUM (cdr) : 0;
3220 }
3221}
3258/* Sort an array of overlays by priority. The array is modified in place. 3222/* Sort an array of overlays by priority. The array is modified in place.
3259 The return value is the new size; this may be smaller than the original 3223 The return value is the new size; this may be smaller than the original
3260 size if some of the overlays were invalid or were window-specific. */ 3224 size if some of the overlays were invalid or were window-specific. */
@@ -3271,47 +3235,18 @@ sort_overlays (Lisp_Object *overlay_vec, ptrdiff_t noverlays, struct window *w)
3271 3235
3272 for (i = 0, j = 0; i < noverlays; i++) 3236 for (i = 0, j = 0; i < noverlays; i++)
3273 { 3237 {
3274 Lisp_Object tem;
3275 Lisp_Object overlay; 3238 Lisp_Object overlay;
3276 3239
3277 overlay = overlay_vec[i]; 3240 overlay = overlay_vec[i];
3278 if (OVERLAYP (overlay) 3241 if (OVERLAYP (overlay)
3279 && OVERLAY_POSITION (OVERLAY_START (overlay)) > 0 3242 && OVERLAY_START (overlay) > 0
3280 && OVERLAY_POSITION (OVERLAY_END (overlay)) > 0) 3243 && OVERLAY_END (overlay) > 0)
3281 { 3244 {
3282 /* If we're interested in a specific window, then ignore 3245 /* If we're interested in a specific window, then ignore
3283 overlays that are limited to some other window. */ 3246 overlays that are limited to some other window. */
3284 if (w) 3247 if (w && ! overlay_matches_window (w, overlay))
3285 { 3248 continue;
3286 Lisp_Object window; 3249 make_sortvec_item (sortvec + j, overlay);
3287
3288 window = Foverlay_get (overlay, Qwindow);
3289 if (WINDOWP (window) && XWINDOW (window) != w)
3290 continue;
3291 }
3292
3293 /* This overlay is good and counts: put it into sortvec. */
3294 sortvec[j].overlay = overlay;
3295 sortvec[j].beg = OVERLAY_POSITION (OVERLAY_START (overlay));
3296 sortvec[j].end = OVERLAY_POSITION (OVERLAY_END (overlay));
3297 tem = Foverlay_get (overlay, Qpriority);
3298 if (NILP (tem))
3299 {
3300 sortvec[j].priority = 0;
3301 sortvec[j].spriority = 0;
3302 }
3303 else if (FIXNUMP (tem))
3304 {
3305 sortvec[j].priority = XFIXNUM (tem);
3306 sortvec[j].spriority = 0;
3307 }
3308 else if (CONSP (tem))
3309 {
3310 Lisp_Object car = XCAR (tem);
3311 Lisp_Object cdr = XCDR (tem);
3312 sortvec[j].priority = FIXNUMP (car) ? XFIXNUM (car) : 0;
3313 sortvec[j].spriority = FIXNUMP (cdr) ? XFIXNUM (cdr) : 0;
3314 }
3315 j++; 3250 j++;
3316 } 3251 }
3317 } 3252 }
@@ -3426,25 +3361,27 @@ ptrdiff_t
3426overlay_strings (ptrdiff_t pos, struct window *w, unsigned char **pstr) 3361overlay_strings (ptrdiff_t pos, struct window *w, unsigned char **pstr)
3427{ 3362{
3428 bool multibyte = ! NILP (BVAR (current_buffer, enable_multibyte_characters)); 3363 bool multibyte = ! NILP (BVAR (current_buffer, enable_multibyte_characters));
3364 struct itree_node *node;
3429 3365
3430 overlay_heads.used = overlay_heads.bytes = 0; 3366 overlay_heads.used = overlay_heads.bytes = 0;
3431 overlay_tails.used = overlay_tails.bytes = 0; 3367 overlay_tails.used = overlay_tails.bytes = 0;
3432 for (struct Lisp_Overlay *ov = current_buffer->overlays_before; 3368
3433 ov; ov = ov->next) 3369 ITREE_FOREACH (node, current_buffer->overlays, pos - 1, pos + 1, DESCENDING)
3434 { 3370 {
3435 Lisp_Object overlay = make_lisp_ptr (ov, Lisp_Vectorlike); 3371 Lisp_Object overlay = node->data;
3436 eassert (OVERLAYP (overlay)); 3372 eassert (OVERLAYP (overlay));
3437 3373
3438 ptrdiff_t startpos = OVERLAY_POSITION (OVERLAY_START (overlay)); 3374 ptrdiff_t startpos = node->begin;
3439 ptrdiff_t endpos = OVERLAY_POSITION (OVERLAY_END (overlay)); 3375 ptrdiff_t endpos = node->end;
3440 if (endpos < pos) 3376
3441 break;
3442 if (endpos != pos && startpos != pos) 3377 if (endpos != pos && startpos != pos)
3443 continue; 3378 continue;
3444 Lisp_Object window = Foverlay_get (overlay, Qwindow); 3379 Lisp_Object window = Foverlay_get (overlay, Qwindow);
3445 if (WINDOWP (window) && XWINDOW (window) != w) 3380 if (WINDOWP (window) && XWINDOW (window) != w)
3446 continue; 3381 continue;
3447 Lisp_Object str; 3382 Lisp_Object str;
3383 /* FIXME: Are we really sure that `record_overlay_string` can
3384 never cause a non-local exit? */
3448 if (startpos == pos 3385 if (startpos == pos
3449 && (str = Foverlay_get (overlay, Qbefore_string), STRINGP (str))) 3386 && (str = Foverlay_get (overlay, Qbefore_string), STRINGP (str)))
3450 record_overlay_string (&overlay_heads, str, 3387 record_overlay_string (&overlay_heads, str,
@@ -3459,36 +3396,7 @@ overlay_strings (ptrdiff_t pos, struct window *w, unsigned char **pstr)
3459 Foverlay_get (overlay, Qpriority), 3396 Foverlay_get (overlay, Qpriority),
3460 endpos - startpos); 3397 endpos - startpos);
3461 } 3398 }
3462 for (struct Lisp_Overlay *ov = current_buffer->overlays_after;
3463 ov; ov = ov->next)
3464 {
3465 Lisp_Object overlay = make_lisp_ptr (ov, Lisp_Vectorlike);
3466 eassert (OVERLAYP (overlay));
3467 3399
3468 ptrdiff_t startpos = OVERLAY_POSITION (OVERLAY_START (overlay));
3469 ptrdiff_t endpos = OVERLAY_POSITION (OVERLAY_END (overlay));
3470 if (startpos > pos)
3471 break;
3472 if (endpos != pos && startpos != pos)
3473 continue;
3474 Lisp_Object window = Foverlay_get (overlay, Qwindow);
3475 if (WINDOWP (window) && XWINDOW (window) != w)
3476 continue;
3477 Lisp_Object str;
3478 if (startpos == pos
3479 && (str = Foverlay_get (overlay, Qbefore_string), STRINGP (str)))
3480 record_overlay_string (&overlay_heads, str,
3481 (startpos == endpos
3482 ? Foverlay_get (overlay, Qafter_string)
3483 : Qnil),
3484 Foverlay_get (overlay, Qpriority),
3485 endpos - startpos);
3486 else if (endpos == pos
3487 && (str = Foverlay_get (overlay, Qafter_string), STRINGP (str)))
3488 record_overlay_string (&overlay_tails, str, Qnil,
3489 Foverlay_get (overlay, Qpriority),
3490 endpos - startpos);
3491 }
3492 if (overlay_tails.used > 1) 3400 if (overlay_tails.used > 1)
3493 qsort (overlay_tails.buf, overlay_tails.used, sizeof (struct sortstr), 3401 qsort (overlay_tails.buf, overlay_tails.used, sizeof (struct sortstr),
3494 cmp_for_strings); 3402 cmp_for_strings);
@@ -3543,384 +3451,26 @@ overlay_strings (ptrdiff_t pos, struct window *w, unsigned char **pstr)
3543 } 3451 }
3544 return 0; 3452 return 0;
3545} 3453}
3546
3547/* Shift overlays in BUF's overlay lists, to center the lists at POS. */
3548
3549void
3550recenter_overlay_lists (struct buffer *buf, ptrdiff_t pos)
3551{
3552 struct Lisp_Overlay *prev, *next;
3553
3554 /* See if anything in overlays_before should move to overlays_after. */
3555
3556 /* We don't strictly need prev in this loop; it should always be nil.
3557 But we use it for symmetry and in case that should cease to be true
3558 with some future change. */
3559 prev = NULL;
3560 for (struct Lisp_Overlay *tail = buf->overlays_before;
3561 tail; prev = tail, tail = next)
3562 {
3563 next = tail->next;
3564 Lisp_Object overlay = make_lisp_ptr (tail, Lisp_Vectorlike);
3565 eassert (OVERLAYP (overlay));
3566
3567 Lisp_Object beg = OVERLAY_START (overlay);
3568 Lisp_Object end = OVERLAY_END (overlay);
3569
3570 if (OVERLAY_POSITION (end) > pos)
3571 {
3572 /* OVERLAY needs to be moved. */
3573 ptrdiff_t where = OVERLAY_POSITION (beg);
3574 struct Lisp_Overlay *other, *other_prev;
3575
3576 /* Splice the cons cell TAIL out of overlays_before. */
3577 if (prev)
3578 prev->next = next;
3579 else
3580 set_buffer_overlays_before (buf, next);
3581
3582 /* Search thru overlays_after for where to put it. */
3583 other_prev = NULL;
3584 for (other = buf->overlays_after; other;
3585 other_prev = other, other = other->next)
3586 {
3587 Lisp_Object otheroverlay = make_lisp_ptr (other, Lisp_Vectorlike);
3588 eassert (OVERLAYP (otheroverlay));
3589
3590 Lisp_Object otherbeg = OVERLAY_START (otheroverlay);
3591 if (OVERLAY_POSITION (otherbeg) >= where)
3592 break;
3593 }
3594
3595 /* Add TAIL to overlays_after before OTHER. */
3596 tail->next = other;
3597 if (other_prev)
3598 other_prev->next = tail;
3599 else
3600 set_buffer_overlays_after (buf, tail);
3601 tail = prev;
3602 }
3603 else
3604 /* We've reached the things that should stay in overlays_before.
3605 All the rest of overlays_before must end even earlier,
3606 so stop now. */
3607 break;
3608 }
3609
3610 /* See if anything in overlays_after should be in overlays_before. */
3611 prev = NULL;
3612 for (struct Lisp_Overlay *tail = buf->overlays_after;
3613 tail; prev = tail, tail = next)
3614 {
3615 next = tail->next;
3616 Lisp_Object overlay = make_lisp_ptr (tail, Lisp_Vectorlike);
3617 eassert (OVERLAYP (overlay));
3618
3619 Lisp_Object beg = OVERLAY_START (overlay);
3620 Lisp_Object end = OVERLAY_END (overlay);
3621
3622 /* Stop looking, when we know that nothing further
3623 can possibly end before POS. */
3624 if (OVERLAY_POSITION (beg) > pos)
3625 break;
3626
3627 if (OVERLAY_POSITION (end) <= pos)
3628 {
3629 /* OVERLAY needs to be moved. */
3630 ptrdiff_t where = OVERLAY_POSITION (end);
3631 struct Lisp_Overlay *other, *other_prev;
3632
3633 /* Splice the cons cell TAIL out of overlays_after. */
3634 if (prev)
3635 prev->next = next;
3636 else
3637 set_buffer_overlays_after (buf, next);
3638
3639 /* Search thru overlays_before for where to put it. */
3640 other_prev = NULL;
3641 for (other = buf->overlays_before; other;
3642 other_prev = other, other = other->next)
3643 {
3644 Lisp_Object otheroverlay = make_lisp_ptr (other, Lisp_Vectorlike);
3645 eassert (OVERLAYP (otheroverlay));
3646
3647 Lisp_Object otherend = OVERLAY_END (otheroverlay);
3648 if (OVERLAY_POSITION (otherend) <= where)
3649 break;
3650 }
3651
3652 /* Add TAIL to overlays_before before OTHER. */
3653 tail->next = other;
3654 if (other_prev)
3655 other_prev->next = tail;
3656 else
3657 set_buffer_overlays_before (buf, tail);
3658 tail = prev;
3659 }
3660 }
3661
3662 buf->overlay_center = pos;
3663}
3664 3454
3455
3665void 3456void
3666adjust_overlays_for_insert (ptrdiff_t pos, ptrdiff_t length) 3457adjust_overlays_for_insert (ptrdiff_t pos, ptrdiff_t length)
3667{ 3458{
3668 /* After an insertion, the lists are still sorted properly, 3459 /* After an insertion, the lists are still sorted properly,
3669 but we may need to update the value of the overlay center. */ 3460 but we may need to update the value of the overlay center. */
3670 if (current_buffer->overlay_center >= pos) 3461 if (! current_buffer->overlays)
3671 current_buffer->overlay_center += length; 3462 return;
3463 itree_insert_gap (current_buffer->overlays, pos, length);
3672} 3464}
3673 3465
3674void 3466void
3675adjust_overlays_for_delete (ptrdiff_t pos, ptrdiff_t length) 3467adjust_overlays_for_delete (ptrdiff_t pos, ptrdiff_t length)
3676{ 3468{
3677 if (current_buffer->overlay_center < pos) 3469 if (! current_buffer->overlays)
3678 /* The deletion was to our right. No change needed; the before- and
3679 after-lists are still consistent. */
3680 ;
3681 else if (current_buffer->overlay_center - pos > length)
3682 /* The deletion was to our left. We need to adjust the center value
3683 to account for the change in position, but the lists are consistent
3684 given the new value. */
3685 current_buffer->overlay_center -= length;
3686 else
3687 /* We're right in the middle. There might be things on the after-list
3688 that now belong on the before-list. Recentering will move them,
3689 and also update the center point. */
3690 recenter_overlay_lists (current_buffer, pos);
3691}
3692
3693/* Fix up overlays that were garbled as a result of permuting markers
3694 in the range START through END. Any overlay with at least one
3695 endpoint in this range will need to be unlinked from the overlay
3696 list and reinserted in its proper place.
3697 Such an overlay might even have negative size at this point.
3698 If so, we'll make the overlay empty. */
3699void
3700fix_start_end_in_overlays (register ptrdiff_t start, register ptrdiff_t end)
3701{
3702 struct Lisp_Overlay *before_list UNINIT;
3703 struct Lisp_Overlay *after_list UNINIT;
3704 /* These are either nil, indicating that before_list or after_list
3705 should be assigned, or the cons cell the cdr of which should be
3706 assigned. */
3707 struct Lisp_Overlay *beforep = NULL, *afterp = NULL;
3708 /* 'Parent', likewise, indicates a cons cell or
3709 current_buffer->overlays_before or overlays_after, depending
3710 which loop we're in. */
3711 struct Lisp_Overlay *parent;
3712
3713 /* This algorithm shifts links around instead of consing and GCing.
3714 The loop invariant is that before_list (resp. after_list) is a
3715 well-formed list except that its last element, the CDR of beforep
3716 (resp. afterp) if beforep (afterp) isn't nil or before_list
3717 (after_list) if it is, is still uninitialized. So it's not a bug
3718 that before_list isn't initialized, although it may look
3719 strange. */
3720 parent = NULL;
3721 for (struct Lisp_Overlay *tail = current_buffer->overlays_before;
3722 tail; tail = tail->next)
3723 {
3724 Lisp_Object overlay = make_lisp_ptr (tail, Lisp_Vectorlike);
3725
3726 ptrdiff_t endpos = OVERLAY_POSITION (OVERLAY_END (overlay));
3727 ptrdiff_t startpos = OVERLAY_POSITION (OVERLAY_START (overlay));
3728
3729 /* If the overlay is backwards, make it empty. */
3730 if (endpos < startpos)
3731 {
3732 startpos = endpos;
3733 Fset_marker (OVERLAY_START (overlay), make_fixnum (startpos),
3734 Qnil);
3735 }
3736
3737 if (endpos < start)
3738 break;
3739
3740 if (endpos < end
3741 || (startpos >= start && startpos < end))
3742 {
3743 /* Add it to the end of the wrong list. Later on,
3744 recenter_overlay_lists will move it to the right place. */
3745 if (endpos < current_buffer->overlay_center)
3746 {
3747 if (!afterp)
3748 after_list = tail;
3749 else
3750 afterp->next = tail;
3751 afterp = tail;
3752 }
3753 else
3754 {
3755 if (!beforep)
3756 before_list = tail;
3757 else
3758 beforep->next = tail;
3759 beforep = tail;
3760 }
3761 if (!parent)
3762 set_buffer_overlays_before (current_buffer, tail->next);
3763 else
3764 parent->next = tail->next;
3765 }
3766 else
3767 parent = tail;
3768 }
3769 parent = NULL;
3770 for (struct Lisp_Overlay *tail = current_buffer->overlays_after;
3771 tail; tail = tail->next)
3772 {
3773 Lisp_Object overlay = make_lisp_ptr (tail, Lisp_Vectorlike);
3774
3775 ptrdiff_t startpos = OVERLAY_POSITION (OVERLAY_START (overlay));
3776 ptrdiff_t endpos = OVERLAY_POSITION (OVERLAY_END (overlay));
3777
3778 /* If the overlay is backwards, make it empty. */
3779 if (endpos < startpos)
3780 {
3781 startpos = endpos;
3782 Fset_marker (OVERLAY_START (overlay), make_fixnum (startpos),
3783 Qnil);
3784 }
3785
3786 if (startpos >= end)
3787 break;
3788
3789 if (startpos >= start
3790 || (endpos >= start && endpos < end))
3791 {
3792 if (endpos < current_buffer->overlay_center)
3793 {
3794 if (!afterp)
3795 after_list = tail;
3796 else
3797 afterp->next = tail;
3798 afterp = tail;
3799 }
3800 else
3801 {
3802 if (!beforep)
3803 before_list = tail;
3804 else
3805 beforep->next = tail;
3806 beforep = tail;
3807 }
3808 if (!parent)
3809 set_buffer_overlays_after (current_buffer, tail->next);
3810 else
3811 parent->next = tail->next;
3812 }
3813 else
3814 parent = tail;
3815 }
3816
3817 /* Splice the constructed (wrong) lists into the buffer's lists,
3818 and let the recenter function make it sane again. */
3819 if (beforep)
3820 {
3821 beforep->next = current_buffer->overlays_before;
3822 set_buffer_overlays_before (current_buffer, before_list);
3823 }
3824
3825 if (afterp)
3826 {
3827 afterp->next = current_buffer->overlays_after;
3828 set_buffer_overlays_after (current_buffer, after_list);
3829 }
3830 recenter_overlay_lists (current_buffer, current_buffer->overlay_center);
3831}
3832
3833/* We have two types of overlay: the one whose ending marker is
3834 after-insertion-marker (this is the usual case) and the one whose
3835 ending marker is before-insertion-marker. When `overlays_before'
3836 contains overlays of the latter type and the former type in this
3837 order and both overlays end at inserting position, inserting a text
3838 increases only the ending marker of the latter type, which results
3839 in incorrect ordering of `overlays_before'.
3840
3841 This function fixes ordering of overlays in the slot
3842 `overlays_before' of the buffer *BP. Before the insertion, `point'
3843 was at PREV, and now is at POS. */
3844
3845void
3846fix_overlays_before (struct buffer *bp, ptrdiff_t prev, ptrdiff_t pos)
3847{
3848 /* If parent is nil, replace overlays_before; otherwise, parent->next. */
3849 struct Lisp_Overlay *tail = bp->overlays_before, *parent = NULL, *right_pair;
3850 Lisp_Object tem;
3851 ptrdiff_t end UNINIT;
3852
3853 /* After the insertion, the several overlays may be in incorrect
3854 order. The possibility is that, in the list `overlays_before',
3855 an overlay which ends at POS appears after an overlay which ends
3856 at PREV. Since POS is greater than PREV, we must fix the
3857 ordering of these overlays, by moving overlays ends at POS before
3858 the overlays ends at PREV. */
3859
3860 /* At first, find a place where disordered overlays should be linked
3861 in. It is where an overlay which end before POS exists. (i.e. an
3862 overlay whose ending marker is after-insertion-marker if disorder
3863 exists). */
3864 while (tail
3865 && (tem = make_lisp_ptr (tail, Lisp_Vectorlike),
3866 (end = OVERLAY_POSITION (OVERLAY_END (tem))) >= pos))
3867 {
3868 parent = tail;
3869 tail = tail->next;
3870 }
3871
3872 /* If we don't find such an overlay,
3873 or the found one ends before PREV,
3874 or the found one is the last one in the list,
3875 we don't have to fix anything. */
3876 if (!tail)
3877 return;
3878 if (end < prev || !tail->next)
3879 return; 3470 return;
3880 3471 itree_delete_gap (current_buffer->overlays, pos, length);
3881 right_pair = parent;
3882 parent = tail;
3883 tail = tail->next;
3884
3885 /* Now, end position of overlays in the list TAIL should be before
3886 or equal to PREV. In the loop, an overlay which ends at POS is
3887 moved ahead to the place indicated by the CDR of RIGHT_PAIR. If
3888 we found an overlay which ends before PREV, the remaining
3889 overlays are in correct order. */
3890 while (tail)
3891 {
3892 tem = make_lisp_ptr (tail, Lisp_Vectorlike);
3893 end = OVERLAY_POSITION (OVERLAY_END (tem));
3894
3895 if (end == pos)
3896 { /* This overlay is disordered. */
3897 struct Lisp_Overlay *found = tail;
3898
3899 /* Unlink the found overlay. */
3900 tail = found->next;
3901 parent->next = tail;
3902 /* Move an overlay at RIGHT_PLACE to the next of the found one,
3903 and link it into the right place. */
3904 if (!right_pair)
3905 {
3906 found->next = bp->overlays_before;
3907 set_buffer_overlays_before (bp, found);
3908 }
3909 else
3910 {
3911 found->next = right_pair->next;
3912 right_pair->next = found;
3913 }
3914 }
3915 else if (end == prev)
3916 {
3917 parent = tail;
3918 tail = tail->next;
3919 }
3920 else /* No more disordered overlay. */
3921 break;
3922 }
3923} 3472}
3473
3924 3474
3925DEFUN ("overlayp", Foverlayp, Soverlayp, 1, 1, 0, 3475DEFUN ("overlayp", Foverlayp, Soverlayp, 1, 1, 0,
3926 doc: /* Return t if OBJECT is an overlay. */) 3476 doc: /* Return t if OBJECT is an overlay. */)
@@ -3942,7 +3492,7 @@ for the rear of the overlay advance when text is inserted there
3942 (Lisp_Object beg, Lisp_Object end, Lisp_Object buffer, 3492 (Lisp_Object beg, Lisp_Object end, Lisp_Object buffer,
3943 Lisp_Object front_advance, Lisp_Object rear_advance) 3493 Lisp_Object front_advance, Lisp_Object rear_advance)
3944{ 3494{
3945 Lisp_Object overlay; 3495 Lisp_Object ov;
3946 struct buffer *b; 3496 struct buffer *b;
3947 3497
3948 if (NILP (buffer)) 3498 if (NILP (buffer))
@@ -3950,6 +3500,10 @@ for the rear of the overlay advance when text is inserted there
3950 else 3500 else
3951 CHECK_BUFFER (buffer); 3501 CHECK_BUFFER (buffer);
3952 3502
3503 b = XBUFFER (buffer);
3504 if (! BUFFER_LIVE_P (b))
3505 error ("Attempt to create overlay in a dead buffer");
3506
3953 if (MARKERP (beg) && !BASE_EQ (Fmarker_buffer (beg), buffer)) 3507 if (MARKERP (beg) && !BASE_EQ (Fmarker_buffer (beg), buffer))
3954 signal_error ("Marker points into wrong buffer", beg); 3508 signal_error ("Marker points into wrong buffer", beg);
3955 if (MARKERP (end) && !BASE_EQ (Fmarker_buffer (end), buffer)) 3509 if (MARKERP (end) && !BASE_EQ (Fmarker_buffer (end), buffer))
@@ -3964,39 +3518,16 @@ for the rear of the overlay advance when text is inserted there
3964 temp = beg; beg = end; end = temp; 3518 temp = beg; beg = end; end = temp;
3965 } 3519 }
3966 3520
3967 b = XBUFFER (buffer); 3521 ptrdiff_t obeg = clip_to_bounds (BUF_BEG (b), XFIXNUM (beg), BUF_Z (b));
3968 3522 ptrdiff_t oend = clip_to_bounds (obeg, XFIXNUM (end), BUF_Z (b));
3969 beg = Fset_marker (Fmake_marker (), beg, buffer); 3523 ov = build_overlay (! NILP (front_advance),
3970 end = Fset_marker (Fmake_marker (), end, buffer); 3524 ! NILP (rear_advance), Qnil);
3971 3525 add_buffer_overlay (b, XOVERLAY (ov), obeg, oend);
3972 if (!NILP (front_advance))
3973 XMARKER (beg)->insertion_type = 1;
3974 if (!NILP (rear_advance))
3975 XMARKER (end)->insertion_type = 1;
3976
3977 overlay = build_overlay (beg, end, Qnil);
3978
3979 /* Put the new overlay on the wrong list. */
3980 end = OVERLAY_END (overlay);
3981 if (OVERLAY_POSITION (end) < b->overlay_center)
3982 {
3983 eassert (b->overlays_after || (XOVERLAY (overlay)->next == NULL));
3984 XOVERLAY (overlay)->next = b->overlays_after;
3985 set_buffer_overlays_after (b, XOVERLAY (overlay));
3986 }
3987 else
3988 {
3989 eassert (b->overlays_before || (XOVERLAY (overlay)->next == NULL));
3990 XOVERLAY (overlay)->next = b->overlays_before;
3991 set_buffer_overlays_before (b, XOVERLAY (overlay));
3992 }
3993 /* This puts it in the right list, and in the right order. */
3994 recenter_overlay_lists (b, b->overlay_center);
3995 3526
3996 /* We don't need to redisplay the region covered by the overlay, because 3527 /* We don't need to redisplay the region covered by the overlay, because
3997 the overlay has no properties at the moment. */ 3528 the overlay has no properties at the moment. */
3998 3529
3999 return overlay; 3530 return ov;
4000} 3531}
4001 3532
4002/* Mark a section of BUF as needing redisplay because of overlays changes. */ 3533/* Mark a section of BUF as needing redisplay because of overlays changes. */
@@ -4018,35 +3549,6 @@ modify_overlay (struct buffer *buf, ptrdiff_t start, ptrdiff_t end)
4018 modiff_incr (&BUF_OVERLAY_MODIFF (buf), 1); 3549 modiff_incr (&BUF_OVERLAY_MODIFF (buf), 1);
4019} 3550}
4020 3551
4021/* Remove OVERLAY from LIST. */
4022
4023static struct Lisp_Overlay *
4024unchain_overlay (struct Lisp_Overlay *list, struct Lisp_Overlay *overlay)
4025{
4026 register struct Lisp_Overlay *tail, **prev = &list;
4027
4028 for (tail = list; tail; prev = &tail->next, tail = *prev)
4029 if (tail == overlay)
4030 {
4031 *prev = overlay->next;
4032 overlay->next = NULL;
4033 break;
4034 }
4035 return list;
4036}
4037
4038/* Remove OVERLAY from both overlay lists of B. */
4039
4040static void
4041unchain_both (struct buffer *b, Lisp_Object overlay)
4042{
4043 struct Lisp_Overlay *ov = XOVERLAY (overlay);
4044
4045 set_buffer_overlays_before (b, unchain_overlay (b->overlays_before, ov));
4046 set_buffer_overlays_after (b, unchain_overlay (b->overlays_after, ov));
4047 eassert (XOVERLAY (overlay)->next == NULL);
4048}
4049
4050DEFUN ("move-overlay", Fmove_overlay, Smove_overlay, 3, 4, 0, 3552DEFUN ("move-overlay", Fmove_overlay, Smove_overlay, 3, 4, 0,
4051 doc: /* Set the endpoints of OVERLAY to BEG and END in BUFFER. 3553 doc: /* Set the endpoints of OVERLAY to BEG and END in BUFFER.
4052If BUFFER is omitted, leave OVERLAY in the same buffer it inhabits now. 3554If BUFFER is omitted, leave OVERLAY in the same buffer it inhabits now.
@@ -4057,12 +3559,11 @@ buffer. */)
4057 struct buffer *b, *ob = 0; 3559 struct buffer *b, *ob = 0;
4058 Lisp_Object obuffer; 3560 Lisp_Object obuffer;
4059 specpdl_ref count = SPECPDL_INDEX (); 3561 specpdl_ref count = SPECPDL_INDEX ();
4060 ptrdiff_t n_beg, n_end;
4061 ptrdiff_t o_beg UNINIT, o_end UNINIT; 3562 ptrdiff_t o_beg UNINIT, o_end UNINIT;
4062 3563
4063 CHECK_OVERLAY (overlay); 3564 CHECK_OVERLAY (overlay);
4064 if (NILP (buffer)) 3565 if (NILP (buffer))
4065 buffer = Fmarker_buffer (OVERLAY_START (overlay)); 3566 buffer = Foverlay_buffer (overlay);
4066 if (NILP (buffer)) 3567 if (NILP (buffer))
4067 XSETBUFFER (buffer, current_buffer); 3568 XSETBUFFER (buffer, current_buffer);
4068 CHECK_BUFFER (buffer); 3569 CHECK_BUFFER (buffer);
@@ -4084,37 +3585,31 @@ buffer. */)
4084 temp = beg; beg = end; end = temp; 3585 temp = beg; beg = end; end = temp;
4085 } 3586 }
4086 3587
4087 specbind (Qinhibit_quit, Qt); 3588 specbind (Qinhibit_quit, Qt); /* FIXME: Why? */
4088 3589
4089 obuffer = Fmarker_buffer (OVERLAY_START (overlay)); 3590 obuffer = Foverlay_buffer (overlay);
4090 b = XBUFFER (buffer); 3591 b = XBUFFER (buffer);
4091 3592
3593 ptrdiff_t n_beg = clip_to_bounds (BUF_BEG (b), XFIXNUM (beg), BUF_Z (b));
3594 ptrdiff_t n_end = clip_to_bounds (n_beg, XFIXNUM (end), BUF_Z (b));
3595
4092 if (!NILP (obuffer)) 3596 if (!NILP (obuffer))
4093 { 3597 {
4094 ob = XBUFFER (obuffer); 3598 ob = XBUFFER (obuffer);
4095 3599
4096 o_beg = OVERLAY_POSITION (OVERLAY_START (overlay)); 3600 o_beg = OVERLAY_START (overlay);
4097 o_end = OVERLAY_POSITION (OVERLAY_END (overlay)); 3601 o_end = OVERLAY_END (overlay);
3602 }
4098 3603
4099 unchain_both (ob, overlay); 3604 if (! EQ (buffer, obuffer))
3605 {
3606 if (! NILP (obuffer))
3607 remove_buffer_overlay (XBUFFER (obuffer), XOVERLAY (overlay));
3608 add_buffer_overlay (XBUFFER (buffer), XOVERLAY (overlay), n_beg, n_end);
4100 } 3609 }
4101 else 3610 else
4102 /* An overlay not associated with any buffer will normally have its 3611 itree_node_set_region (b->overlays, XOVERLAY (overlay)->interval,
4103 `next' field set to NULL, but not always: when killing a buffer, 3612 n_beg, n_end);
4104 we just set its overlays_after and overlays_before to NULL without
4105 manually setting each overlay's `next' field to NULL.
4106 Let's correct it here, to simplify subsequent assertions.
4107 FIXME: Maybe the better fix is to change `kill-buffer'!? */
4108 XOVERLAY (overlay)->next = NULL;
4109
4110 eassert (XOVERLAY (overlay)->next == NULL);
4111
4112 /* Set the overlay boundaries, which may clip them. */
4113 Fset_marker (OVERLAY_START (overlay), beg, buffer);
4114 Fset_marker (OVERLAY_END (overlay), end, buffer);
4115
4116 n_beg = marker_position (OVERLAY_START (overlay));
4117 n_end = marker_position (OVERLAY_END (overlay));
4118 3613
4119 /* If the overlay has changed buffers, do a thorough redisplay. */ 3614 /* If the overlay has changed buffers, do a thorough redisplay. */
4120 if (!BASE_EQ (buffer, obuffer)) 3615 if (!BASE_EQ (buffer, obuffer))
@@ -4137,8 +3632,6 @@ buffer. */)
4137 modify_overlay (b, min (o_beg, n_beg), max (o_end, n_end)); 3632 modify_overlay (b, min (o_beg, n_beg), max (o_end, n_end));
4138 } 3633 }
4139 3634
4140 eassert (XOVERLAY (overlay)->next == NULL);
4141
4142 /* Delete the overlay if it is empty after clipping and has the 3635 /* Delete the overlay if it is empty after clipping and has the
4143 evaporate property. */ 3636 evaporate property. */
4144 if (n_beg == n_end && !NILP (Foverlay_get (overlay, Qevaporate))) 3637 if (n_beg == n_end && !NILP (Foverlay_get (overlay, Qevaporate)))
@@ -4148,26 +3641,10 @@ buffer. */)
4148 contrary to `Fdelete_overlay's assumptions. 3641 contrary to `Fdelete_overlay's assumptions.
4149 - Most of the work done by Fdelete_overlay has already been done 3642 - Most of the work done by Fdelete_overlay has already been done
4150 here for other reasons. */ 3643 here for other reasons. */
4151 drop_overlay (XBUFFER (buffer), XOVERLAY (overlay)); 3644 drop_overlay (XOVERLAY (overlay));
4152 return unbind_to (count, overlay); 3645 return unbind_to (count, overlay);
4153 } 3646 }
4154 3647
4155 /* Put the overlay into the new buffer's overlay lists, first on the
4156 wrong list. */
4157 if (n_end < b->overlay_center)
4158 {
4159 XOVERLAY (overlay)->next = b->overlays_after;
4160 set_buffer_overlays_after (b, XOVERLAY (overlay));
4161 }
4162 else
4163 {
4164 XOVERLAY (overlay)->next = b->overlays_before;
4165 set_buffer_overlays_before (b, XOVERLAY (overlay));
4166 }
4167
4168 /* This puts it in the right list, and in the right order. */
4169 recenter_overlay_lists (b, b->overlay_center);
4170
4171 return unbind_to (count, overlay); 3648 return unbind_to (count, overlay);
4172} 3649}
4173 3650
@@ -4175,21 +3652,18 @@ DEFUN ("delete-overlay", Fdelete_overlay, Sdelete_overlay, 1, 1, 0,
4175 doc: /* Delete the overlay OVERLAY from its buffer. */) 3652 doc: /* Delete the overlay OVERLAY from its buffer. */)
4176 (Lisp_Object overlay) 3653 (Lisp_Object overlay)
4177{ 3654{
4178 Lisp_Object buffer;
4179 struct buffer *b; 3655 struct buffer *b;
4180 specpdl_ref count = SPECPDL_INDEX (); 3656 specpdl_ref count = SPECPDL_INDEX ();
4181 3657
4182 CHECK_OVERLAY (overlay); 3658 CHECK_OVERLAY (overlay);
4183 3659
4184 buffer = Fmarker_buffer (OVERLAY_START (overlay)); 3660 b = OVERLAY_BUFFER (overlay);
4185 if (NILP (buffer)) 3661 if (! b)
4186 return Qnil; 3662 return Qnil;
4187 3663
4188 b = XBUFFER (buffer);
4189 specbind (Qinhibit_quit, Qt); 3664 specbind (Qinhibit_quit, Qt);
4190 3665
4191 unchain_both (b, overlay); 3666 drop_overlay (XOVERLAY (overlay));
4192 drop_overlay (b, XOVERLAY (overlay));
4193 3667
4194 /* When deleting an overlay with before or after strings, turn off 3668 /* When deleting an overlay with before or after strings, turn off
4195 display optimizations for the affected buffer, on the basis that 3669 display optimizations for the affected buffer, on the basis that
@@ -4220,8 +3694,10 @@ DEFUN ("overlay-start", Foverlay_start, Soverlay_start, 1, 1, 0,
4220 (Lisp_Object overlay) 3694 (Lisp_Object overlay)
4221{ 3695{
4222 CHECK_OVERLAY (overlay); 3696 CHECK_OVERLAY (overlay);
3697 if (! OVERLAY_BUFFER (overlay))
3698 return Qnil;
4223 3699
4224 return (Fmarker_position (OVERLAY_START (overlay))); 3700 return make_fixnum (OVERLAY_START (overlay));
4225} 3701}
4226 3702
4227DEFUN ("overlay-end", Foverlay_end, Soverlay_end, 1, 1, 0, 3703DEFUN ("overlay-end", Foverlay_end, Soverlay_end, 1, 1, 0,
@@ -4229,8 +3705,10 @@ DEFUN ("overlay-end", Foverlay_end, Soverlay_end, 1, 1, 0,
4229 (Lisp_Object overlay) 3705 (Lisp_Object overlay)
4230{ 3706{
4231 CHECK_OVERLAY (overlay); 3707 CHECK_OVERLAY (overlay);
3708 if (! OVERLAY_BUFFER (overlay))
3709 return Qnil;
4232 3710
4233 return (Fmarker_position (OVERLAY_END (overlay))); 3711 return make_fixnum (OVERLAY_END (overlay));
4234} 3712}
4235 3713
4236DEFUN ("overlay-buffer", Foverlay_buffer, Soverlay_buffer, 1, 1, 0, 3714DEFUN ("overlay-buffer", Foverlay_buffer, Soverlay_buffer, 1, 1, 0,
@@ -4238,9 +3716,16 @@ DEFUN ("overlay-buffer", Foverlay_buffer, Soverlay_buffer, 1, 1, 0,
4238Return nil if OVERLAY has been deleted. */) 3716Return nil if OVERLAY has been deleted. */)
4239 (Lisp_Object overlay) 3717 (Lisp_Object overlay)
4240{ 3718{
3719 Lisp_Object buffer;
3720
4241 CHECK_OVERLAY (overlay); 3721 CHECK_OVERLAY (overlay);
4242 3722
4243 return Fmarker_buffer (OVERLAY_START (overlay)); 3723 if (! OVERLAY_BUFFER (overlay))
3724 return Qnil;
3725
3726 XSETBUFFER (buffer, OVERLAY_BUFFER (overlay));
3727
3728 return buffer;
4244} 3729}
4245 3730
4246DEFUN ("overlay-properties", Foverlay_properties, Soverlay_properties, 1, 1, 0, 3731DEFUN ("overlay-properties", Foverlay_properties, Soverlay_properties, 1, 1, 0,
@@ -4251,7 +3736,7 @@ OVERLAY. */)
4251{ 3736{
4252 CHECK_OVERLAY (overlay); 3737 CHECK_OVERLAY (overlay);
4253 3738
4254 return Fcopy_sequence (XOVERLAY (overlay)->plist); 3739 return Fcopy_sequence (OVERLAY_PLIST (overlay));
4255} 3740}
4256 3741
4257 3742
@@ -4279,8 +3764,7 @@ interest. */)
4279 3764
4280 /* Put all the overlays we want in a vector in overlay_vec. 3765 /* Put all the overlays we want in a vector in overlay_vec.
4281 Store the length in len. */ 3766 Store the length in len. */
4282 noverlays = overlays_at (XFIXNUM (pos), 1, &overlay_vec, &len, 3767 noverlays = overlays_at (XFIXNUM (pos), true, &overlay_vec, &len, NULL);
4283 NULL, NULL, 0);
4284 3768
4285 if (!NILP (sorted)) 3769 if (!NILP (sorted))
4286 noverlays = sort_overlays (overlay_vec, noverlays, 3770 noverlays = sort_overlays (overlay_vec, noverlays,
@@ -4325,7 +3809,7 @@ end of the accessible part of the buffer. */)
4325 /* Put all the overlays we want in a vector in overlay_vec. 3809 /* Put all the overlays we want in a vector in overlay_vec.
4326 Store the length in len. */ 3810 Store the length in len. */
4327 noverlays = overlays_in (XFIXNUM (beg), XFIXNUM (end), 1, &overlay_vec, &len, 3811 noverlays = overlays_in (XFIXNUM (beg), XFIXNUM (end), 1, &overlay_vec, &len,
4328 NULL, NULL); 3812 true, false, NULL);
4329 3813
4330 /* Make a list of them all. */ 3814 /* Make a list of them all. */
4331 result = Flist (noverlays, overlay_vec); 3815 result = Flist (noverlays, overlay_vec);
@@ -4341,39 +3825,12 @@ If there are no overlay boundaries from POS to (point-max),
4341the value is (point-max). */) 3825the value is (point-max). */)
4342 (Lisp_Object pos) 3826 (Lisp_Object pos)
4343{ 3827{
4344 ptrdiff_t i, len, noverlays;
4345 ptrdiff_t endpos;
4346 Lisp_Object *overlay_vec;
4347
4348 CHECK_FIXNUM_COERCE_MARKER (pos); 3828 CHECK_FIXNUM_COERCE_MARKER (pos);
4349 3829
4350 if (!buffer_has_overlays ()) 3830 if (!buffer_has_overlays ())
4351 return make_fixnum (ZV); 3831 return make_fixnum (ZV);
4352 3832
4353 len = 10; 3833 return make_fixnum (next_overlay_change (XFIXNUM (pos)));
4354 overlay_vec = xmalloc (len * sizeof *overlay_vec);
4355
4356 /* Put all the overlays we want in a vector in overlay_vec.
4357 Store the length in len.
4358 endpos gets the position where the next overlay starts. */
4359 noverlays = overlays_at (XFIXNUM (pos), 1, &overlay_vec, &len,
4360 &endpos, 0, 1);
4361
4362 /* If any of these overlays ends before endpos,
4363 use its ending point instead. */
4364 for (i = 0; i < noverlays; i++)
4365 {
4366 Lisp_Object oend;
4367 ptrdiff_t oendpos;
4368
4369 oend = OVERLAY_END (overlay_vec[i]);
4370 oendpos = OVERLAY_POSITION (oend);
4371 if (oendpos < endpos)
4372 endpos = oendpos;
4373 }
4374
4375 xfree (overlay_vec);
4376 return make_fixnum (endpos);
4377} 3834}
4378 3835
4379DEFUN ("previous-overlay-change", Fprevious_overlay_change, 3836DEFUN ("previous-overlay-change", Fprevious_overlay_change,
@@ -4383,32 +3840,15 @@ If there are no overlay boundaries from (point-min) to POS,
4383the value is (point-min). */) 3840the value is (point-min). */)
4384 (Lisp_Object pos) 3841 (Lisp_Object pos)
4385{ 3842{
4386 ptrdiff_t prevpos;
4387 Lisp_Object *overlay_vec;
4388 ptrdiff_t len;
4389 3843
4390 CHECK_FIXNUM_COERCE_MARKER (pos); 3844 CHECK_FIXNUM_COERCE_MARKER (pos);
4391 3845
4392 if (!buffer_has_overlays ()) 3846 if (!buffer_has_overlays ())
4393 return make_fixnum (BEGV); 3847 return make_fixnum (BEGV);
4394 3848
4395 /* At beginning of buffer, we know the answer; 3849 return make_fixnum (previous_overlay_change (XFIXNUM (pos)));
4396 avoid bug subtracting 1 below. */
4397 if (XFIXNUM (pos) == BEGV)
4398 return pos;
4399
4400 len = 10;
4401 overlay_vec = xmalloc (len * sizeof *overlay_vec);
4402
4403 /* Put all the overlays we want in a vector in overlay_vec.
4404 Store the length in len.
4405 prevpos gets the position of the previous change. */
4406 overlays_at (XFIXNUM (pos), 1, &overlay_vec, &len,
4407 0, &prevpos, 1);
4408
4409 xfree (overlay_vec);
4410 return make_fixnum (prevpos);
4411} 3850}
3851
4412 3852
4413/* These functions are for debugging overlays. */ 3853/* These functions are for debugging overlays. */
4414 3854
@@ -4418,19 +3858,16 @@ The car has all the overlays before the overlay center;
4418the cdr has all the overlays after the overlay center. 3858the cdr has all the overlays after the overlay center.
4419Recentering overlays moves overlays between these lists. 3859Recentering overlays moves overlays between these lists.
4420The lists you get are copies, so that changing them has no effect. 3860The lists you get are copies, so that changing them has no effect.
4421However, the overlays you get are the real objects that the buffer uses. */) 3861However, the overlays you get are the real objects that the buffer uses. */)
4422 (void) 3862 (void)
4423{ 3863{
4424 Lisp_Object before = Qnil, after = Qnil; 3864 Lisp_Object overlays = Qnil;
3865 struct itree_node *node;
4425 3866
4426 for (struct Lisp_Overlay *ol = current_buffer->overlays_before; 3867 ITREE_FOREACH (node, current_buffer->overlays, BEG, Z, DESCENDING)
4427 ol; ol = ol->next) 3868 overlays = Fcons (node->data, overlays);
4428 before = Fcons (make_lisp_ptr (ol, Lisp_Vectorlike), before);
4429 for (struct Lisp_Overlay *ol = current_buffer->overlays_after;
4430 ol; ol = ol->next)
4431 after = Fcons (make_lisp_ptr (ol, Lisp_Vectorlike), after);
4432 3869
4433 return Fcons (Fnreverse (before), Fnreverse (after)); 3870 return Fcons (overlays, Qnil);
4434} 3871}
4435 3872
4436DEFUN ("overlay-recenter", Foverlay_recenter, Soverlay_recenter, 1, 1, 0, 3873DEFUN ("overlay-recenter", Foverlay_recenter, Soverlay_recenter, 1, 1, 0,
@@ -4439,11 +3876,8 @@ That makes overlay lookup faster for positions near POS (but perhaps slower
4439for positions far away from POS). */) 3876for positions far away from POS). */)
4440 (Lisp_Object pos) 3877 (Lisp_Object pos)
4441{ 3878{
4442 ptrdiff_t p;
4443 CHECK_FIXNUM_COERCE_MARKER (pos); 3879 CHECK_FIXNUM_COERCE_MARKER (pos);
4444 3880 /* Noop */
4445 p = clip_to_bounds (PTRDIFF_MIN, XFIXNUM (pos), PTRDIFF_MAX);
4446 recenter_overlay_lists (current_buffer, p);
4447 return Qnil; 3881 return Qnil;
4448} 3882}
4449 3883
@@ -4460,12 +3894,13 @@ DEFUN ("overlay-put", Foverlay_put, Soverlay_put, 3, 3, 0,
4460VALUE will be returned.*/) 3894VALUE will be returned.*/)
4461 (Lisp_Object overlay, Lisp_Object prop, Lisp_Object value) 3895 (Lisp_Object overlay, Lisp_Object prop, Lisp_Object value)
4462{ 3896{
4463 Lisp_Object tail, buffer; 3897 Lisp_Object tail;
3898 struct buffer *b;
4464 bool changed; 3899 bool changed;
4465 3900
4466 CHECK_OVERLAY (overlay); 3901 CHECK_OVERLAY (overlay);
4467 3902
4468 buffer = Fmarker_buffer (OVERLAY_START (overlay)); 3903 b = OVERLAY_BUFFER (overlay);
4469 3904
4470 for (tail = XOVERLAY (overlay)->plist; 3905 for (tail = XOVERLAY (overlay)->plist;
4471 CONSP (tail) && CONSP (XCDR (tail)); 3906 CONSP (tail) && CONSP (XCDR (tail));
@@ -4481,15 +3916,14 @@ VALUE will be returned.*/)
4481 set_overlay_plist 3916 set_overlay_plist
4482 (overlay, Fcons (prop, Fcons (value, XOVERLAY (overlay)->plist))); 3917 (overlay, Fcons (prop, Fcons (value, XOVERLAY (overlay)->plist)));
4483 found: 3918 found:
4484 if (! NILP (buffer)) 3919 if (b)
4485 { 3920 {
4486 if (changed) 3921 if (changed)
4487 modify_overlay (XBUFFER (buffer), 3922 modify_overlay (b, OVERLAY_START (overlay),
4488 marker_position (OVERLAY_START (overlay)), 3923 OVERLAY_END (overlay));
4489 marker_position (OVERLAY_END (overlay)));
4490 if (EQ (prop, Qevaporate) && ! NILP (value) 3924 if (EQ (prop, Qevaporate) && ! NILP (value)
4491 && (OVERLAY_POSITION (OVERLAY_START (overlay)) 3925 && (OVERLAY_START (overlay)
4492 == OVERLAY_POSITION (OVERLAY_END (overlay)))) 3926 == OVERLAY_END (overlay)))
4493 Fdelete_overlay (overlay); 3927 Fdelete_overlay (overlay);
4494 } 3928 }
4495 3929
@@ -4560,70 +3994,33 @@ report_overlay_modification (Lisp_Object start, Lisp_Object end, bool after,
4560 3994
4561 if (!after) 3995 if (!after)
4562 { 3996 {
3997 struct itree_node *node;
3998 EMACS_INT begin_arg = XFIXNUM (start);
3999 EMACS_INT end_arg = XFIXNUM (end);
4563 /* We are being called before a change. 4000 /* We are being called before a change.
4564 Scan the overlays to find the functions to call. */ 4001 Scan the overlays to find the functions to call. */
4565 last_overlay_modification_hooks_used = 0; 4002 last_overlay_modification_hooks_used = 0;
4566 for (struct Lisp_Overlay *tail = current_buffer->overlays_before;
4567 tail; tail = tail->next)
4568 {
4569 ptrdiff_t startpos, endpos;
4570 Lisp_Object ostart, oend;
4571
4572 Lisp_Object overlay = make_lisp_ptr (tail, Lisp_Vectorlike);
4573
4574 ostart = OVERLAY_START (overlay);
4575 oend = OVERLAY_END (overlay);
4576 endpos = OVERLAY_POSITION (oend);
4577 if (XFIXNAT (start) > endpos)
4578 break;
4579 startpos = OVERLAY_POSITION (ostart);
4580 if (insertion && (XFIXNAT (start) == startpos
4581 || XFIXNAT (end) == startpos))
4582 {
4583 Lisp_Object prop = Foverlay_get (overlay, Qinsert_in_front_hooks);
4584 if (!NILP (prop))
4585 add_overlay_mod_hooklist (prop, overlay);
4586 }
4587 if (insertion && (XFIXNAT (start) == endpos
4588 || XFIXNAT (end) == endpos))
4589 {
4590 Lisp_Object prop = Foverlay_get (overlay, Qinsert_behind_hooks);
4591 if (!NILP (prop))
4592 add_overlay_mod_hooklist (prop, overlay);
4593 }
4594 /* Test for intersecting intervals. This does the right thing
4595 for both insertion and deletion. */
4596 if (XFIXNAT (end) > startpos && XFIXNAT (start) < endpos)
4597 {
4598 Lisp_Object prop = Foverlay_get (overlay, Qmodification_hooks);
4599 if (!NILP (prop))
4600 add_overlay_mod_hooklist (prop, overlay);
4601 }
4602 }
4603 4003
4604 for (struct Lisp_Overlay *tail = current_buffer->overlays_after; 4004 if (! current_buffer->overlays)
4605 tail; tail = tail->next) 4005 return;
4006 ITREE_FOREACH (node, current_buffer->overlays,
4007 begin_arg - (insertion ? 1 : 0),
4008 end_arg + (insertion ? 1 : 0),
4009 ASCENDING)
4606 { 4010 {
4607 ptrdiff_t startpos, endpos; 4011 Lisp_Object overlay = node->data;
4608 Lisp_Object ostart, oend; 4012 ptrdiff_t obegin = OVERLAY_START (overlay);
4609 4013 ptrdiff_t oend = OVERLAY_END (overlay);
4610 Lisp_Object overlay = make_lisp_ptr (tail, Lisp_Vectorlike); 4014
4611 4015 if (insertion && (begin_arg == obegin
4612 ostart = OVERLAY_START (overlay); 4016 || end_arg == obegin))
4613 oend = OVERLAY_END (overlay);
4614 startpos = OVERLAY_POSITION (ostart);
4615 endpos = OVERLAY_POSITION (oend);
4616 if (XFIXNAT (end) < startpos)
4617 break;
4618 if (insertion && (XFIXNAT (start) == startpos
4619 || XFIXNAT (end) == startpos))
4620 { 4017 {
4621 Lisp_Object prop = Foverlay_get (overlay, Qinsert_in_front_hooks); 4018 Lisp_Object prop = Foverlay_get (overlay, Qinsert_in_front_hooks);
4622 if (!NILP (prop)) 4019 if (!NILP (prop))
4623 add_overlay_mod_hooklist (prop, overlay); 4020 add_overlay_mod_hooklist (prop, overlay);
4624 } 4021 }
4625 if (insertion && (XFIXNAT (start) == endpos 4022 if (insertion && (begin_arg == oend
4626 || XFIXNAT (end) == endpos)) 4023 || end_arg == oend))
4627 { 4024 {
4628 Lisp_Object prop = Foverlay_get (overlay, Qinsert_behind_hooks); 4025 Lisp_Object prop = Foverlay_get (overlay, Qinsert_behind_hooks);
4629 if (!NILP (prop)) 4026 if (!NILP (prop))
@@ -4631,7 +4028,7 @@ report_overlay_modification (Lisp_Object start, Lisp_Object end, bool after,
4631 } 4028 }
4632 /* Test for intersecting intervals. This does the right thing 4029 /* Test for intersecting intervals. This does the right thing
4633 for both insertion and deletion. */ 4030 for both insertion and deletion. */
4634 if (XFIXNAT (end) > startpos && XFIXNAT (start) < endpos) 4031 if (! insertion || (end_arg > obegin && begin_arg < oend))
4635 { 4032 {
4636 Lisp_Object prop = Foverlay_get (overlay, Qmodification_hooks); 4033 Lisp_Object prop = Foverlay_get (overlay, Qmodification_hooks);
4637 if (!NILP (prop)) 4034 if (!NILP (prop))
@@ -4639,7 +4036,6 @@ report_overlay_modification (Lisp_Object start, Lisp_Object end, bool after,
4639 } 4036 }
4640 } 4037 }
4641 } 4038 }
4642
4643 { 4039 {
4644 /* Call the functions recorded in last_overlay_modification_hooks. 4040 /* Call the functions recorded in last_overlay_modification_hooks.
4645 First copy the vector contents, in case some of these hooks 4041 First copy the vector contents, in case some of these hooks
@@ -4662,7 +4058,7 @@ report_overlay_modification (Lisp_Object start, Lisp_Object end, bool after,
4662 (which makes its markers' buffers be nil), or that (due to 4058 (which makes its markers' buffers be nil), or that (due to
4663 some bug) it belongs to a different buffer. Only run this 4059 some bug) it belongs to a different buffer. Only run this
4664 hook if the overlay belongs to the current buffer. */ 4060 hook if the overlay belongs to the current buffer. */
4665 if (XMARKER (OVERLAY_START (overlay_i))->buffer == current_buffer) 4061 if (OVERLAY_BUFFER (overlay_i) == current_buffer)
4666 call_overlay_mod_hooks (prop_i, overlay_i, after, arg1, arg2, arg3); 4062 call_overlay_mod_hooks (prop_i, overlay_i, after, arg1, arg2, arg3);
4667 } 4063 }
4668 4064
@@ -4690,30 +4086,15 @@ void
4690evaporate_overlays (ptrdiff_t pos) 4086evaporate_overlays (ptrdiff_t pos)
4691{ 4087{
4692 Lisp_Object hit_list = Qnil; 4088 Lisp_Object hit_list = Qnil;
4693 if (pos <= current_buffer->overlay_center) 4089 struct itree_node *node;
4694 for (struct Lisp_Overlay *tail = current_buffer->overlays_before; 4090
4695 tail; tail = tail->next) 4091 ITREE_FOREACH (node, current_buffer->overlays, pos, pos, ASCENDING)
4696 { 4092 {
4697 Lisp_Object overlay = make_lisp_ptr (tail, Lisp_Vectorlike); 4093 if (node->end == pos
4698 ptrdiff_t endpos = OVERLAY_POSITION (OVERLAY_END (overlay)); 4094 && ! NILP (Foverlay_get (node->data, Qevaporate)))
4699 if (endpos < pos) 4095 hit_list = Fcons (node->data, hit_list);
4700 break; 4096 }
4701 if (endpos == pos && OVERLAY_POSITION (OVERLAY_START (overlay)) == pos 4097
4702 && ! NILP (Foverlay_get (overlay, Qevaporate)))
4703 hit_list = Fcons (overlay, hit_list);
4704 }
4705 else
4706 for (struct Lisp_Overlay *tail = current_buffer->overlays_after;
4707 tail; tail = tail->next)
4708 {
4709 Lisp_Object overlay = make_lisp_ptr (tail, Lisp_Vectorlike);
4710 ptrdiff_t startpos = OVERLAY_POSITION (OVERLAY_START (overlay));
4711 if (startpos > pos)
4712 break;
4713 if (startpos == pos && OVERLAY_POSITION (OVERLAY_END (overlay)) == pos
4714 && ! NILP (Foverlay_get (overlay, Qevaporate)))
4715 hit_list = Fcons (overlay, hit_list);
4716 }
4717 for (; CONSP (hit_list); hit_list = XCDR (hit_list)) 4098 for (; CONSP (hit_list); hit_list = XCDR (hit_list))
4718 Fdelete_overlay (XCAR (hit_list)); 4099 Fdelete_overlay (XCAR (hit_list));
4719} 4100}
@@ -5339,9 +4720,7 @@ init_buffer_once (void)
5339 bset_mark_active (&buffer_defaults, Qnil); 4720 bset_mark_active (&buffer_defaults, Qnil);
5340 bset_file_format (&buffer_defaults, Qnil); 4721 bset_file_format (&buffer_defaults, Qnil);
5341 bset_auto_save_file_format (&buffer_defaults, Qt); 4722 bset_auto_save_file_format (&buffer_defaults, Qt);
5342 set_buffer_overlays_before (&buffer_defaults, NULL); 4723 buffer_defaults.overlays = NULL;
5343 set_buffer_overlays_after (&buffer_defaults, NULL);
5344 buffer_defaults.overlay_center = BEG;
5345 4724
5346 XSETFASTINT (BVAR (&buffer_defaults, tab_width), 8); 4725 XSETFASTINT (BVAR (&buffer_defaults, tab_width), 8);
5347 bset_truncate_lines (&buffer_defaults, Qnil); 4726 bset_truncate_lines (&buffer_defaults, Qnil);
@@ -5546,6 +4925,48 @@ defvar_per_buffer (struct Lisp_Buffer_Objfwd *bo_fwd, const char *namestring,
5546 emacs_abort (); 4925 emacs_abort ();
5547} 4926}
5548 4927
4928#ifdef ITREE_DEBUG
4929static Lisp_Object
4930make_lispy_itree_node (const struct itree_node *node)
4931{
4932 return listn (12,
4933 intern (":begin"),
4934 make_fixnum (node->begin),
4935 intern (":end"),
4936 make_fixnum (node->end),
4937 intern (":limit"),
4938 make_fixnum (node->limit),
4939 intern (":offset"),
4940 make_fixnum (node->offset),
4941 intern (":rear-advance"),
4942 node->rear_advance ? Qt : Qnil,
4943 intern (":front-advance"),
4944 node->front_advance ? Qt : Qnil);
4945}
4946
4947static Lisp_Object
4948overlay_tree (const struct itree_tree *tree,
4949 const struct itree_node *node)
4950{
4951 if (node == ITREE_NULL)
4952 return Qnil;
4953 return list3 (make_lispy_itree_node (node),
4954 overlay_tree (tree, node->left),
4955 overlay_tree (tree, node->right));
4956}
4957
4958DEFUN ("overlay-tree", Foverlay_tree, Soverlay_tree, 0, 1, 0,
4959 doc: /* Get the overlay tree for BUFFER. */)
4960 (Lisp_Object buffer)
4961{
4962 struct buffer *b = decode_buffer (buffer);
4963 if (! b->overlays)
4964 return Qnil;
4965 return overlay_tree (b->overlays, b->overlays->root);
4966}
4967#endif
4968
4969
5549 4970
5550/* Initialize the buffer routines. */ 4971/* Initialize the buffer routines. */
5551void 4972void
@@ -6517,6 +5938,10 @@ There is no reason to change that value except for debugging purposes. */);
6517 5938
6518 DEFSYM (Qautosaved, "autosaved"); 5939 DEFSYM (Qautosaved, "autosaved");
6519 5940
5941#ifdef ITREE_DEBUG
5942 defsubr (&Soverlay_tree);
5943#endif
5944
6520 DEFSYM (Qkill_buffer__possibly_save, "kill-buffer--possibly-save"); 5945 DEFSYM (Qkill_buffer__possibly_save, "kill-buffer--possibly-save");
6521 5946
6522 DEFSYM (Qbuffer_stale_function, "buffer-stale-function"); 5947 DEFSYM (Qbuffer_stale_function, "buffer-stale-function");
diff --git a/src/buffer.h b/src/buffer.h
index cbdbae798ba..3ea4125645d 100644
--- a/src/buffer.h
+++ b/src/buffer.h
@@ -1,7 +1,6 @@
1/* Header file for the buffer manipulation primitives. 1/* Header file for the buffer manipulation primitives.
2 2
3Copyright (C) 1985-1986, 1993-1995, 1997-2022 Free Software Foundation, 3Copyright (C) 1985-2022 Free Software Foundation, Inc.
4Inc.
5 4
6This file is part of GNU Emacs. 5This file is part of GNU Emacs.
7 6
@@ -26,6 +25,7 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
26 25
27#include "character.h" 26#include "character.h"
28#include "lisp.h" 27#include "lisp.h"
28#include "itree.h"
29 29
30INLINE_HEADER_BEGIN 30INLINE_HEADER_BEGIN
31 31
@@ -697,16 +697,8 @@ struct buffer
697 display optimizations must be used. */ 697 display optimizations must be used. */
698 bool_bf long_line_optimizations_p : 1; 698 bool_bf long_line_optimizations_p : 1;
699 699
700 /* List of overlays that end at or before the current center, 700 /* The inveral tree containing this buffer's overlays. */
701 in order of end-position. */ 701 struct itree_tree *overlays;
702 struct Lisp_Overlay *overlays_before;
703
704 /* List of overlays that end after the current center,
705 in order of start-position. */
706 struct Lisp_Overlay *overlays_after;
707
708 /* Position where the overlay lists are centered. */
709 ptrdiff_t overlay_center;
710 702
711 /* Changes in the buffer are recorded here for undo, and t means 703 /* Changes in the buffer are recorded here for undo, and t means
712 don't record anything. This information belongs to the base 704 don't record anything. This information belongs to the base
@@ -716,6 +708,14 @@ struct buffer
716 Lisp_Object undo_list_; 708 Lisp_Object undo_list_;
717}; 709};
718 710
711struct sortvec
712{
713 Lisp_Object overlay;
714 ptrdiff_t beg, end;
715 EMACS_INT priority;
716 EMACS_INT spriority; /* Secondary priority. */
717};
718
719INLINE bool 719INLINE bool
720BUFFERP (Lisp_Object a) 720BUFFERP (Lisp_Object a)
721{ 721{
@@ -1171,8 +1171,11 @@ extern void delete_all_overlays (struct buffer *);
1171extern void reset_buffer (struct buffer *); 1171extern void reset_buffer (struct buffer *);
1172extern void compact_buffer (struct buffer *); 1172extern void compact_buffer (struct buffer *);
1173extern void evaporate_overlays (ptrdiff_t); 1173extern void evaporate_overlays (ptrdiff_t);
1174extern ptrdiff_t overlays_at (EMACS_INT, bool, Lisp_Object **, 1174extern ptrdiff_t overlays_at (ptrdiff_t, bool, Lisp_Object **, ptrdiff_t *, ptrdiff_t *);
1175 ptrdiff_t *, ptrdiff_t *, ptrdiff_t *, bool); 1175extern ptrdiff_t overlays_in (ptrdiff_t, ptrdiff_t, bool, Lisp_Object **,
1176 ptrdiff_t *, bool, bool, ptrdiff_t *);
1177extern ptrdiff_t previous_overlay_change (ptrdiff_t);
1178extern ptrdiff_t next_overlay_change (ptrdiff_t);
1176extern ptrdiff_t sort_overlays (Lisp_Object *, ptrdiff_t, struct window *); 1179extern ptrdiff_t sort_overlays (Lisp_Object *, ptrdiff_t, struct window *);
1177extern void recenter_overlay_lists (struct buffer *, ptrdiff_t); 1180extern void recenter_overlay_lists (struct buffer *, ptrdiff_t);
1178extern ptrdiff_t overlay_strings (ptrdiff_t, struct window *, unsigned char **); 1181extern ptrdiff_t overlay_strings (ptrdiff_t, struct window *, unsigned char **);
@@ -1186,6 +1189,7 @@ extern void fix_overlays_before (struct buffer *, ptrdiff_t, ptrdiff_t);
1186extern void mmap_set_vars (bool); 1189extern void mmap_set_vars (bool);
1187extern void restore_buffer (Lisp_Object); 1190extern void restore_buffer (Lisp_Object);
1188extern void set_buffer_if_live (Lisp_Object); 1191extern void set_buffer_if_live (Lisp_Object);
1192extern Lisp_Object build_overlay (bool, bool, Lisp_Object);
1189 1193
1190/* Return B as a struct buffer pointer, defaulting to the current buffer. */ 1194/* Return B as a struct buffer pointer, defaulting to the current buffer. */
1191 1195
@@ -1226,18 +1230,16 @@ record_unwind_current_buffer (void)
1226 This macro might evaluate its args multiple times, 1230 This macro might evaluate its args multiple times,
1227 and it treat some args as lvalues. */ 1231 and it treat some args as lvalues. */
1228 1232
1229#define GET_OVERLAYS_AT(posn, overlays, noverlays, nextp, chrq) \ 1233#define GET_OVERLAYS_AT(posn, overlays, noverlays, next) \
1230 do { \ 1234 do { \
1231 ptrdiff_t maxlen = 40; \ 1235 ptrdiff_t maxlen = 40; \
1232 SAFE_NALLOCA (overlays, 1, maxlen); \ 1236 SAFE_NALLOCA (overlays, 1, maxlen); \
1233 (noverlays) = overlays_at (posn, false, &(overlays), &maxlen, \ 1237 (noverlays) = overlays_at (posn, false, &(overlays), &maxlen, next); \
1234 nextp, NULL, chrq); \
1235 if ((noverlays) > maxlen) \ 1238 if ((noverlays) > maxlen) \
1236 { \ 1239 { \
1237 maxlen = noverlays; \ 1240 maxlen = noverlays; \
1238 SAFE_NALLOCA (overlays, 1, maxlen); \ 1241 SAFE_NALLOCA (overlays, 1, maxlen); \
1239 (noverlays) = overlays_at (posn, false, &(overlays), &maxlen, \ 1242 (noverlays) = overlays_at (posn, false, &(overlays), &maxlen, next); \
1240 nextp, NULL, chrq); \
1241 } \ 1243 } \
1242 } while (false) 1244 } while (false)
1243 1245
@@ -1272,7 +1274,8 @@ set_buffer_intervals (struct buffer *b, INTERVAL i)
1272INLINE bool 1274INLINE bool
1273buffer_has_overlays (void) 1275buffer_has_overlays (void)
1274{ 1276{
1275 return current_buffer->overlays_before || current_buffer->overlays_after; 1277 return current_buffer->overlays
1278 && (current_buffer->overlays->root != NULL);
1276} 1279}
1277 1280
1278/* Functions for accessing a character or byte, 1281/* Functions for accessing a character or byte,
@@ -1390,25 +1393,69 @@ buffer_window_count (struct buffer *b)
1390 1393
1391/* Overlays */ 1394/* Overlays */
1392 1395
1393/* Return the marker that stands for where OV starts in the buffer. */ 1396INLINE ptrdiff_t
1397overlay_start (struct Lisp_Overlay *ov)
1398{
1399 if (! ov->buffer)
1400 return -1;
1401 return itree_node_begin (ov->buffer->overlays, ov->interval);
1402}
1403
1404INLINE ptrdiff_t
1405overlay_end (struct Lisp_Overlay *ov)
1406{
1407 if (! ov->buffer)
1408 return -1;
1409 return itree_node_end (ov->buffer->overlays, ov->interval);
1410}
1394 1411
1395#define OVERLAY_START(OV) XOVERLAY (OV)->start 1412/* Return the start of OV in its buffer, or -1 if OV is not associated
1413 with any buffer. */
1396 1414
1397/* Return the marker that stands for where OV ends in the buffer. */ 1415INLINE ptrdiff_t
1416OVERLAY_START (Lisp_Object ov)
1417{
1418 return overlay_start (XOVERLAY (ov));
1419}
1398 1420
1399#define OVERLAY_END(OV) XOVERLAY (OV)->end 1421/* Return the end of OV in its buffer, or -1. */
1422
1423INLINE ptrdiff_t
1424OVERLAY_END (Lisp_Object ov)
1425{
1426 return overlay_end (XOVERLAY (ov));
1427}
1400 1428
1401/* Return the plist of overlay OV. */ 1429/* Return the plist of overlay OV. */
1402 1430
1403#define OVERLAY_PLIST(OV) XOVERLAY (OV)->plist 1431INLINE Lisp_Object
1432OVERLAY_PLIST (Lisp_Object ov)
1433{
1434 return XOVERLAY (ov)->plist;
1435}
1404 1436
1405/* Return the actual buffer position for the marker P. 1437/* Return the buffer of overlay OV. */
1406 We assume you know which buffer it's pointing into. */
1407 1438
1408INLINE ptrdiff_t 1439INLINE struct buffer *
1409OVERLAY_POSITION (Lisp_Object p) 1440OVERLAY_BUFFER (Lisp_Object ov)
1410{ 1441{
1411 return marker_position (p); 1442 return XOVERLAY (ov)->buffer;
1443}
1444
1445/* Return true, if OV's rear-advance is set. */
1446
1447INLINE bool
1448OVERLAY_REAR_ADVANCE_P (Lisp_Object ov)
1449{
1450 return XOVERLAY (ov)->interval->rear_advance;
1451}
1452
1453/* Return true, if OV's front-advance is set. */
1454
1455INLINE bool
1456OVERLAY_FRONT_ADVANCE_P (Lisp_Object ov)
1457{
1458 return XOVERLAY (ov)->interval->front_advance;
1412} 1459}
1413 1460
1414 1461
@@ -1692,4 +1739,7 @@ dec_both (ptrdiff_t *charpos, ptrdiff_t *bytepos)
1692 1739
1693INLINE_HEADER_END 1740INLINE_HEADER_END
1694 1741
1742int compare_overlays (const void *v1, const void *v2);
1743void make_sortvec_item (struct sortvec *item, Lisp_Object overlay);
1744
1695#endif /* EMACS_BUFFER_H */ 1745#endif /* EMACS_BUFFER_H */
diff --git a/src/editfns.c b/src/editfns.c
index 3f9618edb08..17dca4708ed 100644
--- a/src/editfns.c
+++ b/src/editfns.c
@@ -1,6 +1,6 @@
1/* Lisp functions pertaining to editing. -*- coding: utf-8 -*- 1/* Lisp functions pertaining to editing. -*- coding: utf-8 -*-
2 2
3Copyright (C) 1985-1987, 1989, 1993-2022 Free Software Foundation, Inc. 3Copyright (C) 1985-2022 Free Software Foundation, Inc.
4 4
5This file is part of GNU Emacs. 5This file is part of GNU Emacs.
6 6
@@ -265,51 +265,20 @@ If you set the marker not to point anywhere, the buffer will have no mark. */)
265 265
266/* Find all the overlays in the current buffer that touch position POS. 266/* Find all the overlays in the current buffer that touch position POS.
267 Return the number found, and store them in a vector in VEC 267 Return the number found, and store them in a vector in VEC
268 of length LEN. */ 268 of length LEN.
269
270 Note: this can return overlays that do not touch POS. The caller
271 should filter these out. */
269 272
270static ptrdiff_t 273static ptrdiff_t
271overlays_around (EMACS_INT pos, Lisp_Object *vec, ptrdiff_t len) 274overlays_around (ptrdiff_t pos, Lisp_Object *vec, ptrdiff_t len)
272{ 275{
273 ptrdiff_t idx = 0; 276 /* Find all potentially rear-advance overlays at (POS - 1). Find
274 277 all overlays at POS, so end at (POS + 1). Find even empty
275 for (struct Lisp_Overlay *tail = current_buffer->overlays_before; 278 overlays, which due to the way 'overlays-in' works implies that
276 tail; tail = tail->next) 279 we might also fetch empty overlays starting at (POS + 1). */
277 { 280 return overlays_in (pos - 1, pos + 1, false, &vec, &len,
278 Lisp_Object overlay = make_lisp_ptr (tail, Lisp_Vectorlike); 281 true, false, NULL);
279 Lisp_Object end = OVERLAY_END (overlay);
280 ptrdiff_t endpos = OVERLAY_POSITION (end);
281 if (endpos < pos)
282 break;
283 Lisp_Object start = OVERLAY_START (overlay);
284 ptrdiff_t startpos = OVERLAY_POSITION (start);
285 if (startpos <= pos)
286 {
287 if (idx < len)
288 vec[idx] = overlay;
289 /* Keep counting overlays even if we can't return them all. */
290 idx++;
291 }
292 }
293
294 for (struct Lisp_Overlay *tail = current_buffer->overlays_after;
295 tail; tail = tail->next)
296 {
297 Lisp_Object overlay = make_lisp_ptr (tail, Lisp_Vectorlike);
298 Lisp_Object start = OVERLAY_START (overlay);
299 ptrdiff_t startpos = OVERLAY_POSITION (start);
300 if (pos < startpos)
301 break;
302 Lisp_Object end = OVERLAY_END (overlay);
303 ptrdiff_t endpos = OVERLAY_POSITION (end);
304 if (pos <= endpos)
305 {
306 if (idx < len)
307 vec[idx] = overlay;
308 idx++;
309 }
310 }
311
312 return idx;
313} 282}
314 283
315DEFUN ("get-pos-property", Fget_pos_property, Sget_pos_property, 2, 3, 0, 284DEFUN ("get-pos-property", Fget_pos_property, Sget_pos_property, 2, 3, 0,
@@ -369,11 +338,12 @@ at POSITION. */)
369 if (!NILP (tem)) 338 if (!NILP (tem))
370 { 339 {
371 /* Check the overlay is indeed active at point. */ 340 /* Check the overlay is indeed active at point. */
372 Lisp_Object start = OVERLAY_START (ol), finish = OVERLAY_END (ol); 341 if ((OVERLAY_START (ol) == posn
373 if ((OVERLAY_POSITION (start) == posn 342 && OVERLAY_FRONT_ADVANCE_P (ol))
374 && XMARKER (start)->insertion_type == 1) 343 || (OVERLAY_END (ol) == posn
375 || (OVERLAY_POSITION (finish) == posn 344 && ! OVERLAY_REAR_ADVANCE_P (ol))
376 && XMARKER (finish)->insertion_type == 0)) 345 || OVERLAY_START (ol) > posn
346 || OVERLAY_END (ol) < posn)
377 ; /* The overlay will not cover a char inserted at point. */ 347 ; /* The overlay will not cover a char inserted at point. */
378 else 348 else
379 { 349 {
@@ -4526,7 +4496,6 @@ ring. */)
4526 transpose_markers (start1, end1, start2, end2, 4496 transpose_markers (start1, end1, start2, end2,
4527 start1_byte, start1_byte + len1_byte, 4497 start1_byte, start1_byte + len1_byte,
4528 start2_byte, start2_byte + len2_byte); 4498 start2_byte, start2_byte + len2_byte);
4529 fix_start_end_in_overlays (start1, end2);
4530 } 4499 }
4531 else 4500 else
4532 { 4501 {
diff --git a/src/eval.c b/src/eval.c
index 2928a45ac1e..e1399d6a05c 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -1716,6 +1716,7 @@ signal_or_quit (Lisp_Object error_symbol, Lisp_Object data, bool keyboard_quit)
1716 Lisp_Object clause = Qnil; 1716 Lisp_Object clause = Qnil;
1717 struct handler *h; 1717 struct handler *h;
1718 1718
1719 eassert (!itree_iterator_busy_p ());
1719 if (gc_in_progress || waiting_for_input) 1720 if (gc_in_progress || waiting_for_input)
1720 emacs_abort (); 1721 emacs_abort ();
1721 1722
diff --git a/src/fileio.c b/src/fileio.c
index 8f96e973b25..92335b639cd 100644
--- a/src/fileio.c
+++ b/src/fileio.c
@@ -4167,8 +4167,7 @@ by calling `format-decode', which see. */)
4167 bset_read_only (buf, Qnil); 4167 bset_read_only (buf, Qnil);
4168 bset_filename (buf, Qnil); 4168 bset_filename (buf, Qnil);
4169 bset_undo_list (buf, Qt); 4169 bset_undo_list (buf, Qt);
4170 eassert (buf->overlays_before == NULL); 4170 eassert (buf->overlays == NULL);
4171 eassert (buf->overlays_after == NULL);
4172 4171
4173 set_buffer_internal (buf); 4172 set_buffer_internal (buf);
4174 Ferase_buffer (); 4173 Ferase_buffer ();
diff --git a/src/fns.c b/src/fns.c
index c35f40357b7..035fa129352 100644
--- a/src/fns.c
+++ b/src/fns.c
@@ -1,7 +1,6 @@
1/* Random utility Lisp functions. 1/* Random utility Lisp functions.
2 2
3Copyright (C) 1985-1987, 1993-1995, 1997-2022 Free Software Foundation, 3Copyright (C) 1985-2022 Free Software Foundation, Inc.
4Inc.
5 4
6This file is part of GNU Emacs. 5This file is part of GNU Emacs.
7 6
@@ -2797,10 +2796,9 @@ internal_equal (Lisp_Object o1, Lisp_Object o2, enum equal_kind equal_kind,
2797 return mpz_cmp (*xbignum_val (o1), *xbignum_val (o2)) == 0; 2796 return mpz_cmp (*xbignum_val (o1), *xbignum_val (o2)) == 0;
2798 if (OVERLAYP (o1)) 2797 if (OVERLAYP (o1))
2799 { 2798 {
2800 if (!internal_equal (OVERLAY_START (o1), OVERLAY_START (o2), 2799 if (OVERLAY_BUFFER (o1) != OVERLAY_BUFFER (o2)
2801 equal_kind, depth + 1, ht) 2800 || OVERLAY_START (o1) != OVERLAY_START (o2)
2802 || !internal_equal (OVERLAY_END (o1), OVERLAY_END (o2), 2801 || OVERLAY_END (o1) != OVERLAY_END (o2))
2803 equal_kind, depth + 1, ht))
2804 return false; 2802 return false;
2805 o1 = XOVERLAY (o1)->plist; 2803 o1 = XOVERLAY (o1)->plist;
2806 o2 = XOVERLAY (o2)->plist; 2804 o2 = XOVERLAY (o2)->plist;
@@ -5094,6 +5092,7 @@ sxhash_obj (Lisp_Object obj, int depth)
5094 ? 42 5092 ? 42
5095 : sxhash_vector (obj, depth)); 5093 : sxhash_vector (obj, depth));
5096 } 5094 }
5095 /* FIXME: Use `switch`. */
5097 else if (pvec_type == PVEC_BIGNUM) 5096 else if (pvec_type == PVEC_BIGNUM)
5098 return sxhash_bignum (obj); 5097 return sxhash_bignum (obj);
5099 else if (pvec_type == PVEC_MARKER) 5098 else if (pvec_type == PVEC_MARKER)
@@ -5108,8 +5107,8 @@ sxhash_obj (Lisp_Object obj, int depth)
5108 return sxhash_bool_vector (obj); 5107 return sxhash_bool_vector (obj);
5109 else if (pvec_type == PVEC_OVERLAY) 5108 else if (pvec_type == PVEC_OVERLAY)
5110 { 5109 {
5111 EMACS_UINT hash = sxhash_obj (OVERLAY_START (obj), depth); 5110 EMACS_UINT hash = OVERLAY_START (obj);
5112 hash = sxhash_combine (hash, sxhash_obj (OVERLAY_END (obj), depth)); 5111 hash = sxhash_combine (hash, OVERLAY_END (obj));
5113 hash = sxhash_combine (hash, sxhash_obj (XOVERLAY (obj)->plist, depth)); 5112 hash = sxhash_combine (hash, sxhash_obj (XOVERLAY (obj)->plist, depth));
5114 return SXHASH_REDUCE (hash); 5113 return SXHASH_REDUCE (hash);
5115 } 5114 }
diff --git a/src/indent.c b/src/indent.c
index 4bf597a339f..4671ccccf90 100644
--- a/src/indent.c
+++ b/src/indent.c
@@ -224,9 +224,6 @@ skip_invisible (ptrdiff_t pos, ptrdiff_t *next_boundary_p, ptrdiff_t to, Lisp_Ob
224 XSETFASTINT (position, pos); 224 XSETFASTINT (position, pos);
225 XSETBUFFER (buffer, current_buffer); 225 XSETBUFFER (buffer, current_buffer);
226 226
227 /* Give faster response for overlay lookup near POS. */
228 recenter_overlay_lists (current_buffer, pos);
229
230 /* We must not advance farther than the next overlay change. 227 /* We must not advance farther than the next overlay change.
231 The overlay change might change the invisible property; 228 The overlay change might change the invisible property;
232 or there might be overlay strings to be displayed there. */ 229 or there might be overlay strings to be displayed there. */
@@ -518,7 +515,7 @@ check_display_width (ptrdiff_t pos, ptrdiff_t col, ptrdiff_t *endpos)
518 { 515 {
519 ptrdiff_t start; 516 ptrdiff_t start;
520 if (OVERLAYP (overlay)) 517 if (OVERLAYP (overlay))
521 *endpos = OVERLAY_POSITION (OVERLAY_END (overlay)); 518 *endpos = OVERLAY_END (overlay);
522 else 519 else
523 get_property_and_range (pos, Qdisplay, &val, &start, endpos, Qnil); 520 get_property_and_range (pos, Qdisplay, &val, &start, endpos, Qnil);
524 521
diff --git a/src/insdel.c b/src/insdel.c
index 38d5fbda002..6d56a76c77a 100644
--- a/src/insdel.c
+++ b/src/insdel.c
@@ -284,7 +284,6 @@ adjust_markers_for_insert (ptrdiff_t from, ptrdiff_t from_byte,
284 ptrdiff_t to, ptrdiff_t to_byte, bool before_markers) 284 ptrdiff_t to, ptrdiff_t to_byte, bool before_markers)
285{ 285{
286 struct Lisp_Marker *m; 286 struct Lisp_Marker *m;
287 bool adjusted = 0;
288 ptrdiff_t nchars = to - from; 287 ptrdiff_t nchars = to - from;
289 ptrdiff_t nbytes = to_byte - from_byte; 288 ptrdiff_t nbytes = to_byte - from_byte;
290 289
@@ -300,8 +299,6 @@ adjust_markers_for_insert (ptrdiff_t from, ptrdiff_t from_byte,
300 { 299 {
301 m->bytepos = to_byte; 300 m->bytepos = to_byte;
302 m->charpos = to; 301 m->charpos = to;
303 if (m->insertion_type)
304 adjusted = 1;
305 } 302 }
306 } 303 }
307 else if (m->bytepos > from_byte) 304 else if (m->bytepos > from_byte)
@@ -310,15 +307,6 @@ adjust_markers_for_insert (ptrdiff_t from, ptrdiff_t from_byte,
310 m->charpos += nchars; 307 m->charpos += nchars;
311 } 308 }
312 } 309 }
313
314 /* Adjusting only markers whose insertion-type is t may result in
315 - disordered start and end in overlays, and
316 - disordered overlays in the slot `overlays_before' of current_buffer. */
317 if (adjusted)
318 {
319 fix_start_end_in_overlays (from, to);
320 fix_overlays_before (current_buffer, from, to);
321 }
322} 310}
323 311
324/* Adjust point for an insertion of NBYTES bytes, which are NCHARS characters. 312/* Adjust point for an insertion of NBYTES bytes, which are NCHARS characters.
diff --git a/src/intervals.c b/src/intervals.c
index 7f119815570..78f4f6b6174 100644
--- a/src/intervals.c
+++ b/src/intervals.c
@@ -1836,8 +1836,8 @@ adjust_for_invis_intang (ptrdiff_t pos, ptrdiff_t test_offs, ptrdiff_t adj,
1836 == (test_offs == 0 ? 1 : -1)) 1836 == (test_offs == 0 ? 1 : -1))
1837 /* Invisible property is from an overlay. */ 1837 /* Invisible property is from an overlay. */
1838 : (test_offs == 0 1838 : (test_offs == 0
1839 ? XMARKER (OVERLAY_START (invis_overlay))->insertion_type == 0 1839 ? ! OVERLAY_FRONT_ADVANCE_P (invis_overlay)
1840 : XMARKER (OVERLAY_END (invis_overlay))->insertion_type == 1))) 1840 : OVERLAY_REAR_ADVANCE_P (invis_overlay))))
1841 pos += adj; 1841 pos += adj;
1842 1842
1843 return pos; 1843 return pos;
diff --git a/src/itree.c b/src/itree.c
new file mode 100644
index 00000000000..e824f2c8914
--- /dev/null
+++ b/src/itree.c
@@ -0,0 +1,1421 @@
1/* This file implements an efficient interval data-structure.
2
3Copyright (C) 2017-2022 Free Software Foundation, Inc.
4
5This file is 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
23#include "itree.h"
24
25/*
26 Intervals of the form [BEGIN, END), are stored as nodes inside a RB
27 tree, ordered 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, 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 ==== FIXME: bug#58342 some important operations remain slow ===
66
67 The amortized costs of Emacs' previous-overlay-change and
68 next-overlay-change functions are O(N) with this data structure.
69 The root problem is that we only have an order for the BEG field,
70 but not the END. The previous/next overlay change operations need
71 to find the nearest point where there is *either* an interval BEG
72 or END point, but there is no efficient way to narrow the search
73 space over END postions.
74
75 Consider the case where next-overlay-change is called at POS, all
76 interval BEG positions are less than pos POS and all interval END
77 posistions are after. These END positions have no order, and so
78 *every* interval must be examined. This is at least O(N). The
79 previous-overlay-change case is similar. The root issue is that
80 the iterative "narrowing" approach is not guaranteed to reduce the
81 search space in logarithmic time, since END is not ordered in the
82 tree.
83
84 One might argue that the LIMIT value will do this narrowing, but
85 this narrowing is O(K*log(N)) where K is the size of the result
86 set. If we are interested in finding the node in a range with the
87 smallest END, we might have to examine all K nodes in that range.
88 In the case of the *-overlay-channge functions, K may well be equal
89 to N.
90
91 Ideally, a tree based data structure for overlays would have
92 O(log(N)) performance for previous-overlay-change and
93 next-overlay-change, as these are called in performance sensitive
94 situations such as redisplay. The only way I can think of
95 achieving this is by keeping one ordering by BEG and a separate
96 ordering by END, and then performing logic quite similar to the
97 current Emacs overlays-before and overlays-after lists.
98
99 ==== Adjusting intervals ====
100
101 Since this data-structure will be used for overlays in an Emacs
102 buffer, a second core operation is the ability to insert and delete
103 gaps in the tree. This models the insertion and deletion of text
104 in a buffer and the effects it may have on the positions of
105 overlays.
106
107 Consider this: Something gets inserted at position P into a buffer
108 and assume that all overlays occur strictly after P. Ordinarily,
109 we would have to iterate all overlays and increment their BEGIN and
110 END values accordingly (the insertion of text pushes them back).
111 In order to avoid this, we introduce yet another node attribute,
112 called OFFSET.
113
114 The OFFSET of some some subtree, represented by its root, is the
115 amount of shift that needs to be applied to its BEGIN, END and
116 LIMIT values, in order to get to the actual buffer positions.
117 Coming back to the example, all we would need to do in this case,
118 is to increment the OFFSET of the tree's root, without any
119 traversal of the tree itself.
120
121 As a consequence, the real values of BEGIN, END and LIMIT of some
122 NODE need to be computed by incrementing them by the sum of NODE's
123 OFFSET and all of its ancestors offsets. Therefore, we store a
124 counter (otick) inside every node and also the tree, by which we
125 remember the fact, that a node's path to the root has no offsets
126 applied (i.e. its values are up to date). This is the case if some
127 node's value differs from the tree's one, the later of which is
128 incremented whenever some node's offset has changed.
129*/
130
131/* +=======================================================================+
132 * | Stack
133 * +=======================================================================+ */
134
135typedef uintptr_t nodeptr_and_flag;
136
137static inline nodeptr_and_flag
138make_nav (struct itree_node *ptr, bool flag)
139{
140 uintptr_t v = (uintptr_t) ptr;
141 /* We assume alignment imposes the LSB is clear for us to use it. */
142 eassert (!(v & 1));
143 return v | !!flag;
144}
145
146static inline struct itree_node *
147nav_nodeptr (nodeptr_and_flag nav)
148{
149 return (struct itree_node *) (nav & (~(uintptr_t)1));
150}
151
152static inline bool
153nav_flag (nodeptr_and_flag nav)
154{
155 return (bool) (nav & 1);
156}
157
158/* Simple dynamic array. */
159struct interval_stack
160{
161 nodeptr_and_flag *nodes;
162 size_t size;
163 size_t length;
164};
165
166/* This is just a simple dynamic array with stack semantics. */
167
168static struct interval_stack*
169interval_stack_create (intmax_t initial_size)
170{
171 struct interval_stack *stack = xmalloc (sizeof (struct interval_stack));
172 stack->size = max (0, initial_size);
173 stack->nodes = xmalloc (stack->size * sizeof (struct itree_node*));
174 stack->length = 0;
175 return stack;
176}
177
178static void
179interval_stack_destroy (struct interval_stack *stack)
180{
181 if (! stack)
182 return;
183 if (stack->nodes)
184 xfree (stack->nodes);
185 xfree (stack);
186}
187
188static void
189interval_stack_clear (struct interval_stack *stack)
190{
191 stack->length = 0;
192}
193
194static inline void
195interval_stack_ensure_space (struct interval_stack *stack, intmax_t nelements)
196{
197 if (nelements > stack->size)
198 {
199 stack->size = (nelements + 1) * 2;
200 stack->nodes = xrealloc (stack->nodes,
201 stack->size * sizeof (*stack->nodes));
202 }
203}
204
205/* Push NODE on the STACK, while settings its visited flag to FLAG. */
206
207static inline void
208interval_stack_push_flagged (struct interval_stack *stack,
209 struct itree_node *node, bool flag)
210{
211 eassert (node && node != NULL);
212
213 /* FIXME: While the stack used in the iterator is bounded by the tree
214 depth and could be easily pre-allocated to a large enough size to avoid
215 this "ensure" check, `interval_stack_push` is also used elsewhere to
216 simply collect some subset of the overlays, where it's only bounded by
217 the total number of overlays in the buffer (which can be large and thus
218 preferably not pre-allocated needlessly). */
219 interval_stack_ensure_space (stack, stack->length + 1);
220
221 stack->nodes[stack->length] = make_nav (node, flag);
222 stack->length++;
223}
224
225static inline void
226interval_stack_push (struct interval_stack *stack, struct itree_node *node)
227{
228 interval_stack_push_flagged (stack, node, false);
229}
230
231static inline nodeptr_and_flag
232interval_stack_pop (struct interval_stack *stack)
233{
234 if (stack->length == 0)
235 return make_nav (NULL, false);
236 return stack->nodes[--stack->length];
237}
238
239
240/* +-----------------------------------------------------------------------+ */
241
242/* State used when iterating interval. */
243struct itree_iterator
244{
245 struct interval_stack *stack;
246 ptrdiff_t begin;
247 ptrdiff_t end;
248 uintmax_t otick; /* A copy of the tree's `otick`. */
249 enum itree_order order;
250 bool running;
251 const char* file;
252 int line;
253};
254
255/* Ideally, every iteration would use its own `iter` object, so we could
256 have several iterations active at the same time. In practice, iterations
257 are limited by the fact we don't allow modifying the tree at the same
258 time, making the use of nested iterations quite rare anyway.
259 So we just use a single global iterator instead for now. */
260static struct itree_iterator *iter;
261
262static int
263interval_tree_max_height (const struct itree_tree *tree)
264{
265 return 2 * log (tree->size + 1) / log (2) + 0.5;
266}
267
268/* Allocate a new iterator for TREE. */
269
270static struct itree_iterator *
271itree_iterator_create (struct itree_tree *tree)
272{
273 struct itree_iterator *g = xmalloc (sizeof *g);
274 /* 19 here just avoids starting with a silly-small stack.
275 FIXME: Since this stack only needs to be about 2*max_depth
276 in the worst case, we could completely pre-allocate it to something
277 like word-bit-size * 2 and then never worry about growing it. */
278 const int size = (tree ? interval_tree_max_height (tree) : 19) + 1;
279
280 g->stack = interval_stack_create (size);
281 g->running = false;
282 g->begin = 0;
283 g->end = 0;
284 g->file = NULL;
285 g->line = 0;
286 return g;
287}
288
289static void
290itree_init (void)
291{
292 iter = itree_iterator_create (NULL);
293}
294
295struct check_subtree_result
296{
297 int size; /* Node count of the tree. */
298 ptrdiff_t limit; /* Limit of the tree (max END). */
299 int black_height; /* Black height of the tree. */
300};
301
302static struct check_subtree_result
303check_subtree (struct itree_node *node,
304 bool check_red_black_invariants, uintmax_t tree_otick,
305 ptrdiff_t offset, ptrdiff_t min_begin,
306 ptrdiff_t max_begin)
307{
308 struct check_subtree_result result = { .size = 0,
309 .limit = PTRDIFF_MIN,
310 .black_height = 0 };
311 if (node == NULL)
312 return result;
313
314 /* Validate structure. */
315 eassert (node->left == NULL || node->left->parent == node);
316 eassert (node->right == NULL || node->right->parent == node);
317
318 /* Validate otick. A node's otick must be <= to the tree's otick
319 and <= to its parent's otick.
320
321 Note: we cannot assert that (NODE.otick == NODE.parent.otick)
322 implies (NODE.offset == 0) because interval_tree_inherit_offset()
323 doesn't always update otick. It could, but it is not clear there
324 is a need. */
325 eassert (node->otick <= tree_otick);
326 eassert (node->parent == NULL || node->otick <= node->parent->otick);
327 eassert (node->otick != tree_otick || node->offset == 0);
328
329 offset += node->offset;
330 ptrdiff_t begin = node->begin + offset;
331 ptrdiff_t end = node->end + offset;
332 ptrdiff_t limit = node->limit + offset;
333
334 eassert (min_begin <= max_begin);
335 eassert (min_begin <= begin);
336 eassert (begin <= max_begin);
337 eassert (end <= limit);
338
339 struct check_subtree_result left_result
340 = check_subtree (node->left, check_red_black_invariants,
341 tree_otick, offset, min_begin, begin);
342 struct check_subtree_result right_result
343 = check_subtree (node->right, check_red_black_invariants,
344 tree_otick, offset, begin, max_begin);
345
346 eassert (left_result.limit <= limit);
347 eassert (right_result.limit <= limit);
348 eassert (limit == max (end, max (left_result.limit, right_result.limit)));
349
350 if (check_red_black_invariants)
351 {
352 eassert (left_result.black_height == right_result.black_height);
353 eassert (node->parent == NULL || !node->red || !node->parent->red);
354 }
355
356 result.size = 1 + left_result.size + right_result.size;
357 result.limit = limit;
358 result.black_height = (node->red ? 0 : 1) + left_result.black_height;
359 return result;
360}
361
362/* Validate invariants for TREE. If CHECK_RED_BLACK_INVARIANTS, red
363 nodes with red children are considered invalid.
364
365 This runs in constant time when ENABLE_OVERLAY_CHECKING is 0
366 (i.e. Emacs is not configured with
367 "--enable_checking=yes,overlays"). In this mode it can't check all
368 the invariants. When ENABLE_OVERLAY_CHECKING is 1 it checks the
369 entire tree and validates all invariants.
370*/
371static bool
372check_tree (struct itree_tree *tree,
373 bool check_red_black_invariants)
374{
375 eassert (tree != NULL);
376 eassert (tree->size >= 0);
377 eassert ((tree->size == 0) == (tree->root == NULL));
378 if (tree->root == NULL)
379 return true;
380 eassert (tree->root->parent == NULL);
381 eassert (!check_red_black_invariants || !tree->root->red);
382
383 struct itree_node *node = tree->root;
384 struct check_subtree_result result
385 = check_subtree (node, check_red_black_invariants, tree->otick,
386 node->offset, PTRDIFF_MIN,
387 PTRDIFF_MAX);
388 eassert (result.size == tree->size);
389
390 /* The only way this function fails is eassert(). */
391 return true;
392}
393
394/* +=======================================================================+
395 * | Internal Functions
396 * +=======================================================================+ */
397
398static bool
399null_safe_is_red (struct itree_node *node)
400{
401 return node != NULL && node->red;
402}
403
404static bool
405null_safe_is_black (struct itree_node *node)
406{
407 return node == NULL || !node->red; /* NULL nodes are black */
408}
409
410static inline ptrdiff_t
411itree_newlimit (struct itree_node *node)
412{
413 eassert (node != NULL);
414 return max (node->end,
415 max (node->left == NULL
416 ? PTRDIFF_MIN
417 : node->left->limit + node->left->offset,
418 node->right == NULL
419 ? PTRDIFF_MIN
420 : node->right->limit + node->right->offset));
421}
422
423/* Update NODE's limit attribute according to its children. */
424
425static void
426interval_tree_update_limit (struct itree_node *node)
427{
428 if (node == NULL)
429 return;
430
431 node->limit = itree_newlimit (node);
432}
433
434/* Apply NODE's offset to its begin, end and limit values and
435 propagate it to its children.
436
437 Does nothing, if NODE is clean, i.e. NODE.otick = tree.otick .
438*/
439
440static void
441interval_tree_inherit_offset (uintmax_t otick, struct itree_node *node)
442{
443 eassert (node->parent == NULL || node->parent->otick >= node->otick);
444 if (node->otick == otick)
445 {
446 eassert (node->offset == 0);
447 return;
448 }
449
450 /* Offsets can be inherited from dirty nodes (with out of date
451 otick) during removal, since we do not travel down from the root
452 in that case. In this case rotations are performed on
453 potentially "dirty" nodes, where we only need to make sure the
454 *local* offsets are zero. */
455
456 if (node->offset)
457 {
458 node->begin += node->offset;
459 node->end += node->offset;
460 node->limit += node->offset;
461 if (node->left != NULL)
462 node->left->offset += node->offset;
463 if (node->right != NULL)
464 node->right->offset += node->offset;
465 node->offset = 0;
466 }
467 /* The only thing that matters about `otick` is whether it's equal to
468 that of the tree. We could also "blindly" inherit from parent->otick,
469 but we need to tree's `otick` anyway for when there's no parent. */
470 if (node->parent == NULL || node->parent->otick == otick)
471 node->otick = otick;
472}
473
474/* Update limit of NODE and its ancestors. Stop when it becomes
475 stable, i.e. new_limit = old_limit. */
476
477static void
478interval_tree_propagate_limit (struct itree_node *node)
479{
480 if (node == NULL)
481 return;
482
483 while (1) {
484 ptrdiff_t newlimit = itree_newlimit (node);
485 if (newlimit == node->limit)
486 break;
487 node->limit = newlimit;
488 if (node->parent == NULL)
489 break;
490 node = node->parent;
491 }
492}
493
494static struct itree_node*
495interval_tree_validate (struct itree_tree *tree, struct itree_node *node)
496{
497
498 if (tree->otick == node->otick || node == NULL)
499 return node;
500 if (node != tree->root)
501 interval_tree_validate (tree, node->parent);
502
503 interval_tree_inherit_offset (tree->otick, node);
504 return node;
505}
506
507/* +=======================================================================+
508 * | Tree operations
509 * +=======================================================================+ */
510
511/* Initialize an allocated node. */
512
513void
514itree_node_init (struct itree_node *node,
515 bool front_advance, bool rear_advance,
516 Lisp_Object data)
517{
518 node->parent = NULL;
519 node->left = NULL;
520 node->right = NULL;
521 node->begin = -1;
522 node->end = -1;
523 node->front_advance = front_advance;
524 node->rear_advance = rear_advance;
525 node->data = data;
526}
527
528/* Return NODE's begin value, computing it if necessary. */
529
530ptrdiff_t
531itree_node_begin (struct itree_tree *tree,
532 struct itree_node *node)
533{
534 interval_tree_validate (tree, node);
535 return node->begin;
536}
537
538/* Return NODE's end value, computing it if necessary. */
539
540ptrdiff_t
541itree_node_end (struct itree_tree *tree,
542 struct itree_node *node)
543{
544 interval_tree_validate (tree, node);
545 return node->end;
546}
547
548/* Allocate an interval_tree. Free with interval_tree_destroy. */
549
550struct itree_tree*
551itree_create (void)
552{
553 /* FIXME? Maybe avoid the initialization of itree_null in the same
554 way that is used to call mem_init in alloc.c? It's not really
555 important though. */
556 itree_init ();
557
558 struct itree_tree *tree = xmalloc (sizeof (*tree));
559 itree_clear (tree);
560 return tree;
561}
562
563/* Reset the tree TREE to its empty state. */
564
565void
566itree_clear (struct itree_tree *tree)
567{
568 tree->root = NULL;
569 tree->otick = 1;
570 tree->size = 0;
571}
572
573#ifdef ITREE_TESTING
574/* Initialize a pre-allocated tree (presumably on the stack). */
575
576static void
577interval_tree_init (struct interval_tree *tree)
578{
579 interval_tree_clear (tree);
580 /* tree->iter = itree_iterator_create (tree); */
581}
582#endif
583
584/* Release a tree, freeing its allocated memory. */
585void
586itree_destroy (struct itree_tree *tree)
587{
588 eassert (tree->root == NULL);
589 /* if (tree->iter)
590 * itree_iterator_destroy (tree->iter); */
591 xfree (tree);
592}
593
594/* Return the number of nodes in TREE. */
595
596intmax_t
597itree_size (struct itree_tree *tree)
598{
599 return tree->size;
600}
601
602/* Perform the familiar left-rotation on node NODE. */
603
604static void
605interval_tree_rotate_left (struct itree_tree *tree,
606 struct itree_node *node)
607{
608 eassert (node->right != NULL);
609
610 struct itree_node *right = node->right;
611
612 interval_tree_inherit_offset (tree->otick, node);
613 interval_tree_inherit_offset (tree->otick, right);
614
615 /* Turn right's left subtree into node's right subtree. */
616 node->right = right->left;
617 if (right->left != NULL)
618 right->left->parent = node;
619
620 /* right's parent was node's parent. */
621 if (right != NULL)
622 right->parent = node->parent;
623
624 /* Get the parent to point to right instead of node. */
625 if (node != tree->root)
626 {
627 if (node == node->parent->left)
628 node->parent->left = right;
629 else
630 node->parent->right = right;
631 }
632 else
633 tree->root = right;
634
635 /* Put node on right's left. */
636 right->left = node;
637 if (node != NULL)
638 node->parent = right;
639
640 /* Order matters here. */
641 interval_tree_update_limit (node);
642 interval_tree_update_limit (right);
643}
644
645/* Perform the familiar right-rotation on node NODE. */
646
647static void
648interval_tree_rotate_right (struct itree_tree *tree,
649 struct itree_node *node)
650{
651 eassert (tree && node && node->left != NULL);
652
653 struct itree_node *left = node->left;
654
655 interval_tree_inherit_offset (tree->otick, node);
656 interval_tree_inherit_offset (tree->otick, left);
657
658 node->left = left->right;
659 if (left->right != NULL)
660 left->right->parent = node;
661
662 if (left != NULL)
663 left->parent = node->parent;
664 if (node != tree->root)
665 {
666 if (node == node->parent->right)
667 node->parent->right = left;
668 else
669 node->parent->left = left;
670 }
671 else
672 tree->root = left;
673
674 left->right = node;
675 if (node != NULL)
676 node->parent = left;
677
678 interval_tree_update_limit (left);
679 interval_tree_update_limit (node);
680}
681
682/* Repair the tree after an insertion.
683 The new NODE was added as red, so we may have 2 reds in a row.
684 Rebalance the parents as needed to re-establish the RB invariants. */
685
686static void
687interval_tree_insert_fix (struct itree_tree *tree,
688 struct itree_node *node)
689{
690 eassert (tree->root->red == false);
691
692 while (null_safe_is_red (node->parent))
693 {
694 /* NODE is red and its parent is red. This is a violation of
695 red-black tree property #3. */
696 eassert (node->red);
697
698 if (node->parent == node->parent->parent->left)
699 {
700 /* We're on the left side of our grandparent, and OTHER is
701 our "uncle". */
702 struct itree_node *uncle = node->parent->parent->right;
703
704 if (null_safe_is_red (uncle)) /* case 1.a */
705 {
706 /* Uncle and parent are red but should be black because
707 NODE is red. Change the colors accordingly and
708 proceed with the grandparent. */
709 node->parent->red = false;
710 uncle->red = false;
711 node->parent->parent->red = true;
712 node = node->parent->parent;
713 }
714 else
715 {
716 /* Parent and uncle have different colors; parent is
717 red, uncle is black. */
718 if (node == node->parent->right) /* case 2.a */
719 {
720 node = node->parent;
721 interval_tree_rotate_left (tree, node);
722 }
723 /* case 3.a */
724 node->parent->red = false;
725 node->parent->parent->red = true;
726 interval_tree_rotate_right (tree, node->parent->parent);
727 }
728 }
729 else
730 {
731 /* This is the symmetrical case of above. */
732 struct itree_node *uncle = node->parent->parent->left;
733
734 if (null_safe_is_red (uncle)) /* case 1.b */
735 {
736 node->parent->red = false;
737 uncle->red = false;
738 node->parent->parent->red = true;
739 node = node->parent->parent;
740 }
741 else
742 {
743 if (node == node->parent->left) /* case 2.b */
744 {
745 node = node->parent;
746 interval_tree_rotate_right (tree, node);
747 }
748 /* case 3.b */
749 node->parent->red = false;
750 node->parent->parent->red = true;
751 interval_tree_rotate_left (tree, node->parent->parent);
752 }
753 }
754 }
755
756 /* The root may have been changed to red due to the algorithm.
757 Set it to black so that property #5 is satisfied. */
758 tree->root->red = false;
759 eassert (check_tree (tree, true)); /* FIXME: Too expensive. */
760}
761
762/* Insert a NODE into the TREE.
763 Note, that inserting a node twice results in undefined behaviour. */
764
765static void
766interval_tree_insert (struct itree_tree *tree, struct itree_node *node)
767{
768 eassert (node->begin <= node->end && node != NULL);
769 /* FIXME: The assertion below fails because `delete_all_overlays`
770 doesn't set left/right/parent to NULL. */
771 /* eassert (node->left == NULL && node->right == NULL
772 && node->parent == NULL) */;
773 eassert (check_tree (tree, true)); /* FIXME: Too expensive. */
774
775 struct itree_node *parent = NULL;
776 struct itree_node *child = tree->root;
777 uintmax_t otick = tree->otick;
778 /* It's the responsability of the caller to set `otick` on the node,
779 to "confirm" that the begin/end fields are up to date. */
780 eassert (node->otick == otick);
781
782 /* Find the insertion point, accumulate node's offset and update
783 ancestors limit values. */
784 while (child != NULL)
785 {
786 interval_tree_inherit_offset (otick, child);
787 parent = child;
788 eassert (child->offset == 0);
789 child->limit = max (child->limit, node->end);
790 /* This suggests that nodes in the right subtree are strictly
791 greater. But this is not true due to later rotations. */
792 child = node->begin <= child->begin ? child->left : child->right;
793 }
794
795 /* Insert the node */
796 if (parent == NULL)
797 tree->root = node;
798 else if (node->begin <= parent->begin)
799 parent->left = node;
800 else
801 parent->right = node;
802
803 /* Init the node */
804 node->parent = parent;
805 node->left = NULL;
806 node->right = NULL;
807 node->offset = 0;
808 node->limit = node->end;
809 eassert (node->parent == NULL || node->parent->otick >= node->otick);
810
811 /* Fix/update the tree */
812 ++tree->size;
813 if (node == tree->root)
814 node->red = false;
815 else
816 {
817 node->red = true;
818 eassert (check_tree (tree, false)); /* FIXME: Too expensive. */
819 interval_tree_insert_fix (tree, node);
820 }
821}
822
823void
824itree_insert (struct itree_tree *tree, struct itree_node *node,
825 ptrdiff_t begin, ptrdiff_t end)
826{
827 node->begin = begin;
828 node->end = end;
829 node->otick = tree->otick;
830 interval_tree_insert (tree, node);
831}
832
833/* Safely modify a node's interval. */
834
835void
836itree_node_set_region (struct itree_tree *tree,
837 struct itree_node *node,
838 ptrdiff_t begin, ptrdiff_t end)
839{
840 interval_tree_validate (tree, node);
841 if (begin != node->begin)
842 {
843 itree_remove (tree, node);
844 node->begin = min (begin, PTRDIFF_MAX - 1);
845 node->end = max (node->begin, end);
846 interval_tree_insert (tree, node);
847 }
848 else if (end != node->end)
849 {
850 node->end = max (node->begin, end);
851 eassert (node != NULL);
852 interval_tree_propagate_limit (node);
853 }
854}
855
856/* Return true, if NODE is a member of TREE. */
857
858static bool
859interval_tree_contains (struct itree_tree *tree, struct itree_node *node)
860{
861 eassert (node);
862 struct itree_node *other;
863 ITREE_FOREACH (other, tree, node->begin, PTRDIFF_MAX, ASCENDING)
864 if (other == node)
865 {
866 ITREE_FOREACH_ABORT ();
867 return true;
868 }
869
870 return false;
871}
872
873static bool
874itree_limit_is_stable (struct itree_node *node)
875{
876 if (node == NULL)
877 return true;
878 ptrdiff_t newlimit = itree_newlimit (node);
879 return (newlimit == node->limit);
880}
881
882static struct itree_node*
883interval_tree_subtree_min (uintmax_t otick, struct itree_node *node)
884{
885 if (node == NULL)
886 return node;
887 while ((interval_tree_inherit_offset (otick, node),
888 node->left != NULL))
889 node = node->left;
890 return node;
891}
892
893/* Repair the tree after a deletion.
894 The black-depth of NODE is one less than that of its sibling,
895 so re-balance the parents to re-establish the RB invariants. */
896
897static void
898interval_tree_remove_fix (struct itree_tree *tree,
899 struct itree_node *node,
900 struct itree_node *parent)
901{
902 if (parent == NULL)
903 eassert (node == tree->root);
904 else
905 eassert (node == NULL || node->parent == parent);
906
907 while (parent != NULL && null_safe_is_black (node))
908 {
909 eassert (node == parent->left || node == parent->right);
910
911 if (node == parent->left)
912 {
913 struct itree_node *other = parent->right;
914
915 if (null_safe_is_red (other)) /* case 1.a */
916 {
917 other->red = false;
918 parent->red = true;
919 interval_tree_rotate_left (tree, parent);
920 other = parent->right;
921 }
922 eassume (other != NULL);
923
924 if (null_safe_is_black (other->left) /* 2.a */
925 && null_safe_is_black (other->right))
926 {
927 other->red = true;
928 node = parent;
929 eassert (node != NULL);
930 parent = node->parent;
931 }
932 else
933 {
934 if (null_safe_is_black (other->right)) /* 3.a */
935 {
936 other->left->red = false;
937 other->red = true;
938 interval_tree_rotate_right (tree, other);
939 other = parent->right;
940 }
941 other->red = parent->red; /* 4.a */
942 parent->red = false;
943 other->right->red = false;
944 interval_tree_rotate_left (tree, parent);
945 node = tree->root;
946 parent = NULL;
947 }
948 }
949 else
950 {
951 struct itree_node *other = parent->left;
952
953 if (null_safe_is_red (other)) /* 1.b */
954 {
955 other->red = false;
956 parent->red = true;
957 interval_tree_rotate_right (tree, parent);
958 other = parent->left;
959 }
960 eassume (other != NULL);
961
962 if (null_safe_is_black (other->right) /* 2.b */
963 && null_safe_is_black (other->left))
964 {
965 other->red = true;
966 node = parent;
967 eassert (node != NULL);
968 parent = node->parent;
969 }
970 else
971 {
972 if (null_safe_is_black (other->left)) /* 3.b */
973 {
974 other->right->red = false;
975 other->red = true;
976 interval_tree_rotate_left (tree, other);
977 other = parent->left;
978 }
979
980 other->red = parent->red; /* 4.b */
981 parent->red = false;
982 other->left->red = false;
983 interval_tree_rotate_right (tree, parent);
984 node = tree->root;
985 parent = NULL;
986 }
987 }
988 }
989
990 if (node != NULL)
991 node->red = false;
992}
993
994/* Return accumulated offsets of NODE's parents. */
995static ptrdiff_t
996itree_total_offset (struct itree_node *node)
997{
998 eassert (node != NULL);
999 ptrdiff_t offset = 0;
1000 while (node->parent != NULL)
1001 {
1002 node = node->parent;
1003 offset += node->offset;
1004 }
1005 return offset;
1006}
1007
1008/* Replace DEST with SOURCE as a child of DEST's parent. Adjusts
1009 *only* the parent linkage of SOURCE and either the parent's child
1010 link the tree root.
1011
1012 Warning: DEST is left unmodified. SOURCE's child links are
1013 unchanged. Caller is responsible for recalculation of `limit`.
1014 Requires both nodes to be using the same effective `offset`. */
1015static void
1016interval_tree_replace_child (struct itree_tree *tree,
1017 struct itree_node *source,
1018 struct itree_node *dest)
1019{
1020 eassert (tree && dest != NULL);
1021 eassert (source == NULL
1022 || itree_total_offset (source) == itree_total_offset (dest));
1023
1024 if (dest == tree->root)
1025 tree->root = source;
1026 else if (dest == dest->parent->left)
1027 dest->parent->left = source;
1028 else
1029 dest->parent->right = source;
1030
1031 if (source != NULL)
1032 source->parent = dest->parent;
1033}
1034/* Replace DEST with SOURCE in the tree. Copies the following fields
1035 from DEST to SOURCE: red, parent, left, right. Also updates
1036 parent, left and right in surrounding nodes to point to SOURCE.
1037
1038 Warning: DEST is left unmodified. Caller is responsible for
1039 recalculation of `limit`. Requires both nodes to be using the same
1040 effective `offset`. */
1041static void
1042interval_tree_transplant (struct itree_tree *tree,
1043 struct itree_node *source,
1044 struct itree_node *dest)
1045{
1046 interval_tree_replace_child (tree, source, dest);
1047 source->left = dest->left;
1048 if (source->left != NULL)
1049 source->left->parent = source;
1050 source->right = dest->right;
1051 if (source->right != NULL)
1052 source->right->parent = source;
1053 source->red = dest->red;
1054}
1055
1056/* Remove NODE from TREE and return it. NODE must exist in TREE. */
1057
1058struct itree_node*
1059itree_remove (struct itree_tree *tree, struct itree_node *node)
1060{
1061 eassert (interval_tree_contains (tree, node));
1062 eassert (check_tree (tree, true)); /* FIXME: Too expensive. */
1063
1064 /* Find `splice`, the leaf node to splice out of the tree. When
1065 `node` has at most one child this is `node` itself. Otherwise,
1066 it is the in order successor of `node`. */
1067 interval_tree_inherit_offset (tree->otick, node);
1068 struct itree_node *splice
1069 = (node->left == NULL || node->right == NULL)
1070 ? node
1071 : interval_tree_subtree_min (tree->otick, node->right);
1072
1073 /* Find `subtree`, the only child of `splice` (may be NULL). Note:
1074 `subtree` will not be modified other than changing its parent to
1075 `splice`. */
1076 eassert (splice->left == NULL || splice->right == NULL);
1077 struct itree_node *subtree
1078 = (splice->left != NULL) ? splice->left : splice->right;
1079
1080 /* Save a pointer to the parent of where `subtree` will eventually
1081 be in `subtree_parent`. */
1082 struct itree_node *subtree_parent
1083 = (splice->parent != node) ? splice->parent : splice;
1084
1085 /* If `splice` is black removing it may violate Red-Black
1086 invariants, so note this for later. */
1087
1088 /* Replace `splice` with `subtree` under subtree's parent. If
1089 `splice` is black, this creates a red-red violation, so remember
1090 this now as the field can be overwritten when splice is
1091 transplanted below. */
1092 interval_tree_replace_child (tree, subtree, splice);
1093 bool removed_black = !splice->red;
1094
1095 /* Replace `node` with `splice` in the tree and propagate limit
1096 upwards, if necessary. Note: Limit propagation can stabilize at
1097 any point, so we must call from bottom to top for every node that
1098 has a new child. */
1099 if (splice != node)
1100 {
1101 interval_tree_transplant (tree, splice, node);
1102 interval_tree_propagate_limit (subtree_parent);
1103 if (splice != subtree_parent)
1104 interval_tree_update_limit (splice);
1105 }
1106 interval_tree_propagate_limit (splice->parent);
1107
1108 --tree->size;
1109
1110 /* Fix any black height violation caused by removing a black node. */
1111 if (removed_black)
1112 interval_tree_remove_fix (tree, subtree, subtree_parent);
1113
1114 eassert ((tree->size == 0) == (tree->root == NULL));
1115 eassert (check_tree (tree, true)); /* FIXME: Too expensive. */
1116
1117 /* Clear fields related to the tree for sanity while debugging. */
1118 node->red = false;
1119 node->right = node->left = node->parent = NULL;
1120 node->limit = 0;
1121
1122 /* Must be clean (all offsets applied). Also, some callers rely on
1123 node's otick being the tree's otick. */
1124 eassert (node->otick == tree->otick);
1125 eassert (node->offset == 0);
1126
1127 return node;
1128}
1129
1130bool
1131itree_iterator_busy_p (void)
1132{
1133 return (iter && iter->running);
1134}
1135
1136/* Start a iterator enumerating all intervals in [BEGIN,END) in the
1137 given ORDER. Only one iterator per tree can be running at any time. */
1138
1139struct itree_iterator *
1140itree_iterator_start (struct itree_tree *tree, ptrdiff_t begin,
1141 ptrdiff_t end, enum itree_order order,
1142 const char *file, int line)
1143{
1144 /* struct itree_iterator *iter = tree->iter; */
1145 if (iter->running)
1146 {
1147 fprintf (stderr,
1148 "Detected nested iteration!\nOuter: %s:%d\nInner: %s:%d\n",
1149 iter->file, iter->line, file, line);
1150 emacs_abort ();
1151 }
1152 iter->begin = begin;
1153 iter->end = end;
1154 iter->otick = tree->otick;
1155 iter->order = order;
1156 interval_stack_clear (iter->stack);
1157 if (begin <= end && tree->root != NULL)
1158 interval_stack_push_flagged (iter->stack, tree->root, false);
1159 iter->file = file;
1160 iter->line = line;
1161 iter->running = true;
1162 /* interval_stack_ensure_space (iter->stack,
1163 2 * interval_tree_max_height (tree)); */
1164 return iter;
1165}
1166
1167/* Stop using the iterator. */
1168
1169void
1170itree_iterator_finish (struct itree_iterator *iter)
1171{
1172 eassert (iter->running);
1173 iter->running = false;
1174}
1175
1176
1177/* +=======================================================================+
1178 * | Insert/Delete Gaps
1179 * +=======================================================================+ */
1180
1181/* Insert a gap at POS of length LENGTH expanding all intervals
1182 intersecting it, while respecting their rear_advance and
1183 front_advance setting. */
1184
1185void
1186itree_insert_gap (struct itree_tree *tree,
1187 ptrdiff_t pos, ptrdiff_t length)
1188{
1189 if (length <= 0 || tree->root == NULL)
1190 return;
1191 uintmax_t ootick = tree->otick;
1192
1193 /* FIXME: Don't allocate iterator/stack anew every time. */
1194
1195 /* Nodes with front_advance starting at pos may mess up the tree
1196 order, so we need to remove them first. */
1197 struct interval_stack *saved = interval_stack_create (0);
1198 struct itree_node *node = NULL;
1199 ITREE_FOREACH (node, tree, pos, pos + 1, PRE_ORDER)
1200 {
1201 if (node->begin == pos && node->front_advance
1202 && (node->begin != node->end || node->rear_advance))
1203 interval_stack_push (saved, node);
1204 }
1205 for (int i = 0; i < saved->length; ++i)
1206 itree_remove (tree, nav_nodeptr (saved->nodes[i]));
1207
1208 /* We can't use an iterator here, because we can't effectively
1209 narrow AND shift some subtree at the same time. */
1210 if (tree->root != NULL)
1211 {
1212 const int size = interval_tree_max_height (tree) + 1;
1213 struct interval_stack *stack = interval_stack_create (size);
1214 interval_stack_push (stack, tree->root);
1215 nodeptr_and_flag nav;
1216 while ((nav = interval_stack_pop (stack),
1217 node = nav_nodeptr (nav)))
1218 {
1219 /* Process in pre-order. */
1220 interval_tree_inherit_offset (tree->otick, node);
1221 if (node->right != NULL)
1222 {
1223 if (node->begin > pos)
1224 {
1225 /* All nodes in this subtree are shifted by length. */
1226 node->right->offset += length;
1227 ++tree->otick;
1228 }
1229 else
1230 interval_stack_push (stack, node->right);
1231 }
1232 if (node->left != NULL
1233 && pos <= node->left->limit + node->left->offset)
1234 interval_stack_push (stack, node->left);
1235
1236 /* node->begin == pos implies no front-advance. */
1237 if (node->begin > pos)
1238 node->begin += length;
1239 if (node->end > pos || (node->end == pos && node->rear_advance))
1240 {
1241 node->end += length;
1242 eassert (node != NULL);
1243 interval_tree_propagate_limit (node);
1244 }
1245 }
1246 interval_stack_destroy (stack);
1247 }
1248
1249 /* Reinsert nodes starting at POS having front-advance. */
1250 uintmax_t notick = tree->otick;
1251 nodeptr_and_flag nav;
1252 while ((nav = interval_stack_pop (saved),
1253 node = nav_nodeptr (nav)))
1254 {
1255 eassert (node->otick == ootick);
1256 node->begin += length;
1257 if (node->end != pos || node->rear_advance)
1258 node->end += length;
1259 node->otick = notick;
1260 interval_tree_insert (tree, node);
1261 }
1262
1263 interval_stack_destroy (saved);
1264}
1265
1266/* Delete a gap at POS of length LENGTH, contracting all intervals
1267 intersecting it. */
1268
1269void
1270itree_delete_gap (struct itree_tree *tree,
1271 ptrdiff_t pos, ptrdiff_t length)
1272{
1273 if (length <= 0 || tree->root == NULL)
1274 return;
1275
1276 /* FIXME: Don't allocate stack anew every time. */
1277
1278 /* Can't use the iterator here, because by decrementing begin, we
1279 might unintentionally bring shifted nodes back into our search space. */
1280 const int size = interval_tree_max_height (tree) + 1;
1281 struct interval_stack *stack = interval_stack_create (size);
1282 struct itree_node *node;
1283
1284 interval_stack_push (stack, tree->root);
1285 nodeptr_and_flag nav;
1286 while ((nav = interval_stack_pop (stack)))
1287 {
1288 node = nav_nodeptr (nav);
1289 interval_tree_inherit_offset (tree->otick, node);
1290 if (node->right != NULL)
1291 {
1292 if (node->begin > pos + length)
1293 {
1294 /* Shift right subtree to the left. */
1295 node->right->offset -= length;
1296 ++tree->otick;
1297 }
1298 else
1299 interval_stack_push (stack, node->right);
1300 }
1301 if (node->left != NULL
1302 && pos <= node->left->limit + node->left->offset)
1303 interval_stack_push (stack, node->left);
1304
1305 if (pos < node->begin)
1306 node->begin = max (pos, node->begin - length);
1307 if (node->end > pos)
1308 {
1309 node->end = max (pos , node->end - length);
1310 eassert (node != NULL);
1311 interval_tree_propagate_limit (node);
1312 }
1313 }
1314 interval_stack_destroy (stack);
1315}
1316
1317
1318
1319/* +=======================================================================+
1320 * | Iterator
1321 * +=======================================================================+ */
1322
1323/* Return true, if NODE's interval intersects with [BEGIN, END).
1324 Note: We always include empty nodes at BEGIN (and not at END),
1325 but if BEGIN==END, then we don't include non-empty nodes starting
1326 at BEGIN or ending at END. This seems to match the behavior of the
1327 old overlays code but it's not clear if it's The Right Thing
1328 (e.g. it breaks the expectation that if NODE1 is included, then
1329 a NODE2 strictly bigger than NODE1 should also be included). */
1330
1331static inline bool
1332interval_node_intersects (const struct itree_node *node,
1333 ptrdiff_t begin, ptrdiff_t end)
1334{
1335 return (begin < node->end && node->begin < end)
1336 || (node->begin == node->end && begin == node->begin);
1337}
1338
1339/* Return the next node of the iterator in the order given when it was
1340 started; or NULL if there are no more nodes. */
1341
1342struct itree_node *
1343itree_iterator_next (struct itree_iterator *g)
1344{
1345 eassert (g->running);
1346
1347 struct itree_node * const null = NULL;
1348 struct itree_node *node;
1349
1350 /* The `visited` flag stored in each node is used here (and only here):
1351 We keep a "workstack" of nodes we need to consider. This stack
1352 consist of nodes of two types: nodes that we have decided
1353 should be returned by the iterator, and nodes which we may
1354 need to consider (including checking their children).
1355 We start an iteration with a stack containing just the root
1356 node marked as "not visited" which means that it (and its children)
1357 needs to be considered but we haven't yet decided whether it's included
1358 in the iterator's output. */
1359
1360 do {
1361 nodeptr_and_flag nav;
1362 bool visited;
1363 while ((nav = interval_stack_pop (g->stack),
1364 node = nav_nodeptr (nav),
1365 visited = nav_flag (nav),
1366 node && !visited))
1367 {
1368 struct itree_node * const left = node->left;
1369 struct itree_node * const right = node->right;
1370
1371 interval_tree_inherit_offset (g->otick, node);
1372 eassert (itree_limit_is_stable (node));
1373 switch (g->order)
1374 {
1375 case ITREE_ASCENDING:
1376 if (right != null && node->begin <= g->end)
1377 interval_stack_push_flagged (g->stack, right, false);
1378 if (interval_node_intersects (node, g->begin, g->end))
1379 interval_stack_push_flagged (g->stack, node, true);
1380 /* Node's children may still be off-set and we need to add it. */
1381 if (left != null && g->begin <= left->limit + left->offset)
1382 interval_stack_push_flagged (g->stack, left, false);
1383 break;
1384 case ITREE_DESCENDING:
1385 if (left != null && g->begin <= left->limit + left->offset)
1386 interval_stack_push_flagged (g->stack, left, false);
1387 if (interval_node_intersects (node, g->begin, g->end))
1388 interval_stack_push_flagged (g->stack, node, true);
1389 if (right != null && node->begin <= g->end)
1390 interval_stack_push_flagged (g->stack, right, false);
1391 break;
1392 case ITREE_PRE_ORDER:
1393 if (right != null && node->begin <= g->end)
1394 interval_stack_push_flagged (g->stack, right, false);
1395 if (left != null && g->begin <= left->limit + left->offset)
1396 interval_stack_push_flagged (g->stack, left, false);
1397 if (interval_node_intersects (node, g->begin, g->end))
1398 interval_stack_push_flagged (g->stack, node, true);
1399 break;
1400 }
1401 }
1402 /* Node may have been invalidated by itree_iterator_narrow
1403 after it was pushed: Check if it still intersects. */
1404 } while (node && ! interval_node_intersects (node, g->begin, g->end));
1405
1406 return node;
1407}
1408
1409/* Limit G to the new interval [BEGIN, END), which must be a subset of
1410 the current one. I.E. it can't grow on either side. */
1411
1412void
1413itree_iterator_narrow (struct itree_iterator *g,
1414 ptrdiff_t begin, ptrdiff_t end)
1415{
1416 eassert (g->running);
1417 eassert (begin >= g->begin);
1418 eassert (end <= g->end);
1419 g->begin = max (begin, g->begin);
1420 g->end = min (end, g->end);
1421}
diff --git a/src/itree.h b/src/itree.h
new file mode 100644
index 00000000000..3df07ac1b7e
--- /dev/null
+++ b/src/itree.h
@@ -0,0 +1,181 @@
1/* This file implements an efficient interval data-structure.
2
3Copyright (C) 2017-2022 Free Software Foundation, Inc.
4
5This file is 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#include "lisp.h"
27
28/* The tree and node structs are mainly here, so they can be
29 allocated.
30
31 NOTE: The only time where it is safe to modify node.begin and
32 node.end directly, is while the node is not part of any tree.
33
34 NOTE: It is safe to read node.begin and node.end directly, if the
35 node came from an iterator, because it validates the nodes it
36 returns as a side-effect. See ITREE_FOREACH.
37 */
38
39struct itree_node
40{
41 /* The normal parent, left and right links found in binary trees.
42 See also `red`, below, which completes the Red-Black tree
43 representation. */
44 struct itree_node *parent;
45 struct itree_node *left;
46 struct itree_node *right;
47
48 /* The following five fields comprise the interval abstraction.
49
50 BEGIN, END are buffer positions describing the range. When a
51 node is in a tree these fields are read only, written only by
52 itree functions.
53
54 The LIMIT, OFFSET and OTICK fields should be considered internal
55 to itree.c and used only by itree functions.
56
57 LIMIT is a buffer position, the maximum of END of this node and
58 its children. See itree.c for its use.
59
60 OFFSET is in buffer position units, and will be non-zero only
61 when the node is dirty.
62
63 OTICK determines whether BEGIN, END, LIMIT and OFFSET are
64 considered dirty. A node is clean when its OTICK is equal to the
65 OTICK of its tree (see struct itree_tree). Otherwise, it is
66 dirty.
67
68 In a clean node, BEGIN, END and LIMIT are correct buffer
69 positions, and OFFSET is zero. The parent of a clean node is
70 also clean, recursively.
71
72 In a dirty node, the node's OTICK won't equal its tree's OTICK,
73 and its OFFSET may be non-zero. At all times the descendents of
74 a dirty node are also dirty. BEGIN, END and LIMIT require
75 adjustment before use as buffer positions.
76
77 NOTE: BEGIN and END must not be modified while the node is part
78 of a tree. Use itree_insert_gap and itree_delete_gap instead.
79
80 NOTE: The interval iterators ensure nodes are clean before
81 yielding them, so BEGIN and END may be safely used as buffer
82 positions then.
83 */
84
85 ptrdiff_t begin; /* The beginning of this interval. */
86 ptrdiff_t end; /* The end of the interval. */
87 ptrdiff_t limit; /* The maximum end in this subtree. */
88 ptrdiff_t offset; /* The amount of shift to apply to this subtree. */
89 uintmax_t otick; /* offset modified tick */
90 Lisp_Object data; /* Exclusively used by the client. */
91 bool_bf red : 1;
92 bool_bf rear_advance : 1; /* Same as for marker and overlays. */
93 bool_bf front_advance : 1; /* Same as for marker and overlays. */
94};
95
96struct itree_tree
97{
98 struct itree_node *root;
99 uintmax_t otick; /* offset tick, compared with node's otick. */
100 intmax_t size; /* Number of nodes in the tree. */
101};
102
103enum itree_order {
104 ITREE_ASCENDING,
105 ITREE_DESCENDING,
106 ITREE_PRE_ORDER,
107};
108
109void itree_node_init (struct itree_node *, bool, bool, Lisp_Object);
110ptrdiff_t itree_node_begin (struct itree_tree *, struct itree_node *);
111ptrdiff_t itree_node_end (struct itree_tree *, struct itree_node *);
112void itree_node_set_region (struct itree_tree *, struct itree_node *,
113 ptrdiff_t, ptrdiff_t);
114struct itree_tree *itree_create (void);
115void itree_destroy (struct itree_tree *);
116intmax_t itree_size (struct itree_tree *);
117void itree_clear (struct itree_tree *);
118void itree_insert (struct itree_tree *tree, struct itree_node *node,
119 ptrdiff_t begin, ptrdiff_t end);
120struct itree_node *itree_remove (struct itree_tree *,
121 struct itree_node *);
122void itree_insert_gap (struct itree_tree *, ptrdiff_t, ptrdiff_t);
123void itree_delete_gap (struct itree_tree *, ptrdiff_t, ptrdiff_t);
124
125/* Iteration functions. Almost all code should use ITREE_FOREACH
126 instead. */
127bool itree_iterator_busy_p (void);
128struct itree_iterator *
129itree_iterator_start (struct itree_tree *tree, ptrdiff_t begin,
130 ptrdiff_t end, enum itree_order order,
131 const char *file, int line);
132void itree_iterator_narrow (struct itree_iterator *, ptrdiff_t,
133 ptrdiff_t);
134void itree_iterator_finish (struct itree_iterator *);
135struct itree_node *itree_iterator_next (struct itree_iterator *);
136
137/* Iterate over the intervals between BEG and END in the tree T.
138 N will hold successive nodes. ORDER can be one of : `ASCENDING`,
139 `DESCENDING`, or `PRE_ORDER`.
140 It should be used as:
141
142 ITREE_FOREACH (n, t, beg, end, order)
143 {
144 .. do the thing with n ..
145 }
146
147 BEWARE:
148 - The expression T may be evaluated more than once, so make sure
149 it is cheap a pure.
150 - Only a single iteration can happen at a time, so make sure none of the
151 code within the loop can start another tree iteration, i.e. it shouldn't
152 be able to run ELisp code, nor GC since GC can run ELisp by way
153 of `post-gc-hook`.
154 - If you need to exit the loop early, you *have* to call `ITREE_ABORT`
155 just before exiting (e.g. with `break` or `return`).
156 - Non-local exits are not supported within the body of the loop.
157 - Don't modify the tree during the iteration.
158 */
159#define ITREE_FOREACH(n, t, beg, end, order) \
160 /* FIXME: We'd want to declare `x` right here, but I can't figure out
161 how to make that work here: the `for` syntax only allows a single
162 clause for the var declarations where we need 2 different types.
163 We could use the `struct {foo x; bar y; } p;` trick to declare two
164 vars `p.x` and `p.y` of unrelated types, but then none of the names
165 of the vars matches the `n` we receive :-(. */ \
166 if (!t) \
167 { } \
168 else \
169 for (struct itree_iterator *itree_iter_ \
170 = itree_iterator_start (t, beg, end, ITREE_##order, \
171 __FILE__, __LINE__); \
172 ((n = itree_iterator_next (itree_iter_)) \
173 || (itree_iterator_finish (itree_iter_), false));)
174
175#define ITREE_FOREACH_ABORT() \
176 itree_iterator_finish (itree_iter_)
177
178#define ITREE_FOREACH_NARROW(beg, end) \
179 itree_iterator_narrow (itree_iter_, beg, end)
180
181#endif
diff --git a/src/keyboard.c b/src/keyboard.c
index b9a08ab91bf..a978d6f02b3 100644
--- a/src/keyboard.c
+++ b/src/keyboard.c
@@ -1695,8 +1695,8 @@ adjust_point_for_property (ptrdiff_t last_pt, bool modified)
1695 && display_prop_intangible_p (val, overlay, PT, PT_BYTE) 1695 && display_prop_intangible_p (val, overlay, PT, PT_BYTE)
1696 && (!OVERLAYP (overlay) 1696 && (!OVERLAYP (overlay)
1697 ? get_property_and_range (PT, Qdisplay, &val, &beg, &end, Qnil) 1697 ? get_property_and_range (PT, Qdisplay, &val, &beg, &end, Qnil)
1698 : (beg = OVERLAY_POSITION (OVERLAY_START (overlay)), 1698 : (beg = OVERLAY_START (overlay),
1699 end = OVERLAY_POSITION (OVERLAY_END (overlay)))) 1699 end = OVERLAY_END (overlay)))
1700 && (beg < PT /* && end > PT <- It's always the case. */ 1700 && (beg < PT /* && end > PT <- It's always the case. */
1701 || (beg <= PT && STRINGP (val) && SCHARS (val) == 0))) 1701 || (beg <= PT && STRINGP (val) && SCHARS (val) == 0)))
1702 { 1702 {
diff --git a/src/lisp.h b/src/lisp.h
index 1eed323133a..4701dfa868d 100644
--- a/src/lisp.h
+++ b/src/lisp.h
@@ -1,7 +1,6 @@
1/* Fundamental definitions for GNU Emacs Lisp interpreter. -*- coding: utf-8 -*- 1/* Fundamental definitions for GNU Emacs Lisp interpreter. -*- coding: utf-8 -*-
2 2
3Copyright (C) 1985-1987, 1993-1995, 1997-2022 Free Software Foundation, 3Copyright (C) 1985-2022 Free Software Foundation, Inc.
4Inc.
5 4
6This file is part of GNU Emacs. 5This file is part of GNU Emacs.
7 6
@@ -2606,10 +2605,9 @@ struct Lisp_Overlay
2606*/ 2605*/
2607 { 2606 {
2608 union vectorlike_header header; 2607 union vectorlike_header header;
2609 Lisp_Object start;
2610 Lisp_Object end;
2611 Lisp_Object plist; 2608 Lisp_Object plist;
2612 struct Lisp_Overlay *next; 2609 struct buffer *buffer; /* eassert (live buffer || NULL). */
2610 struct itree_node *interval;
2613 } GCALIGNED_STRUCT; 2611 } GCALIGNED_STRUCT;
2614 2612
2615struct Lisp_Misc_Ptr 2613struct Lisp_Misc_Ptr
@@ -4420,7 +4418,6 @@ extern Lisp_Object make_float (double);
4420extern void display_malloc_warning (void); 4418extern void display_malloc_warning (void);
4421extern specpdl_ref inhibit_garbage_collection (void); 4419extern specpdl_ref inhibit_garbage_collection (void);
4422extern Lisp_Object build_symbol_with_pos (Lisp_Object, Lisp_Object); 4420extern Lisp_Object build_symbol_with_pos (Lisp_Object, Lisp_Object);
4423extern Lisp_Object build_overlay (Lisp_Object, Lisp_Object, Lisp_Object);
4424extern void free_cons (struct Lisp_Cons *); 4421extern void free_cons (struct Lisp_Cons *);
4425extern void init_alloc_once (void); 4422extern void init_alloc_once (void);
4426extern void init_alloc (void); 4423extern void init_alloc (void);
diff --git a/src/pdumper.c b/src/pdumper.c
index 5e6ccd9bd88..d6ae57afb2e 100644
--- a/src/pdumper.c
+++ b/src/pdumper.c
@@ -2134,16 +2134,63 @@ dump_marker (struct dump_context *ctx, const struct Lisp_Marker *marker)
2134} 2134}
2135 2135
2136static dump_off 2136static dump_off
2137dump_interval_node (struct dump_context *ctx, struct itree_node *node,
2138 dump_off parent_offset)
2139{
2140#if CHECK_STRUCTS && !defined (HASH_interval_node_5765524F7E)
2141# error "interval_node changed. See CHECK_STRUCTS comment in config.h."
2142#endif
2143 struct itree_node out;
2144 dump_object_start (ctx, &out, sizeof (out));
2145 if (node->parent)
2146 dump_field_fixup_later (ctx, &out, node, &node->parent);
2147 if (node->left)
2148 dump_field_fixup_later (ctx, &out, node, &node->parent);
2149 if (node->right)
2150 dump_field_fixup_later (ctx, &out, node, &node->parent);
2151 DUMP_FIELD_COPY (&out, node, begin);
2152 DUMP_FIELD_COPY (&out, node, end);
2153 DUMP_FIELD_COPY (&out, node, limit);
2154 DUMP_FIELD_COPY (&out, node, offset);
2155 DUMP_FIELD_COPY (&out, node, otick);
2156 dump_field_lv (ctx, &out, node, &node->data, WEIGHT_STRONG);
2157 DUMP_FIELD_COPY (&out, node, red);
2158 DUMP_FIELD_COPY (&out, node, rear_advance);
2159 DUMP_FIELD_COPY (&out, node, front_advance);
2160 dump_off offset = dump_object_finish (ctx, &out, sizeof (out));
2161 if (node->parent)
2162 dump_remember_fixup_ptr_raw
2163 (ctx,
2164 offset + dump_offsetof (struct itree_node, parent),
2165 dump_interval_node (ctx, node->parent, offset));
2166 if (node->left)
2167 dump_remember_fixup_ptr_raw
2168 (ctx,
2169 offset + dump_offsetof (struct itree_node, left),
2170 dump_interval_node (ctx, node->left, offset));
2171 if (node->right)
2172 dump_remember_fixup_ptr_raw
2173 (ctx,
2174 offset + dump_offsetof (struct itree_node, right),
2175 dump_interval_node (ctx, node->right, offset));
2176 return offset;
2177}
2178
2179static dump_off
2137dump_overlay (struct dump_context *ctx, const struct Lisp_Overlay *overlay) 2180dump_overlay (struct dump_context *ctx, const struct Lisp_Overlay *overlay)
2138{ 2181{
2139#if CHECK_STRUCTS && !defined (HASH_Lisp_Overlay_72EADA9882) 2182#if CHECK_STRUCTS && !defined (HASH_Lisp_Overlay_1CD4249AEC)
2140# error "Lisp_Overlay changed. See CHECK_STRUCTS comment in config.h." 2183# error "Lisp_Overlay changed. See CHECK_STRUCTS comment in config.h."
2141#endif 2184#endif
2142 START_DUMP_PVEC (ctx, &overlay->header, struct Lisp_Overlay, out); 2185 START_DUMP_PVEC (ctx, &overlay->header, struct Lisp_Overlay, out);
2143 dump_pseudovector_lisp_fields (ctx, &out->header, &overlay->header); 2186 dump_pseudovector_lisp_fields (ctx, &out->header, &overlay->header);
2144 dump_field_lv_rawptr (ctx, out, overlay, &overlay->next, 2187 dump_field_fixup_later (ctx, &out, overlay, &overlay->interval);
2145 Lisp_Vectorlike, WEIGHT_STRONG); 2188 dump_off offset = finish_dump_pvec (ctx, &out->header);
2146 return finish_dump_pvec (ctx, &out->header); 2189 dump_remember_fixup_ptr_raw
2190 (ctx,
2191 offset + dump_offsetof (struct Lisp_Overlay, interval),
2192 dump_interval_node (ctx, overlay->interval, offset));
2193 return offset;
2147} 2194}
2148 2195
2149static void 2196static void
@@ -2701,7 +2748,7 @@ dump_hash_table (struct dump_context *ctx,
2701static dump_off 2748static dump_off
2702dump_buffer (struct dump_context *ctx, const struct buffer *in_buffer) 2749dump_buffer (struct dump_context *ctx, const struct buffer *in_buffer)
2703{ 2750{
2704#if CHECK_STRUCTS && !defined HASH_buffer_AA373AEE10 2751#if CHECK_STRUCTS && !defined HASH_buffer_F0F08347A5
2705# error "buffer changed. See CHECK_STRUCTS comment in config.h." 2752# error "buffer changed. See CHECK_STRUCTS comment in config.h."
2706#endif 2753#endif
2707 struct buffer munged_buffer = *in_buffer; 2754 struct buffer munged_buffer = *in_buffer;
@@ -2816,13 +2863,12 @@ dump_buffer (struct dump_context *ctx, const struct buffer *in_buffer)
2816 DUMP_FIELD_COPY (out, buffer, inhibit_buffer_hooks); 2863 DUMP_FIELD_COPY (out, buffer, inhibit_buffer_hooks);
2817 DUMP_FIELD_COPY (out, buffer, long_line_optimizations_p); 2864 DUMP_FIELD_COPY (out, buffer, long_line_optimizations_p);
2818 2865
2819 dump_field_lv_rawptr (ctx, out, buffer, &buffer->overlays_before, 2866 if (buffer->overlays && buffer->overlays->root != NULL)
2820 Lisp_Vectorlike, WEIGHT_NORMAL); 2867 /* We haven't implemented the code to dump overlays. */
2821 2868 emacs_abort ();
2822 dump_field_lv_rawptr (ctx, out, buffer, &buffer->overlays_after, 2869 else
2823 Lisp_Vectorlike, WEIGHT_NORMAL); 2870 out->overlays = NULL;
2824 2871
2825 DUMP_FIELD_COPY (out, buffer, overlay_center);
2826 dump_field_lv (ctx, out, buffer, &buffer->undo_list_, 2872 dump_field_lv (ctx, out, buffer, &buffer->undo_list_,
2827 WEIGHT_STRONG); 2873 WEIGHT_STRONG);
2828 dump_off offset = finish_dump_pvec (ctx, &out->header); 2874 dump_off offset = finish_dump_pvec (ctx, &out->header);
diff --git a/src/print.c b/src/print.c
index 1c96ec14b86..65218084a4c 100644
--- a/src/print.c
+++ b/src/print.c
@@ -1,7 +1,6 @@
1/* Lisp object printing and output streams. 1/* Lisp object printing and output streams.
2 2
3Copyright (C) 1985-1986, 1988, 1993-1995, 1997-2022 Free Software 3Copyright (C) 1985-2022 Free Software Foundation, Inc.
4Foundation, Inc.
5 4
6This file is part of GNU Emacs. 5This file is part of GNU Emacs.
7 6
@@ -594,8 +593,7 @@ temp_output_buffer_setup (const char *bufname)
594 bset_read_only (current_buffer, Qnil); 593 bset_read_only (current_buffer, Qnil);
595 bset_filename (current_buffer, Qnil); 594 bset_filename (current_buffer, Qnil);
596 bset_undo_list (current_buffer, Qt); 595 bset_undo_list (current_buffer, Qt);
597 eassert (current_buffer->overlays_before == NULL); 596 eassert (current_buffer->overlays == NULL);
598 eassert (current_buffer->overlays_after == NULL);
599 bset_enable_multibyte_characters 597 bset_enable_multibyte_characters
600 (current_buffer, BVAR (&buffer_defaults, enable_multibyte_characters)); 598 (current_buffer, BVAR (&buffer_defaults, enable_multibyte_characters));
601 specbind (Qinhibit_read_only, Qt); 599 specbind (Qinhibit_read_only, Qt);
@@ -1745,15 +1743,15 @@ print_vectorlike (Lisp_Object obj, Lisp_Object printcharfun, bool escapeflag,
1745 1743
1746 case PVEC_OVERLAY: 1744 case PVEC_OVERLAY:
1747 print_c_string ("#<overlay ", printcharfun); 1745 print_c_string ("#<overlay ", printcharfun);
1748 if (! XMARKER (OVERLAY_START (obj))->buffer) 1746 if (! OVERLAY_BUFFER (obj))
1749 print_c_string ("in no buffer", printcharfun); 1747 print_c_string ("in no buffer", printcharfun);
1750 else 1748 else
1751 { 1749 {
1752 int len = sprintf (buf, "from %"pD"d to %"pD"d in ", 1750 int len = sprintf (buf, "from %"pD"d to %"pD"d in ",
1753 marker_position (OVERLAY_START (obj)), 1751 OVERLAY_START (obj),
1754 marker_position (OVERLAY_END (obj))); 1752 OVERLAY_END (obj));
1755 strout (buf, len, len, printcharfun); 1753 strout (buf, len, len, printcharfun);
1756 print_string (BVAR (XMARKER (OVERLAY_START (obj))->buffer, name), 1754 print_string (BVAR (OVERLAY_BUFFER (obj), name),
1757 printcharfun); 1755 printcharfun);
1758 } 1756 }
1759 printchar ('>', printcharfun); 1757 printchar ('>', printcharfun);
diff --git a/src/textprop.c b/src/textprop.c
index c22b579af22..ca693fd6800 100644
--- a/src/textprop.c
+++ b/src/textprop.c
@@ -1,6 +1,5 @@
1/* Interface code for dealing with text properties. 1/* Interface code for dealing with text properties.
2 Copyright (C) 1993-1995, 1997, 1999-2022 Free Software Foundation, 2 Copyright (C) 1993-2022 Free Software Foundation, Inc.
3 Inc.
4 3
5This file is part of GNU Emacs. 4This file is part of GNU Emacs.
6 5
@@ -634,36 +633,40 @@ get_char_property_and_overlay (Lisp_Object position, register Lisp_Object prop,
634 } 633 }
635 if (BUFFERP (object)) 634 if (BUFFERP (object))
636 { 635 {
637 ptrdiff_t noverlays; 636 struct buffer *b = XBUFFER (object);
638 Lisp_Object *overlay_vec; 637 struct itree_node *node;
639 struct buffer *obuf = current_buffer; 638 struct sortvec items[2];
640 639 struct sortvec *result = NULL;
641 if (! (BUF_BEGV (XBUFFER (object)) <= pos 640 Lisp_Object result_tem = Qnil;
642 && pos <= BUF_ZV (XBUFFER (object)))) 641
642 if (! (BUF_BEGV (b) <= pos
643 && pos <= BUF_ZV (b)))
643 xsignal1 (Qargs_out_of_range, position); 644 xsignal1 (Qargs_out_of_range, position);
644 645
645 set_buffer_temp (XBUFFER (object));
646
647 USE_SAFE_ALLOCA;
648 GET_OVERLAYS_AT (pos, overlay_vec, noverlays, NULL, false);
649 noverlays = sort_overlays (overlay_vec, noverlays, w);
650
651 set_buffer_temp (obuf);
652
653 /* Now check the overlays in order of decreasing priority. */ 646 /* Now check the overlays in order of decreasing priority. */
654 while (--noverlays >= 0) 647 ITREE_FOREACH (node, b->overlays, pos, pos + 1, ASCENDING)
655 { 648 {
656 Lisp_Object tem = Foverlay_get (overlay_vec[noverlays], prop); 649 Lisp_Object tem = Foverlay_get (node->data, prop);
657 if (!NILP (tem)) 650 struct sortvec *this;
658 { 651
659 if (overlay) 652 if (NILP (tem) || node->end < pos + 1
660 /* Return the overlay we got the property from. */ 653 || (w && ! overlay_matches_window (w, node->data)))
661 *overlay = overlay_vec[noverlays]; 654 continue;
662 SAFE_FREE (); 655
663 return tem; 656 this = (result == items ? items + 1 : items);
664 } 657 make_sortvec_item (this, node->data);
658 if (! result || (compare_overlays (result, this) < 0))
659 {
660 result = this;
661 result_tem = tem;
662 }
665 } 663 }
666 SAFE_FREE (); 664 if (result)
665 {
666 if (overlay)
667 *overlay = result->overlay;
668 return result_tem;
669 }
667 } 670 }
668 671
669 if (overlay) 672 if (overlay)
diff --git a/src/window.h b/src/window.h
index 93817a95445..b5d0c69ab52 100644
--- a/src/window.h
+++ b/src/window.h
@@ -1212,6 +1212,16 @@ output_cursor_to (struct window *w, int vpos, int hpos, int y, int x)
1212 w->output_cursor.y = y; 1212 w->output_cursor.y = y;
1213} 1213}
1214 1214
1215/* Return true, if overlay OV's properties should have an effect in
1216 window W. */
1217INLINE bool
1218overlay_matches_window (const struct window *w, Lisp_Object ov)
1219{
1220 eassert (OVERLAYP (ov));
1221 Lisp_Object window = Foverlay_get (ov, Qwindow);
1222 return (! WINDOWP (window) || XWINDOW (window) == w);
1223}
1224
1215INLINE_HEADER_END 1225INLINE_HEADER_END
1216 1226
1217#endif /* not WINDOW_H_INCLUDED */ 1227#endif /* not WINDOW_H_INCLUDED */
diff --git a/src/xdisp.c b/src/xdisp.c
index 32675cd76ac..dd243eca986 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -1,7 +1,6 @@
1/* Display generation from window structure and buffer text. 1/* Display generation from window structure and buffer text.
2 2
3Copyright (C) 1985-1988, 1993-1995, 1997-2022 Free Software Foundation, 3Copyright (C) 1985-2022 Free Software Foundation, Inc.
4Inc.
5 4
6This file is part of GNU Emacs. 5This file is part of GNU Emacs.
7 6
@@ -1159,7 +1158,6 @@ static enum move_it_result
1159static void get_visually_first_element (struct it *); 1158static void get_visually_first_element (struct it *);
1160static void compute_stop_pos (struct it *); 1159static void compute_stop_pos (struct it *);
1161static int face_before_or_after_it_pos (struct it *, bool); 1160static int face_before_or_after_it_pos (struct it *, bool);
1162static ptrdiff_t next_overlay_change (ptrdiff_t);
1163static int handle_display_spec (struct it *, Lisp_Object, Lisp_Object, 1161static int handle_display_spec (struct it *, Lisp_Object, Lisp_Object,
1164 Lisp_Object, struct text_pos *, ptrdiff_t, bool); 1162 Lisp_Object, struct text_pos *, ptrdiff_t, bool);
1165static int handle_single_display_spec (struct it *, Lisp_Object, Lisp_Object, 1163static int handle_single_display_spec (struct it *, Lisp_Object, Lisp_Object,
@@ -4168,39 +4166,6 @@ compute_stop_pos (struct it *it)
4168 && it->stop_charpos >= IT_CHARPOS (*it))); 4166 && it->stop_charpos >= IT_CHARPOS (*it)));
4169} 4167}
4170 4168
4171
4172/* Return the position of the next overlay change after POS in
4173 current_buffer. Value is point-max if no overlay change
4174 follows. This is like `next-overlay-change' but doesn't use
4175 xmalloc. */
4176
4177static ptrdiff_t
4178next_overlay_change (ptrdiff_t pos)
4179{
4180 ptrdiff_t i, noverlays;
4181 ptrdiff_t endpos;
4182 Lisp_Object *overlays;
4183 USE_SAFE_ALLOCA;
4184
4185 /* Get all overlays at the given position. */
4186 GET_OVERLAYS_AT (pos, overlays, noverlays, &endpos, true);
4187
4188 /* If any of these overlays ends before endpos,
4189 use its ending point instead. */
4190 for (i = 0; i < noverlays; ++i)
4191 {
4192 Lisp_Object oend;
4193 ptrdiff_t oendpos;
4194
4195 oend = OVERLAY_END (overlays[i]);
4196 oendpos = OVERLAY_POSITION (oend);
4197 endpos = min (endpos, oendpos);
4198 }
4199
4200 SAFE_FREE ();
4201 return endpos;
4202}
4203
4204/* How many characters forward to search for a display property or 4169/* How many characters forward to search for a display property or
4205 display string. Searching too far forward makes the bidi display 4170 display string. Searching too far forward makes the bidi display
4206 sluggish, especially in small windows. */ 4171 sluggish, especially in small windows. */
@@ -5838,7 +5803,7 @@ handle_single_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object,
5838 overlay's display string/image twice. */ 5803 overlay's display string/image twice. */
5839 if (!NILP (overlay)) 5804 if (!NILP (overlay))
5840 { 5805 {
5841 ptrdiff_t ovendpos = OVERLAY_POSITION (OVERLAY_END (overlay)); 5806 ptrdiff_t ovendpos = OVERLAY_END (overlay);
5842 5807
5843 /* Some borderline-sane Lisp might call us with the current 5808 /* Some borderline-sane Lisp might call us with the current
5844 buffer narrowed so that overlay-end is outside the 5809 buffer narrowed so that overlay-end is outside the
@@ -6572,6 +6537,8 @@ load_overlay_strings (struct it *it, ptrdiff_t charpos)
6572 struct overlay_entry entriesbuf[20]; 6537 struct overlay_entry entriesbuf[20];
6573 ptrdiff_t size = ARRAYELTS (entriesbuf); 6538 ptrdiff_t size = ARRAYELTS (entriesbuf);
6574 struct overlay_entry *entries = entriesbuf; 6539 struct overlay_entry *entries = entriesbuf;
6540 struct itree_node *node;
6541
6575 USE_SAFE_ALLOCA; 6542 USE_SAFE_ALLOCA;
6576 6543
6577 if (charpos <= 0) 6544 if (charpos <= 0)
@@ -6603,27 +6570,24 @@ load_overlay_strings (struct it *it, ptrdiff_t charpos)
6603 } \ 6570 } \
6604 while (false) 6571 while (false)
6605 6572
6606 /* Process overlay before the overlay center. */ 6573
6607 for (struct Lisp_Overlay *ov = current_buffer->overlays_before; 6574 /* Process overlays. */
6608 ov; ov = ov->next) 6575 ITREE_FOREACH (node, current_buffer->overlays, charpos - 1, charpos + 1, DESCENDING)
6609 { 6576 {
6610 Lisp_Object overlay = make_lisp_ptr (ov, Lisp_Vectorlike); 6577 Lisp_Object overlay = node->data;
6611 eassert (OVERLAYP (overlay)); 6578 eassert (OVERLAYP (overlay));
6612 ptrdiff_t start = OVERLAY_POSITION (OVERLAY_START (overlay)); 6579 ptrdiff_t start = node->begin;
6613 ptrdiff_t end = OVERLAY_POSITION (OVERLAY_END (overlay)); 6580 ptrdiff_t end = node->end;
6614
6615 if (end < charpos)
6616 break;
6617 6581
6618 /* Skip this overlay if it doesn't start or end at IT's current 6582 /* Skip this overlay if it doesn't start or end at IT's current
6619 position. */ 6583 position. */
6620 if (end != charpos && start != charpos) 6584 if (end != charpos && start != charpos)
6621 continue; 6585 continue;
6622 6586
6623 /* Skip this overlay if it doesn't apply to IT->w. */ 6587 /* Skip this overlay if it doesn't apply to IT->w. */
6624 Lisp_Object window = Foverlay_get (overlay, Qwindow); 6588 Lisp_Object window = Foverlay_get (overlay, Qwindow);
6625 if (WINDOWP (window) && XWINDOW (window) != it->w) 6589 if (WINDOWP (window) && XWINDOW (window) != it->w)
6626 continue; 6590 continue;
6627 6591
6628 /* If the text ``under'' the overlay is invisible, both before- 6592 /* If the text ``under'' the overlay is invisible, both before-
6629 and after-strings from this overlay are visible; start and 6593 and after-strings from this overlay are visible; start and
@@ -6634,56 +6598,15 @@ load_overlay_strings (struct it *it, ptrdiff_t charpos)
6634 /* If overlay has a non-empty before-string, record it. */ 6598 /* If overlay has a non-empty before-string, record it. */
6635 Lisp_Object str; 6599 Lisp_Object str;
6636 if ((start == charpos || (end == charpos && invis != 0)) 6600 if ((start == charpos || (end == charpos && invis != 0))
6637 && (str = Foverlay_get (overlay, Qbefore_string), STRINGP (str)) 6601 && (str = Foverlay_get (overlay, Qbefore_string), STRINGP (str))
6638 && SCHARS (str)) 6602 && SCHARS (str))
6639 RECORD_OVERLAY_STRING (overlay, str, false); 6603 RECORD_OVERLAY_STRING (overlay, str, false);
6640
6641 /* If overlay has a non-empty after-string, record it. */
6642 if ((end == charpos || (start == charpos && invis != 0))
6643 && (str = Foverlay_get (overlay, Qafter_string), STRINGP (str))
6644 && SCHARS (str))
6645 RECORD_OVERLAY_STRING (overlay, str, true);
6646 }
6647
6648 /* Process overlays after the overlay center. */
6649 for (struct Lisp_Overlay *ov = current_buffer->overlays_after;
6650 ov; ov = ov->next)
6651 {
6652 Lisp_Object overlay = make_lisp_ptr (ov, Lisp_Vectorlike);
6653 eassert (OVERLAYP (overlay));
6654 ptrdiff_t start = OVERLAY_POSITION (OVERLAY_START (overlay));
6655 ptrdiff_t end = OVERLAY_POSITION (OVERLAY_END (overlay));
6656
6657 if (start > charpos)
6658 break;
6659
6660 /* Skip this overlay if it doesn't start or end at IT's current
6661 position. */
6662 if (end != charpos && start != charpos)
6663 continue;
6664
6665 /* Skip this overlay if it doesn't apply to IT->w. */
6666 Lisp_Object window = Foverlay_get (overlay, Qwindow);
6667 if (WINDOWP (window) && XWINDOW (window) != it->w)
6668 continue;
6669
6670 /* If the text ``under'' the overlay is invisible, it has a zero
6671 dimension, and both before- and after-strings apply. */
6672 Lisp_Object invisible = Foverlay_get (overlay, Qinvisible);
6673 int invis = TEXT_PROP_MEANS_INVISIBLE (invisible);
6674
6675 /* If overlay has a non-empty before-string, record it. */
6676 Lisp_Object str;
6677 if ((start == charpos || (end == charpos && invis != 0))
6678 && (str = Foverlay_get (overlay, Qbefore_string), STRINGP (str))
6679 && SCHARS (str))
6680 RECORD_OVERLAY_STRING (overlay, str, false);
6681 6604
6682 /* If overlay has a non-empty after-string, record it. */ 6605 /* If overlay has a non-empty after-string, record it. */
6683 if ((end == charpos || (start == charpos && invis != 0)) 6606 if ((end == charpos || (start == charpos && invis != 0))
6684 && (str = Foverlay_get (overlay, Qafter_string), STRINGP (str)) 6607 && (str = Foverlay_get (overlay, Qafter_string), STRINGP (str))
6685 && SCHARS (str)) 6608 && SCHARS (str))
6686 RECORD_OVERLAY_STRING (overlay, str, true); 6609 RECORD_OVERLAY_STRING (overlay, str, true);
6687 } 6610 }
6688 6611
6689#undef RECORD_OVERLAY_STRING 6612#undef RECORD_OVERLAY_STRING
@@ -7088,11 +7011,11 @@ back_to_previous_line_start (struct it *it)
7088static bool 7011static bool
7089strings_with_newlines (ptrdiff_t startpos, ptrdiff_t endpos, struct window *w) 7012strings_with_newlines (ptrdiff_t startpos, ptrdiff_t endpos, struct window *w)
7090{ 7013{
7091 /* Process overlays before the overlay center. */ 7014 struct itree_node *node;
7092 for (struct Lisp_Overlay *ov = current_buffer->overlays_before; 7015 /* Process overlays. */
7093 ov; ov = ov->next) 7016 ITREE_FOREACH (node, current_buffer->overlays, startpos, endpos, DESCENDING)
7094 { 7017 {
7095 Lisp_Object overlay = make_lisp_ptr (ov, Lisp_Vectorlike); 7018 Lisp_Object overlay = node->data;
7096 eassert (OVERLAYP (overlay)); 7019 eassert (OVERLAYP (overlay));
7097 7020
7098 /* Skip this overlay if it doesn't apply to our window. */ 7021 /* Skip this overlay if it doesn't apply to our window. */
@@ -7100,14 +7023,8 @@ strings_with_newlines (ptrdiff_t startpos, ptrdiff_t endpos, struct window *w)
7100 if (WINDOWP (window) && XWINDOW (window) != w) 7023 if (WINDOWP (window) && XWINDOW (window) != w)
7101 continue; 7024 continue;
7102 7025
7103 ptrdiff_t ostart = OVERLAY_POSITION (OVERLAY_START (overlay)); 7026 ptrdiff_t ostart = node->begin;
7104 ptrdiff_t oend = OVERLAY_POSITION (OVERLAY_END (overlay)); 7027 ptrdiff_t oend = node->end;
7105
7106 /* Due to the order of overlays in overlays_before, once we get
7107 to an overlay whose end position is before STARTPOS, all the
7108 rest also end before STARTPOS, and thus are of no concern to us. */
7109 if (oend < startpos)
7110 break;
7111 7028
7112 /* Skip overlays that don't overlap the range. */ 7029 /* Skip overlays that don't overlap the range. */
7113 if (!((startpos < oend && ostart < endpos) 7030 if (!((startpos < oend && ostart < endpos)
@@ -7119,49 +7036,17 @@ strings_with_newlines (ptrdiff_t startpos, ptrdiff_t endpos, struct window *w)
7119 str = Foverlay_get (overlay, Qbefore_string); 7036 str = Foverlay_get (overlay, Qbefore_string);
7120 if (STRINGP (str) && SCHARS (str) 7037 if (STRINGP (str) && SCHARS (str)
7121 && memchr (SDATA (str), '\n', SBYTES (str))) 7038 && memchr (SDATA (str), '\n', SBYTES (str)))
7122 return true; 7039 {
7123 str = Foverlay_get (overlay, Qafter_string); 7040 ITREE_FOREACH_ABORT ();
7124 if (STRINGP (str) && SCHARS (str) 7041 return true;
7125 && memchr (SDATA (str), '\n', SBYTES (str))) 7042 }
7126 return true;
7127 }
7128
7129 /* Process overlays after the overlay center. */
7130 for (struct Lisp_Overlay *ov = current_buffer->overlays_after;
7131 ov; ov = ov->next)
7132 {
7133 Lisp_Object overlay = make_lisp_ptr (ov, Lisp_Vectorlike);
7134 eassert (OVERLAYP (overlay));
7135
7136 /* Skip this overlay if it doesn't apply to our window. */
7137 Lisp_Object window = Foverlay_get (overlay, Qwindow);
7138 if (WINDOWP (window) && XWINDOW (window) != w)
7139 continue;
7140
7141 ptrdiff_t ostart = OVERLAY_POSITION (OVERLAY_START (overlay));
7142 ptrdiff_t oend = OVERLAY_POSITION (OVERLAY_END (overlay));
7143
7144 /* Due to the order of overlays in overlays_after, once we get
7145 to an overlay whose start position is after ENDPOS, all the
7146 rest also start after ENDPOS, and thus are of no concern to us. */
7147 if (ostart > endpos)
7148 break;
7149
7150 /* Skip overlays that don't overlap the range. */
7151 if (!((startpos < oend && ostart < endpos)
7152 || (ostart == oend
7153 && (startpos == oend || (endpos == ZV && oend == endpos)))))
7154 continue;
7155
7156 Lisp_Object str;
7157 str = Foverlay_get (overlay, Qbefore_string);
7158 if (STRINGP (str) && SCHARS (str)
7159 && memchr (SDATA (str), '\n', SBYTES (str)))
7160 return true;
7161 str = Foverlay_get (overlay, Qafter_string); 7043 str = Foverlay_get (overlay, Qafter_string);
7162 if (STRINGP (str) && SCHARS (str) 7044 if (STRINGP (str) && SCHARS (str)
7163 && memchr (SDATA (str), '\n', SBYTES (str))) 7045 && memchr (SDATA (str), '\n', SBYTES (str)))
7164 return true; 7046 {
7047 ITREE_FOREACH_ABORT ();
7048 return true;
7049 }
7165 } 7050 }
7166 7051
7167 /* Check for 'display' properties whose values include strings. */ 7052 /* Check for 'display' properties whose values include strings. */
@@ -7404,7 +7289,7 @@ back_to_previous_visible_line_start (struct it *it)
7404 && !NILP (val = get_char_property_and_overlay 7289 && !NILP (val = get_char_property_and_overlay
7405 (make_fixnum (pos), Qdisplay, Qnil, &overlay)) 7290 (make_fixnum (pos), Qdisplay, Qnil, &overlay))
7406 && (OVERLAYP (overlay) 7291 && (OVERLAYP (overlay)
7407 ? (beg = OVERLAY_POSITION (OVERLAY_START (overlay))) 7292 ? (beg = OVERLAY_START (overlay))
7408 : get_property_and_range (pos, Qdisplay, &val, &beg, &end, Qnil))) 7293 : get_property_and_range (pos, Qdisplay, &val, &beg, &end, Qnil)))
7409 { 7294 {
7410 RESTORE_IT (it, it, it2data); 7295 RESTORE_IT (it, it, it2data);
@@ -10639,7 +10524,6 @@ move_it_to (struct it *it, ptrdiff_t to_charpos, int to_x, int to_y, int to_vpos
10639 } 10524 }
10640 10525
10641 /* Reset/increment for the next run. */ 10526 /* Reset/increment for the next run. */
10642 recenter_overlay_lists (current_buffer, IT_CHARPOS (*it));
10643 it->current_x = line_start_x; 10527 it->current_x = line_start_x;
10644 line_start_x = 0; 10528 line_start_x = 0;
10645 it->hpos = 0; 10529 it->hpos = 0;
@@ -24618,13 +24502,6 @@ display_line (struct it *it, int cursor_vpos)
24618 it->stretch_adjust = 0; 24502 it->stretch_adjust = 0;
24619 it->line_number_produced_p = false; 24503 it->line_number_produced_p = false;
24620 24504
24621 /* Arrange the overlays nicely for our purposes. Usually, we call
24622 display_line on only one line at a time, in which case this
24623 can't really hurt too much, or we call it on lines which appear
24624 one after another in the buffer, in which case all calls to
24625 recenter_overlay_lists but the first will be pretty cheap. */
24626 recenter_overlay_lists (current_buffer, IT_CHARPOS (*it));
24627
24628 /* If we are going to display the cursor's line, account for the 24505 /* If we are going to display the cursor's line, account for the
24629 hscroll of that line. We subtract the window's min_hscroll, 24506 hscroll of that line. We subtract the window's min_hscroll,
24630 because that was already accounted for in init_iterator. */ 24507 because that was already accounted for in init_iterator. */
@@ -35256,7 +35133,7 @@ note_mouse_highlight (struct frame *f, int x, int y)
35256 if (BUFFERP (object)) 35133 if (BUFFERP (object))
35257 { 35134 {
35258 /* Put all the overlays we want in a vector in overlay_vec. */ 35135 /* Put all the overlays we want in a vector in overlay_vec. */
35259 GET_OVERLAYS_AT (pos, overlay_vec, noverlays, NULL, false); 35136 GET_OVERLAYS_AT (pos, overlay_vec, noverlays, NULL);
35260 /* Sort overlays into increasing priority order. */ 35137 /* Sort overlays into increasing priority order. */
35261 noverlays = sort_overlays (overlay_vec, noverlays, w); 35138 noverlays = sort_overlays (overlay_vec, noverlays, w);
35262 } 35139 }
@@ -35284,7 +35161,7 @@ note_mouse_highlight (struct frame *f, int x, int y)
35284 || (!hlinfo->mouse_face_hidden 35161 || (!hlinfo->mouse_face_hidden
35285 && OVERLAYP (hlinfo->mouse_face_overlay) 35162 && OVERLAYP (hlinfo->mouse_face_overlay)
35286 /* It's possible the overlay was deleted (Bug#35273). */ 35163 /* It's possible the overlay was deleted (Bug#35273). */
35287 && XMARKER (OVERLAY_START (hlinfo->mouse_face_overlay))->buffer 35164 && OVERLAY_BUFFER (hlinfo->mouse_face_overlay)
35288 && mouse_face_overlay_overlaps (hlinfo->mouse_face_overlay))) 35165 && mouse_face_overlay_overlaps (hlinfo->mouse_face_overlay)))
35289 { 35166 {
35290 /* Find the highest priority overlay with a mouse-face. */ 35167 /* Find the highest priority overlay with a mouse-face. */
diff --git a/src/xfaces.c b/src/xfaces.c
index 5e3a47d7f8b..ed76db9adb7 100644
--- a/src/xfaces.c
+++ b/src/xfaces.c
@@ -6540,8 +6540,7 @@ face_at_buffer_position (struct window *w, ptrdiff_t pos,
6540 USE_SAFE_ALLOCA; 6540 USE_SAFE_ALLOCA;
6541 { 6541 {
6542 ptrdiff_t next_overlay; 6542 ptrdiff_t next_overlay;
6543 6543 GET_OVERLAYS_AT (pos, overlay_vec, noverlays, &next_overlay);
6544 GET_OVERLAYS_AT (pos, overlay_vec, noverlays, &next_overlay, false);
6545 if (next_overlay < endpos) 6544 if (next_overlay < endpos)
6546 endpos = next_overlay; 6545 endpos = next_overlay;
6547 } 6546 }
@@ -6594,7 +6593,6 @@ face_at_buffer_position (struct window *w, ptrdiff_t pos,
6594 { 6593 {
6595 for (prop = Qnil, i = noverlays - 1; i >= 0 && NILP (prop); --i) 6594 for (prop = Qnil, i = noverlays - 1; i >= 0 && NILP (prop); --i)
6596 { 6595 {
6597 Lisp_Object oend;
6598 ptrdiff_t oendpos; 6596 ptrdiff_t oendpos;
6599 6597
6600 prop = Foverlay_get (overlay_vec[i], propname); 6598 prop = Foverlay_get (overlay_vec[i], propname);
@@ -6607,8 +6605,7 @@ face_at_buffer_position (struct window *w, ptrdiff_t pos,
6607 merge_face_ref (w, f, prop, attrs, true, NULL, attr_filter); 6605 merge_face_ref (w, f, prop, attrs, true, NULL, attr_filter);
6608 } 6606 }
6609 6607
6610 oend = OVERLAY_END (overlay_vec[i]); 6608 oendpos = OVERLAY_END (overlay_vec[i]);
6611 oendpos = OVERLAY_POSITION (oend);
6612 if (oendpos < endpos) 6609 if (oendpos < endpos)
6613 endpos = oendpos; 6610 endpos = oendpos;
6614 } 6611 }
@@ -6617,7 +6614,6 @@ face_at_buffer_position (struct window *w, ptrdiff_t pos,
6617 { 6614 {
6618 for (i = 0; i < noverlays; i++) 6615 for (i = 0; i < noverlays; i++)
6619 { 6616 {
6620 Lisp_Object oend;
6621 ptrdiff_t oendpos; 6617 ptrdiff_t oendpos;
6622 6618
6623 prop = Foverlay_get (overlay_vec[i], propname); 6619 prop = Foverlay_get (overlay_vec[i], propname);
@@ -6625,11 +6621,10 @@ face_at_buffer_position (struct window *w, ptrdiff_t pos,
6625 if (!NILP (prop)) 6621 if (!NILP (prop))
6626 merge_face_ref (w, f, prop, attrs, true, NULL, attr_filter); 6622 merge_face_ref (w, f, prop, attrs, true, NULL, attr_filter);
6627 6623
6628 oend = OVERLAY_END (overlay_vec[i]); 6624 oendpos = OVERLAY_END (overlay_vec[i]);
6629 oendpos = OVERLAY_POSITION (oend); 6625 if (oendpos < endpos)
6630 if (oendpos < endpos) 6626 endpos = oendpos;
6631 endpos = oendpos; 6627 }
6632 }
6633 } 6628 }
6634 6629
6635 *endptr = endpos; 6630 *endptr = endpos;