mirror of
https://github.com/neovim/neovim.git
synced 2025-09-05 19:08:15 +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 *s = cts->cts_ptr;
|
||||
colnr_T vcol = cts->cts_vcol;
|
||||
|
||||
colnr_T col_adj = 0; // vcol + screen size of tab
|
||||
int mb_added = 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 (*s == TAB) {
|
||||
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)) {
|
||||
if (size == 2 && MB_BYTE2LEN((uint8_t)(*s)) > 1
|
||||
&& wp->w_p_wrap && in_win_border(wp, vcol)) {
|
||||
// Count the ">" in the last column.
|
||||
size++;
|
||||
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) {
|
||||
head += head_prev;
|
||||
}
|
||||
} else {
|
||||
head_prev = 0;
|
||||
}
|
||||
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)
|
||||
+ width2 - 1) / width2 * head_mid;
|
||||
} 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 (size > off) {
|
||||
head += (1 + (off - prev_rem) / width) * head_mid;
|
||||
@@ -384,6 +338,45 @@ int win_lbr_chartabsize(chartabsize_T *cts, int *headp)
|
||||
if (headp != NULL) {
|
||||
*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;
|
||||
}
|
||||
|
||||
|
@@ -3217,6 +3217,33 @@ describe('decorations: inline virtual text', function()
|
||||
|
|
||||
]]}
|
||||
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)
|
||||
|
||||
describe('decorations: virtual lines', function()
|
||||
|
Reference in New Issue
Block a user