]> granicus.if.org Git - vim/commitdiff
patch 8.2.2563: cannot use multibyte characters for folding in 'fillchars' v8.2.2563
authorBram Moolenaar <Bram@vim.org>
Wed, 3 Mar 2021 12:26:02 +0000 (13:26 +0100)
committerBram Moolenaar <Bram@vim.org>
Wed, 3 Mar 2021 12:26:02 +0000 (13:26 +0100)
Problem:    Cannot use multibyte characters for folding in 'fillchars'.
Solution:   Port pull request 11568 to Vim. (Yegappan Lakshmanan,
            closes #7924)

src/drawline.c
src/drawscreen.c
src/macros.h
src/proto/screen.pro
src/screen.c
src/testdir/test_fold.vim
src/testdir/test_profile.vim
src/version.c

index 2f865127f7127f7fc80744988680f3aa41b5254b..03a229eaecfe611cd22d86b2134faa02097b9899 100644 (file)
@@ -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;
index 3fe1c0c7971139aca217aa5e3dadbdb50740d4f9..c2752bdd8ac8b903a346aa7fc6eaa415e9770095 100644 (file)
@@ -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);
index 3db2456f3c877828e8c93de78898f386d4956888..5a57a89284b30ff03b7127dafaead4f75402095a 100644 (file)
 
 // 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
index 1ab40df0c93619a46bce258824e99250e3010bfa..fc45fa15fef15747c9669a5ff5395008e22fc6c8 100644 (file)
@@ -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);
index a012c70037f119c742aa58be84825f6163fe5ac9..ce4ab11461a26d805472d3ecc9b1a589e591d36d 100644 (file)
@@ -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,39 +255,54 @@ 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;
+    empty = (fdc == 1) ? 0 : 1;
+
+    // If the column is too narrow, we start at the lowest level that
+    // fits and use numbers to indicated the depth.
+    first_level = level - fdc - closed + 1 + empty;
+    if (first_level < 1)
+       first_level = 1;
 
-       // If the column is too narrow, we start at the lowest level that
-       // fits and use numbers to indicated the depth.
-       first_level = level - fdc - closed + 1 + empty;
-       if (first_level < 1)
-           first_level = 1;
+    for (i = 0; i < MIN(fdc, level); i++)
+    {
+       if (win_foldinfo.fi_lnum == lnum
+               && first_level + i >= win_foldinfo.fi_low_level)
+           symbol = fill_foldopen;
+       else if (first_level == 1)
+           symbol = fill_foldsep;
+       else if (first_level + i <= 9)
+           symbol = '0' + first_level + i;
+       else
+           symbol = '>';
 
-       for (i = 0; i + empty < fdc; ++i)
+       len = utf_char2bytes(symbol, &p[byte_counter]);
+       byte_counter += len;
+       if (first_level + i >= level)
        {
-           if (win_foldinfo.fi_lnum == lnum
-                             && first_level + i >= win_foldinfo.fi_low_level)
-               p[i] = fill_foldopen;
-           else if (first_level == 1)
-               p[i] = fill_foldsep;
-           else if (first_level + i <= 9)
-               p[i] = '0' + first_level + i;
-           else
-               p[i] = '>';
-           if (first_level + i == level)
-               break;
+           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
 
index 8206193c4a4008052dd579982fdd9a54a55956a0..920dcc406de327a33f44cd0ed23f12e78cf3e871 100644 (file)
@@ -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
index 835a60279e916b4dc9364aeda51d54186eefb421..785cee3270933f49b20d156a7ba05c57f530805c 100644 (file)
@@ -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
 
 
index c4859dedad9d9f5adc08961d3b602366f8a30f98..83854d1ebb43b568f5eb601e9dff2dfc403ce4e1 100644 (file)
@@ -750,6 +750,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    2563,
 /**/
     2562,
 /**/