From: glepnir Date: Tue, 24 Dec 2024 08:44:35 +0000 (+0100) Subject: patch 9.1.0956: completion may crash, completion highlight wrong with preview window X-Git-Tag: v9.1.0956^0 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=8d0bb6dc9f2e5d94ebb59671d592c1b7fa325ca6;p=thirdparty%2Fvim.git patch 9.1.0956: completion may crash, completion highlight wrong with preview window Problem: completion may crash, completion highlight wrong with preview window (after v9.1.0954) Solution: correctly calculate scroll offset, check for preview window when adding extra highlighting (glepnir) when there have a preview window prepare_tagpreview will change curwin to preview window and this may cause ComplMatchIns check condition not correct. check wp is curwin and also the type of wp is not a preview or poup info fixes: #16284 closes: #16283 Signed-off-by: glepnir Signed-off-by: Christian Brabandt --- diff --git a/src/drawline.c b/src/drawline.c index bc8e4d2ad7..f3838572c3 100644 --- a/src/drawline.c +++ b/src/drawline.c @@ -1869,7 +1869,7 @@ win_line( } #endif - if ((State & MODE_INSERT) && in_curline && ins_compl_active()) + if ((State & MODE_INSERT) && in_curline && ins_compl_win_active(wp)) area_highlighting = TRUE; #ifdef FEAT_SYN_HL @@ -2415,7 +2415,8 @@ win_line( #endif // Check if ComplMatchIns highlight is needed. - if ((State & MODE_INSERT) && in_curline && ins_compl_active()) + if ((State & MODE_INSERT) && in_curline + && ins_compl_win_active(wp)) { int ins_match_attr = ins_compl_col_range_attr((int)(ptr - line)); diff --git a/src/insexpand.c b/src/insexpand.c index 2d1490428b..522b7f73ea 100644 --- a/src/insexpand.c +++ b/src/insexpand.c @@ -1864,6 +1864,23 @@ ins_compl_active(void) return compl_started; } +/* + * Return True when wp is the actual completion window + */ + int +ins_compl_win_active(win_T *wp UNUSED) +{ + return ins_compl_active() +#if defined(FEAT_QUICKFIX) + && (!wp->w_p_pvw +# ifdef FEAT_PROP_POPUP + && !(wp->w_popup_flags & POPF_INFO) +# endif + ) +#endif + ; +} + /* * Selected one of the matches. When FALSE the match was edited or using the * longest common string. diff --git a/src/popupmenu.c b/src/popupmenu.c index 6298b5cb62..ea2edca9ab 100644 --- a/src/popupmenu.c +++ b/src/popupmenu.c @@ -917,7 +917,7 @@ pum_set_selected(int n, int repeat UNUSED) { int resized = FALSE; int context = pum_height / 2; - int scroll_offset = pum_selected - pum_height; + int scroll_offset; #ifdef FEAT_QUICKFIX int prev_selected = pum_selected; unsigned cur_cot_flags = get_cot_flags(); @@ -927,6 +927,7 @@ pum_set_selected(int n, int repeat UNUSED) #endif pum_selected = n; + scroll_offset = pum_selected - pum_height; if (pum_selected >= 0 && pum_selected < pum_size) { @@ -950,7 +951,7 @@ pum_set_selected(int n, int repeat UNUSED) // scroll up; when we did a jump it's probably a PageDown then // scroll a whole page if (pum_first < scroll_offset + 3) - pum_first = MAX(pum_first, scroll_offset + 1); + pum_first = MAX(pum_first + pum_height - 2, scroll_offset + 1); else pum_first = scroll_offset + 1; } diff --git a/src/proto/insexpand.pro b/src/proto/insexpand.pro index 2e769b89f8..24c325fe6e 100644 --- a/src/proto/insexpand.pro +++ b/src/proto/insexpand.pro @@ -36,6 +36,7 @@ char_u *find_word_start(char_u *ptr); char_u *find_word_end(char_u *ptr); void ins_compl_clear(void); int ins_compl_active(void); +int ins_compl_win_active(win_T *wp); int ins_compl_used_match(void); void ins_compl_init_get_longest(void); int ins_compl_interrupted(void); diff --git a/src/testdir/dumps/Test_pum_matchins_11.dump b/src/testdir/dumps/Test_pum_matchins_11.dump new file mode 100644 index 0000000000..a44a6ee566 --- /dev/null +++ b/src/testdir/dumps/Test_pum_matchins_11.dump @@ -0,0 +1,20 @@ +|i+0&#ffffff0|n|f|o| @70 +|~+0#4040ff13&| @73 +|~| @73 +|[+1#0000000&|S|c|r|a|t|c|h|]| |[|P|r|e|v|i|e|w|]| @37|1|,|1| @11|A|l@1 +|f+0&&|o@1> @71 +|f+0#0000001#e0e0e08|o@1| @11| +0#4040ff13#ffffff0@59 +|b+0#0000001#ffd7ff255|a|r| @11| +0#4040ff13#ffffff0@59 +|你*0#0000001#ffd7ff255|好| +&@10| +0#4040ff13#ffffff0@59 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|[+3#0000000&|N|o| |N|a|m|e|]| |[|+|]| @43|1|,|1| @11|A|l@1 +|-+2&&@1| |O|m|n|i| |c|o|m|p|l|e|t|i|o|n| |(|^|O|^|N|^|P|)| |m+0#00e0003&|a|t|c|h| |1| |o|f| |3| +0#0000000&@34 diff --git a/src/testdir/test_popup.vim b/src/testdir/test_popup.vim index 8f053fab89..729fbecffa 100644 --- a/src/testdir/test_popup.vim +++ b/src/testdir/test_popup.vim @@ -1715,11 +1715,15 @@ endfunc func Test_pum_matchins_highlight() CheckScreendump let lines =<< trim END + let g:change = 0 func Omni_test(findstart, base) if a:findstart return col(".") endif - return [#{word: "foo"}, #{word: "bar"}, #{word: "你好"}] + if g:change == 0 + return [#{word: "foo"}, #{word: "bar"}, #{word: "你好"}] + endif + return [#{word: "foo", info: "info"}, #{word: "bar"}, #{word: "你好"}] endfunc set omnifunc=Omni_test hi ComplMatchIns ctermfg=red @@ -1766,6 +1770,10 @@ func Test_pum_matchins_highlight() call VerifyScreenDump(buf, 'Test_pum_matchins_10', {}) call term_sendkeys(buf, "\") + call term_sendkeys(buf, ":let g:change=1\S\\") + call VerifyScreenDump(buf, 'Test_pum_matchins_11', {}) + call term_sendkeys(buf, "\") + call StopVimInTerminal(buf) endfunc @@ -1811,4 +1819,15 @@ func Test_pum_matchins_highlight_combine() call StopVimInTerminal(buf) endfunc +" this used to crash +func Test_popup_completion_many_ctrlp() + new + let candidates=repeat(['a0'], 99) + call setline(1, candidates) + exe ":norm! VGg\" + norm! G + call feedkeys("o" .. repeat("\", 100), 'tx') + bw! +endfunc + " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/version.c b/src/version.c index d668ad77a1..700603962b 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 */ +/**/ + 956, /**/ 955, /**/