# HG changeset patch # User Bram Moolenaar # Date 1622204103 -7200 # Node ID 9d304d363ab6305917a6664d35a66aebb72db646 # Parent 46c0305949ee983c141001d581f3fb2c95b83015 patch 8.2.2893: multi-byte text in popup title shows up wrong Commit: https://github.com/vim/vim/commit/bc869874fedf094129831836f131c64f10d98854 Author: Ralf Schandl Date: Fri May 28 14:12:14 2021 +0200 patch 8.2.2893: multi-byte text in popup title shows up wrong Problem: Multi-byte text in popup title shows up wrong. Solution: Use the character width instead of the byte length. (Ralf Schandl, closes #8267, closes #8264) diff --git a/src/message_test.c b/src/message_test.c --- a/src/message_test.c +++ b/src/message_test.c @@ -121,6 +121,37 @@ test_trunc_string(void) } /* + * Test trunc_string() with mbyte chars. + */ + static void +test_trunc_string_mbyte(void) +{ + char_u *buf; // allocated every time to find uninit errors + char_u *s; + + buf = alloc(40); + s = vim_strsave((char_u *)"Ä text tha just fits"); + trunc_string(s, buf, 20, 40); + assert(STRCMP(buf, "Ä text tha just fits") == 0); + vim_free(buf); + vim_free(s); + + buf = alloc(40); + s = vim_strsave((char_u *)"a text ÄÖÜä nott fits"); + trunc_string(s, buf, 20, 40); + assert(STRCMP(buf, "a text Ä...nott fits") == 0); + vim_free(buf); + vim_free(s); + + buf = alloc(40); + s = vim_strsave((char_u *)"a text that not fitsÄ"); + trunc_string(s, buf, 20, 40); + assert(STRCMP(buf, "a text t...not fitsÄ") == 0); + vim_free(buf); + vim_free(s); +} + +/* * Test vim_snprintf() with a focus on checking that truncation is * correct when buffer is small, since it cannot be tested from * vim scrip tests. Check that: @@ -286,6 +317,7 @@ main(int argc, char **argv) set_option_value((char_u *)"encoding", 0, (char_u *)"utf-8", 0); init_chartab(); test_trunc_string(); + test_trunc_string_mbyte(); test_vim_snprintf(); set_option_value((char_u *)"encoding", 0, (char_u *)"latin1", 0); diff --git a/src/popupwin.c b/src/popupwin.c --- a/src/popupwin.c +++ b/src/popupwin.c @@ -3822,17 +3822,29 @@ update_popups(void (*win_update)(win_T * title_wincol = wp->w_wincol + 1; if (wp->w_popup_title != NULL) { - char_u *title_text; - - title_len = (int)STRLEN(wp->w_popup_title); - title_text = alloc(title_len + 1); - trunc_string(wp->w_popup_title, title_text, - total_width - 2, title_len + 1); - screen_puts(title_text, wp->w_winrow, title_wincol, + title_len = (int)MB_CHARLEN(wp->w_popup_title); + + // truncate the title if too long + if (title_len > total_width - 2) + { + int title_byte_len = (int)STRLEN(wp->w_popup_title); + char_u *title_text = alloc(title_byte_len + 1); + + if (title_text != NULL) + { + trunc_string(wp->w_popup_title, title_text, + total_width - 2, title_byte_len + 1); + screen_puts(title_text, wp->w_winrow, title_wincol, + wp->w_popup_border[0] > 0 + ? border_attr[0] : popup_attr); + vim_free(title_text); + } + + title_len = total_width - 2; + } + else + screen_puts(wp->w_popup_title, wp->w_winrow, title_wincol, wp->w_popup_border[0] > 0 ? border_attr[0] : popup_attr); - vim_free(title_text); - if (title_len > total_width - 2) - title_len = total_width - 2; } wincol = wp->w_wincol - wp->w_popup_leftoff; diff --git a/src/testdir/dumps/Test_popupwin_multibytetitle.dump b/src/testdir/dumps/Test_popupwin_multibytetitle.dump new file mode 100644 --- /dev/null +++ b/src/testdir/dumps/Test_popupwin_multibytetitle.dump @@ -0,0 +1,10 @@ +>1+0&#ffffff0| @73 +|2| @73 +|3| @73 +|4| @25|╔+0#0000001#ffd7ff255|▶|Ä|Ö|Ü|◀|═@12|╗| +0#0000000#ffffff0@27 +|5| @25|║+0#0000001#ffd7ff255| |T+0&#e0e0e08|h|i|s| |i|s| |a| |l|i|n|e| @1| +0&#ffd7ff255|║| +0#0000000#ffffff0@27 +|6| @25|║+0#0000001#ffd7ff255| |a|n|d| |a|n|o|t|h|e|r| |l|i|n|e| |║| +0#0000000#ffffff0@27 +|7| @25|╚+0#0000001#ffd7ff255|═@17|╝| +0#0000000#ffffff0@27 +|8| @73 +|9| @73 +@57|1|,|1| @10|T|o|p| diff --git a/src/testdir/test_popupwin.vim b/src/testdir/test_popupwin.vim --- a/src/testdir/test_popupwin.vim +++ b/src/testdir/test_popupwin.vim @@ -1799,6 +1799,11 @@ func Test_popup_title() call term_sendkeys(buf, ":\") call VerifyScreenDump(buf, 'Test_popupwin_longtitle_4', {}) + call term_sendkeys(buf, ":call popup_clear()\") + call term_sendkeys(buf, ":call popup_menu(['This is a line', 'and another line'], #{title: '▶ÄÖÜ◀', })\") + call VerifyScreenDump(buf, 'Test_popupwin_multibytetitle', {}) + call term_sendkeys(buf, "x") + " clean up call StopVimInTerminal(buf) call delete('XtestPopupTitle') diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -751,6 +751,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 2893, +/**/ 2892, /**/ 2891,