Commit: patch 9.1.1885: Wrong restored cursor pos when re-entering buffer after changes

1 view
Skip to first unread message

Christian Brabandt

unread,
Oct 28, 2025, 4:30:16 PMOct 28
to vim...@googlegroups.com
patch 9.1.1885: Wrong restored cursor pos when re-entering buffer after changes

Commit: https://github.com/vim/vim/commit/b2e6b328dafe1cdfff10f1e811355e514da8071d
Author: zeertzjq <zeer...@outlook.com>
Date: Tue Oct 28 20:27:19 2025 +0000

patch 9.1.1885: Wrong restored cursor pos when re-entering buffer after changes

Problem: Wrong restored cursor position when re-entering a buffer
previously viewed in a window after making changes to the same
buffer in another window.
Solution: Adjust per-window "last cursor" positions on buffer changes.
(zeertzjq)

closes: #18655

Signed-off-by: zeertzjq <zeer...@outlook.com>
Signed-off-by: Christian Brabandt <c...@256bit.org>

diff --git a/src/mark.c b/src/mark.c
index 33cd55fea..c872e2f0f 100644
--- a/src/mark.c
+++ b/src/mark.c
@@ -1031,6 +1031,25 @@ ex_changes(exarg_T *eap UNUSED)
*lp += amount_after; \
}

+// Like one_adjust_nodel(), but if the position is within the deleted range,
+// move it to the start of the line before the range.
+#define one_adjust_cursor(pp) \
+ { \
+ pos_T *posp = pp; \
+ if (posp->lnum >= line1 && posp->lnum <= line2) \
+ { \
+ if (amount == MAXLNUM) /* line with cursor is deleted */ \
+ { \
+ posp->lnum = MAX(line1 - 1, 1); \
+ posp->col = 0; \
+ } \
+ else /* keep cursor on the same line */ \
+ posp->lnum += amount; \
+ } \
+ else if (amount_after && posp->lnum > line2) \
+ posp->lnum += amount_after; \
+ }
+
/*
* Adjust marks between "line1" and "line2" (inclusive) to move "amount" lines.
* Must be called before changed_*(), appended_lines() or deleted_lines().
@@ -1075,6 +1094,7 @@ mark_adjust_internal(
linenr_T *lp;
win_T *win;
tabpage_T *tab;
+ wininfo_T *wip;
static pos_T initpos = {1, 0, 0};

if (line2 < line1 && amount_after == 0L) // nothing to do
@@ -1192,21 +1212,7 @@ mark_adjust_internal(
win->w_topfill = 0;
#endif
}
- if (win->w_cursor.lnum >= line1 && win->w_cursor.lnum <= line2)
- {
- if (amount == MAXLNUM) // line with cursor is deleted
- {
- if (line1 <= 1)
- win->w_cursor.lnum = 1;
- else
- win->w_cursor.lnum = line1 - 1;
- win->w_cursor.col = 0;
- }
- else // keep cursor on the same line
- win->w_cursor.lnum += amount;
- }
- else if (amount_after && win->w_cursor.lnum > line2)
- win->w_cursor.lnum += amount_after;
+ one_adjust_cursor(&(win->w_cursor));
}

#ifdef FEAT_FOLDING
@@ -1221,6 +1227,10 @@ mark_adjust_internal(
// adjust diffs
diff_mark_adjust(line1, line2, amount, amount_after);
#endif
+
+ // adjust per-window "last cursor" positions
+ FOR_ALL_BUF_WININFO(curbuf, wip)
+ one_adjust_cursor(&(wip->wi_fpos));
}

// This code is used often, needs to be fast.
diff --git a/src/testdir/test_buffer.vim b/src/testdir/test_buffer.vim
index 90b7a9aa4..1ffa7ae87 100644
--- a/src/testdir/test_buffer.vim
+++ b/src/testdir/test_buffer.vim
@@ -623,17 +623,48 @@ func Test_switch_to_previously_viewed_buffer()
vsplit

call cursor(100, 3)
+ call assert_equal('100', getline('.'))
edit Xotherbuf
buffer Xviewbuf
call assert_equal([0, 100, 3, 0], getpos('.'))
+ call assert_equal('100', getline('.'))

+ edit Xotherbuf
+ wincmd p
+ normal! gg10dd
+ wincmd p
+ buffer Xviewbuf
+ call assert_equal([0, 90, 3, 0], getpos('.'))
+ call assert_equal('100', getline('.'))
+
+ edit Xotherbuf
+ wincmd p
+ normal! ggP
+ wincmd p
+ buffer Xviewbuf
+ call assert_equal([0, 100, 3, 0], getpos('.'))
+ call assert_equal('100', getline('.'))
+
+ edit Xotherbuf
+ wincmd p
+ normal! 96gg10ddgg
+ wincmd p
+ buffer Xviewbuf
+ " The original cursor line was deleted, so cursor is restored to the start
+ " of the line before the deleted range.
+ call assert_equal([0, 95, 1, 0], getpos('.'))
+ call assert_equal('95', getline('.'))
+
+ normal! u
exe win_id2win(oldwin) .. 'close'
setlocal bufhidden=hide

call cursor(200, 3)
+ call assert_equal('200', getline('.'))
edit Xotherbuf
buffer Xviewbuf
call assert_equal([0, 200, 3, 0], getpos('.'))
+ call assert_equal('200', getline('.'))

bwipe! Xotherbuf
bwipe! Xviewbuf
diff --git a/src/version.c b/src/version.c
index e225e9439..7b814f726 100644
--- a/src/version.c
+++ b/src/version.c
@@ -729,6 +729,8 @@ static char *(features[]) =

static int included_patches[] =
{ /* Add new patch number below this line */
+/**/
+ 1885,
/**/
1884,
/**/
Reply all
Reply to author
Forward
0 new messages