]> granicus.if.org Git - vim/commitdiff
patch 8.2.2569: 'fillchars' "stl" and "stlnc" items must be single byte v8.2.2569
authorBram Moolenaar <Bram@vim.org>
Thu, 4 Mar 2021 20:55:58 +0000 (21:55 +0100)
committerBram Moolenaar <Bram@vim.org>
Thu, 4 Mar 2021 20:55:58 +0000 (21:55 +0100)
Problem:    'fillchars' "stl" and "stlnc" items must be single byte.
Solution:   Accept multi-byte characters. (Christian Wellenbrock, Yegappan
            Lakshmanan, closes #7927)

runtime/doc/options.txt
src/buffer.c
src/macros.h
src/screen.c
src/testdir/test_fold.vim
src/testdir/test_statusline.vim
src/version.c

index 70746082cfe70a165f054354a731dd3dcb3c8855..7fcdfbe953a1f143b40d9b97852edb29ebc57213 100644 (file)
@@ -3262,7 +3262,8 @@ A jump table for the options with a short description can be found at |Q_op|.
 <      This is similar to the default, except that these characters will also
        be used when there is highlighting.
 
-       for "stl" and "stlnc" only single-byte values are supported.
+       For "stl" and "stlnc" single-byte and multibyte characters are
+       supported.  But double-width characters are not supported.
 
        The highlighting used for these items:
          item          highlight group ~
index 4e4f87c9269f957f03e4b343f26f861d58b5201b..f80d42494386a4375cfc2e335e40478cad341d98 100644 (file)
@@ -4157,9 +4157,6 @@ build_stl_str_hl(
 
     if (fillchar == 0)
        fillchar = ' ';
-    // Can't handle a multi-byte fill character yet.
-    else if (mb_char2len(fillchar) > 1)
-       fillchar = '-';
 
     // The cursor in windows other than the current one isn't always
     // up-to-date, esp. because of autocommands and timers.
@@ -4335,7 +4332,7 @@ build_stl_str_hl(
 
                // Fill up space left over by half a double-wide char.
                while (++l < stl_items[stl_groupitem[groupdepth]].stl_minwid)
-                   *p++ = fillchar;
+                   MB_CHAR2BYTES(fillchar, p);
 
                // correct the start of the items for the truncation
                for (l = stl_groupitem[groupdepth] + 1; l < curitem; l++)
@@ -4354,20 +4351,20 @@ build_stl_str_hl(
                    // fill by appending characters
                    n = 0 - n;
                    while (l++ < n && p + 1 < out + outlen)
-                       *p++ = fillchar;
+                       MB_CHAR2BYTES(fillchar, p);
                }
                else
                {
                    // fill by inserting characters
-                   mch_memmove(t + n - l, t, (size_t)(p - t));
-                   l = n - l;
+                   l = (n - l) * MB_CHAR2LEN(fillchar);
+                   mch_memmove(t + l, t, (size_t)(p - t));
                    if (p + l >= out + outlen)
                        l = (long)((out + outlen) - p - 1);
                    p += l;
                    for (n = stl_groupitem[groupdepth] + 1; n < curitem; n++)
                        stl_items[n].stl_start += l;
                    for ( ; l > 0; l--)
-                       *t++ = fillchar;
+                       MB_CHAR2BYTES(fillchar, t);
                }
            }
            continue;
@@ -4746,23 +4743,24 @@ build_stl_str_hl(
                    if (l + 1 == minwid && fillchar == '-' && VIM_ISDIGIT(*t))
                        *p++ = ' ';
                    else
-                       *p++ = fillchar;
+                       MB_CHAR2BYTES(fillchar, p);
                }
                minwid = 0;
            }
            else
                minwid *= -1;
-           while (*t && p + 1 < out + outlen)
+           for (; *t && p + 1 < out + outlen; t++)
            {
-               *p++ = *t++;
                // Change a space by fillchar, unless fillchar is '-' and a
                // digit follows.
-               if (fillable && p[-1] == ' '
-                                    && (!VIM_ISDIGIT(*t) || fillchar != '-'))
-                   p[-1] = fillchar;
+               if (fillable && *t == ' '
+                               && (!VIM_ISDIGIT(*(t + 1)) || fillchar != '-'))
+                   MB_CHAR2BYTES(fillchar, p);
+               else
+                   *p++ = *t;
            }
            for (; l < minwid && p + 1 < out + outlen; l++)
-               *p++ = fillchar;
+               MB_CHAR2BYTES(fillchar, p);
        }
        else if (num >= 0)
        {
@@ -4865,7 +4863,7 @@ build_stl_str_hl(
                }
                // Fill up for half a double-wide character.
                while (++width < maxwidth)
-                   *s++ = fillchar;
+                   MB_CHAR2BYTES(fillchar, s);
            }
            else
                s = out + maxwidth - 1;
