patch 9.1.1296: completion: incorrect truncation logic Commit: https://github.com/vim/vim/commit/d4dbf822dcb9fd95379bebab85def391e1179b21 Author: glepnir <glephun...@gmail.com> Date: Sat Apr 12 18:35:34 2025 +0200
patch 9.1.1296: completion: incorrect truncation logic Problem: completion: incorrect truncation logic (after: v9.1.1284) Solution: replace string allocation with direct screen rendering and fixe RTL/LTR truncation calculations (glepnir) closes: #17081 Signed-off-by: glepnir <glephun...@gmail.com> Signed-off-by: Christian Brabandt <c...@256bit.org> diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt index 9fab3f46d..089df1411 100644 --- a/runtime/doc/options.txt +++ b/runtime/doc/options.txt @@ -3621,6 +3621,7 @@ A jump table for the options with a short description can be found at |Q_op|. lastline '@' 'display' contains lastline/truncate trunc '>' truncated text in the |ins-completion-menu|. + truncrl '<' same as "trunc' in 'rightleft' mode Any one that is omitted will fall back to the default. @@ -3645,6 +3646,7 @@ A jump table for the options with a short description can be found at |Q_op|. lastline NonText |hl-NonText| trunc one of the many Popup menu highlighting groups like |hl-PmenuSel| + truncrl same as "trunc" *'findfunc'* *'ffu'* *E1514* 'findfunc' 'ffu' string (default empty) diff --git a/runtime/doc/version9.txt b/runtime/doc/version9.txt index 8a7f49e33..befd92ffd 100644 --- a/runtime/doc/version9.txt +++ b/runtime/doc/version9.txt @@ -1,4 +1,4 @@ -*version9.txt* For Vim version 9.1. Last change: 2025 Apr 08 +*version9.txt* For Vim version 9.1. Last change: 2025 Apr 12 VIM REFERENCE MANUAL by Bram Moolenaar @@ -41631,6 +41631,7 @@ Options: ~ and CTRL-D / CTRL-U for half-pagewise scrolling - New option value for 'fillchars': "trunc" - configure truncation indicator, 'pummaxwidth' + "truncrl" - like "trunc" but in 'rl' mode, 'pummaxwidth' Ex commands: ~ - allow to specify a priority when defining a new sign |:sign-define| diff --git a/src/popupmenu.c b/src/popupmenu.c index 556c2c350..07c99f052 100644 --- a/src/popupmenu.c +++ b/src/popupmenu.c @@ -604,10 +604,15 @@ pum_redraw(void) int last_isabbr = FALSE; int orig_attr = -1; int scroll_range = pum_size - pum_height; - char_u *new_str = NULL; - char_u *ptr = NULL; int remaining = 0; - int fcs_trunc = curwin->w_fill_chars.trunc; + int fcs_trunc; + +#ifdef FEAT_RIGHTLEFT + if (pum_rl) + fcs_trunc = curwin->w_fill_chars.truncrl; + else +#endif + fcs_trunc = curwin->w_fill_chars.trunc; hlf_T hlfsNorm[3]; hlf_T hlfsSel[3]; @@ -722,10 +727,19 @@ pum_redraw(void) if (rt != NULL) { - char_u *rt_start = rt; - int cells; + char_u *rt_start = rt; + int cells; + int over_cell = 0; + int truncated = FALSE; cells = mb_string2cells(rt , -1); + truncated = pum_width == p_pmw + && pum_width - totwidth < cells; + + if (pum_width == p_pmw && !truncated + && (j + 1 < 3 && pum_get_item(idx, order[j + 1]) != NULL)) + truncated = TRUE; + if (cells > pum_width) { do @@ -746,13 +760,9 @@ pum_redraw(void) } } - // truncated - if (pum_width == p_pmw - && totwidth + 1 + cells >= pum_width) + if (truncated) { char_u *orig_rt = rt; - char_u *old_rt = NULL; - int over_cell = 0; int size = 0; remaining = pum_width - totwidth - 1; @@ -768,26 +778,19 @@ pum_redraw(void) size = (int)STRLEN(orig_rt); if (cells < remaining) over_cell = remaining - cells; - new_str = alloc(size + over_cell + 1 + utf_char2len(fcs_trunc)); - if (!new_str) - return; - ptr = new_str; - if (fcs_trunc != NUL && fcs_trunc != '>') - ptr += (*mb_char2bytes)(fcs_trunc, ptr); + + cells = mb_string2cells(orig_rt, size); + width = cells + over_cell + 1; + rt = orig_rt; + + if (fcs_trunc != NUL) + screen_putchar(fcs_trunc, row, col - width + 1, attr); else - *ptr++ = '<'; - if (over_cell) - { - vim_memset(ptr, ' ', over_cell); - ptr += over_cell; - } - memcpy(ptr, orig_rt, size); - ptr[size] = NUL; - old_rt = rt_start; - rt = rt_start = new_str; - vim_free(old_rt); - cells = mb_string2cells(rt, -1); - width = cells; + screen_putchar('<', row, col - width + 1, attr); + + if (over_cell > 0) + screen_fill(row, row + 1, col - width + 2, + col - width + 2 + over_cell, ' ', ' ', attr); } if (attrs == NULL) @@ -809,10 +812,16 @@ pum_redraw(void) { if (st != NULL) { - int size = (int)STRLEN(st); - int cells = (*mb_string2cells)(st, size); - char_u *st_end = NULL; - int over_cell = 0; + int size = (int)STRLEN(st); + int cells = (*mb_string2cells)(st, size); + char_u *st_end = NULL; + int over_cell = 0; + int truncated = pum_width == p_pmw + && pum_width - totwidth < cells; + + if (pum_width == p_pmw && !truncated + && (j + 1 < 3 && pum_get_item(idx, order[j + 1]) != NULL)) + truncated = TRUE; // only draw the text that fits while (size > 0 @@ -829,8 +838,7 @@ pum_redraw(void) } // truncated - if (pum_width == p_pmw - && totwidth + 1 + cells >= pum_width) + if (truncated) { remaining = pum_width - totwidth - 1; if (cells > remaining) @@ -846,28 +854,8 @@ pum_redraw(void) if (cells < remaining) over_cell = remaining - cells; - new_str = alloc(size + over_cell + 1 + utf_char2len(fcs_trunc)); - if (!new_str) - return; - memcpy(new_str, st, size); - ptr = new_str + size; - if (over_cell > 0) - { - vim_memset(ptr, ' ', over_cell); - ptr += over_cell; - } - - if (fcs_trunc != NUL) - ptr += (*mb_char2bytes)(fcs_trunc, ptr); - else - *ptr++ = '>'; - - *ptr = NUL; - vim_free(st); - st = new_str; - cells = mb_string2cells(st, -1); - size = (int)STRLEN(st); - width = cells; + cells = mb_string2cells(st, size); + width = cells + over_cell + 1; } if (attrs == NULL) @@ -875,6 +863,18 @@ pum_redraw(void) else pum_screen_puts_with_attrs(row, col, cells, st, size, attrs); + if (truncated) + { + if (over_cell > 0) + screen_fill(row, row + 1, col + cells, + col + cells + over_cell, ' ', ' ', attr); + if (fcs_trunc != NUL) + screen_putchar(fcs_trunc, row, + col + cells + over_cell, attr); + else + screen_putchar('>', row, + col + cells + over_cell, attr); + } vim_free(st); } diff --git a/src/screen.c b/src/screen.c index 9a5927abe..ab37e1d61 100644 --- a/src/screen.c +++ b/src/screen.c @@ -4714,6 +4714,7 @@ static struct charstab filltab[] = CHARSTAB_ENTRY(&fill_chars.eob, "eob"), CHARSTAB_ENTRY(&fill_chars.lastline, "lastline"), CHARSTAB_ENTRY(&fill_chars.trunc, "trunc"), + CHARSTAB_ENTRY(&fill_chars.truncrl, "truncrl"), }; static lcs_chars_T lcs_chars; static struct charstab lcstab[] = @@ -4828,6 +4829,7 @@ set_chars_option(win_T *wp, char_u *value, int is_listchars, int apply, fill_chars.eob = '~'; fill_chars.lastline = '@'; fill_chars.trunc = '>'; + fill_chars.truncrl = '<'; } } p = value; diff --git a/src/structs.h b/src/structs.h index 9b44598ac..b5c898d16 100644 --- a/src/structs.h +++ b/src/structs.h @@ -3851,6 +3851,7 @@ typedef struct int eob; int lastline; int trunc; + int truncrl; } fill_chars_T; /* diff --git a/src/testdir/dumps/Test_pum_maxwidth_07.dump b/src/testdir/dumps/Test_pum_maxwidth_07.dump index ada8acb0d..112e1f588 100644 --- a/src/testdir/dumps/Test_pum_maxwidth_07.dump +++ b/src/testdir/dumps/Test_pum_maxwidth_07.dump @@ -1,7 +1,7 @@ |1+0&#ffffff0|2|3|4|5|6|7|8|9|_|1|2|3|4|5|6|7|8|9|_|1|2|3|4|5|6|7|8|9|_> @44 |1+0#0000001#e0e0e08|2|3|4|5|6|7|8|9|>| +0#4040ff13#ffffff0@64 |一*0#0000001#ffd7ff255|二|三|四| +&|>| +0#4040ff13#ffffff0@64 -|a+0#0000001#ffd7ff255|b|c|d|e|f|g|h|i|>| +0#4040ff13#ffffff0@64 +|a+0#0000001#ffd7ff255|b|c|d|e|f|g|h|i|j| +0#4040ff13#ffffff0@64 |上*0#0000001#ffd7ff255|下|左|右| +&@1| +0#4040ff13#ffffff0@64 |~| @73 |~| @73 diff --git a/src/testdir/dumps/Test_pum_maxwidth_08.dump b/src/testdir/dumps/Test_pum_maxwidth_08.dump index aa41b76d1..9f92ae706 100644 --- a/src/testdir/dumps/Test_pum_maxwidth_08.dump +++ b/src/testdir/dumps/Test_pum_maxwidth_08.dump @@ -1,7 +1,7 @@ | +0&#ffffff0@43> |_|9|8|7|6|5|4|3|2|1|_|9|8|7|6|5|4|3|2|1|_|9|8|7|6|5|4|3|2|1 | +0#4040ff13&@64|<+0#0000001#e0e0e08|9|8|7|6|5|4|3|2|1 | +0#4040ff13#ffffff0@64|<+0#0000001#ffd7ff255| |四*&|三|二|一 -| +0#4040ff13#ffffff0@64|<+0#0000001#ffd7ff255|i|h|g|f|e|d|c|b|a +| +0#4040ff13#ffffff0@64|j+0#0000001#ffd7ff255|i|h|g|f|e|d|c|b|a | +0#4040ff13#ffffff0@64| +0#0000001#ffd7ff255@1|右*&|左|下|上 | +0#4040ff13#ffffff0@73|~ | @73|~ diff --git a/src/testdir/test_popup.vim b/src/testdir/test_popup.vim index d282f91cf..b2952fdc3 100644 --- a/src/testdir/test_popup.vim +++ b/src/testdir/test_popup.vim @@ -2126,7 +2126,7 @@ func Test_pum_maxwidth_multibyte() call VerifyScreenDump(buf, 'Test_pum_maxwidth_16', {'rows': 8}) call term_sendkeys(buf, "\<ESC>") - call term_sendkeys(buf, ":set fcs+=trunc:…\<CR>") + call term_sendkeys(buf, ":set fcs+=truncrl:…\<CR>") call term_sendkeys(buf, "S\<C-X>\<C-O>") call VerifyScreenDump(buf, 'Test_pum_maxwidth_17', {'rows': 8}) call term_sendkeys(buf, "\<ESC>") diff --git a/src/version.c b/src/version.c index 53b794173..6f3f24178 100644 --- a/src/version.c +++ b/src/version.c @@ -704,6 +704,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1296, /**/ 1295, /**/ -- -- You received this message from the "vim_dev" maillist. Do not top-post! Type your reply below the text you are replying to. For more information, visit http://www.vim.org/maillist.php --- You received this message because you are subscribed to the Google Groups "vim_dev" group. To unsubscribe from this group and stop receiving emails from it, send an email to vim_dev+unsubscr...@googlegroups.com. To view this discussion visit https://groups.google.com/d/msgid/vim_dev/E1u3dyZ-00GOwy-AO%40256bit.org.