vim-patch:9.0.0712: wrong column when calling setcursorcharpos() with zero lnum

Problem:    Wrong column when calling setcursorcharpos() with zero lnum.
Solution:   Set the line number before calling buf_charidx_to_byteidx().
            (closes vim/vim#11329)
79f234499b
This commit is contained in:
zeertzjq
2022-10-10 21:38:24 +08:00
parent 5c9f6bdd8c
commit 249cb8345d
3 changed files with 25 additions and 11 deletions

View File

@@ -6454,11 +6454,14 @@ pos_T *var2fpos(const typval_T *const tv, const bool dollar_lnum, int *const ret
return NULL; return NULL;
} }
/// Convert list in "arg" into a position and optional file number. /// Convert list in "arg" into position "posp" and optional file number "fnump".
/// When "fnump" is NULL there is no file number, only 3 items. /// When "fnump" is NULL there is no file number, only 3 items: [lnum, col, off]
/// Note that the column is passed on as-is, the caller may want to decrement /// Note that the column is passed on as-is, the caller may want to decrement
/// it to use 1 for the first column. /// it to use 1 for the first column.
/// ///
/// @param charcol if true, use the column as the character index instead of the
/// byte index.
///
/// @return FAIL when conversion is not possible, doesn't check the position for /// @return FAIL when conversion is not possible, doesn't check the position for
/// validity. /// validity.
int list2fpos(typval_T *arg, pos_T *posp, int *fnump, colnr_T *curswantp, bool charcol) int list2fpos(typval_T *arg, pos_T *posp, int *fnump, colnr_T *curswantp, bool charcol)
@@ -6498,13 +6501,16 @@ int list2fpos(typval_T *arg, pos_T *posp, int *fnump, colnr_T *curswantp, bool c
return FAIL; return FAIL;
} }
// If character position is specified, then convert to byte position // If character position is specified, then convert to byte position
// If the line number is zero use the cursor line.
if (charcol) { if (charcol) {
// Get the text for the specified line in a loaded buffer // Get the text for the specified line in a loaded buffer
buf_T *buf = buflist_findnr(fnump == NULL ? curbuf->b_fnum : *fnump); buf_T *buf = buflist_findnr(fnump == NULL ? curbuf->b_fnum : *fnump);
if (buf == NULL || buf->b_ml.ml_mfp == NULL) { if (buf == NULL || buf->b_ml.ml_mfp == NULL) {
return FAIL; return FAIL;
} }
n = buf_charidx_to_byteidx(buf, posp->lnum, (int)n) + 1; n = buf_charidx_to_byteidx(buf,
posp->lnum == 0 ? curwin->w_cursor.lnum : posp->lnum,
(int)n) + 1;
} }
posp->col = (colnr_T)n; posp->col = (colnr_T)n;

View File

@@ -1270,7 +1270,7 @@ static void f_ctxsize(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
/// Otherwise use the column number as a byte offset. /// Otherwise use the column number as a byte offset.
static void set_cursorpos(typval_T *argvars, typval_T *rettv, bool charcol) static void set_cursorpos(typval_T *argvars, typval_T *rettv, bool charcol)
{ {
long line, col; long lnum, col;
long coladd = 0; long coladd = 0;
bool set_curswant = true; bool set_curswant = true;
@@ -1284,7 +1284,7 @@ static void set_cursorpos(typval_T *argvars, typval_T *rettv, bool charcol)
return; return;
} }
line = pos.lnum; lnum = pos.lnum;
col = pos.col; col = pos.col;
coladd = pos.coladd; coladd = pos.coladd;
if (curswant >= 0) { if (curswant >= 0) {
@@ -1293,13 +1293,15 @@ static void set_cursorpos(typval_T *argvars, typval_T *rettv, bool charcol)
} }
} else if ((argvars[0].v_type == VAR_NUMBER || argvars[0].v_type == VAR_STRING) } else if ((argvars[0].v_type == VAR_NUMBER || argvars[0].v_type == VAR_STRING)
&& (argvars[1].v_type == VAR_NUMBER || argvars[1].v_type == VAR_STRING)) { && (argvars[1].v_type == VAR_NUMBER || argvars[1].v_type == VAR_STRING)) {
line = tv_get_lnum(argvars); lnum = tv_get_lnum(argvars);
if (line < 0) { if (lnum < 0) {
semsg(_(e_invarg2), tv_get_string(&argvars[0])); semsg(_(e_invarg2), tv_get_string(&argvars[0]));
} else if (lnum == 0) {
lnum = curwin->w_cursor.lnum;
} }
col = (long)tv_get_number_chk(&argvars[1], NULL); col = (long)tv_get_number_chk(&argvars[1], NULL);
if (charcol) { if (charcol) {
col = buf_charidx_to_byteidx(curbuf, (linenr_T)line, (int)col) + 1; col = buf_charidx_to_byteidx(curbuf, (linenr_T)lnum, (int)col) + 1;
} }
if (argvars[2].v_type != VAR_UNKNOWN) { if (argvars[2].v_type != VAR_UNKNOWN) {
coladd = (long)tv_get_number_chk(&argvars[2], NULL); coladd = (long)tv_get_number_chk(&argvars[2], NULL);
@@ -1308,11 +1310,11 @@ static void set_cursorpos(typval_T *argvars, typval_T *rettv, bool charcol)
emsg(_(e_invarg)); emsg(_(e_invarg));
return; return;
} }
if (line < 0 || col < 0 || coladd < 0) { if (lnum < 0 || col < 0 || coladd < 0) {
return; // type error; errmsg already given return; // type error; errmsg already given
} }
if (line > 0) { if (lnum > 0) {
curwin->w_cursor.lnum = (linenr_T)line; curwin->w_cursor.lnum = (linenr_T)lnum;
} }
if (col > 0) { if (col > 0) {
curwin->w_cursor.col = (colnr_T)col - 1; curwin->w_cursor.col = (colnr_T)col - 1;

View File

@@ -353,8 +353,14 @@ func Test_setcursorcharpos()
normal G normal G
call setcursorcharpos([1, 1]) call setcursorcharpos([1, 1])
call assert_equal([1, 1], [line('.'), col('.')]) call assert_equal([1, 1], [line('.'), col('.')])
call setcursorcharpos([2, 7, 0]) call setcursorcharpos([2, 7, 0])
call assert_equal([2, 9], [line('.'), col('.')]) call assert_equal([2, 9], [line('.'), col('.')])
call setcursorcharpos([0, 7, 0])
call assert_equal([2, 9], [line('.'), col('.')])
call setcursorcharpos(0, 7, 0)
call assert_equal([2, 9], [line('.'), col('.')])
call setcursorcharpos(3, 4) call setcursorcharpos(3, 4)
call assert_equal([3, 1], [line('.'), col('.')]) call assert_equal([3, 1], [line('.'), col('.')])
call setcursorcharpos([3, 1]) call setcursorcharpos([3, 1])