1
Fork 0
mirror of git://git.sv.gnu.org/emacs.git synced 2026-01-07 20:30:32 -08:00

src/buffer.c: Fix interaction between overlays & indirect buffers (bug#58928)

* src/buffer.c (adjust_overlays_for_insert)
(adjust_overlays_for_delete): Repeat for all buffers sharing the same text.

* src/itree.c (itree_insert_gap, itree_delete_gap): Allow an empty tree.

* test/src/buffer-tests.el (buffer-tests--overlays-indirect-bug58928):
New test.
This commit is contained in:
Stefan Monnier 2022-11-01 21:38:55 -04:00
parent 835295381b
commit 8a5678906f
3 changed files with 49 additions and 10 deletions

View file

@ -3456,19 +3456,37 @@ overlay_strings (ptrdiff_t pos, struct window *w, unsigned char **pstr)
void
adjust_overlays_for_insert (ptrdiff_t pos, ptrdiff_t length)
{
/* After an insertion, the lists are still sorted properly,
but we may need to update the value of the overlay center. */
if (! current_buffer->overlays)
return;
itree_insert_gap (current_buffer->overlays, pos, length);
if (!current_buffer->indirections)
itree_insert_gap (current_buffer->overlays, pos, length);
else
{
struct buffer *base = current_buffer->base_buffer
? current_buffer->base_buffer
: current_buffer;
Lisp_Object tail, other;
itree_insert_gap (base->overlays, pos, length);
FOR_EACH_LIVE_BUFFER (tail, other)
if (XBUFFER (other)->base_buffer == base)
itree_insert_gap (XBUFFER (other)->overlays, pos, length);
}
}
void
adjust_overlays_for_delete (ptrdiff_t pos, ptrdiff_t length)
{
if (! current_buffer->overlays)
return;
itree_delete_gap (current_buffer->overlays, pos, length);
if (!current_buffer->indirections)
itree_delete_gap (current_buffer->overlays, pos, length);
else
{
struct buffer *base = current_buffer->base_buffer
? current_buffer->base_buffer
: current_buffer;
Lisp_Object tail, other;
itree_delete_gap (base->overlays, pos, length);
FOR_EACH_LIVE_BUFFER (tail, other)
if (XBUFFER (other)->base_buffer == base)
itree_delete_gap (XBUFFER (other)->overlays, pos, length);
}
}

View file

@ -1196,7 +1196,7 @@ void
itree_insert_gap (struct itree_tree *tree,
ptrdiff_t pos, ptrdiff_t length)
{
if (length <= 0 || tree->root == NULL)
if (!tree || length <= 0 || tree->root == NULL)
return;
uintmax_t ootick = tree->otick;
@ -1280,7 +1280,7 @@ void
itree_delete_gap (struct itree_tree *tree,
ptrdiff_t pos, ptrdiff_t length)
{
if (length <= 0 || tree->root == NULL)
if (!tree || length <= 0 || tree->root == NULL)
return;
/* FIXME: Don't allocate stack anew every time. */

View file

@ -275,6 +275,27 @@ with parameters from the *Messages* buffer modification."
(with-temp-buffer
(should (eq (buffer-base-buffer (current-buffer)) nil))))
(ert-deftest buffer-tests--overlays-indirect-bug58928 ()
(with-temp-buffer
(insert "hello world")
(let* ((base (current-buffer))
(ol1 (make-overlay (+ 2 (point-min)) (+ 8 (point-min))))
(ib (make-indirect-buffer
base (generate-new-buffer-name "bug58928")))
(ol2 (with-current-buffer ib
(make-overlay (+ 2 (point-min)) (+ 8 (point-min))))))
(should (equal (overlay-start ol1) (overlay-start ol2)))
(should (equal (overlay-end ol1) (overlay-end ol2)))
(goto-char (+ 3 (point-min)))
(insert "a") (delete-char 2)
(should (equal (overlay-start ol1) (overlay-start ol2)))
(should (equal (overlay-end ol1) (overlay-end ol2)))
(with-current-buffer ib
(goto-char (+ 4 (point-min)))
(insert "a") (delete-char 2))
(should (equal (overlay-start ol1) (overlay-start ol2)))
(should (equal (overlay-end ol1) (overlay-end ol2))))))
(ert-deftest overlay-evaporation-after-killed-buffer ()
(let* ((ols (with-temp-buffer
(insert "toto")