From f2a51774a934f29848c5796b46faa5e3b022c401 Mon Sep 17 00:00:00 2001 From: Matt Armstrong Date: Fri, 21 Oct 2022 19:45:13 -0700 Subject: [PATCH] Fix a narrow-to-region vs. overlays-at bug See bug#58703. * src/buffer.c (overlays_in): Add a new TRAILING arg expressing the behavior wanted by `overlays-at', namely to include all overlays beginning at the POS passed to `overlays-at', even if POS is the end of the narrowed region. Pass true and the search range is extended to ZV+1 if END is greater than ZV, just as is done for EMPTY. (overlays_at): Pass 'true' for the new trailing arg. At present this is the only caller passing 'true'. (mouse_face_overlay_overlaps): Pass 'false' for the new trailing arg. (disable_line_numbers_overlay_at_eob): ditto. (Foverlays_in): ditto. * src/editfns.c (overlays_around): ditto. * test/src/buffer-tests.el (sorted-overlays): Add a spot test for this. --- src/buffer.c | 31 +++++++++++++++++++++---------- src/buffer.h | 2 +- src/editfns.c | 2 +- test/src/buffer-tests.el | 39 +++++++++++++++++++++++++++------------ 4 files changed, 50 insertions(+), 24 deletions(-) diff --git a/src/buffer.c b/src/buffer.c index fe6b515493e..dcb3c3944b7 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -2943,6 +2943,10 @@ the normal hook `change-major-mode-hook'. */) END, provided END denotes the position at the end of the accessible part of the buffer. + If TRAILING is true, include overlays that begin at END, provided + END denotes the position at the end of the accessible part of the + buffer. + Return the number found, and store them in a vector in *VEC_PTR. Store in *LEN_PTR the size allocated for the vector. Store in *NEXT_PTR the next position after POS where an overlay starts, @@ -2959,7 +2963,8 @@ the normal hook `change-major-mode-hook'. */) ptrdiff_t overlays_in (ptrdiff_t beg, ptrdiff_t end, bool extend, - Lisp_Object **vec_ptr, ptrdiff_t *len_ptr, bool empty, + Lisp_Object **vec_ptr, ptrdiff_t *len_ptr, + bool empty, bool trailing, ptrdiff_t *next_ptr) { ptrdiff_t idx = 0; @@ -2968,9 +2973,14 @@ overlays_in (ptrdiff_t beg, ptrdiff_t end, bool extend, Lisp_Object *vec = *vec_ptr; struct itree_node *node; - ITREE_FOREACH (node, current_buffer->overlays, beg, - /* Find empty OV at ZV ? */ - (end >= ZV && empty) ? ZV + 1 : ZV, ASCENDING) + /* Extend the search range if overlays beginning at ZV are + wanted. */ + ptrdiff_t search_end = ZV; + if (end >= ZV && (empty || trailing)) + ++search_end; + + ITREE_FOREACH (node, current_buffer->overlays, beg, search_end, + ASCENDING) { if (node->begin > end) { @@ -3022,7 +3032,8 @@ overlays_at (ptrdiff_t pos, bool extend, Lisp_Object **vec_ptr, ptrdiff_t *len_ptr, ptrdiff_t *next_ptr) { - return overlays_in (pos, pos + 1, extend, vec_ptr, len_ptr, false, next_ptr); + return overlays_in (pos, pos + 1, extend, vec_ptr, len_ptr, + false, true, next_ptr); } ptrdiff_t @@ -3085,11 +3096,11 @@ mouse_face_overlay_overlaps (Lisp_Object overlay) size = ARRAYELTS (vbuf); v = vbuf; - n = overlays_in (start, end, 0, &v, &size, true, NULL); + n = overlays_in (start, end, 0, &v, &size, true, false, NULL); if (n > size) { SAFE_NALLOCA (v, 1, n); - overlays_in (start, end, 0, &v, &n, true, NULL); + overlays_in (start, end, 0, &v, &n, true, false, NULL); } for (i = 0; i < n; ++i) @@ -3114,11 +3125,11 @@ disable_line_numbers_overlay_at_eob (void) size = ARRAYELTS (vbuf); v = vbuf; - n = overlays_in (ZV, ZV, 0, &v, &size, false, NULL); + n = overlays_in (ZV, ZV, 0, &v, &size, false, false, NULL); if (n > size) { SAFE_NALLOCA (v, 1, n); - overlays_in (ZV, ZV, 0, &v, &n, false, NULL); + overlays_in (ZV, ZV, 0, &v, &n, false, false, NULL); } for (i = 0; i < n; ++i) @@ -3798,7 +3809,7 @@ end of the accessible part of the buffer. */) /* Put all the overlays we want in a vector in overlay_vec. Store the length in len. */ noverlays = overlays_in (XFIXNUM (beg), XFIXNUM (end), 1, &overlay_vec, &len, - true, NULL); + true, false, NULL); /* Make a list of them all. */ result = Flist (noverlays, overlay_vec); diff --git a/src/buffer.h b/src/buffer.h index ce1b7b27b0f..3ea4125645d 100644 --- a/src/buffer.h +++ b/src/buffer.h @@ -1173,7 +1173,7 @@ extern void compact_buffer (struct buffer *); extern void evaporate_overlays (ptrdiff_t); extern ptrdiff_t overlays_at (ptrdiff_t, bool, Lisp_Object **, ptrdiff_t *, ptrdiff_t *); extern ptrdiff_t overlays_in (ptrdiff_t, ptrdiff_t, bool, Lisp_Object **, - ptrdiff_t *, bool, ptrdiff_t *); + ptrdiff_t *, bool, bool, ptrdiff_t *); extern ptrdiff_t previous_overlay_change (ptrdiff_t); extern ptrdiff_t next_overlay_change (ptrdiff_t); extern ptrdiff_t sort_overlays (Lisp_Object *, ptrdiff_t, struct window *); diff --git a/src/editfns.c b/src/editfns.c index 1af6ea1b11d..00380175859 100644 --- a/src/editfns.c +++ b/src/editfns.c @@ -270,7 +270,7 @@ If you set the marker not to point anywhere, the buffer will have no mark. */) static ptrdiff_t overlays_around (ptrdiff_t pos, Lisp_Object *vec, ptrdiff_t len) { - return overlays_in (pos - 1, pos, false, &vec, &len, false, NULL); + return overlays_in (pos - 1, pos, false, &vec, &len, false, false, NULL); } DEFUN ("get-pos-property", Fget_pos_property, Sget_pos_property, 2, 3, 0, diff --git a/test/src/buffer-tests.el b/test/src/buffer-tests.el index 6d5d9913a01..c6d176cc171 100644 --- a/test/src/buffer-tests.el +++ b/test/src/buffer-tests.el @@ -860,6 +860,33 @@ with parameters from the *Messages* buffer modification." (should-length 1 (overlays-at 15)) (should-length 1 (overlays-at (point-max)))))) +(defun sorted-overlays (overlays) + (sort + (mapcar (lambda (overlay) + (list (overlay-start overlay) + (overlay-end overlay))) + overlays) + (lambda (first second) + (cl-loop for a in first + for b in second + thereis (< a b) + until (> a b))))) + +(defun sorted-overlays-at (pos) + (sorted-overlays (overlays-at pos))) + +(defun sorted-overlays-in (beg end) + (sorted-overlays (overlays-in beg end))) + +(ert-deftest test-overlays-at-narrow-to-region-end () + ;; See bug#58703. + (with-temp-buffer + (insert (make-string 30 ?x)) + (make-overlay 10 11) + (narrow-to-region 10 10) + (should (equal + '((10 11)) + (sorted-overlays-at 10))))) ;; +==========================================================================+ ;; | overlay-in @@ -937,18 +964,6 @@ with parameters from the *Messages* buffer modification." (deftest-overlays-in-1 ae 9 11 (a) (a 10 10)) (deftest-overlays-in-1 af 10 11 (a) (a 10 10)) -(defun sorted-overlays-in (beg end) - (sort - (mapcar (lambda (overlay) - (list (overlay-start overlay) - (overlay-end overlay))) - (overlays-in beg end)) - (lambda (first second) - (cl-loop for a in first - for b in second - thereis (< a b) - until (> a b))))) - ;; behavior for empty range (ert-deftest test-overlays-in-empty-range () (with-temp-buffer -- 2.39.5