aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorzeertzjq <zeertzjq@outlook.com>2023-08-18 15:00:03 +0800
committerzeertzjq <zeertzjq@outlook.com>2023-08-18 19:34:16 +0800
commit551998b7eed7dd411e4d14f65b108ae8a93c4081 (patch)
tree3121aa578a285678a58e2dbd1ed578750a284d95
parentb0dda500e9b45e39e872d76e8b753933c5467f83 (diff)
downloadrneovim-551998b7eed7dd411e4d14f65b108ae8a93c4081.tar.gz
rneovim-551998b7eed7dd411e4d14f65b108ae8a93c4081.tar.bz2
rneovim-551998b7eed7dd411e4d14f65b108ae8a93c4081.zip
vim-patch:9.0.1725: cursor pos wrong after concealed text with 'virtualedit'
Problem: Wrong cursor position when clicking after concealed text with 'virtualedit'. Solution: Store virtual columns in ScreenCols[] instead of text columns, and always use coladvance() when clicking. This also fixes incorrect curswant when clicking on a TAB, so now Test_normal_click_on_ctrl_char() asserts the same results as the ones before patch 9.0.0048. closes: vim/vim#12808 https://github.com/vim/vim/commit/e500ae8e29ad921378085f5d70ee5c0c537be1ba Remove the mouse_adjust_click() function. There is a difference in behavior with the old mouse_adjust_click() approach: when clicking on the character immediately after concealed text that is completely hidden, cursor is put on the clicked character rather than at the start of the concealed text. The new behavior is better, but it causes unnecessary scrolling in a functional test (which is an existing issue unrelated to these patches), so adjust the test. Now fully merged: vim-patch:9.0.0177: cursor position wrong with 'virtualedit' and mouse click
-rw-r--r--src/nvim/drawline.c12
-rw-r--r--src/nvim/grid.c24
-rw-r--r--src/nvim/grid.h1
-rw-r--r--src/nvim/grid_defs.h15
-rw-r--r--src/nvim/mouse.c188
-rw-r--r--test/functional/ui/mouse_spec.lua3
-rw-r--r--test/old/testdir/test_conceal.vim49
-rw-r--r--test/old/testdir/test_normal.vim10
-rw-r--r--test/old/testdir/test_virtualedit.vim6
9 files changed, 162 insertions, 146 deletions
diff --git a/src/nvim/drawline.c b/src/nvim/drawline.c
index d0142c6efa..4c90a562ce 100644
--- a/src/nvim/drawline.c
+++ b/src/nvim/drawline.c
@@ -2022,6 +2022,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl
c = NUL;
} else {
int c0;
+ char *prev_ptr = ptr;
// Get a character from the line itself.
c0 = c = (uint8_t)(*ptr);
@@ -2209,7 +2210,6 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl
v = (ptr - line);
if (spv->spv_has_spell && v >= word_end && v > cur_checked_col) {
spell_attr = 0;
- char *prev_ptr = ptr - mb_l;
// do not calculate cap_col at the end of the line or when
// only white space is following
if (c != 0 && (*skipwhite(prev_ptr) != NUL) && can_spell) {
@@ -2746,6 +2746,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl
eol_attr = hl_combine_attr(wlv.cul_attr, eol_attr);
}
linebuf_attr[wlv.off] = eol_attr;
+ linebuf_vcol[wlv.off] = MAXCOL;
if (wp->w_p_rl) {
wlv.col--;
wlv.off--;
@@ -2832,6 +2833,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl
while (wp->w_p_rl ? wlv.col >= 0 : wlv.col < grid->cols) {
schar_from_ascii(linebuf_char[wlv.off], ' ');
+ linebuf_vcol[wlv.off] = MAXCOL;
wlv.col += col_stride;
if (draw_color_col) {
draw_color_col = advance_color_col(VCOL_HLC, &color_cols);
@@ -2866,6 +2868,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl
while (wlv.col >= 0 && wlv.col < grid->cols) {
schar_from_ascii(linebuf_char[wlv.off], ' ');
linebuf_attr[wlv.off] = wlv.vcol >= TERM_ATTRS_MAX ? 0 : term_attrs[wlv.vcol];
+ linebuf_vcol[wlv.off] = wlv.vcol;
wlv.off += n;
wlv.vcol += n;
wlv.col += n;
@@ -2945,9 +2948,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl
// Skip characters that are left of the screen for 'nowrap'.
vcol_prev = wlv.vcol;
if (wlv.draw_state < WL_LINE || n_skip <= 0) {
- //
// Store the character.
- //
if (wp->w_p_rl && utf_char2cells(mb_c) > 1) {
// A double-wide character is: put first half in left cell.
wlv.off--;
@@ -2965,6 +2966,8 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl
linebuf_attr[wlv.off] = wlv.char_attr;
}
+ linebuf_vcol[wlv.off] = wlv.vcol;
+
if (utf_char2cells(mb_c) > 1) {
// Need to fill two screen columns.
wlv.off++;
@@ -2980,6 +2983,9 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl
if (wlv.tocol == wlv.vcol) {
wlv.tocol++;
}
+
+ linebuf_vcol[wlv.off] = wlv.vcol;
+
if (wp->w_p_rl) {
// now it's time to backup one cell
wlv.off--;
diff --git a/src/nvim/grid.c b/src/nvim/grid.c
index aef10db414..e25b1b1a73 100644
--- a/src/nvim/grid.c
+++ b/src/nvim/grid.c
@@ -78,6 +78,7 @@ void grid_clear_line(ScreenGrid *grid, size_t off, int width, bool valid)
}
int fill = valid ? 0 : -1;
(void)memset(grid->attrs + off, fill, (size_t)width * sizeof(sattr_T));
+ (void)memset(grid->vcols + off, -1, (size_t)width * sizeof(colnr_T));
}
void grid_invalidate(ScreenGrid *grid)
@@ -196,6 +197,7 @@ void grid_put_schar(ScreenGrid *grid, int row, int col, char *schar, int attr)
// TODO(bfredl): Y U NO DOUBLEWIDTH?
put_dirty_last = MAX(put_dirty_last, col + 1);
}
+ grid->vcols[off] = -1;
}
/// like grid_puts(), but output "text[len]". When "len" is -1 output up to
@@ -324,9 +326,11 @@ int grid_puts_len(ScreenGrid *grid, const char *text, int textlen, int row, int
schar_copy(grid->chars[off], buf);
grid->attrs[off] = attr;
+ grid->vcols[off] = -1;
if (mbyte_cells == 2) {
grid->chars[off + 1][0] = 0;
grid->attrs[off + 1] = attr;
+ grid->vcols[off + 1] = -1;
}
put_dirty_first = MIN(put_dirty_first, col);
put_dirty_last = MAX(put_dirty_last, col + mbyte_cells);
@@ -437,6 +441,7 @@ void grid_fill(ScreenGrid *grid, int start_row, int end_row, int start_col, int
}
dirty_last = col + 1;
}
+ grid->vcols[off] = -1;
if (col == start_col) {
schar_from_char(sc, c2);
}
@@ -620,13 +625,20 @@ void grid_put_linebuf(ScreenGrid *grid, int row, int coloff, int endcol, int cle
}
grid->attrs[off_to] = linebuf_attr[off_from];
+ grid->vcols[off_to] = linebuf_vcol[off_from];
// For simplicity set the attributes of second half of a
// double-wide character equal to the first half.
if (char_cells == 2) {
grid->attrs[off_to + 1] = linebuf_attr[off_from];
+ grid->vcols[off_to + 1] = linebuf_vcol[off_from + 1];
}
}
+ grid->vcols[off_to] = linebuf_vcol[off_from];
+ if (char_cells == 2) {
+ grid->vcols[off_to + 1] = linebuf_vcol[off_from];
+ }
+
off_to += (size_t)char_cells;
off_from += (size_t)char_cells;
col += char_cells;
@@ -659,6 +671,7 @@ void grid_put_linebuf(ScreenGrid *grid, int row, int coloff, int endcol, int cle
}
clear_end = col + 1;
}
+ grid->vcols[off_to] = MAXCOL;
col++;
off_to++;
}
@@ -690,6 +703,8 @@ void grid_alloc(ScreenGrid *grid, int rows, int columns, bool copy, bool valid)
size_t ncells = (size_t)rows * (size_t)columns;
ngrid.chars = xmalloc(ncells * sizeof(schar_T));
ngrid.attrs = xmalloc(ncells * sizeof(sattr_T));
+ ngrid.vcols = xmalloc(ncells * sizeof(colnr_T));
+ memset(ngrid.vcols, -1, ncells * sizeof(colnr_T));
ngrid.line_offset = xmalloc((size_t)rows * sizeof(*ngrid.line_offset));
ngrid.line_wraps = xmalloc((size_t)rows * sizeof(*ngrid.line_wraps));
@@ -715,6 +730,9 @@ void grid_alloc(ScreenGrid *grid, int rows, int columns, bool copy, bool valid)
memmove(ngrid.attrs + ngrid.line_offset[new_row],
grid->attrs + grid->line_offset[new_row],
(size_t)len * sizeof(sattr_T));
+ memmove(ngrid.vcols + ngrid.line_offset[new_row],
+ grid->vcols + grid->line_offset[new_row],
+ (size_t)len * sizeof(colnr_T));
}
}
}
@@ -726,8 +744,10 @@ void grid_alloc(ScreenGrid *grid, int rows, int columns, bool copy, bool valid)
if (linebuf_size < (size_t)columns) {
xfree(linebuf_char);
xfree(linebuf_attr);
+ xfree(linebuf_vcol);
linebuf_char = xmalloc((size_t)columns * sizeof(schar_T));
linebuf_attr = xmalloc((size_t)columns * sizeof(sattr_T));
+ linebuf_vcol = xmalloc((size_t)columns * sizeof(colnr_T));
linebuf_size = (size_t)columns;
}
}
@@ -736,11 +756,13 @@ void grid_free(ScreenGrid *grid)
{
xfree(grid->chars);
xfree(grid->attrs);
+ xfree(grid->vcols);
xfree(grid->line_offset);
xfree(grid->line_wraps);
grid->chars = NULL;
grid->attrs = NULL;
+ grid->vcols = NULL;
grid->line_offset = NULL;
grid->line_wraps = NULL;
}
@@ -751,6 +773,7 @@ void grid_free_all_mem(void)
grid_free(&default_grid);
xfree(linebuf_char);
xfree(linebuf_attr);
+ xfree(linebuf_vcol);
}
/// (Re)allocates a window grid if size changed while in ext_multigrid mode.
@@ -939,6 +962,7 @@ static void linecopy(ScreenGrid *grid, int to, int from, int col, int width)
memmove(grid->chars + off_to, grid->chars + off_from, (size_t)width * sizeof(schar_T));
memmove(grid->attrs + off_to, grid->attrs + off_from, (size_t)width * sizeof(sattr_T));
+ memmove(grid->vcols + off_to, grid->vcols + off_from, (size_t)width * sizeof(colnr_T));
}
win_T *get_win_by_grid_handle(handle_T handle)
diff --git a/src/nvim/grid.h b/src/nvim/grid.h
index deb3d3785d..0db97345d1 100644
--- a/src/nvim/grid.h
+++ b/src/nvim/grid.h
@@ -27,6 +27,7 @@ EXTERN bool resizing_screen INIT(= 0);
EXTERN schar_T *linebuf_char INIT(= NULL);
EXTERN sattr_T *linebuf_attr INIT(= NULL);
+EXTERN colnr_T *linebuf_vcol INIT(= NULL);
// Low-level functions to manipulate individual character cells on the
// screen grid.
diff --git a/src/nvim/grid_defs.h b/src/nvim/grid_defs.h
index aae61cc719..aeaadea73c 100644
--- a/src/nvim/grid_defs.h
+++ b/src/nvim/grid_defs.h
@@ -5,6 +5,7 @@
#include <stddef.h>
#include <stdint.h>
+#include "nvim/pos.h"
#include "nvim/types.h"
#define MAX_MCO 6 // fixed value for 'maxcombine'
@@ -37,9 +38,14 @@ enum {
/// screen is cleared, the cells should be filled with a single whitespace char.
///
/// attrs[] contains the highlighting attribute for each cell.
-/// line_offset[n] is the offset from chars[] and attrs[] for the
-/// start of line 'n'. These offsets are in general not linear, as full screen
-/// scrolling is implemented by rotating the offsets in the line_offset array.
+///
+/// vcols[] countain the virtual columns in the line. -1 means not available
+/// (below last line), MAXCOL means after the end of the line.
+///
+/// line_offset[n] is the offset from chars[], attrs[] and vcols[] for the start
+/// of line 'n'. These offsets are in general not linear, as full screen scrolling
+/// is implemented by rotating the offsets in the line_offset array.
+///
/// line_wraps[] is an array of boolean flags indicating if the screen line
/// wraps to the next line. It can only be true if a window occupies the entire
/// screen width.
@@ -49,6 +55,7 @@ struct ScreenGrid {
schar_T *chars;
sattr_T *attrs;
+ colnr_T *vcols;
size_t *line_offset;
char *line_wraps;
@@ -106,7 +113,7 @@ struct ScreenGrid {
bool comp_disabled;
};
-#define SCREEN_GRID_INIT { 0, NULL, NULL, NULL, NULL, NULL, 0, 0, false, \
+#define SCREEN_GRID_INIT { 0, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, false, \
false, 0, 0, NULL, false, true, 0, \
0, 0, 0, 0, 0, false }
diff --git a/src/nvim/mouse.c b/src/nvim/mouse.c
index d8341d2b10..0f3405bf0d 100644
--- a/src/nvim/mouse.c
+++ b/src/nvim/mouse.c
@@ -1329,15 +1329,15 @@ retnomove:
}
}
+ colnr_T col_from_screen = -1;
+ int mouse_fold_flags = 0;
+ mouse_check_grid(&col_from_screen, &mouse_fold_flags);
+
// compute the position in the buffer line from the posn on the screen
if (mouse_comp_pos(curwin, &row, &col, &curwin->w_cursor.lnum)) {
mouse_past_bottom = true;
}
- if (!(flags & MOUSE_RELEASED) && which_button == MOUSE_LEFT) {
- col = mouse_adjust_click(curwin, row, col);
- }
-
// Start Visual mode before coladvance(), for when 'sel' != "old"
if ((flags & MOUSE_MAY_VIS) && !VIsual_active) {
VIsual = old_cursor;
@@ -1352,6 +1352,10 @@ retnomove:
}
}
+ if (col_from_screen >= 0) {
+ col = col_from_screen;
+ }
+
curwin->w_curswant = col;
curwin->w_set_curswant = false; // May still have been true
if (coladvance(col) == FAIL) { // Mouse click beyond end of line
@@ -1369,14 +1373,14 @@ retnomove:
count |= CURSOR_MOVED; // Cursor has moved
}
- count |= mouse_check_fold();
+ count |= mouse_fold_flags;
return count;
}
-// Compute the position in the buffer line from the posn on the screen in
-// window "win".
-// Returns true if the position is below the last line.
+/// Compute the position in the buffer line from the posn on the screen in
+/// window "win".
+/// Returns true if the position is below the last line.
bool mouse_comp_pos(win_T *win, int *rowp, int *colp, linenr_T *lnump)
{
int col = *colp;
@@ -1573,9 +1577,7 @@ static void set_mouse_topline(win_T *wp)
orig_topfill = wp->w_topfill;
}
-///
/// Return length of line "lnum" for horizontal scrolling.
-///
static colnr_T scroll_line_len(linenr_T lnum)
{
colnr_T col = 0;
@@ -1663,116 +1665,9 @@ bool mouse_scroll_horiz(int dir)
return set_leftcol(leftcol);
}
-/// Adjusts the clicked column position when 'conceallevel' > 0
-static int mouse_adjust_click(win_T *wp, int row, int col)
-{
- if (!(wp->w_p_cole > 0 && curbuf->b_p_smc > 0
- && wp->w_leftcol < curbuf->b_p_smc && conceal_cursor_line(wp))) {
- return col;
- }
-
- // `col` is the position within the current line that is highlighted by the
- // cursor without consideration for concealed characters. The current line is
- // scanned *up to* `col`, nudging it left or right when concealed characters
- // are encountered.
- //
- // win_chartabsize() is used to keep track of the virtual column position
- // relative to the line's bytes. For example: if col == 9 and the line
- // starts with a tab that's 8 columns wide, we would want the cursor to be
- // highlighting the second byte, not the ninth.
-
- linenr_T lnum = wp->w_cursor.lnum;
- // Make a copy of the line, because syntax matching may free it.
- char *line = xstrdup(ml_get(lnum));
- char *ptr = line;
- char *ptr_end;
- char *ptr_row_offset = line; // Where we begin adjusting `ptr_end`
-
- // Find the offset where scanning should begin.
- int offset = wp->w_leftcol;
- if (row > 0) {
- offset += row * (wp->w_width_inner - win_col_off(wp) - win_col_off2(wp) -
- wp->w_leftcol + wp->w_skipcol);
- }
-
- int vcol;
-
- if (offset) {
- // Skip everything up to an offset since nvim takes care of displaying the
- // correct portion of the line when horizontally scrolling.
- // When 'wrap' is enabled, only the row (of the wrapped line) needs to be
- // checked for concealed characters.
- vcol = 0;
- while (vcol < offset && *ptr != NUL) {
- vcol += win_chartabsize(curwin, ptr, vcol);
- ptr += utfc_ptr2len(ptr);
- }
-
- ptr_row_offset = ptr;
- }
-
- // Align `ptr_end` with `col`
- vcol = offset;
- ptr_end = ptr_row_offset;
- while (vcol < col && *ptr_end != NUL) {
- vcol += win_chartabsize(curwin, ptr_end, vcol);
- ptr_end += utfc_ptr2len(ptr_end);
- }
-
- int prev_matchid;
- int nudge = 0;
-
- vcol = offset;
-
-#define INCR() nudge++; ptr_end += utfc_ptr2len(ptr_end)
-#define DECR() nudge--; ptr_end -= utfc_ptr2len(ptr_end)
-
- while (ptr < ptr_end && *ptr != NUL) {
- int cwidth = win_chartabsize(curwin, ptr, vcol);
- vcol += cwidth;
- if (cwidth > 1 && *ptr == '\t' && nudge > 0) {
- // A tab will "absorb" any previous adjustments.
- cwidth = MIN(cwidth, nudge);
- while (cwidth > 0) {
- DECR();
- cwidth--;
- }
- }
-
- int matchid = syn_get_concealed_id(wp, lnum, (colnr_T)(ptr - line));
- if (matchid != 0) {
- if (wp->w_p_cole == 3) {
- INCR();
- } else {
- if (!(row > 0 && ptr == ptr_row_offset)
- && (wp->w_p_cole == 1 || (wp->w_p_cole == 2
- && (wp->w_p_lcs_chars.conceal != NUL
- || syn_get_sub_char() != NUL)))) {
- // At least one placeholder character will be displayed.
- DECR();
- }
-
- prev_matchid = matchid;
-
- while (prev_matchid == matchid && *ptr != NUL) {
- INCR();
- ptr += utfc_ptr2len(ptr);
- matchid = syn_get_concealed_id(wp, lnum, (colnr_T)(ptr - line));
- }
-
- continue;
- }
- }
-
- ptr += utfc_ptr2len(ptr);
- }
-
- xfree(line);
- return col + nudge;
-}
-
-// Check clicked cell is foldcolumn
-int mouse_check_fold(void)
+/// Check clicked cell on its grid
+static void mouse_check_grid(colnr_T *vcolp, int *flagsp)
+ FUNC_ATTR_NONNULL_ALL
{
int click_grid = mouse_grid;
int click_row = mouse_row;
@@ -1780,7 +1675,8 @@ int mouse_check_fold(void)
int mouse_char = ' ';
int max_row = Rows;
int max_col = Columns;
- int multigrid = ui_has(kUIMultigrid);
+ bool multigrid = ui_has(kUIMultigrid);
+ colnr_T col_from_screen = -1;
win_T *wp = mouse_find_win(&click_grid, &click_row, &click_col);
if (wp && multigrid) {
@@ -1792,14 +1688,46 @@ int mouse_check_fold(void)
&& mouse_col >= 0 && mouse_col < max_col) {
ScreenGrid *gp = multigrid ? &wp->w_grid_alloc : &default_grid;
int fdc = win_fdccol_count(wp);
- int row = multigrid && mouse_grid == 0 ? click_row : mouse_row;
- int col = multigrid && mouse_grid == 0 ? click_col : mouse_col;
+ int use_row = multigrid && mouse_grid == 0 ? click_row : mouse_row;
+ int use_col = multigrid && mouse_grid == 0 ? click_col : mouse_col;
- // Remember the character under the mouse, might be one of foldclose or
- // foldopen fillchars in the fold column.
if (gp->chars != NULL) {
- mouse_char = utf_ptr2char((char *)gp->chars[gp->line_offset[row]
- + (unsigned)col]);
+ const size_t off = gp->line_offset[use_row] + (size_t)use_col;
+
+ // Only use vcols[] after the window was redrawn. Mainly matters
+ // for tests, a user would not click before redrawing.
+ if (wp->w_redr_type == 0) {
+ col_from_screen = gp->vcols[off];
+ }
+
+ if (col_from_screen == MAXCOL) {
+ // When clicking after end of line, still need to set correct curswant
+ size_t off_l = gp->line_offset[use_row];
+ if (gp->vcols[off_l] < MAXCOL) {
+ // Binary search to find last char in line
+ size_t off_r = off;
+ while (off_l < off_r) {
+ size_t off_m = (off_l + off_r + 1) / 2;
+ if (gp->vcols[off_m] < MAXCOL) {
+ off_l = off_m;
+ } else {
+ off_r = off_m - 1;
+ }
+ }
+ *vcolp = gp->vcols[off_r] + (int)(off - off_r);
+ } else {
+ // Shouldn't normally happen
+ *vcolp = MAXCOL;
+ }
+ } else if (col_from_screen >= 0) {
+ // Use the virtual column from vcols[], it is accurate also after
+ // concealed characters.
+ *vcolp = col_from_screen;
+ }
+
+ // Remember the character under the mouse, might be one of foldclose or
+ // foldopen fillchars in the fold column.
+ mouse_char = utf_ptr2char((char *)gp->chars[off]);
}
// Check for position outside of the fold column.
@@ -1810,10 +1738,8 @@ int mouse_check_fold(void)
}
if (wp && mouse_char == wp->w_p_fcs_chars.foldclosed) {
- return MOUSE_FOLD_OPEN;
+ *flagsp |= MOUSE_FOLD_OPEN;
} else if (mouse_char != ' ') {
- return MOUSE_FOLD_CLOSE;
+ *flagsp |= MOUSE_FOLD_CLOSE;
}
-
- return 0;
}
diff --git a/test/functional/ui/mouse_spec.lua b/test/functional/ui/mouse_spec.lua
index d126e27cde..657cc0c325 100644
--- a/test/functional/ui/mouse_spec.lua
+++ b/test/functional/ui/mouse_spec.lua
@@ -1089,7 +1089,6 @@ describe('ui/mouse/input', function()
command([[setlocal concealcursor=ni nowrap shiftwidth=2 tabstop=4 list listchars=tab:>-]])
command([[syntax region X0 matchgroup=X1 start=/\*/ end=/\*/ concealends contains=X2]])
command([[syntax match X2 /cats/ conceal cchar=X contained]])
- -- No heap-use-after-free with multi-line syntax pattern #24317
command([[syntax match X3 /\n\@<=x/ conceal cchar=>]])
command([[highlight link X0 Normal]])
command([[highlight link X1 NonText]])
@@ -1497,7 +1496,6 @@ describe('ui/mouse/input', function()
]])
end) -- level 2 - wrapped
-
it('(level 3) click on non-wrapped lines', function()
feed_command('let &conceallevel=3', 'echo')
@@ -1535,6 +1533,7 @@ describe('ui/mouse/input', function()
]])
feed('<esc><LeftMouse><20,2>')
+ feed('zH') -- FIXME: unnecessary horizontal scrolling
screen:expect([[
Section{0:>>--->--->---}t1 |
{0:>--->--->---} t2 t3 t4 |
diff --git a/test/old/testdir/test_conceal.vim b/test/old/testdir/test_conceal.vim
index b9541b9e82..0ec171aa2f 100644
--- a/test/old/testdir/test_conceal.vim
+++ b/test/old/testdir/test_conceal.vim
@@ -349,9 +349,56 @@ func Test_conceal_mouse_click()
call Ntest_setmouse(1, 16)
call feedkeys("\<LeftMouse>", "tx")
call assert_equal([0, 1, 20, 0, 20], getcurpos())
+ " click on 'e' of "here" puts cursor there
+ call Ntest_setmouse(1, 19)
+ call feedkeys("\<LeftMouse>", "tx")
+ call assert_equal([0, 1, 23, 0, 23], getcurpos())
+ " click after end of line puts cursor on 'e' without 'virtualedit'
+ call Ntest_setmouse(1, 20)
+ call feedkeys("\<LeftMouse>", "tx")
+ call assert_equal([0, 1, 23, 0, 24], getcurpos())
+ call Ntest_setmouse(1, 21)
+ call feedkeys("\<LeftMouse>", "tx")
+ call assert_equal([0, 1, 23, 0, 25], getcurpos())
+ call Ntest_setmouse(1, 22)
+ call feedkeys("\<LeftMouse>", "tx")
+ call assert_equal([0, 1, 23, 0, 26], getcurpos())
+ call Ntest_setmouse(1, 31)
+ call feedkeys("\<LeftMouse>", "tx")
+ call assert_equal([0, 1, 23, 0, 35], getcurpos())
+ call Ntest_setmouse(1, 32)
+ call feedkeys("\<LeftMouse>", "tx")
+ call assert_equal([0, 1, 23, 0, 36], getcurpos())
+
+ set virtualedit=all
+ redraw " Nvim: redraw_for_cursorcolumn() redraws for conceal
+ " click on 'h' of "here" puts cursor there
+ call Ntest_setmouse(1, 16)
+ call feedkeys("\<LeftMouse>", "tx")
+ call assert_equal([0, 1, 20, 0, 20], getcurpos())
+ " click on 'e' of "here" puts cursor there
+ call Ntest_setmouse(1, 19)
+ call feedkeys("\<LeftMouse>", "tx")
+ call assert_equal([0, 1, 23, 0, 23], getcurpos())
+ " click after end of line puts cursor there without 'virtualedit'
+ call Ntest_setmouse(1, 20)
+ call feedkeys("\<LeftMouse>", "tx")
+ call assert_equal([0, 1, 24, 0, 24], getcurpos())
+ call Ntest_setmouse(1, 21)
+ call feedkeys("\<LeftMouse>", "tx")
+ call assert_equal([0, 1, 24, 1, 25], getcurpos())
+ call Ntest_setmouse(1, 22)
+ call feedkeys("\<LeftMouse>", "tx")
+ call assert_equal([0, 1, 24, 2, 26], getcurpos())
+ call Ntest_setmouse(1, 31)
+ call feedkeys("\<LeftMouse>", "tx")
+ call assert_equal([0, 1, 24, 11, 35], getcurpos())
+ call Ntest_setmouse(1, 32)
+ call feedkeys("\<LeftMouse>", "tx")
+ call assert_equal([0, 1, 24, 12, 36], getcurpos())
bwipe!
- set mouse&
+ set mouse& virtualedit&
endfunc
" vim: shiftwidth=2 sts=2 expandtab
diff --git a/test/old/testdir/test_normal.vim b/test/old/testdir/test_normal.vim
index 57b68bcbb6..c022133b4f 100644
--- a/test/old/testdir/test_normal.vim
+++ b/test/old/testdir/test_normal.vim
@@ -4062,13 +4062,13 @@ func Test_normal_click_on_ctrl_char()
call assert_equal([0, 1, 1, 0, 1], getcurpos())
call Ntest_setmouse(1, 2)
call feedkeys("\<LeftMouse>", 'xt')
- call assert_equal([0, 1, 2, 0, 8], getcurpos())
+ call assert_equal([0, 1, 2, 0, 2], getcurpos())
call Ntest_setmouse(1, 3)
call feedkeys("\<LeftMouse>", 'xt')
- call assert_equal([0, 1, 2, 0, 8], getcurpos())
+ call assert_equal([0, 1, 2, 0, 3], getcurpos())
call Ntest_setmouse(1, 7)
call feedkeys("\<LeftMouse>", 'xt')
- call assert_equal([0, 1, 2, 0, 8], getcurpos())
+ call assert_equal([0, 1, 2, 0, 7], getcurpos())
call Ntest_setmouse(1, 8)
call feedkeys("\<LeftMouse>", 'xt')
call assert_equal([0, 1, 2, 0, 8], getcurpos())
@@ -4080,13 +4080,13 @@ func Test_normal_click_on_ctrl_char()
call assert_equal([0, 1, 4, 0, 10], getcurpos())
call Ntest_setmouse(1, 11)
call feedkeys("\<LeftMouse>", 'xt')
- call assert_equal([0, 1, 4, 0, 10], getcurpos())
+ call assert_equal([0, 1, 4, 0, 11], getcurpos())
call Ntest_setmouse(1, 12)
call feedkeys("\<LeftMouse>", 'xt')
call assert_equal([0, 1, 5, 0, 12], getcurpos())
call Ntest_setmouse(1, 13)
call feedkeys("\<LeftMouse>", 'xt')
- call assert_equal([0, 1, 5, 0, v:maxcol], getcurpos())
+ call assert_equal([0, 1, 5, 0, 13], getcurpos())
bwipe!
let &mouse = save_mouse
diff --git a/test/old/testdir/test_virtualedit.vim b/test/old/testdir/test_virtualedit.vim
index a2baf276ac..f97b3f987d 100644
--- a/test/old/testdir/test_virtualedit.vim
+++ b/test/old/testdir/test_virtualedit.vim
@@ -586,6 +586,12 @@ func Test_virtualedit_mouse()
call Ntest_setmouse(1, 9)
call feedkeys("\<LeftMouse>", "xt")
call assert_equal([0, 1, 6, 0, 9], getcurpos())
+ call Ntest_setmouse(1, 12)
+ call feedkeys("\<LeftMouse>", "xt")
+ call assert_equal([0, 1, 9, 0, 12], getcurpos())
+ call Ntest_setmouse(1, 13)
+ call feedkeys("\<LeftMouse>", "xt")
+ call assert_equal([0, 1, 10, 0, 13], getcurpos())
call Ntest_setmouse(1, 15)
call feedkeys("\<LeftMouse>", "xt")
call assert_equal([0, 1, 10, 2, 15], getcurpos())