vim-patch:9.1.0433: Wrong yanking with exclusive selection and ve=all (#28933)

Problem:  Wrong yanking with exclusive selection and virtualedit=all,
          and integer overflow when using getregion() on it.
Solution: Set coladd when decreasing column and 'virtualedit' is active.
          Add more tests for getregion() with 'virtualedit' (zeertzjq).

closes: vim/vim#14830

701ad50a9e
This commit is contained in:
zeertzjq
2024-05-23 14:23:09 +08:00
committed by GitHub
parent cd48b72b60
commit bdf15dbe69
3 changed files with 223 additions and 34 deletions

View File

@@ -2913,24 +2913,13 @@ static int getregionpos(typval_T *argvars, typval_T *rettv, pos_T *p1, pos_T *p2
}
if (*region_type == kMTCharWise) {
// handle 'selection' == "exclusive"
// Handle 'selection' == "exclusive".
if (is_select_exclusive && !equalpos(*p1, *p2)) {
if (p2->coladd > 0) {
p2->coladd--;
} else if (p2->col > 0) {
p2->col--;
mark_mb_adjustpos(curbuf, p2);
} else if (p2->lnum > 1) {
p2->lnum--;
p2->col = ml_get_len(p2->lnum);
if (p2->col > 0) {
p2->col--;
mark_mb_adjustpos(curbuf, p2);
}
}
// When backing up to previous line, inclusive becomes false.
*inclusive = !unadjust_for_sel_inner(p2);
}
// if fp2 is on NUL (empty line) inclusive becomes false
if (*ml_get_pos(p2) == NUL && !virtual_op) {
// If p2 is on NUL (end of line), inclusive becomes false.
if (*inclusive && !virtual_op && *ml_get_pos(p2) == NUL) {
*inclusive = false;
}
} else if (*region_type == kMTBlockWise) {

View File

@@ -6014,26 +6014,37 @@ static void adjust_for_sel(cmdarg_T *cap)
bool unadjust_for_sel(void)
{
if (*p_sel == 'e' && !equalpos(VIsual, curwin->w_cursor)) {
pos_T *pp;
if (lt(VIsual, curwin->w_cursor)) {
pp = &curwin->w_cursor;
} else {
pp = &VIsual;
}
if (pp->coladd > 0) {
pp->coladd--;
} else if (pp->col > 0) {
pp->col--;
mark_mb_adjustpos(curbuf, pp);
} else if (pp->lnum > 1) {
pp->lnum--;
pp->col = ml_get_len(pp->lnum);
return true;
}
return unadjust_for_sel_inner(lt(VIsual, curwin->w_cursor)
? &curwin->w_cursor : &VIsual);
}
return false;
}
/// Move position "*pp" back one character for 'selection' == "exclusive".
///
/// @return true when backed up to the previous line.
bool unadjust_for_sel_inner(pos_T *pp)
{
colnr_T cs, ce;
if (pp->coladd > 0) {
pp->coladd--;
} else if (pp->col > 0) {
pp->col--;
mark_mb_adjustpos(curbuf, pp);
if (virtual_active(curwin)) {
getvcol(curwin, pp, &cs, NULL, &ce);
pp->coladd = ce - cs;
}
} else if (pp->lnum > 1) {
pp->lnum--;
pp->col = ml_get_len(pp->lnum);
return true;
}
return false;
}
/// SELECT key in Normal or Visual mode: end of Select mode mapping.
static void nv_select(cmdarg_T *cap)
{