summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStefan Monnier <monnier@iro.umontreal.ca>2022-11-05 17:22:37 -0400
committerStefan Monnier <monnier@iro.umontreal.ca>2022-11-05 17:22:37 -0400
commit6e5ec085510ccf52ac6cb07c3a1a2778324a1d89 (patch)
tree0ad67bf3aa5a7a6c9eb9e01754e5f57da19dd4b6
parent5c9895fffe4e34b7a31b0a8e4bce0b59a4bc0326 (diff)
downloademacs-6e5ec085510ccf52ac6cb07c3a1a2778324a1d89.tar.gz
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.
-rw-r--r--src/buffer.c51
-rw-r--r--src/buffer.h1
-rw-r--r--src/insdel.c18
-rw-r--r--test/src/buffer-tests.el1
4 files changed, 36 insertions, 35 deletions
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))