]> git.eshelyaron.com Git - emacs.git/commitdiff
buffer.c: evaporate overlays in all indirect buffers
authorStefan Monnier <monnier@iro.umontreal.ca>
Sat, 5 Nov 2022 21:22:37 +0000 (17:22 -0400)
committerStefan Monnier <monnier@iro.umontreal.ca>
Sat, 5 Nov 2022 21:22:37 +0000 (17:22 -0400)
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.

src/buffer.c
src/buffer.h
src/insdel.c
test/src/buffer-tests.el

index 390ccff5c8a724b4ee5fabc80774bcdf37d1df4a..ec2d34daf89b0e0e8af52e55dae23c5946998705 100644 (file)
@@ -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
  ***********************************************************************/
index 3ea4125645d1dcff69b3eda5b689ed51de600daf..2e80c8a7b047f96d4493ae3f8ee19ea7964f79c1 100644 (file)
@@ -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 *);
index ef17f99d21feec48e8d12fa89a667e262b687b1e..03ce59b34099909d3b5394ca93c4e72cbec0c8df 100644 (file)
@@ -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;
 }
 
index 3c371760952afbfe7c352769b9cc78c73e4e4ec0..b11243e021f989fc97a612582382f7e08e0b6f14 100644 (file)
@@ -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))