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