@@ -4897,7 +4895,7 @@ build_stl_str_hl(
            while (++width < maxwidth)
            {
                s = s + STRLEN(s);
-               *s++ = fillchar;
+               MB_CHAR2BYTES(fillchar, s);
                *s = NUL;
            }
 
@@ -4920,12 +4918,13 @@ build_stl_str_hl(
                break;
        if (l < itemcnt)
        {
-           p = stl_items[l].stl_start + maxwidth - width;
+           int middlelength = (maxwidth - width) * MB_CHAR2LEN(fillchar);
+           p = stl_items[l].stl_start + middlelength;
            STRMOVE(p, stl_items[l].stl_start);
-           for (s = stl_items[l].stl_start; s < p; s++)
-               *s = fillchar;
+           for (s = stl_items[l].stl_start; s < p;)
+               MB_CHAR2BYTES(fillchar, s);
            for (l++; l < itemcnt; l++)
-               stl_items[l].stl_start += maxwidth - width;
+               stl_items[l].stl_start += middlelength;
            width = maxwidth;
        }
     }
index 5a57a89284b30ff03b7127dafaead4f75402095a..c11ee660c9fbb9427a6c4cea1389026add411ee2 100644 (file)
 #define MB_CHARLEN(p)      (has_mbyte ? mb_charlen(p) : (int)STRLEN(p))
 #define MB_CHAR2LEN(c)     (has_mbyte ? mb_char2len(c) : 1)
 #define PTR2CHAR(p)        (has_mbyte ? mb_ptr2char(p) : (int)*(p))
+#define MB_CHAR2BYTES(c, b) do { if (has_mbyte) (b) += (*mb_char2bytes)((c), (b)); else *(b)++ = (c); } while(0)
 
 #ifdef FEAT_AUTOCHDIR
 # define DO_AUTOCHDIR do { if (p_acd) do_autochdir(); } while (0)
index ce4ab11461a26d805472d3ecc9b1a589e591d36d..84951c5cc65442b764cbaaa729e4e581028f86f6 100644 (file)
@@ -266,7 +266,7 @@ fill_foldcolumn(
     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.
+    // fits and use numbers to indicate the depth.
     first_level = level - fdc - closed + 1 + empty;
     if (first_level < 1)
        first_level = 1;
index 920dcc406de327a33f44cd0ed23f12e78cf3e871..d451b1eb495c7f105acc4a280f10a10a8d1558ce 100644 (file)
@@ -987,7 +987,66 @@ func s:mbyte_fillchar_tests(fo, fc, fs)
         \ a:fs .. 'six   ',
         \ ], ScreenLines([1, 6], 7))
 
-  setlocal foldcolumn&
+  " Enable number and sign columns and place some signs
+  setlocal fdc=3
+  setlocal number
+  setlocal signcolumn=auto
+  sign define S1 text=->
+  sign place 10 line=3 name=S1
+  call assert_equal([
+        \ a:fo .. '      1 one  ',
+        \ a:fs .. a:fo .. '     2 two  ',
+        \ '2' .. a:fo .. ' ->  3 three',
+        \ '23     4 four ',
+        \ a:fs .. a:fs .. '     5 five ',
+        \ a:fs .. '      6 six  '
+        \ ], ScreenLines([1, 6], 14))
+
+  " Test with 'rightleft'
+  if has('rightleft')
+    setlocal rightleft
+    let lines = ScreenLines([1, 6], winwidth(0))
+    call assert_equal('o 1      ' .. a:fo,
+          \  strcharpart(lines[0], strchars(lines[0]) - 10, 10))
+    call assert_equal('t 2     ' .. a:fo .. a:fs,
+          \  strcharpart(lines[1], strchars(lines[1]) - 10, 10))
+    call assert_equal('t 3  >- ' .. a:fo .. '2',
+          \  strcharpart(lines[2], strchars(lines[2]) - 10, 10))
+    call assert_equal('f 4     32',
+          \  strcharpart(lines[3], strchars(lines[3]) - 10, 10))
+    call assert_equal('f 5     ' .. a:fs .. a:fs,
+          \  strcharpart(lines[4], strchars(lines[4]) - 10, 10))
+    call assert_equal('s 6      ' .. a:fs,
+          \  strcharpart(lines[5], strchars(lines[5]) - 10, 10))
+    setlocal norightleft
+  endif
+
+  sign unplace *
+  sign undefine S1
+  setlocal number& signcolumn&
+
+  " Add a test with more than 9 folds (and then delete some folds)
+  normal zE
+  for i in range(1, 10)
+    normal zfGzo
+  endfor
+  normal zR
+  call assert_equal([
+        \ a:fo .. a:fo .. ' one ',
+        \ '9> two '
+        \ ], ScreenLines([1, 2], 7))
+  normal 1Gzd
+  call assert_equal([
+        \ a:fo .. a:fo .. ' one ',
+        \ '89 two '
+        \ ], ScreenLines([1, 2], 7))
+  normal 1Gzdzdzdzdzdzdzd
+  call assert_equal([
+        \ a:fo .. a:fo .. ' one ',
+        \ a:fs .. a:fs .. ' two '
+        \ ], ScreenLines([1, 2], 7))
+
+  setlocal foldcolumn& number& signcolumn&
 endfunc
 
 func Test_foldcolumn_multibyte_char()
index b28dbb953905b58de385b08a5bc8534a9836033f..f6c05f661bf3b168aae0ed6e6e891a21fa792d90 100644 (file)
@@ -464,5 +464,20 @@ func Test_statusline_after_split_vsplit()
   set ls& stl&
 endfunc
 
+" Test using a multibyte character for 'stl' and 'stlnc' items in 'fillchars'
+" with a custom 'statusline'
+func Test_statusline_mbyte_fillchar()
+  only
+  set laststatus=2
+  set fillchars=vert:\|,fold:-,stl:━,stlnc:═
+  set statusline=a%=b
+  call assert_match('^a\+━\+b$', s:get_statusline())
+  vnew
+  call assert_match('^a\+━\+b━a\+═\+b$', s:get_statusline())
+  wincmd w
+  call assert_match('^a\+═\+b═a\+━\+b$', s:get_statusline())
+  set statusline& fillchars& laststatus&
+  %bw!
+endfunc
 
 " vim: shiftwidth=2 sts=2 expandtab
index da9328c69be5e7459ac83406a8401af1973124cd..ffedb4fdf6feafebc61f1a129ff63f015a4e27fa 100644 (file)
@@ -750,6 +750,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    2569,
 /**/
     2568,
 /**/