0
0
mirror of https://github.com/vim/vim.git synced 2025-09-26 04:04:07 -04:00

patch 8.2.2563: cannot use multibyte characters for folding in 'fillchars'

Problem:    Cannot use multibyte characters for folding in 'fillchars'.
Solution:   Port pull request 11568 to Vim. (Yegappan Lakshmanan,
            closes #7924)
This commit is contained in:
Bram Moolenaar
2021-03-03 13:26:02 +01:00
parent 37096afd3f
commit 4fa1175765
8 changed files with 219 additions and 53 deletions

View File

@@ -1031,12 +1031,11 @@ win_line(
// Draw the 'foldcolumn'. Allocate a buffer, "extra" may // Draw the 'foldcolumn'. Allocate a buffer, "extra" may
// already be in use. // already be in use.
vim_free(p_extra_free); vim_free(p_extra_free);
p_extra_free = alloc(12 + 1); p_extra_free = alloc(MAX_MCO * fdc + 1);
if (p_extra_free != NULL) if (p_extra_free != NULL)
{ {
fill_foldcolumn(p_extra_free, wp, FALSE, lnum); n_extra = fill_foldcolumn(p_extra_free, wp,
n_extra = fdc; FALSE, lnum);
p_extra_free[n_extra] = NUL; p_extra_free[n_extra] = NUL;
p_extra = p_extra_free; p_extra = p_extra_free;
c_extra = NUL; c_extra = NUL;

View File

@@ -1044,7 +1044,9 @@ fold_line(
linenr_T lnum, linenr_T lnum,
int row) int row)
{ {
char_u buf[FOLD_TEXT_LEN]; // Max value of 'foldcolumn' is 12 and maximum number of bytes in a
// multi-byte character is MAX_MCO.
char_u buf[MAX_MCO * 12 + 1];
pos_T *top, *bot; pos_T *top, *bot;
linenr_T lnume = lnum + fold_count - 1; linenr_T lnume = lnum + fold_count - 1;
int len; int len;
@@ -1077,29 +1079,6 @@ fold_line(
} }
#endif #endif
// 2. Add the 'foldcolumn'
// Reduce the width when there is not enough space.
fdc = compute_foldcolumn(wp, col);
if (fdc > 0)
{
fill_foldcolumn(buf, wp, TRUE, lnum);
#ifdef FEAT_RIGHTLEFT
if (wp->w_p_rl)
{
int i;
copy_text_attr(off + wp->w_width - fdc - col, buf, fdc,
HL_ATTR(HLF_FC));
// reverse the fold column
for (i = 0; i < fdc; ++i)
ScreenLines[off + wp->w_width - i - 1 - col] = buf[i];
}
else
#endif
copy_text_attr(off + col, buf, fdc, HL_ATTR(HLF_FC));
col += fdc;
}
#ifdef FEAT_RIGHTLEFT #ifdef FEAT_RIGHTLEFT
# define RL_MEMSET(p, v, l) \ # define RL_MEMSET(p, v, l) \
do { \ do { \
@@ -1118,6 +1097,53 @@ fold_line(
} while (0) } while (0)
#endif #endif
// 2. Add the 'foldcolumn'
// Reduce the width when there is not enough space.
fdc = compute_foldcolumn(wp, col);
if (fdc > 0)
{
char_u *p;
int i;
int idx;
fill_foldcolumn(buf, wp, TRUE, lnum);
p = buf;
for (i = 0; i < fdc; i++)
{
int ch;
if (has_mbyte)
ch = mb_ptr2char_adv(&p);
else
ch = *p++;
#ifdef FEAT_RIGHTLEFT
if (wp->w_p_rl)
idx = off + wp->w_width - i - 1 - col;
else
#endif
idx = off + col + i;
if (enc_utf8)
{
if (ch >= 0x80)
{
ScreenLinesUC[idx] = ch;
ScreenLinesC[0][idx] = 0;
ScreenLines[idx] = 0x80;
}
else
{
ScreenLines[idx] = ch;
ScreenLinesUC[idx] = 0;
}
}
else
ScreenLines[idx] = ch;
}
RL_MEMSET(col, HL_ATTR(HLF_FC), fdc);
col += fdc;
}
// Set all attributes of the 'number' or 'relativenumber' column and the // Set all attributes of the 'number' or 'relativenumber' column and the
// text // text
RL_MEMSET(col, HL_ATTR(HLF_FL), wp->w_width - col); RL_MEMSET(col, HL_ATTR(HLF_FL), wp->w_width - col);

View File

@@ -388,3 +388,10 @@
// Inlined version of ga_grow(). Especially useful if "n" is a constant. // Inlined version of ga_grow(). Especially useful if "n" is a constant.
#define GA_GROW(gap, n) (((gap)->ga_maxlen - (gap)->ga_len < n) ? ga_grow_inner((gap), (n)) : OK) #define GA_GROW(gap, n) (((gap)->ga_maxlen - (gap)->ga_len < n) ? ga_grow_inner((gap), (n)) : OK)
#ifndef MIN
# define MIN(a, b) ((a) < (b) ? (a) : (b))
#endif
#ifndef MAX
# define MAX(a, b) ((a) > (b) ? (a) : (b))
#endif

View File

@@ -4,7 +4,7 @@ void conceal_check_cursor_line(void);
int get_wcr_attr(win_T *wp); int get_wcr_attr(win_T *wp);
void win_draw_end(win_T *wp, int c1, int c2, int draw_margin, int row, int endrow, hlf_T hl); void win_draw_end(win_T *wp, int c1, int c2, int draw_margin, int row, int endrow, hlf_T hl);
int compute_foldcolumn(win_T *wp, int col); int compute_foldcolumn(win_T *wp, int col);
void fill_foldcolumn(char_u *p, win_T *wp, int closed, linenr_T lnum); size_t fill_foldcolumn(char_u *p, win_T *wp, int closed, linenr_T lnum);
int screen_get_current_line_off(void); int screen_get_current_line_off(void);
void reset_screen_attr(void); void reset_screen_attr(void);
void screen_line(int row, int coloff, int endcol, int clear_width, int flags); void screen_line(int row, int coloff, int endcol, int clear_width, int flags);

View File

@@ -239,8 +239,11 @@ compute_foldcolumn(win_T *wp, int col)
/* /*
* Fill the foldcolumn at "p" for window "wp". * Fill the foldcolumn at "p" for window "wp".
* Only to be called when 'foldcolumn' > 0. * Only to be called when 'foldcolumn' > 0.
* Returns the number of bytes stored in 'p'. When non-multibyte characters are
* used for the fold column markers, this is equal to 'fdc' setting. Otherwise,
* this will be greater than 'fdc'.
*/ */
void size_t
fill_foldcolumn( fill_foldcolumn(
char_u *p, char_u *p,
win_T *wp, win_T *wp,
@@ -252,14 +255,14 @@ fill_foldcolumn(
int first_level; int first_level;
int empty; int empty;
int fdc = compute_foldcolumn(wp, 0); int fdc = compute_foldcolumn(wp, 0);
size_t byte_counter = 0;
int symbol = 0;
int len = 0;
// Init to all spaces. // Init to all spaces.
vim_memset(p, ' ', (size_t)fdc); vim_memset(p, ' ', MAX_MCO * fdc + 1);
level = win_foldinfo.fi_level; level = win_foldinfo.fi_level;
if (level > 0)
{
// If there is only one column put more info in it.
empty = (fdc == 1) ? 0 : 1; empty = (fdc == 1) ? 0 : 1;
// If the column is too narrow, we start at the lowest level that // If the column is too narrow, we start at the lowest level that
@@ -268,23 +271,38 @@ fill_foldcolumn(
if (first_level < 1) if (first_level < 1)
first_level = 1; first_level = 1;
for (i = 0; i + empty < fdc; ++i) for (i = 0; i < MIN(fdc, level); i++)
{ {
if (win_foldinfo.fi_lnum == lnum if (win_foldinfo.fi_lnum == lnum
&& first_level + i >= win_foldinfo.fi_low_level) && first_level + i >= win_foldinfo.fi_low_level)
p[i] = fill_foldopen; symbol = fill_foldopen;
else if (first_level == 1) else if (first_level == 1)
p[i] = fill_foldsep; symbol = fill_foldsep;
else if (first_level + i <= 9) else if (first_level + i <= 9)
p[i] = '0' + first_level + i; symbol = '0' + first_level + i;
else else
p[i] = '>'; symbol = '>';
if (first_level + i == level)
len = utf_char2bytes(symbol, &p[byte_counter]);
byte_counter += len;
if (first_level + i >= level)
{
i++;
break; break;
} }
} }
if (closed) if (closed)
p[i >= fdc ? i - 1 : i] = fill_foldclosed; {
if (symbol != 0)
// rollback length
byte_counter -= len;
symbol = fill_foldclosed;
len = utf_char2bytes(symbol, &p[byte_counter]);
byte_counter += len;
}
return MAX(byte_counter + (fdc - i), (size_t)fdc);
} }
#endif // FEAT_FOLDING #endif // FEAT_FOLDING

View File

@@ -894,4 +894,116 @@ func Test_fold_relative_move()
set fdm& sw& wrap& tw& set fdm& sw& wrap& tw&
endfunc endfunc
" Test for using multibyte characters as 'foldopen', 'foldclose' and
" 'foldsetp' items in 'fillchars'
func s:mbyte_fillchar_tests(fo, fc, fs)
setlocal foldcolumn=3
normal zE
1,2fold
call assert_equal([a:fc .. ' +-- 2 ', ' three '],
\ ScreenLines([1, 2], 10))
1,2foldopen
call assert_equal([a:fo .. ' one ', a:fs .. ' two '],
\ ScreenLines([1, 2], 7))
1,2foldclose
redraw!
call assert_equal([a:fc .. ' +-- 2 ', ' three '],
\ ScreenLines([1, 2], 10))
" Two level fold
normal zE
2,3fold
1,4fold
call assert_equal([a:fc .. ' +-- 4 ', ' five '],
\ ScreenLines([1, 2], 10))
1,4foldopen
call assert_equal([a:fo .. ' one ', a:fs .. a:fc .. ' +--- 2'],
\ ScreenLines([1, 2], 10))
1,4foldopen
call assert_equal([a:fo .. ' one ', a:fs .. a:fo .. ' two ',
\ a:fs .. a:fs .. ' three '], ScreenLines([1, 3], 10))
2,3foldclose
call assert_equal([a:fo .. ' one ', a:fs .. a:fc .. ' +--- 2'],
\ ScreenLines([1, 2], 10))
1,4foldclose
call assert_equal([a:fc .. ' +-- 4 ', ' five '],
\ ScreenLines([1, 2], 10))
" Three level fold
normal zE
3,4fold
2,5fold
1,6fold
call assert_equal([a:fc .. ' +-- 6 '], ScreenLines(1, 10))
" open all the folds
normal zR
call assert_equal([
\ a:fo .. ' one ',
\ a:fs .. a:fo .. ' two ',
\ '2' .. a:fo .. ' three ',
\ '23 four ',
\ a:fs .. a:fs .. ' five ',
\ a:fs .. ' six ',
\ ], ScreenLines([1, 6], 10))
" close the innermost fold
3,4foldclose
call assert_equal([
\ a:fo .. ' one ',
\ a:fs .. a:fo .. ' two ',
\ a:fs .. a:fs .. a:fc .. '+---- ',
\ a:fs .. a:fs .. ' five ',
\ a:fs .. ' six ',
\ ], ScreenLines([1, 5], 10))
" close the next fold
2,5foldclose
call assert_equal([
\ a:fo .. ' one ',
\ a:fs .. a:fc .. ' +--- 4',
\ a:fs .. ' six ',
\ ], ScreenLines([1, 3], 10))
" set the fold column size to 2
setlocal fdc=2
normal zR
call assert_equal([
\ a:fo .. ' one ',
\ a:fo .. ' two ',
\ a:fo .. ' three',
\ '3 four ',
\ '2 five ',
\ a:fs .. ' six ',
\ ], ScreenLines([1, 6], 7))
" set the fold column size to 1
setlocal fdc=1
normal zR
call assert_equal([
\ a:fo .. 'one ',
\ a:fo .. 'two ',
\ a:fo .. 'three ',
\ '3four ',
\ '2five ',
\ a:fs .. 'six ',
\ ], ScreenLines([1, 6], 7))
setlocal foldcolumn&
endfunc
func Test_foldcolumn_multibyte_char()
new
call setline(1, ['one', 'two', 'three', 'four', 'five', 'six'])
setlocal foldenable foldmethod=manual
" First test with the default setting
call s:mbyte_fillchar_tests('-', '+', '|')
" Use multi-byte characters
set fillchars+=foldopen:▾,foldsep:│,foldclose:▸
call s:mbyte_fillchar_tests('▾', '▸', '│')
bw!
set foldenable& fdc& fdm& fillchars&
endfunc
" vim: shiftwidth=2 sts=2 expandtab " vim: shiftwidth=2 sts=2 expandtab

View File

@@ -636,6 +636,8 @@ func Test_vim9_nested_call()
call assert_match('FUNCTION <SNR>\d\+_Two().*' call assert_match('FUNCTION <SNR>\d\+_Two().*'
\ .. '#Called 3 times.*' \ .. '#Called 3 times.*'
\ .. '# 3 \s*[0-9.]\+ total += nr', prof_lines) \ .. '# 3 \s*[0-9.]\+ total += nr', prof_lines)
call delete('Xprofile_nested.vim')
call delete('Xprofile_nested.log')
endfunc endfunc

View File

@@ -750,6 +750,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 */
/**/
2563,
/**/ /**/
2562, 2562,
/**/ /**/