# HG changeset patch # User Bram Moolenaar # Date 1637437502 -3600 # Node ID 2093cc976da8970f0f122cc8b4cf720f4cc02a56 # Parent 75bc457099c4a8f9c2de1bb56381393f4ab54726 patch 8.2.3630: printf() with %S does not handle multi-byte correctly Commit: https://github.com/vim/vim/commit/d85fccdfed58108c4e0958d0b17c64690b5f073f Author: presuku Date: Sat Nov 20 19:38:31 2021 +0000 patch 8.2.3630: printf() with %S does not handle multi-byte correctly Problem: Printf() with %S does not handle multi-byte correctly. Solution: Count cells instead of bytes. (closes https://github.com/vim/vim/issues/9169, closes https://github.com/vim/vim/issues/7486) diff --git a/src/strings.c b/src/strings.c --- a/src/strings.c +++ b/src/strings.c @@ -2137,14 +2137,15 @@ vim_vsnprintf_typval( char *q = memchr(str_arg, '\0', precision <= (size_t)0x7fffffffL ? precision : (size_t)0x7fffffffL); + str_arg_l = (q == NULL) ? precision : (size_t)(q - str_arg); } if (fmt_spec == 'S') { - if (min_field_width != 0) - min_field_width += STRLEN(str_arg) - - mb_string2cells((char_u *)str_arg, -1); + size_t base_width = min_field_width; + size_t pad_cell = 0; + if (precision) { char_u *p1; @@ -2157,8 +2158,12 @@ vim_vsnprintf_typval( if (i > precision) break; } - str_arg_l = precision = p1 - (char_u *)str_arg; + pad_cell = min_field_width - precision; + base_width = str_arg_l = precision = + p1 - (char_u *)str_arg; } + if (min_field_width != 0) + min_field_width = base_width + pad_cell; } break; diff --git a/src/testdir/test_expr.vim b/src/testdir/test_expr.vim --- a/src/testdir/test_expr.vim +++ b/src/testdir/test_expr.vim @@ -297,6 +297,11 @@ function Test_printf_misc() call assert_equal('🐍', printf('%.2S', '🐍🐍')) call assert_equal('', printf('%.1S', '🐍🐍')) + call assert_equal('[ あいう]', printf('[%10.6S]', 'あいうえお')) + call assert_equal('[ あいうえ]', printf('[%10.8S]', 'あいうえお')) + call assert_equal('[あいうえお]', printf('[%10.10S]', 'あいうえお')) + call assert_equal('[あいうえお]', printf('[%10.12S]', 'あいうえお')) + call assert_equal('1%', printf('%d%%', 1)) endfunc diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -758,6 +758,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 3630, +/**/ 3629, /**/ 3628,