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:
@@ -1031,12 +1031,11 @@ win_line(
|
||||
// Draw the 'foldcolumn'. Allocate a buffer, "extra" may
|
||||
// already be in use.
|
||||
vim_free(p_extra_free);
|
||||
p_extra_free = alloc(12 + 1);
|
||||
|
||||
p_extra_free = alloc(MAX_MCO * fdc + 1);
|
||||
if (p_extra_free != NULL)
|
||||
{
|
||||
fill_foldcolumn(p_extra_free, wp, FALSE, lnum);
|
||||
n_extra = fdc;
|
||||
n_extra = fill_foldcolumn(p_extra_free, wp,
|
||||
FALSE, lnum);
|
||||
p_extra_free[n_extra] = NUL;
|
||||
p_extra = p_extra_free;
|
||||
c_extra = NUL;
|
||||
|
@@ -1044,7 +1044,9 @@ fold_line(
|
||||
linenr_T lnum,
|
||||
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;
|
||||
linenr_T lnume = lnum + fold_count - 1;
|
||||
int len;
|
||||
@@ -1077,29 +1079,6 @@ fold_line(
|
||||
}
|
||||
#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
|
||||
# define RL_MEMSET(p, v, l) \
|
||||
do { \
|
||||
@@ -1118,6 +1097,53 @@ fold_line(
|
||||
} while (0)
|
||||
#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
|
||||
// text
|
||||
RL_MEMSET(col, HL_ATTR(HLF_FL), wp->w_width - col);
|
||||
|
@@ -388,3 +388,10 @@
|
||||
|
||||
// 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)
|
||||
|
||||
#ifndef MIN
|
||||
# define MIN(a, b) ((a) < (b) ? (a) : (b))
|
||||
#endif
|
||||
#ifndef MAX
|
||||
# define MAX(a, b) ((a) > (b) ? (a) : (b))
|
||||
#endif
|
||||
|
@@ -4,7 +4,7 @@ void conceal_check_cursor_line(void);
|
||||
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);
|
||||
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);
|
||||
void reset_screen_attr(void);
|
||||
void screen_line(int row, int coloff, int endcol, int clear_width, int flags);
|
||||
|
42
src/screen.c
42
src/screen.c
@@ -239,8 +239,11 @@ compute_foldcolumn(win_T *wp, int col)
|
||||
/*
|
||||
* Fill the foldcolumn at "p" for window "wp".
|
||||
* 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(
|
||||
char_u *p,
|
||||
win_T *wp,
|
||||
@@ -252,14 +255,14 @@ fill_foldcolumn(
|
||||
int first_level;
|
||||
int empty;
|
||||
int fdc = compute_foldcolumn(wp, 0);
|
||||
size_t byte_counter = 0;
|
||||
int symbol = 0;
|
||||
int len = 0;
|
||||
|
||||
// Init to all spaces.
|
||||
vim_memset(p, ' ', (size_t)fdc);
|
||||
vim_memset(p, ' ', MAX_MCO * fdc + 1);
|
||||
|
||||
level = win_foldinfo.fi_level;
|
||||
if (level > 0)
|
||||
{
|
||||
// If there is only one column put more info in it.
|
||||
empty = (fdc == 1) ? 0 : 1;
|
||||
|
||||
// If the column is too narrow, we start at the lowest level that
|
||||
@@ -268,23 +271,38 @@ fill_foldcolumn(
|
||||
if (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
|
||||
&& first_level + i >= win_foldinfo.fi_low_level)
|
||||
p[i] = fill_foldopen;
|
||||
symbol = fill_foldopen;
|
||||
else if (first_level == 1)
|
||||
p[i] = fill_foldsep;
|
||||
symbol = fill_foldsep;
|
||||
else if (first_level + i <= 9)
|
||||
p[i] = '0' + first_level + i;
|
||||
symbol = '0' + first_level + i;
|
||||
else
|
||||
p[i] = '>';
|
||||
if (first_level + i == level)
|
||||
symbol = '>';
|
||||
|
||||
len = utf_char2bytes(symbol, &p[byte_counter]);
|
||||
byte_counter += len;
|
||||
if (first_level + i >= level)
|
||||
{
|
||||
i++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
|
@@ -894,4 +894,116 @@ func Test_fold_relative_move()
|
||||
set fdm& sw& wrap& tw&
|
||||
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
|
||||
|
@@ -636,6 +636,8 @@ func Test_vim9_nested_call()
|
||||
call assert_match('FUNCTION <SNR>\d\+_Two().*'
|
||||
\ .. '#Called 3 times.*'
|
||||
\ .. '# 3 \s*[0-9.]\+ total += nr', prof_lines)
|
||||
call delete('Xprofile_nested.vim')
|
||||
call delete('Xprofile_nested.log')
|
||||
endfunc
|
||||
|
||||
|
||||
|
@@ -750,6 +750,8 @@ static char *(features[]) =
|
||||
|
||||
static int included_patches[] =
|
||||
{ /* Add new patch number below this line */
|
||||
/**/
|
||||
2563,
|
||||
/**/
|
||||
2562,
|
||||
/**/
|
||||
|
Reference in New Issue
Block a user