summaryrefslogtreecommitdiffstats
path: root/src/evalfunc.c
diff options
context:
space:
mode:
authorzeertzjq <zeertzjq@outlook.com>2024-05-24 07:48:51 +0200
committerChristian Brabandt <cb@256bit.org>2024-05-24 07:48:51 +0200
commit2b09de910458247b70751928217422c38fd5abf8 (patch)
treed649c131b442e7e3d3aa717ba4ca77de629748b7 /src/evalfunc.c
parent44cadaa18c1816f7a576f1870790ee01a23c1071 (diff)
patch 9.1.0441: getregionpos() can't properly indicate positions beyond eolv9.1.0441
Problem: getregionpos() can't properly indicate positions beyond eol. Solution: Add an "eol" flag that enables handling positions beyond end of line like getpos() does (zeertzjq). Also fix the problem that a position still has the coladd beyond the end of the line when its column has been clamped. In the last test case with TABs at the end of the line the old behavior is obviously wrong. I decided to gate this behind a flag because returning positions that don't correspond to actual characters in the line may lead to mistakes for callers that want to calculate the length of the selected text, so the behavior is only enabled if the caller wants it. closes: #14838 Signed-off-by: zeertzjq <zeertzjq@outlook.com> Signed-off-by: Christian Brabandt <cb@256bit.org>
Diffstat (limited to 'src/evalfunc.c')
-rw-r--r--src/evalfunc.c39
1 files changed, 32 insertions, 7 deletions
diff --git a/src/evalfunc.c b/src/evalfunc.c
index f70b032ad2..a1f8a8f8e2 100644
--- a/src/evalfunc.c
+++ b/src/evalfunc.c
@@ -5695,7 +5695,6 @@ f_getregion(typval_T *argvars, typval_T *rettv)
add_regionpos_range(typval_T *rettv, pos_T p1, pos_T p2)
{
list_T *l1, *l2, *l3;
- int max_col1, max_col2;
l1 = list_alloc();
if (l1 == NULL)
@@ -5737,16 +5736,14 @@ add_regionpos_range(typval_T *rettv, pos_T p1, pos_T p2)
return;
}
- max_col1 = ml_get_len(p1.lnum);
list_append_number(l2, curbuf->b_fnum);
list_append_number(l2, p1.lnum);
- list_append_number(l2, p1.col > max_col1 ? max_col1 : p1.col);
+ list_append_number(l2, p1.col);
list_append_number(l2, p1.coladd);
- max_col2 = ml_get_len(p2.lnum);
list_append_number(l3, curbuf->b_fnum);
list_append_number(l3, p2.lnum);
- list_append_number(l3, p2.col > max_col2 ? max_col2 : p2.col);
+ list_append_number(l3, p2.col);
list_append_number(l3, p2.coladd);
}
@@ -5759,6 +5756,7 @@ f_getregionpos(typval_T *argvars, typval_T *rettv)
pos_T p1, p2;
int inclusive = TRUE;
int region_type = -1;
+ int allow_eol = FALSE;
oparg_T oa;
int lnum;
@@ -5772,9 +5770,13 @@ f_getregionpos(typval_T *argvars, typval_T *rettv)
&p1, &p2, &inclusive, &region_type, &oa) == FAIL)
return;
+ if (argvars[2].v_type == VAR_DICT)
+ allow_eol = dict_get_bool(argvars[2].vval.v_dict, "eol", FALSE);
+
for (lnum = p1.lnum; lnum <= p2.lnum; lnum++)
{
- pos_T ret_p1, ret_p2;
+ pos_T ret_p1, ret_p2;
+ colnr_T line_len = ml_get_len(lnum);
if (region_type == MLINE)
{
@@ -5806,6 +5808,13 @@ f_getregionpos(typval_T *argvars, typval_T *rettv)
ret_p1.coladd = p1.coladd;
}
}
+ else if (region_type == MBLOCK && oa.start_vcol > bd.start_vcol)
+ {
+ // blockwise selection entirely beyond end of line
+ ret_p1.col = MAXCOL;
+ ret_p1.coladd = oa.start_vcol - bd.start_vcol;
+ bd.is_oneChar = TRUE;
+ }
else if (bd.startspaces > 0)
{
ret_p1.col = bd.textcol;
@@ -5820,7 +5829,7 @@ f_getregionpos(typval_T *argvars, typval_T *rettv)
if (bd.is_oneChar) // selection entirely inside one char
{
ret_p2.col = ret_p1.col;
- ret_p2.coladd = ret_p1.coladd + bd.startspaces;
+ ret_p2.coladd = ret_p1.coladd + bd.startspaces + bd.endspaces;
}
else if (bd.endspaces > 0)
{
@@ -5834,6 +5843,22 @@ f_getregionpos(typval_T *argvars, typval_T *rettv)
}
}
+ if (!allow_eol && ret_p1.col > line_len)
+ {
+ ret_p1.col = 0;
+ ret_p1.coladd = 0;
+ }
+ else if (ret_p1.col > line_len + 1)
+ ret_p1.col = line_len + 1;
+
+ if (!allow_eol && ret_p2.col > line_len)
+ {
+ ret_p2.col = ret_p1.col == 0 ? 0 : line_len;
+ ret_p2.coladd = 0;
+ }
+ else if (ret_p2.col > line_len + 1)
+ ret_p2.col = line_len + 1;
+
ret_p1.lnum = lnum;
ret_p2.lnum = lnum;
add_regionpos_range(rettv, ret_p1, ret_p2);