diff options
author | Bram Moolenaar <Bram@vim.org> | 2021-09-07 20:45:31 +0200 |
---|---|---|
committer | Bram Moolenaar <Bram@vim.org> | 2021-09-07 20:45:31 +0200 |
commit | 89a54b413a8c96206ce7e038dde81a6eff6cd6b8 (patch) | |
tree | 4c4f903381f3e92f8a441443855958c6d2f5a1d6 | |
parent | 65b605665997fad54ef39a93199e305af2fe4d7f (diff) | |
download | vim-git-89a54b413a8c96206ce7e038dde81a6eff6cd6b8.tar.gz |
patch 8.2.3410: crash with linebreak, listchars and large tabstopv8.2.3410
Problem: Crash with linebreak, listchars and large tabstop.
Solution: Account for different size listchars for a tab. (closes #8841)
-rw-r--r-- | src/drawline.c | 67 | ||||
-rw-r--r-- | src/testdir/test_listlbr_utf8.vim | 10 | ||||
-rw-r--r-- | src/version.c | 2 |
3 files changed, 48 insertions, 31 deletions
diff --git a/src/drawline.c b/src/drawline.c index 98d76930f..2ad83f4b5 100644 --- a/src/drawline.c +++ b/src/drawline.c @@ -2109,55 +2109,60 @@ win_line( int i; int saved_nextra = n_extra; -#ifdef FEAT_CONCEAL +# ifdef FEAT_CONCEAL if (vcol_off > 0) // there are characters to conceal tab_len += vcol_off; + // boguscols before FIX_FOR_BOGUSCOLS macro from above if (wp->w_p_list && wp->w_lcs_chars.tab1 && old_boguscols > 0 && n_extra > tab_len) tab_len += n_extra - tab_len; -#endif - - // if n_extra > 0, it gives the number of chars, to +# endif + // If n_extra > 0, it gives the number of chars, to // 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)); + if (wp->w_lcs_chars.tab3) + len += mb_char2len(wp->w_lcs_chars.tab3); if (n_extra > 0) len += n_extra - tab_len; c = wp->w_lcs_chars.tab1; p = alloc(len + 1); - vim_memset(p, ' ', len); - p[len] = NUL; - vim_free(p_extra_free); - p_extra_free = p; - for (i = 0; i < tab_len; i++) + if (p == NULL) + n_extra = 0; + else { - int lcs = wp->w_lcs_chars.tab2; - - if (*p == NUL) + vim_memset(p, ' ', len); + p[len] = NUL; + vim_free(p_extra_free); + p_extra_free = p; + for (i = 0; i < tab_len; i++) { - tab_len = i; - break; - } - - // if tab3 is given, need to change the char - // for tab - if (wp->w_lcs_chars.tab3 && i == tab_len - 1) - lcs = wp->w_lcs_chars.tab3; - mb_char2bytes(lcs, p); - p += mb_char2len(lcs); - n_extra += mb_char2len(lcs) + int lcs = wp->w_lcs_chars.tab2; + + if (*p == NUL) + { + tab_len = i; + break; + } + + // 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); + } + 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 #ifdef FEAT_CONCEAL diff --git a/src/testdir/test_listlbr_utf8.vim b/src/testdir/test_listlbr_utf8.vim index 6f12b5f53..0d77dbfd3 100644 --- a/src/testdir/test_listlbr_utf8.vim +++ b/src/testdir/test_listlbr_utf8.vim @@ -70,6 +70,16 @@ func Test_nolinebreak_with_list() call s:close_windows() 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() call s:test_windows('setl nolist') call setline(1, "\t*mask = nil;") diff --git a/src/version.c b/src/version.c index 0eb6899ed..979c039ba 100644 --- a/src/version.c +++ b/src/version.c @@ -756,6 +756,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 3410, +/**/ 3409, /**/ 3408, |