forked from aniani/vim
patch 8.2.3410: crash with linebreak, listchars and large tabstop
Problem: Crash with linebreak, listchars and large tabstop. Solution: Account for different size listchars for a tab. (closes #8841)
This commit is contained in:
@@ -2109,55 +2109,60 @@ win_line(
|
|||||||
int i;
|
int i;
|
||||||
int saved_nextra = n_extra;
|
int saved_nextra = n_extra;
|
||||||
|
|
||||||
#ifdef FEAT_CONCEAL
|
# ifdef FEAT_CONCEAL
|
||||||
if (vcol_off > 0)
|
if (vcol_off > 0)
|
||||||
// there are characters to conceal
|
// there are characters to conceal
|
||||||
tab_len += vcol_off;
|
tab_len += vcol_off;
|
||||||
|
|
||||||
// boguscols before FIX_FOR_BOGUSCOLS macro from above
|
// boguscols before FIX_FOR_BOGUSCOLS macro from above
|
||||||
if (wp->w_p_list && wp->w_lcs_chars.tab1
|
if (wp->w_p_list && wp->w_lcs_chars.tab1
|
||||||
&& old_boguscols > 0
|
&& old_boguscols > 0
|
||||||
&& n_extra > tab_len)
|
&& n_extra > tab_len)
|
||||||
tab_len += n_extra - tab_len;
|
tab_len += n_extra - tab_len;
|
||||||
#endif
|
# endif
|
||||||
|
// If n_extra > 0, it gives the number of chars, to
|
||||||
// if n_extra > 0, it gives the number of chars, to
|
|
||||||
// use for a tab, else we need to calculate the width
|
// use for a tab, else we need to calculate the width
|
||||||
// for a tab
|
// for a tab.
|
||||||
len = (tab_len * mb_char2len(wp->w_lcs_chars.tab2));
|
len = (tab_len * mb_char2len(wp->w_lcs_chars.tab2));
|
||||||
|
if (wp->w_lcs_chars.tab3)
|
||||||
|
len += mb_char2len(wp->w_lcs_chars.tab3);
|
||||||
if (n_extra > 0)
|
if (n_extra > 0)
|
||||||
len += n_extra - tab_len;
|
len += n_extra - tab_len;
|
||||||
c = wp->w_lcs_chars.tab1;
|
c = wp->w_lcs_chars.tab1;
|
||||||
p = alloc(len + 1);
|
p = alloc(len + 1);
|
||||||
vim_memset(p, ' ', len);
|
if (p == NULL)
|
||||||
p[len] = NUL;
|
n_extra = 0;
|
||||||
vim_free(p_extra_free);
|
else
|
||||||
p_extra_free = p;
|
|
||||||
for (i = 0; i < tab_len; i++)
|
|
||||||
{
|
{
|
||||||
int lcs = wp->w_lcs_chars.tab2;
|
vim_memset(p, ' ', len);
|
||||||
|
p[len] = NUL;
|
||||||
if (*p == NUL)
|
vim_free(p_extra_free);
|
||||||
|
p_extra_free = p;
|
||||||
|
for (i = 0; i < tab_len; i++)
|
||||||
{
|
{
|
||||||
tab_len = i;
|
int lcs = wp->w_lcs_chars.tab2;
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// if tab3 is given, need to change the char
|
if (*p == NUL)
|
||||||
// for tab
|
{
|
||||||
if (wp->w_lcs_chars.tab3 && i == tab_len - 1)
|
tab_len = i;
|
||||||
lcs = wp->w_lcs_chars.tab3;
|
break;
|
||||||
mb_char2bytes(lcs, p);
|
}
|
||||||
p += mb_char2len(lcs);
|
|
||||||
n_extra += mb_char2len(lcs)
|
// if tab3 is given, use it for the last char
|
||||||
|
if (wp->w_lcs_chars.tab3 && i == tab_len - 1)
|
||||||
|
lcs = wp->w_lcs_chars.tab3;
|
||||||
|
p += mb_char2bytes(lcs, p);
|
||||||
|
n_extra += mb_char2len(lcs)
|
||||||
- (saved_nextra > 0 ? 1 : 0);
|
- (saved_nextra > 0 ? 1 : 0);
|
||||||
|
}
|
||||||
|
p_extra = p_extra_free;
|
||||||
|
# ifdef FEAT_CONCEAL
|
||||||
|
// n_extra will be increased by FIX_FOX_BOGUSCOLS
|
||||||
|
// macro below, so need to adjust for that here
|
||||||
|
if (vcol_off > 0)
|
||||||
|
n_extra -= vcol_off;
|
||||||
|
# endif
|
||||||
}
|
}
|
||||||
p_extra = p_extra_free;
|
|
||||||
#ifdef FEAT_CONCEAL
|
|
||||||
// n_extra will be increased by FIX_FOX_BOGUSCOLS
|
|
||||||
// macro below, so need to adjust for that here
|
|
||||||
if (vcol_off > 0)
|
|
||||||
n_extra -= vcol_off;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#ifdef FEAT_CONCEAL
|
#ifdef FEAT_CONCEAL
|
||||||
|
@@ -70,6 +70,16 @@ func Test_nolinebreak_with_list()
|
|||||||
call s:close_windows()
|
call s:close_windows()
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
|
" this was causing a crash
|
||||||
|
func Test_linebreak_with_list_and_tabs()
|
||||||
|
set linebreak list listchars=tab:⇤\ ⇥ tabstop=100
|
||||||
|
new
|
||||||
|
call setline(1, "\t\t\ttext")
|
||||||
|
redraw
|
||||||
|
bwipe!
|
||||||
|
set nolinebreak nolist listchars&vim tabstop=8
|
||||||
|
endfunc
|
||||||
|
|
||||||
func Test_linebreak_with_nolist()
|
func Test_linebreak_with_nolist()
|
||||||
call s:test_windows('setl nolist')
|
call s:test_windows('setl nolist')
|
||||||
call setline(1, "\t*mask = nil;")
|
call setline(1, "\t*mask = nil;")
|
||||||
|
@@ -755,6 +755,8 @@ static char *(features[]) =
|
|||||||
|
|
||||||
static int included_patches[] =
|
static int included_patches[] =
|
||||||
{ /* Add new patch number below this line */
|
{ /* Add new patch number below this line */
|
||||||
|
/**/
|
||||||
|
3410,
|
||||||
/**/
|
/**/
|
||||||
3409,
|
3409,
|
||||||
/**/
|
/**/
|
||||||
|
Reference in New Issue
Block a user