mirror of
https://github.com/neovim/neovim.git
synced 2025-09-06 19:38:20 +00:00
vim-patch:9.0.1825: wrong cursor position with virt text and 'linebreak' (#24957)
Problem: Wrong cursor position with virtual text before a whitespace
character and 'linebreak'.
Solution: Always set "col_adj" to "size - 1" and apply 'linebreak' after
adding the size of 'breakindent' and 'showbreak'.
closes: vim/vim#12956
6e55e85f92
N/A patches:
vim-patch:9.0.1826: keytrans() doesn't translate recorded key typed in a GUI
This commit is contained in:
@@ -195,8 +195,6 @@ int win_lbr_chartabsize(chartabsize_T *cts, int *headp)
|
|||||||
char *line = cts->cts_line; // start of the line
|
char *line = cts->cts_line; // start of the line
|
||||||
char *s = cts->cts_ptr;
|
char *s = cts->cts_ptr;
|
||||||
colnr_T vcol = cts->cts_vcol;
|
colnr_T vcol = cts->cts_vcol;
|
||||||
|
|
||||||
colnr_T col_adj = 0; // vcol + screen size of tab
|
|
||||||
int mb_added = 0;
|
int mb_added = 0;
|
||||||
|
|
||||||
cts->cts_cur_text_width_left = 0;
|
cts->cts_cur_text_width_left = 0;
|
||||||
@@ -249,54 +247,8 @@ int win_lbr_chartabsize(chartabsize_T *cts, int *headp)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int c = (uint8_t)(*s);
|
if (size == 2 && MB_BYTE2LEN((uint8_t)(*s)) > 1
|
||||||
if (*s == TAB) {
|
&& wp->w_p_wrap && in_win_border(wp, vcol)) {
|
||||||
col_adj = size - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If 'linebreak' set check at a blank before a non-blank if the line
|
|
||||||
// needs a break here
|
|
||||||
if (wp->w_p_lbr
|
|
||||||
&& vim_isbreak(c)
|
|
||||||
&& !vim_isbreak((uint8_t)s[1])
|
|
||||||
&& wp->w_p_wrap
|
|
||||||
&& (wp->w_width_inner != 0)) {
|
|
||||||
// Count all characters from first non-blank after a blank up to next
|
|
||||||
// non-blank after a blank.
|
|
||||||
int numberextra = win_col_off(wp);
|
|
||||||
colnr_T col2 = vcol;
|
|
||||||
colnr_T colmax = (colnr_T)(wp->w_width_inner - numberextra - col_adj);
|
|
||||||
|
|
||||||
if (vcol >= colmax) {
|
|
||||||
colmax += col_adj;
|
|
||||||
int n = colmax + win_col_off2(wp);
|
|
||||||
|
|
||||||
if (n > 0) {
|
|
||||||
colmax += (((vcol - colmax) / n) + 1) * n - col_adj;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
while (true) {
|
|
||||||
char *ps = s;
|
|
||||||
MB_PTR_ADV(s);
|
|
||||||
c = (uint8_t)(*s);
|
|
||||||
|
|
||||||
if (!(c != NUL
|
|
||||||
&& (vim_isbreak(c) || col2 == vcol || !vim_isbreak((uint8_t)(*ps))))) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
col2 += win_chartabsize(wp, s, col2);
|
|
||||||
|
|
||||||
if (col2 >= colmax) { // doesn't fit
|
|
||||||
size = colmax - vcol + col_adj;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if ((size == 2)
|
|
||||||
&& (MB_BYTE2LEN((uint8_t)(*s)) > 1)
|
|
||||||
&& wp->w_p_wrap
|
|
||||||
&& in_win_border(wp, vcol)) {
|
|
||||||
// Count the ">" in the last column.
|
// Count the ">" in the last column.
|
||||||
size++;
|
size++;
|
||||||
mb_added = 1;
|
mb_added = 1;
|
||||||
@@ -335,6 +287,8 @@ int win_lbr_chartabsize(chartabsize_T *cts, int *headp)
|
|||||||
if (max_head_vcol <= 0 || vcol < max_head_vcol) {
|
if (max_head_vcol <= 0 || vcol < max_head_vcol) {
|
||||||
head += head_prev;
|
head += head_prev;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
head_prev = 0;
|
||||||
}
|
}
|
||||||
wcol += col_off_prev;
|
wcol += col_off_prev;
|
||||||
}
|
}
|
||||||
@@ -366,7 +320,7 @@ int win_lbr_chartabsize(chartabsize_T *cts, int *headp)
|
|||||||
head += (max_head_vcol - (vcol + head_prev + prev_rem)
|
head += (max_head_vcol - (vcol + head_prev + prev_rem)
|
||||||
+ width2 - 1) / width2 * head_mid;
|
+ width2 - 1) / width2 * head_mid;
|
||||||
} else if (max_head_vcol < 0) {
|
} else if (max_head_vcol < 0) {
|
||||||
int off = virt_text_cursor_off(cts, c == NUL);
|
int off = virt_text_cursor_off(cts, *s == NUL);
|
||||||
if (off >= prev_rem) {
|
if (off >= prev_rem) {
|
||||||
if (size > off) {
|
if (size > off) {
|
||||||
head += (1 + (off - prev_rem) / width) * head_mid;
|
head += (1 + (off - prev_rem) / width) * head_mid;
|
||||||
@@ -384,6 +338,45 @@ int win_lbr_chartabsize(chartabsize_T *cts, int *headp)
|
|||||||
if (headp != NULL) {
|
if (headp != NULL) {
|
||||||
*headp = head;
|
*headp = head;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If 'linebreak' set check at a blank before a non-blank if the line
|
||||||
|
// needs a break here
|
||||||
|
if (wp->w_p_lbr
|
||||||
|
&& vim_isbreak((uint8_t)s[0])
|
||||||
|
&& !vim_isbreak((uint8_t)s[1])
|
||||||
|
&& wp->w_p_wrap
|
||||||
|
&& wp->w_width_inner != 0) {
|
||||||
|
// Count all characters from first non-blank after a blank up to next
|
||||||
|
// non-blank after a blank.
|
||||||
|
int numberextra = win_col_off(wp);
|
||||||
|
colnr_T col_adj = size - 1;
|
||||||
|
colnr_T colmax = (colnr_T)(wp->w_width_inner - numberextra - col_adj);
|
||||||
|
if (vcol >= colmax) {
|
||||||
|
colmax += col_adj;
|
||||||
|
int n = colmax + win_col_off2(wp);
|
||||||
|
if (n > 0) {
|
||||||
|
colmax += (((vcol - colmax) / n) + 1) * n - col_adj;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
colnr_T vcol2 = vcol;
|
||||||
|
while (true) {
|
||||||
|
char *ps = s;
|
||||||
|
MB_PTR_ADV(s);
|
||||||
|
int c = (uint8_t)(*s);
|
||||||
|
if (!(c != NUL
|
||||||
|
&& (vim_isbreak(c) || vcol2 == vcol || !vim_isbreak((uint8_t)(*ps))))) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
vcol2 += win_chartabsize(wp, s, vcol2);
|
||||||
|
if (vcol2 >= colmax) { // doesn't fit
|
||||||
|
size = colmax - vcol + col_adj;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -3217,6 +3217,33 @@ describe('decorations: inline virtual text', function()
|
|||||||
|
|
|
|
||||||
]]}
|
]]}
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
it('before a space with linebreak', function()
|
||||||
|
screen:try_resize(50, 6)
|
||||||
|
exec([[
|
||||||
|
setlocal linebreak showbreak=+ breakindent breakindentopt=shift:2
|
||||||
|
call setline(1, repeat('a', 50) .. ' ' .. repeat('c', 45))
|
||||||
|
normal! $
|
||||||
|
]])
|
||||||
|
meths.buf_set_extmark(0, ns, 0, 50, { virt_text = { { ('b'):rep(10) } }, virt_text_pos = 'inline' })
|
||||||
|
screen:expect{grid=[[
|
||||||
|
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
|
||||||
|
{1:+}bbbbbbbbbb |
|
||||||
|
{1:+}cccccccccccccccccccccccccccccccccccccccccccc^c |
|
||||||
|
{1:~ }|
|
||||||
|
{1:~ }|
|
||||||
|
|
|
||||||
|
]]}
|
||||||
|
feed('05x$')
|
||||||
|
screen:expect{grid=[[
|
||||||
|
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbb|
|
||||||
|
{1:+}bbbbb |
|
||||||
|
{1:+}cccccccccccccccccccccccccccccccccccccccccccc^c |
|
||||||
|
{1:~ }|
|
||||||
|
{1:~ }|
|
||||||
|
|
|
||||||
|
]]}
|
||||||
|
end)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
describe('decorations: virtual lines', function()
|
describe('decorations: virtual lines', function()
|
||||||
|
Reference in New Issue
Block a user