fix(marks): make jumpoptions=view work with 'smoothscroll' (#38339)

Problem:  'jumpoptions' "view" doesn't remember skipcol and may lead to
          glitched display with 'smoothscroll'.
Solution: Save skipcol in the mark view. Also make sure skipcol doesn't
          exceed line size.
This commit is contained in:
zeertzjq
2026-03-17 21:52:25 +08:00
committed by GitHub
parent a5b8cf145d
commit 5773f0e994
8 changed files with 171 additions and 101 deletions

View File

@@ -2764,7 +2764,7 @@ void buflist_setfpos(buf_T *const buf, win_T *const win, linenr_T lnum, colnr_T
wip->wi_mark.mark.lnum = lnum;
wip->wi_mark.mark.col = col;
if (win != NULL) {
wip->wi_mark.view = mark_view_make(win->w_topline, wip->wi_mark.mark);
wip->wi_mark.view = mark_view_make(win, wip->wi_mark.mark);
}
}
if (win != NULL) {

View File

@@ -254,7 +254,7 @@ static void changed_common(buf_T *buf, linenr_T lnum, colnr_T col, linenr_T lnum
if (curwin->w_buffer == buf) {
if (lnum >= curwin->w_topline && lnum <= curwin->w_botline) {
view = mark_view_make(curwin->w_topline, curwin->w_cursor);
view = mark_view_make(curwin, curwin->w_cursor);
}
}
RESET_FMARK(&buf->b_last_change, ((pos_T) { lnum, col, 0 }), buf->handle, view);

View File

@@ -3087,7 +3087,7 @@ static bool ins_esc(int *count, int cmdchar, bool nomove)
// Remember the last Insert position in the '^ mark.
if ((cmdmod.cmod_flags & CMOD_KEEPJUMPS) == 0) {
fmarkv_T view = mark_view_make(curwin->w_topline, curwin->w_cursor);
fmarkv_T view = mark_view_make(curwin, curwin->w_cursor);
RESET_FMARK(&curbuf->b_last_insert, curwin->w_cursor, curbuf->b_fnum, view);
}

View File

@@ -41,6 +41,7 @@
#include "nvim/os/time.h"
#include "nvim/os/time_defs.h"
#include "nvim/path.h"
#include "nvim/plines.h"
#include "nvim/pos_defs.h"
#include "nvim/quickfix.h"
#include "nvim/strings.h"
@@ -63,7 +64,7 @@
// Returns OK on success, FAIL if bad name given.
int setmark(int c)
{
fmarkv_T view = mark_view_make(curwin->w_topline, curwin->w_cursor);
fmarkv_T view = mark_view_make(curwin, curwin->w_cursor);
return setmark_pos(c, &curwin->w_cursor, curbuf->b_fnum, &view);
}
@@ -283,7 +284,7 @@ void setpcmark(void)
curwin->w_jumplistidx = curwin->w_jumplistlen;
fm = &curwin->w_jumplist[curwin->w_jumplistlen - 1];
fmarkv_T view = mark_view_make(curwin->w_topline, curwin->w_pcmark);
fmarkv_T view = mark_view_make(curwin, curwin->w_pcmark);
SET_XFMARK(fm, curwin->w_pcmark, curbuf->b_fnum, view, NULL);
}
@@ -691,13 +692,17 @@ void mark_view_restore(fmark_T *fm)
// and this check can prevent restoring mark view in that case.
if (topline >= 1) {
set_topline(curwin, topline);
curwin->w_skipcol = (fm->view.skipcol > 0
&& !hasFolding(curwin, topline, NULL, NULL)
&& fm->view.skipcol < linetabsize_eol(curwin, topline))
? fm->view.skipcol : 0;
}
}
}
fmarkv_T mark_view_make(linenr_T topline, pos_T pos)
fmarkv_T mark_view_make(const win_T *wp, pos_T pos)
{
return (fmarkv_T){ pos.lnum - topline };
return (fmarkv_T){ pos.lnum - wp->w_topline, wp->w_skipcol };
}
/// Search for the next named mark in the current file from a start position.

View File

@@ -74,9 +74,10 @@ typedef enum {
typedef struct {
linenr_T topline_offset; ///< Amount of lines from the mark lnum to the top of the window.
///< Use MAXLNUM to indicate that the mark does not have a view.
colnr_T skipcol;
} fmarkv_T;
#define INIT_FMARKV { MAXLNUM }
#define INIT_FMARKV { MAXLNUM, 0 }
/// Structure defining single local mark
typedef struct {

View File

@@ -534,7 +534,7 @@ void do_tag(char *tag, int type, int count, int forceit, bool verbose)
if (save_pos) {
tagstack[tagstackidx].fmark.mark = curwin->w_cursor;
tagstack[tagstackidx].fmark.fnum = curbuf->b_fnum;
tagstack[tagstackidx].fmark.view = mark_view_make(curwin->w_topline, curwin->w_cursor);
tagstack[tagstackidx].fmark.view = mark_view_make(curwin, curwin->w_cursor);
}
// Curwin will change in the call to jumpto_tag() if ":stag" was