summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStefan Monnier <monnier@iro.umontreal.ca>2025-03-29 16:40:19 -0400
committerStefan Monnier <monnier@iro.umontreal.ca>2025-03-29 17:49:49 -0400
commit57da44fa702782e19cd9d60ea63ec2fd9ca48521 (patch)
tree7182b458505348be363d9c0093a98a8b5043fb79
parent7c82cc8b975175aebbad1c43ec1cd98b3232f482 (diff)
downloademacs-57da44fa702782e19cd9d60ea63ec2fd9ca48521.tar.gz
emacs-57da44fa702782e19cd9d60ea63ec2fd9ca48521.tar.bz2
emacs-57da44fa702782e19cd9d60ea63ec2fd9ca48521.zip
src/insdel.c (adjust_markers_for_replace): Fix insertion case
test/src/editfns-tests.el (editfns-tests--insert-via-replace): New test
-rw-r--r--src/insdel.c19
-rw-r--r--test/src/editfns-tests.el14
2 files changed, 27 insertions, 6 deletions
diff --git a/src/insdel.c b/src/insdel.c
index 20267265ab8..053b2d46380 100644
--- a/src/insdel.c
+++ b/src/insdel.c
@@ -348,12 +348,20 @@ adjust_markers_for_replace (ptrdiff_t from, ptrdiff_t from_byte,
ptrdiff_t diff_chars = new_chars - old_chars;
ptrdiff_t diff_bytes = new_bytes - old_bytes;
+ if (old_chars == 0)
+ {
+ /* Just an insertion: markers at FROM may need to move or not depending
+ on their marker type. Delegate this special case to
+ 'adjust_markers_for_insert' so the loop below can remain oblivious
+ to marker types. */
+ adjust_markers_for_insert (from, from_byte,
+ from + new_chars, from_byte + new_bytes,
+ false);
+ return;
+ }
+
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)
@@ -371,8 +379,7 @@ adjust_markers_for_replace (ptrdiff_t from, ptrdiff_t from_byte,
check_markers ();
adjust_overlays_for_insert (from + old_chars, new_chars, true);
- if (old_chars)
- adjust_overlays_for_delete (from, old_chars);
+ adjust_overlays_for_delete (from, old_chars);
}
/* Starting at POS (BYTEPOS), find the byte position corresponding to
diff --git a/test/src/editfns-tests.el b/test/src/editfns-tests.el
index 3da9d4e8acd..2553ad3ec2c 100644
--- a/test/src/editfns-tests.el
+++ b/test/src/editfns-tests.el
@@ -357,6 +357,20 @@
(should (= m7a (+ (point-min) 7)))))
(widen)))))
+(ert-deftest editfns-tests--insert-via-replace ()
+ (with-temp-buffer
+ (insert "bar")
+ (goto-char (point-min))
+ ;; Check that markers insertion type is respected when an insertion
+ ;; happens via a "replace" operation.
+ (let ((m1 (copy-marker (point) nil))
+ (m2 (copy-marker (point) t)))
+ (looking-at "\\(\\)")
+ (replace-match "foo")
+ (should (equal "foobar" (buffer-string)))
+ (should (= (point-min) m1))
+ (should (= (+ (point-min) 3) m2)))))
+
(ert-deftest delete-region-undo-markers-1 ()
"Make sure we don't end up with freed markers reachable from Lisp."
;; https://debbugs.gnu.org/cgi/bugreport.cgi?bug=30931#40