vim-patch:9.0.1783: Display issues with virt text smoothscroll and showbreak

Problem:  Wrong display with wrapping virtual text or unprintable chars,
          'showbreak' and 'smoothscroll'.
Solution: Don't skip cells taken by 'showbreak' in screen lines before
          "w_skipcol". Combined "n_skip" and "skip_cells".

closes: vim/vim#12597

b557f48982
This commit is contained in:
zeertzjq 2023-08-23 10:12:00 +08:00
parent 3e80b39a8e
commit a1d71ad55e
8 changed files with 557 additions and 88 deletions

View File

@ -991,6 +991,7 @@ void getvcol(win_T *wp, pos_T *pos, colnr_T *start, colnr_T *cursor, colnr_T *en
chartabsize_T cts;
bool on_NUL = false;
init_chartabsize_arg(&cts, wp, pos->lnum, 0, line, line);
cts.cts_max_head_vcol = -1;
// This function is used very often, do some speed optimizations.
// When 'list', 'linebreak', 'showbreak' and 'breakindent' are not set

View File

@ -132,9 +132,12 @@ typedef struct {
bool reset_extra_attr;
int skip_cells; // nr of cells to skip for virtual text
int skipped_cells; // nr of skipped virtual text cells
bool more_virt_inline_chunks; // indicates if there is more inline virtual text after n_extra
int skip_cells; ///< nr of cells to skip for w_leftcol
///< or w_skipcol or concealing
int skipped_cells; ///< nr of skipped cells for virtual text
///< to be added to wlv.vcol later
bool more_virt_inline_chunks; ///< indicates if there is more inline virtual text
///< after n_extra
} winlinevars_T;
/// for line_putchar. Contains the state that needs to be remembered from
@ -1090,9 +1093,6 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl
int n_attr3 = 0; // chars with overruling special attr
int saved_attr3 = 0; // char_attr saved for n_attr3
int n_skip = 0; // nr of chars to skip for 'nowrap' or
// concealing
int fromcol_prev = -2; // start of inverting after cursor
bool noinvcur = false; // don't invert the cursor
bool lnum_in_visual_area = false;
@ -1500,10 +1500,13 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl
char *prev_ptr = ptr;
chartabsize_T cts;
int charsize = 0;
int head = 0;
init_chartabsize_arg(&cts, wp, lnum, wlv.vcol, line, ptr);
cts.cts_max_head_vcol = (int)v;
while (cts.cts_vcol < v && *cts.cts_ptr != NUL) {
charsize = win_lbr_chartabsize(&cts, NULL);
head = 0;
charsize = win_lbr_chartabsize(&cts, &head);
cts.cts_vcol += charsize;
prev_ptr = cts.cts_ptr;
MB_PTR_ADV(cts.cts_ptr);
@ -1530,17 +1533,10 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl
if (wlv.vcol > v) {
wlv.vcol -= charsize;
ptr = prev_ptr;
// If the character fits on the screen, don't need to skip it.
// Except for a TAB.
if (utf_ptr2cells(ptr) >= charsize || *ptr == TAB) {
n_skip = (int)(v - wlv.vcol);
}
}
// If there the text doesn't reach to the desired column, need to skip
// "skip_cells" cells when virtual text follows.
if ((!wp->w_p_wrap || (lnum == wp->w_topline && wp->w_skipcol > 0)) && v > wlv.vcol) {
wlv.skip_cells = (int)(v - wlv.vcol);
if (v > wlv.vcol) {
wlv.skip_cells = (int)v - wlv.vcol - head;
}
// Adjust for when the inverted text is before the screen,
@ -1808,9 +1804,6 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl
decor_attr = 0;
search_attr_from_match = false;
}
if (wlv.n_extra > 0) {
n_skip = 0;
}
}
}
@ -2027,6 +2020,12 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl
// Get a character from the line itself.
c0 = c = (uint8_t)(*ptr);
mb_c = c;
if (c == NUL) {
// no more cells to skip
wlv.skip_cells = 0;
}
// If the UTF-8 character is more than one byte: Decode it
// into "mb_c".
mb_l = utfc_ptr2len(ptr);
@ -2118,7 +2117,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl
// If a double-width char doesn't fit at the left side display a '<' in
// the first column. Don't do this for unprintable characters.
if (n_skip > 0 && mb_l > 1 && wlv.n_extra == 0) {
if (wlv.skip_cells > 0 && mb_l > 1 && wlv.n_extra == 0) {
wlv.n_extra = 1;
wlv.c_extra = MB_FILLER_CHAR;
wlv.c_final = NUL;
@ -2619,9 +2618,9 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl
}
wlv.n_extra = 0;
wlv.n_attr = 0;
} else if (n_skip == 0) {
} else if (wlv.skip_cells == 0) {
is_concealing = true;
n_skip = 1;
wlv.skip_cells = 1;
}
mb_c = c;
mb_utf8 = check_mb_utf8(&c, u8cc);
@ -2630,7 +2629,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl
is_concealing = false;
}
if (n_skip > 0 && did_decrement_ptr) {
if (wlv.skip_cells > 0 && did_decrement_ptr) {
// not showing the '>', put pointer back to avoid getting stuck
ptr++;
}
@ -2641,7 +2640,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl
if (!did_wcol && wlv.draw_state == WL_LINE
&& wp == curwin && lnum == wp->w_cursor.lnum
&& conceal_cursor_line(wp)
&& (int)wp->w_virtcol <= wlv.vcol + n_skip) {
&& (int)wp->w_virtcol <= wlv.vcol + wlv.skip_cells) {
if (wp->w_p_rl) {
wp->w_wcol = grid->cols - wlv.col + wlv.boguscols - 1;
} else {
@ -2946,7 +2945,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl
// Store character to be displayed.
// Skip characters that are left of the screen for 'nowrap'.
if (wlv.draw_state < WL_LINE || n_skip <= 0) {
if (wlv.draw_state < WL_LINE || wlv.skip_cells <= 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.
@ -2999,7 +2998,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl
wlv.col++;
}
} else if (wp->w_p_cole > 0 && is_concealing) {
n_skip--;
wlv.skip_cells--;
wlv.vcol_off++;
if (wlv.n_extra > 0) {
wlv.vcol_off += wlv.n_extra;
@ -3055,7 +3054,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl
}
}
} else {
n_skip--;
wlv.skip_cells--;
}
// The skipped cells need to be accounted for in vcol.

View File

@ -232,7 +232,8 @@ static void insert_enter(InsertState *s)
may_trigger_modechanged();
stop_insert_mode = false;
// need to position cursor again when on a TAB
// need to position cursor again when on a TAB and
// when on a char with inline virtual text
if (gchar_cursor() == TAB || curbuf->b_virt_text_inline > 0) {
curwin->w_valid &= ~(VALID_WROW|VALID_WCOL|VALID_VIRTCOL);
}
@ -3471,7 +3472,8 @@ static bool ins_esc(long *count, int cmdchar, bool nomove)
State = MODE_NORMAL;
may_trigger_modechanged();
// need to position cursor again when on a TAB
// need to position cursor again when on a TAB and
// when on a char with inline virtual text
if (gchar_cursor() == TAB || curbuf->b_virt_text_inline > 0) {
curwin->w_valid &= ~(VALID_WROW|VALID_WCOL|VALID_VIRTCOL);
}

View File

@ -369,16 +369,19 @@ int lbr_chartabsize_adv(chartabsize_T *cts)
return retval;
}
/// Get the number of characters taken up on the screen indicated by "cts".
/// "cts->cts_cur_text_width_left" and "cts->cts_cur_text_width_right" are set
/// to the extra size for inline virtual text.
/// This function is used very often, keep it fast!!!!
///
/// If "headp" not NULL, set *headp to the size of what we for 'showbreak'
/// string at start of line. Warning: *headp is only set if it's a non-zero
/// value, init to 0 before calling.
/// If "headp" not NULL, set "*headp" to the size of 'showbreak'/'breakindent'
/// included in the return value.
/// When "cts->cts_max_head_vcol" is positive, only count in "*headp" the size
/// of 'showbreak'/'breakindent' before "cts->cts_max_head_vcol".
/// When "cts->cts_max_head_vcol" is negative, only count in "*headp" the size
/// of 'showbreak'/'breakindent' before where cursor should be placed.
///
/// @param cts
/// @param headp
///
/// @return The number of characters taken up on the screen.
/// Warning: "*headp" may not be set if it's 0, init to 0 before calling.
int win_lbr_chartabsize(chartabsize_T *cts, int *headp)
{
win_T *wp = cts->cts_win;
@ -388,7 +391,6 @@ int win_lbr_chartabsize(chartabsize_T *cts, int *headp)
colnr_T col_adj = 0; // vcol + screen size of tab
int mb_added = 0;
int numberextra;
cts->cts_cur_text_width_left = 0;
cts->cts_cur_text_width_right = 0;
@ -449,7 +451,7 @@ int win_lbr_chartabsize(chartabsize_T *cts, int *headp)
&& (wp->w_width_inner != 0)) {
// Count all characters from first non-blank after a blank up to next
// non-blank after a blank.
numberextra = win_col_off(wp);
int numberextra = win_col_off(wp);
colnr_T col2 = vcol;
colnr_T colmax = (colnr_T)(wp->w_width_inner - numberextra - col_adj);
@ -490,72 +492,92 @@ int win_lbr_chartabsize(chartabsize_T *cts, int *headp)
// May have to add something for 'breakindent' and/or 'showbreak'
// string at start of line.
// Set *headp to the size of what we add.
// Do not use 'showbreak' at the NUL after the text.
int added = 0;
int head = mb_added;
char *const sbr = c == NUL ? empty_option : get_showbreak_value(wp);
if ((*sbr != NUL || wp->w_p_bri) && wp->w_p_wrap && vcol != 0) {
colnr_T sbrlen = 0;
int numberwidth = win_col_off(wp);
numberextra = numberwidth;
vcol += numberextra + mb_added;
if (vcol >= (colnr_T)wp->w_width_inner) {
vcol -= wp->w_width_inner;
numberextra = wp->w_width_inner - (numberextra - win_col_off2(wp));
if (vcol >= numberextra && numberextra > 0) {
vcol %= numberextra;
if ((*sbr != NUL || wp->w_p_bri) && wp->w_p_wrap) {
int col_off_prev = win_col_off(wp);
int width2 = wp->w_width_inner - col_off_prev + win_col_off2(wp);
colnr_T wcol = vcol + col_off_prev;
// cells taken by 'showbreak'/'breakindent' before current char
int head_prev = 0;
if (wcol >= wp->w_width_inner) {
wcol -= wp->w_width_inner;
col_off_prev = wp->w_width_inner - width2;
if (wcol >= width2 && width2 > 0) {
wcol %= width2;
}
if (*sbr != NUL) {
sbrlen = (colnr_T)mb_charlen(sbr);
if (vcol >= sbrlen) {
vcol -= sbrlen;
head_prev += vim_strsize(sbr);
}
if (wp->w_p_bri) {
head_prev += get_breakindent_win(wp, line);
}
if (vcol >= numberextra && numberextra > 0) {
vcol %= numberextra;
} else if (vcol > 0 && numberextra > 0) {
vcol += numberwidth - win_col_off2(wp);
if (wcol < head_prev) {
wcol = head_prev;
}
wcol += col_off_prev;
}
numberwidth -= win_col_off2(wp);
if ((vcol > 0 && wcol == col_off_prev + head_prev)
|| wcol + size > wp->w_width_inner) {
int added = 0;
colnr_T max_head_vcol = cts->cts_max_head_vcol;
if (vcol > 0 && wcol == col_off_prev + head_prev) {
added += head_prev;
if (max_head_vcol <= 0 || vcol < max_head_vcol) {
head += head_prev;
}
}
if (vcol == 0 || (vcol + size + sbrlen > (colnr_T)wp->w_width_inner)) {
// cells taken by 'showbreak'/'breakindent' halfway current char
int head_mid = 0;
if (*sbr != NUL) {
if (size + sbrlen + numberwidth > (colnr_T)wp->w_width_inner) {
head_mid += vim_strsize(sbr);
}
if (wp->w_p_bri) {
head_mid += get_breakindent_win(wp, line);
}
if (head_mid > 0) {
if (wcol + size > wp->w_width_inner) {
// Calculate effective window width.
int width = (colnr_T)wp->w_width_inner - sbrlen - numberwidth;
int prev_width = vcol ? ((colnr_T)wp->w_width_inner - (sbrlen + vcol))
: 0;
int prev_rem = wp->w_width_inner - wcol;
int width = width2 - head_mid;
if (width <= 0) {
width = 1;
}
added += ((size - prev_width) / width) * vim_strsize(sbr);
if ((size - prev_width) % width) {
// Wrapped, add another length of 'sbr'.
added += vim_strsize(sbr);
}
} else {
added += vim_strsize(sbr);
}
}
// divide "size - prev_width" by "width", rounding up
int cnt = (size - prev_rem + width - 1) / width;
added += cnt * head_mid;
if (wp->w_p_bri) {
added += get_breakindent_win(wp, line);
if (max_head_vcol == 0 || vcol + size + added < max_head_vcol) {
head += cnt * head_mid;
} else if (max_head_vcol > vcol + head_prev + prev_rem) {
head += (max_head_vcol - (vcol + head_prev + prev_rem)
+ width2 - 1) / width2 * head_mid;
} else if (max_head_vcol < 0) {
int off = 0;
if (c != NUL || !(State & MODE_NORMAL)) {
off += cts->cts_cur_text_width_left;
}
if (c != NUL && (State & MODE_NORMAL)) {
off += cts->cts_cur_text_width_right;
}
if (off >= prev_rem) {
head += (1 + (off - prev_rem) / width) * head_mid;
}
}
}
}
size += added;
if (vcol != 0) {
added = 0;
}
}
}
if (headp != NULL) {
*headp = added + mb_added;
*headp = head;
}
return size;
}

View File

@ -19,6 +19,7 @@ typedef struct {
MarkTreeIter cts_iter[1];
int cts_vcol; ///< virtual column at current position
int cts_max_head_vcol; ///< see win_lbr_chartabsize()
} chartabsize_T;
#ifdef INCLUDE_GENERATED_DECLARATIONS

View File

@ -2021,7 +2021,7 @@ bbbbbbb]])
]]}
end)
it('cursor position is correct with virtual text attached to hard tabs', function()
it('cursor position is correct with virtual text attached to hard TABs', function()
command('set noexpandtab')
feed('i')
feed('<TAB>')
@ -2692,7 +2692,7 @@ bbbbbbb]])
]]}
end)
it('correctly draws when overflowing virtual text is followed by tab with no wrap', function()
it('correctly draws when overflowing virtual text is followed by TAB with no wrap', function()
command('set nowrap')
feed('i<TAB>test<ESC>')
meths.buf_set_extmark(
@ -2984,6 +2984,328 @@ bbbbbbb]])
{8:-- VISUAL BLOCK --} |
]]}
end)
local function test_virt_inline_showbreak_smoothscroll()
screen:try_resize(30, 6)
exec([[
highlight! link LineNr Normal
call setline(1, repeat('a', 28))
setlocal number showbreak=+ breakindent breakindentopt=shift:2
setlocal scrolloff=0 smoothscroll
normal! $
]])
meths.buf_set_extmark(0, ns, 0, 27, { virt_text = { { ('123'):rep(23) } }, virt_text_pos = 'inline' })
feed(':<CR>') -- Have a screen line that doesn't start with spaces
screen:expect{grid=[[
1 aaaaaaaaaaaaaaaaaaaaaaaaaa|
{1:+}a1231231231231231231231|
{1:+}23123123123123123123123|
{1:+}12312312312312312312312|
{1:+}3^a |
: |
]]}
feed('<C-E>')
screen:expect{grid=[[
{1:+}a1231231231231231231231|
{1:+}23123123123123123123123|
{1:+}12312312312312312312312|
{1:+}3^a |
{1:~ }|
: |
]]}
feed('<C-E>')
screen:expect{grid=[[
{1:+}23123123123123123123123|
{1:+}12312312312312312312312|
{1:+}3^a |
{1:~ }|
{1:~ }|
: |
]]}
feed('<C-E>')
screen:expect{grid=[[
{1:+}12312312312312312312312|
{1:+}3^a |
{1:~ }|
{1:~ }|
{1:~ }|
: |
]]}
feed('<C-E>')
screen:expect{grid=[[
{1:+}3^a |
{1:~ }|
{1:~ }|
{1:~ }|
{1:~ }|
: |
]]}
feed('zbi')
screen:expect{grid=[[
1 aaaaaaaaaaaaaaaaaaaaaaaaaa|
{1:+}a^1231231231231231231231|
{1:+}23123123123123123123123|
{1:+}12312312312312312312312|
{1:+}3a |
{8:-- INSERT --} |
]]}
feed('<BS>')
screen:expect{grid=[[
1 aaaaaaaaaaaaaaaaaaaaaaaaaa|
{1:+}^12312312312312312312312|
{1:+}31231231231231231231231|
{1:+}23123123123123123123123|
{1:+}a |
{8:-- INSERT --} |
]]}
feed('<Esc>l')
feed(':<CR>') -- Have a screen line that doesn't start with spaces
screen:expect{grid=[[
1 aaaaaaaaaaaaaaaaaaaaaaaaaa|
{1:+}12312312312312312312312|
{1:+}31231231231231231231231|
{1:+}23123123123123123123123|
{1:+}^a |
: |
]]}
feed('<C-E>')
screen:expect{grid=[[
{1:+}12312312312312312312312|
{1:+}31231231231231231231231|
{1:+}23123123123123123123123|
{1:+}^a |
{1:~ }|
: |
]]}
feed('<C-E>')
screen:expect{grid=[[
{1:+}31231231231231231231231|
{1:+}23123123123123123123123|
{1:+}^a |
{1:~ }|
{1:~ }|
: |
]]}
feed('<C-E>')
screen:expect{grid=[[
{1:+}23123123123123123123123|
{1:+}^a |
{1:~ }|
{1:~ }|
{1:~ }|
: |
]]}
feed('<C-E>')
screen:expect{grid=[[
{1:+}^a |
{1:~ }|
{1:~ }|
{1:~ }|
{1:~ }|
: |
]]}
feed('023x$')
screen:expect{grid=[[
1 aaa12312312312312312312312|
{1:+}31231231231231231231231|
{1:+}23123123123123123123123|
{1:+}^a |
{1:~ }|
: |
]]}
feed('<C-E>')
screen:expect{grid=[[
{1:+}31231231231231231231231|
{1:+}23123123123123123123123|
{1:+}^a |
{1:~ }|
{1:~ }|
: |
]]}
feed('<C-E>')
screen:expect{grid=[[
{1:+}23123123123123123123123|
{1:+}^a |
{1:~ }|
{1:~ }|
{1:~ }|
: |
]]}
feed('<C-E>')
screen:expect{grid=[[
{1:+}^a |
{1:~ }|
{1:~ }|
{1:~ }|
{1:~ }|
: |
]]}
feed('zbi')
screen:expect{grid=[[
1 aaa^12312312312312312312312|
{1:+}31231231231231231231231|
{1:+}23123123123123123123123|
{1:+}a |
{1:~ }|
{8:-- INSERT --} |
]]}
feed('<C-U>')
screen:expect{grid=[[
1 ^12312312312312312312312312|
{1:+}31231231231231231231231|
{1:+}23123123123123123123a |
{1:~ }|
{1:~ }|
{8:-- INSERT --} |
]]}
feed('<Esc>')
screen:expect{grid=[[
1 12312312312312312312312312|
{1:+}31231231231231231231231|
{1:+}23123123123123123123^a |
{1:~ }|
{1:~ }|
|
]]}
feed('<C-E>')
screen:expect{grid=[[
{1:+}31231231231231231231231|
{1:+}23123123123123123123^a |
{1:~ }|
{1:~ }|
{1:~ }|
|
]]}
feed('<C-E>')
screen:expect{grid=[[
{1:+}23123123123123123123^a |
{1:~ }|
{1:~ }|
{1:~ }|
{1:~ }|
|
]]}
end
describe('with showbreak, smoothscroll', function()
it('and cpoptions-=n', function()
test_virt_inline_showbreak_smoothscroll()
end)
it('and cpoptions+=n', function()
command('set cpoptions+=n')
-- because of 'breakindent' the screen states are the same
test_virt_inline_showbreak_smoothscroll()
end)
end)
it('before TABs with smoothscroll', function()
screen:try_resize(30, 6)
exec([[
call setline(1, repeat("\t", 4) .. 'a')
setlocal list listchars=tab:<-> scrolloff=0 smoothscroll
normal! $
]])
meths.buf_set_extmark(0, ns, 0, 3, { virt_text = { { ('12'):rep(32) } }, virt_text_pos = 'inline' })
screen:expect{grid=[[
{1:<------><------><------>}121212|
121212121212121212121212121212|
1212121212121212121212121212{1:<-}|
{1:----->}^a |
{1:~ }|
|
]]}
feed('<C-E>')
screen:expect{grid=[[
{1:<<<}212121212121212121212121212|
1212121212121212121212121212{1:<-}|
{1:----->}^a |
{1:~ }|
{1:~ }|
|
]]}
feed('<C-E>')
screen:expect{grid=[[
{1:<<<}2121212121212121212121212{1:<-}|
{1:----->}^a |
{1:~ }|
{1:~ }|
{1:~ }|
|
]]}
feed('<C-E>')
screen:expect{grid=[[
{1:<<<-->}^a |
{1:~ }|
{1:~ }|
{1:~ }|
{1:~ }|
|
]]}
feed('zbh')
screen:expect{grid=[[
{1:<------><------><------>}121212|
121212121212121212121212121212|
1212121212121212121212121212{1:^<-}|
{1:----->}a |
{1:~ }|
|
]]}
feed('i')
screen:expect{grid=[[
{1:<------><------><------>}^121212|
121212121212121212121212121212|
1212121212121212121212121212{1:<-}|
{1:----->}a |
{1:~ }|
{8:-- INSERT --} |
]]}
feed('<C-O>:setlocal nolist<CR>')
screen:expect{grid=[[
^121212|
121212121212121212121212121212|
1212121212121212121212121212 |
a |
{1:~ }|
{8:-- INSERT --} |
]]}
feed('<Esc>l')
screen:expect{grid=[[
121212|
121212121212121212121212121212|
1212121212121212121212121212 |
^ a |
{1:~ }|
|
]]}
feed('<C-E>')
screen:expect{grid=[[
{1:<<<}212121212121212121212121212|
1212121212121212121212121212 |
^ a |
{1:~ }|
{1:~ }|
|
]]}
feed('<C-E>')
screen:expect{grid=[[
{1:<<<}2121212121212121212121212 |
^ a |
{1:~ }|
{1:~ }|
{1:~ }|
|
]]}
feed('<C-E>')
screen:expect{grid=[[
{1:<<<} ^ a |
{1:~ }|
{1:~ }|
{1:~ }|
{1:~ }|
|
]]}
end)
end)
describe('decorations: virtual lines', function()
@ -3643,7 +3965,7 @@ if (h->n_buckets < new_n_buckets) { // expand
end)
it('works with hard tabs', function()
it('works with hard TABs', function()
insert(example_text2)
feed 'gg'
meths.buf_set_extmark(0, ns, 1, 0, {

View File

@ -14,7 +14,7 @@ function s:screen_lines(lnum, width) abort
endfunction
func s:compare_lines(expect, actual)
call assert_equal(join(a:expect, "\n"), join(a:actual, "\n"))
call assert_equal(a:expect, a:actual)
endfunc
function s:test_windows(...)
@ -330,4 +330,47 @@ func Test_list_with_tab_and_skipping_first_chars()
\ ]
call s:compare_lines(expect, lines)
call s:close_windows()
endfu
endfunc
func Test_ctrl_char_on_wrap_column()
call s:test_windows("setl nolbr wrap sbr=")
call setline(1, 'aaa' .. repeat("\<C-A>", 150) .. 'bbb')
call cursor(1,1)
norm! $
redraw!
let expect=[
\ '<<<^A^A^A^A^A^A^A^A^',
\ 'A^A^A^A^A^A^A^A^A^A^',
\ 'A^A^A^A^A^A^A^A^A^A^',
\ 'A^A^A^A^A^A^A^A^A^A^',
\ 'A^A^A^A^A^A^A^A^A^A^',
\ 'A^A^A^A^A^A^A^A^A^A^',
\ 'A^A^A^A^A^A^A^A^A^A^',
\ 'A^A^A^A^A^A^A^A^A^A^',
\ 'A^A^A^A^A^A^A^A^A^A^',
\ 'A^Abbb ']
let lines = s:screen_lines([1, 10], winwidth(0))
call s:compare_lines(expect, lines)
call assert_equal(len(expect), winline())
call assert_equal(strwidth(trim(expect[-1], ' ', 2)), wincol())
setl sbr=!!
redraw!
let expect=[
\ '!!A^A^A^A^A^A^A^A^A^',
\ '!!A^A^A^A^A^A^A^A^A^',
\ '!!A^A^A^A^A^A^A^A^A^',
\ '!!A^A^A^A^A^A^A^A^A^',
\ '!!A^A^A^A^A^A^A^A^A^',
\ '!!A^A^A^A^A^A^A^A^A^',
\ '!!A^A^A^A^A^A^A^A^A^',
\ '!!A^A^A^A^A^A^A^A^A^',
\ '!!A^A^A^A^A^A^A^A^A^',
\ '!!A^A^A^A^A^A^Abbb ']
let lines = s:screen_lines([1, 10], winwidth(0))
call s:compare_lines(expect, lines)
call assert_equal(len(expect), winline())
call assert_equal(strwidth(trim(expect[-1], ' ', 2)), wincol())
call s:close_windows()
endfunc
" vim: shiftwidth=2 sts=2 expandtab

View File

@ -249,7 +249,6 @@ endfunc
func Test_chinese_char_on_wrap_column()
call s:test_windows("setl nolbr wrap sbr=")
syntax off
call setline(1, [
\ 'aaaaaaaaaaaaaaaaaaa中'.
\ 'aaaaaaaaaaaaaaaaa中'.
@ -278,5 +277,85 @@ func Test_chinese_char_on_wrap_column()
\ '中hello ']
let lines = s:screen_lines([1, 10], winwidth(0))
call s:compare_lines(expect, lines)
call assert_equal(len(expect), winline())
call assert_equal(strwidth(trim(expect[-1], ' ', 2)), wincol())
call s:close_windows()
endfu
endfunc
func Test_chinese_char_on_wrap_column_sbr()
call s:test_windows("setl nolbr wrap sbr=!!!")
call setline(1, [
\ 'aaaaaaaaaaaaaaaaaaa中'.
\ 'aaaaaaaaaaaaaa中'.
\ 'aaaaaaaaaaaaaa中'.
\ 'aaaaaaaaaaaaaa中'.
\ 'aaaaaaaaaaaaaa中'.
\ 'aaaaaaaaaaaaaa中'.
\ 'aaaaaaaaaaaaaa中'.
\ 'aaaaaaaaaaaaaa中'.
\ 'aaaaaaaaaaaaaa中'.
\ 'aaaaaaaaaaaaaa中'.
\ 'hello'])
call cursor(1,1)
norm! $
redraw!
let expect=[
\ '!!!中aaaaaaaaaaaaaa>',
\ '!!!中aaaaaaaaaaaaaa>',
\ '!!!中aaaaaaaaaaaaaa>',
\ '!!!中aaaaaaaaaaaaaa>',
\ '!!!中aaaaaaaaaaaaaa>',
\ '!!!中aaaaaaaaaaaaaa>',
\ '!!!中aaaaaaaaaaaaaa>',
\ '!!!中aaaaaaaaaaaaaa>',
\ '!!!中aaaaaaaaaaaaaa>',
\ '!!!中hello ']
let lines = s:screen_lines([1, 10], winwidth(0))
call s:compare_lines(expect, lines)
call assert_equal(len(expect), winline())
call assert_equal(strwidth(trim(expect[-1], ' ', 2)), wincol())
call s:close_windows()
endfunc
func Test_unprintable_char_on_wrap_column()
call s:test_windows("setl nolbr wrap sbr=")
call setline(1, 'aaa' .. repeat("\uFEFF", 50) .. 'bbb')
call cursor(1,1)
norm! $
redraw!
let expect=[
\ '<<<<feff><feff><feff',
\ '><feff><feff><feff><',
\ 'feff><feff><feff><fe',
\ 'ff><feff><feff><feff',
\ '><feff><feff><feff><',
\ 'feff><feff><feff><fe',
\ 'ff><feff><feff><feff',
\ '><feff><feff><feff><',
\ 'feff><feff><feff><fe',
\ 'ff>bbb ']
let lines = s:screen_lines([1, 10], winwidth(0))
call s:compare_lines(expect, lines)
call assert_equal(len(expect), winline())
call assert_equal(strwidth(trim(expect[-1], ' ', 2)), wincol())
setl sbr=!!
redraw!
let expect=[
\ '!!><feff><feff><feff',
\ '!!><feff><feff><feff',
\ '!!><feff><feff><feff',
\ '!!><feff><feff><feff',
\ '!!><feff><feff><feff',
\ '!!><feff><feff><feff',
\ '!!><feff><feff><feff',
\ '!!><feff><feff><feff',
\ '!!><feff><feff><feff',
\ '!!><feff><feff>bbb ']
let lines = s:screen_lines([1, 10], winwidth(0))
call s:compare_lines(expect, lines)
call assert_equal(len(expect), winline())
call assert_equal(strwidth(trim(expect[-1], ' ', 2)), wincol())
call s:close_windows()
endfunc
" vim: shiftwidth=2 sts=2 expandtab