From: Hirohito Higashi Date: Tue, 11 Aug 2026 19:16:00 +0000 (+0000) Subject: patch 9.2.0939: mbyte: wrong cell count for an overlong UTF-8 sequence X-Git-Tag: v9.2.0939^0 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=0cdcd95cc2f6a000aafe084f31299cc69affc139;p=thirdparty%2Fvim.git patch 9.2.0939: mbyte: wrong cell count for an overlong UTF-8 sequence Problem: An overlong UTF-8 encoding of an unprintable ASCII character is displayed as but counted as two screen cells, so that the cursor ends up in the wrong position when editing the line. Solution: Count four cells for an unprintable overlong sequence. fixes: #20988 closes: #21005 Co-Authored-By: Claude Opus 5 (1M context) Signed-off-by: Hirohito Higashi Signed-off-by: Christian Brabandt --- diff --git a/src/mbyte.c b/src/mbyte.c index 54ee229a1a..e196f30cae 100644 --- a/src/mbyte.c +++ b/src/mbyte.c @@ -1645,7 +1645,7 @@ utf_ptr2cells( return 4; // If the char is ASCII it must be an overlong sequence. if (c < 0x80) - return char2cells(c); + return vim_isprintc(c) ? char2cells(c) : 4; return utf_char2cells(c); } return 1; @@ -1689,7 +1689,7 @@ utf_ptr2cells_len(char_u *p, int size) return 4; // If the char is ASCII it must be an overlong sequence. if (c < 0x80) - return char2cells(c); + return vim_isprintc(c) ? char2cells(c) : 4; return utf_char2cells(c); } return 1; diff --git a/src/testdir/test_utf8.vim b/src/testdir/test_utf8.vim index a0cd5bd79f..3070d4cc4b 100644 --- a/src/testdir/test_utf8.vim +++ b/src/testdir/test_utf8.vim @@ -372,4 +372,20 @@ func Test_print_overlong() bwipe! endfunc +" The cell count of an overlong encoded character must match what is drawn. +func Test_overlong_utf8_cells() + call assert_equal(4, strdisplaywidth("\xc0\x81")) " <01> + call assert_equal(4, strdisplaywidth("\xe0\x80\x81")) " <01>, three bytes + call assert_equal(4, strdisplaywidth("\xc1\xbf")) " <7f> + call assert_equal(4, strdisplaywidth("\xc0\x89")) " <09>, not a Tab + + new + call setline(1, "\xc1\x81\xc0\x81\xc0\x80") + call assert_equal('A<01><00>', ScreenLines(1, 9)[0]) + normal! $ + call assert_equal(5, col('.')) + call assert_equal([6, 9], virtcol('.', v:true)) + bwipe! +endfunc + " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/version.c b/src/version.c index 48a1faf0fb..6405f229e6 100644 --- a/src/version.c +++ b/src/version.c @@ -763,6 +763,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 939, /**/ 938, /**/