From: Stefan Monnier Date: Sat, 5 Nov 2022 21:22:37 +0000 (-0400) Subject: buffer.c: evaporate overlays in all indirect buffers X-Git-Tag: emacs-29.0.90~1616^2~272 X-Git-Url: http://git.eshelyaron.com/gitweb/?a=commitdiff_plain;h=6e5ec085510ccf52ac6cb07c3a1a2778324a1d89;p=emacs.git buffer.c: evaporate overlays in all indirect buffers This fixes bug#58928. The patch works by moving the `evaporate_overlays` check closer to `itree_delete_gap`. * src/buffer.c (adjust_overlays_for_delete_in_buffer): New function, integrating the functionality of `evaporate_overlays`. (adjust_overlays_for_delete): Use it. (evaporate_overlays): Delete function. * src/buffer.h (evaporate_overlays): Delete declaration. * src/insdel.c (adjust_markers_for_replace): Minor optimization. (adjust_after_replace, replace_range, replace_range_2, del_range_2): Don't call `evaporate_overlays`. * test/src/buffer-tests.el (buffer-tests--overlays-indirect-evaporate): Remove the `:expected-result :failed` attribute. --- diff --git a/src/buffer.c b/src/buffer.c index 390ccff5c8a..ec2d34daf89 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -3472,21 +3472,47 @@ adjust_overlays_for_insert (ptrdiff_t pos, ptrdiff_t length, bool before_markers } } +static void +adjust_overlays_for_delete_in_buffer (struct buffer * buf, + ptrdiff_t pos, ptrdiff_t length) +{ + Lisp_Object hit_list = Qnil; + struct itree_node *node; + + /* Ideally, the evaporate check would be done directly within + `itree_delete_gap`, but that code isn't supposed to know about overlays, + only about `itree_node`s, so it would break an abstraction boundary. */ + itree_delete_gap (buf->overlays, pos, length); + + /* Delete any zero-sized overlays at position POS, if the `evaporate' + property is set. */ + + ITREE_FOREACH (node, buf->overlays, pos, pos, ASCENDING) + { + if (node->end == pos && node->begin == pos + && ! NILP (Foverlay_get (node->data, Qevaporate))) + hit_list = Fcons (node->data, hit_list); + } + + for (; CONSP (hit_list); hit_list = XCDR (hit_list)) + Fdelete_overlay (XCAR (hit_list)); +} + void adjust_overlays_for_delete (ptrdiff_t pos, ptrdiff_t length) { if (!current_buffer->indirections) - itree_delete_gap (current_buffer->overlays, pos, length); + adjust_overlays_for_delete_in_buffer (current_buffer, 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); + adjust_overlays_for_delete_in_buffer (base, pos, length); FOR_EACH_LIVE_BUFFER (tail, other) if (XBUFFER (other)->base_buffer == base) - itree_delete_gap (XBUFFER (other)->overlays, pos, length); + adjust_overlays_for_delete_in_buffer (XBUFFER (other), pos, length); } } @@ -4099,25 +4125,6 @@ call_overlay_mod_hooks (Lisp_Object list, Lisp_Object overlay, bool after, } } -/* Delete any zero-sized overlays at position POS, if the `evaporate' - property is set. */ -void -evaporate_overlays (ptrdiff_t pos) -{ - Lisp_Object hit_list = Qnil; - struct itree_node *node; - - ITREE_FOREACH (node, current_buffer->overlays, pos, pos, ASCENDING) - { - if (node->end == pos - && ! NILP (Foverlay_get (node->data, Qevaporate))) - hit_list = Fcons (node->data, hit_list); - } - - for (; CONSP (hit_list); hit_list = XCDR (hit_list)) - Fdelete_overlay (XCAR (hit_list)); -} - /*********************************************************************** Allocation with mmap ***********************************************************************/ diff --git a/src/buffer.h b/src/buffer.h index 3ea4125645d..2e80c8a7b04 100644 --- a/src/buffer.h +++ b/src/buffer.h @@ -1170,7 +1170,6 @@ extern EMACS_INT fix_position (Lisp_Object); extern void delete_all_overlays (struct buffer *); extern void reset_buffer (struct buffer *); 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, bool, ptrdiff_t *); diff --git a/src/insdel.c b/src/insdel.c index ef17f99d21f..03ce59b3409 100644 --- a/src/insdel.c +++ b/src/insdel.c @@ -345,6 +345,11 @@ adjust_markers_for_replace (ptrdiff_t from, ptrdiff_t from_byte, ptrdiff_t diff_bytes = new_bytes - old_bytes; adjust_suspend_auto_hscroll (from, from + old_chars); + + /* FIXME: When OLD_CHARS is 0, this "replacement" is really just an + insertion, but the behavior we provide here in that case is that of + `insert-before-markers` rather than that of `insert`. + Maybe not a bug, but not a feature either. */ for (m = BUF_MARKERS (current_buffer); m; m = m->next) { if (m->bytepos >= prev_to_byte) @@ -362,7 +367,8 @@ adjust_markers_for_replace (ptrdiff_t from, ptrdiff_t from_byte, check_markers (); adjust_overlays_for_insert (from + old_chars, new_chars, true); - adjust_overlays_for_delete (from, old_chars); + if (old_chars) + adjust_overlays_for_delete (from, old_chars); } /* Starting at POS (BYTEPOS), find the byte position corresponding to @@ -1334,8 +1340,6 @@ adjust_after_replace (ptrdiff_t from, ptrdiff_t from_byte, check_markers (); - if (len == 0) - evaporate_overlays (from); modiff_incr (&MODIFF, nchars_del + len); CHARS_MODIFF = MODIFF; } @@ -1521,9 +1525,6 @@ replace_range (ptrdiff_t from, ptrdiff_t to, Lisp_Object new, (from_byte + outgoing_insbytes - (PT_BYTE < to_byte ? PT_BYTE : to_byte))); - if (outgoing_insbytes == 0) - evaporate_overlays (from); - check_markers (); modiff_incr (&MODIFF, nchars_del + inschars); @@ -1647,9 +1648,6 @@ replace_range_2 (ptrdiff_t from, ptrdiff_t from_byte, adjust_point (inschars - nchars_del, insbytes - nbytes_del); } - if (insbytes == 0) - evaporate_overlays (from); - check_markers (); modiff_incr (&MODIFF, nchars_del + inschars); @@ -1858,8 +1856,6 @@ del_range_2 (ptrdiff_t from, ptrdiff_t from_byte, check_markers (); - evaporate_overlays (from); - return deletion; } diff --git a/test/src/buffer-tests.el b/test/src/buffer-tests.el index 3c371760952..b11243e021f 100644 --- a/test/src/buffer-tests.el +++ b/test/src/buffer-tests.el @@ -301,7 +301,6 @@ with parameters from the *Messages* buffer modification." Deleting characters from either a base or an indirect buffer should evaporate overlays in both." - :expected-result :failed ;; Loop twice, erasing from the base buffer the first time and the ;; indirect buffer the second. (dolist (erase-where '(base indirect))