# HG changeset patch # User Christian Brabandt # Date 1506717903 -7200 # Node ID 33a900199c25faa46b2d3e380fd4c6c03b1409b2 # Parent 657abf4f50baa0c879e04a791813b590cec015c3 patch 8.0.1161: popup menu drawing problem when resizing terminal commit https://github.com/vim/vim/commit/a5e6621aadadf78c7b344e93a4b328788076f14c Author: Bram Moolenaar Date: Fri Sep 29 22:42:33 2017 +0200 patch 8.0.1161: popup menu drawing problem when resizing terminal Problem: Popup menu drawing problem when resizing terminal. Solution: Redraw after resizing also when a popup menu is visible. (Ozaki Kiichi, closes #2110) diff --git a/src/popupmnu.c b/src/popupmnu.c --- a/src/popupmnu.c +++ b/src/popupmnu.c @@ -64,206 +64,207 @@ pum_display( win_T *pvwin; #endif -redo: - def_width = PUM_DEF_WIDTH; - max_width = 0; - kind_width = 0; - extra_width = 0; - above_row = 0; - below_row = cmdline_row; + do + { + def_width = PUM_DEF_WIDTH; + max_width = 0; + kind_width = 0; + extra_width = 0; + above_row = 0; + below_row = cmdline_row; - /* Pretend the pum is already there to avoid that must_redraw is set when - * 'cuc' is on. */ - pum_array = (pumitem_T *)1; - validate_cursor_col(); - pum_array = NULL; + /* Pretend the pum is already there to avoid that must_redraw is set + * when 'cuc' is on. */ + pum_array = (pumitem_T *)1; + validate_cursor_col(); + pum_array = NULL; - row = curwin->w_wrow + W_WINROW(curwin); + row = curwin->w_wrow + W_WINROW(curwin); #if defined(FEAT_QUICKFIX) - FOR_ALL_WINDOWS(pvwin) - if (pvwin->w_p_pvw) - break; - if (pvwin != NULL) - { - if (W_WINROW(pvwin) < W_WINROW(curwin)) - above_row = W_WINROW(pvwin) + pvwin->w_height; - else if (W_WINROW(pvwin) > W_WINROW(curwin) + curwin->w_height) - below_row = W_WINROW(pvwin); - } + FOR_ALL_WINDOWS(pvwin) + if (pvwin->w_p_pvw) + break; + if (pvwin != NULL) + { + if (W_WINROW(pvwin) < W_WINROW(curwin)) + above_row = W_WINROW(pvwin) + pvwin->w_height; + else if (W_WINROW(pvwin) > W_WINROW(curwin) + curwin->w_height) + below_row = W_WINROW(pvwin); + } #endif - /* - * Figure out the size and position of the pum. - */ - if (size < PUM_DEF_HEIGHT) - pum_height = size; - else - pum_height = PUM_DEF_HEIGHT; - if (p_ph > 0 && pum_height > p_ph) - pum_height = p_ph; + /* + * Figure out the size and position of the pum. + */ + if (size < PUM_DEF_HEIGHT) + pum_height = size; + else + pum_height = PUM_DEF_HEIGHT; + if (p_ph > 0 && pum_height > p_ph) + pum_height = p_ph; + + /* Put the pum below "row" if possible. If there are few lines decide + * on where there is more room. */ + if (row + 2 >= below_row - pum_height + && row - above_row > (below_row - above_row) / 2) + { + /* pum above "row" */ - /* Put the pum below "row" if possible. If there are few lines decide on - * where there is more room. */ - if (row + 2 >= below_row - pum_height - && row - above_row > (below_row - above_row) / 2) - { - /* pum above "row" */ + /* Leave two lines of context if possible */ + if (curwin->w_wrow - curwin->w_cline_row >= 2) + context_lines = 2; + else + context_lines = curwin->w_wrow - curwin->w_cline_row; - /* Leave two lines of context if possible */ - if (curwin->w_wrow - curwin->w_cline_row >= 2) - context_lines = 2; - else - context_lines = curwin->w_wrow - curwin->w_cline_row; - - if (row >= size + context_lines) - { - pum_row = row - size - context_lines; - pum_height = size; + if (row >= size + context_lines) + { + pum_row = row - size - context_lines; + pum_height = size; + } + else + { + pum_row = 0; + pum_height = row - context_lines; + } + if (p_ph > 0 && pum_height > p_ph) + { + pum_row += pum_height - p_ph; + pum_height = p_ph; + } } else { - pum_row = 0; - pum_height = row - context_lines; - } - if (p_ph > 0 && pum_height > p_ph) - { - pum_row += pum_height - p_ph; - pum_height = p_ph; - } - } - else - { - /* pum below "row" */ + /* pum below "row" */ + + /* Leave two lines of context if possible */ + if (curwin->w_cline_row + + curwin->w_cline_height - curwin->w_wrow >= 3) + context_lines = 3; + else + context_lines = curwin->w_cline_row + + curwin->w_cline_height - curwin->w_wrow; - /* Leave two lines of context if possible */ - if (curwin->w_cline_row + curwin->w_cline_height - curwin->w_wrow >= 3) - context_lines = 3; - else - context_lines = curwin->w_cline_row - + curwin->w_cline_height - curwin->w_wrow; + pum_row = row + context_lines; + if (size > below_row - pum_row) + pum_height = below_row - pum_row; + else + pum_height = size; + if (p_ph > 0 && pum_height > p_ph) + pum_height = p_ph; + } - pum_row = row + context_lines; - if (size > below_row - pum_row) - pum_height = below_row - pum_row; - else - pum_height = size; - if (p_ph > 0 && pum_height > p_ph) - pum_height = p_ph; - } - - /* don't display when we only have room for one line */ - if (pum_height < 1 || (pum_height == 1 && size > 1)) - return; + /* don't display when we only have room for one line */ + if (pum_height < 1 || (pum_height == 1 && size > 1)) + return; #if defined(FEAT_QUICKFIX) - /* If there is a preview window at the above avoid drawing over it. */ - if (pvwin != NULL && pum_row < above_row && pum_height > above_row) - { - pum_row += above_row; - pum_height -= above_row; - } + /* If there is a preview window at the above avoid drawing over it. */ + if (pvwin != NULL && pum_row < above_row && pum_height > above_row) + { + pum_row += above_row; + pum_height -= above_row; + } #endif - /* Compute the width of the widest match and the widest extra. */ - for (i = 0; i < size; ++i) - { - w = vim_strsize(array[i].pum_text); - if (max_width < w) - max_width = w; - if (array[i].pum_kind != NULL) + /* Compute the width of the widest match and the widest extra. */ + for (i = 0; i < size; ++i) { - w = vim_strsize(array[i].pum_kind) + 1; - if (kind_width < w) - kind_width = w; + w = vim_strsize(array[i].pum_text); + if (max_width < w) + max_width = w; + if (array[i].pum_kind != NULL) + { + w = vim_strsize(array[i].pum_kind) + 1; + if (kind_width < w) + kind_width = w; + } + if (array[i].pum_extra != NULL) + { + w = vim_strsize(array[i].pum_extra) + 1; + if (extra_width < w) + extra_width = w; + } } - if (array[i].pum_extra != NULL) - { - w = vim_strsize(array[i].pum_extra) + 1; - if (extra_width < w) - extra_width = w; - } - } - pum_base_width = max_width; - pum_kind_width = kind_width; + pum_base_width = max_width; + pum_kind_width = kind_width; - /* Calculate column */ + /* Calculate column */ #ifdef FEAT_RIGHTLEFT - if (curwin->w_p_rl) - col = curwin->w_wincol + curwin->w_width - curwin->w_wcol - 1; - else + if (curwin->w_p_rl) + col = curwin->w_wincol + curwin->w_width - curwin->w_wcol - 1; + else #endif - col = curwin->w_wincol + curwin->w_wcol; + col = curwin->w_wincol + curwin->w_wcol; - /* if there are more items than room we need a scrollbar */ - if (pum_height < size) - { - pum_scrollbar = 1; - ++max_width; - } - else - pum_scrollbar = 0; + /* if there are more items than room we need a scrollbar */ + if (pum_height < size) + { + pum_scrollbar = 1; + ++max_width; + } + else + pum_scrollbar = 0; - if (def_width < max_width) - def_width = max_width; + if (def_width < max_width) + def_width = max_width; - if (((col < Columns - PUM_DEF_WIDTH || col < Columns - max_width) + if (((col < Columns - PUM_DEF_WIDTH || col < Columns - max_width) #ifdef FEAT_RIGHTLEFT - && !curwin->w_p_rl) - || (curwin->w_p_rl && (col > PUM_DEF_WIDTH || col > max_width) + && !curwin->w_p_rl) + || (curwin->w_p_rl && (col > PUM_DEF_WIDTH || col > max_width) #endif - )) - { - /* align pum column with "col" */ - pum_col = col; + )) + { + /* align pum column with "col" */ + pum_col = col; #ifdef FEAT_RIGHTLEFT - if (curwin->w_p_rl) - pum_width = pum_col - pum_scrollbar + 1; - else + if (curwin->w_p_rl) + pum_width = pum_col - pum_scrollbar + 1; + else #endif - pum_width = Columns - pum_col - pum_scrollbar; + pum_width = Columns - pum_col - pum_scrollbar; - if (pum_width > max_width + kind_width + extra_width + 1 - && pum_width > PUM_DEF_WIDTH) + if (pum_width > max_width + kind_width + extra_width + 1 + && pum_width > PUM_DEF_WIDTH) + { + pum_width = max_width + kind_width + extra_width + 1; + if (pum_width < PUM_DEF_WIDTH) + pum_width = PUM_DEF_WIDTH; + } + } + else if (Columns < def_width) { - pum_width = max_width + kind_width + extra_width + 1; - if (pum_width < PUM_DEF_WIDTH) - pum_width = PUM_DEF_WIDTH; - } - } - else if (Columns < def_width) - { - /* not enough room, will use what we have */ + /* not enough room, will use what we have */ #ifdef FEAT_RIGHTLEFT - if (curwin->w_p_rl) - pum_col = Columns - 1; - else + if (curwin->w_p_rl) + pum_col = Columns - 1; + else #endif - pum_col = 0; - pum_width = Columns - 1; - } - else - { - if (max_width > PUM_DEF_WIDTH) - max_width = PUM_DEF_WIDTH; /* truncate */ + pum_col = 0; + pum_width = Columns - 1; + } + else + { + if (max_width > PUM_DEF_WIDTH) + max_width = PUM_DEF_WIDTH; /* truncate */ #ifdef FEAT_RIGHTLEFT - if (curwin->w_p_rl) - pum_col = max_width - 1; - else + if (curwin->w_p_rl) + pum_col = max_width - 1; + else #endif - pum_col = Columns - max_width; - pum_width = max_width - pum_scrollbar; - } + pum_col = Columns - max_width; + pum_width = max_width - pum_scrollbar; + } - pum_array = array; - pum_size = size; + pum_array = array; + pum_size = size; - /* Set selected item and redraw. If the window size changed need to redo - * the positioning. Limit this to two times, when there is not much - * room the window size will keep changing. */ - if (pum_set_selected(selected, redo_count) && ++redo_count <= 2) - goto redo; + /* Set selected item and redraw. If the window size changed need to + * redo the positioning. Limit this to two times, when there is not + * much room the window size will keep changing. */ + } while (pum_set_selected(selected, redo_count) && ++redo_count <= 2); } /* diff --git a/src/term.c b/src/term.c --- a/src/term.c +++ b/src/term.c @@ -3271,11 +3271,10 @@ set_shellsize(int width, int height, int if (pum_visible()) { redraw_later(NOT_VALID); - ins_compl_show_pum(); /* This includes the redraw. */ + ins_compl_show_pum(); } - else #endif - update_screen(NOT_VALID); + update_screen(NOT_VALID); if (redrawing()) setcursor(); } diff --git a/src/testdir/shared.vim b/src/testdir/shared.vim --- a/src/testdir/shared.vim +++ b/src/testdir/shared.vim @@ -1,5 +1,10 @@ " Functions shared by several tests. +" Only load this script once. +if exists('*WaitFor') + finish +endif + " Get the name of the Python executable. " Also keeps it in s:python. func PythonProg() diff --git a/src/testdir/test_popup.vim b/src/testdir/test_popup.vim --- a/src/testdir/test_popup.vim +++ b/src/testdir/test_popup.vim @@ -1,5 +1,7 @@ " Test for completion menu +source shared.vim + let g:months = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'] let g:setting = '' @@ -36,6 +38,7 @@ endfu func! Test_popup_complete() new inoremap =ListMonths() + set belloff=all " - select original typed text before the completion started call feedkeys("aJu\\\\", 'tx') @@ -212,6 +215,7 @@ func! Test_popup_complete() call feedkeys("aM\\\", 'tx') call assert_equal(["March", "M", "March"], getline(1,4)) %d + set belloff& endfu @@ -513,6 +517,7 @@ endfunc func Test_completion_respect_bs_option() new + set belloff=all let li = ["aaa", "aaa12345", "aaaabcdef", "aaaABC"] set bs=indent,eol @@ -528,6 +533,7 @@ func Test_completion_respect_bs_option() call feedkeys("A\\\\\\\", "tx") call assert_equal('', getline(1)) + set belloff& bw! endfunc @@ -614,6 +620,7 @@ endfunc func Test_complete_CTRLN_startofbuffer() new + set belloff=all call setline(1, [ 'organize(cupboard, 3, 2);', \ 'prioritize(bureau, 8, 7);', \ 'realize(bannister, 4, 4);', @@ -624,6 +631,33 @@ func Test_complete_CTRLN_startofbuffer() \ 'railing.moralize(3,9);'] call feedkeys("qai\\.\3wdW\q3@a", 'tx') call assert_equal(expected, getline(1,'$')) + set belloff& + bwipe! +endfunc + +func Test_popup_and_window_resize() + if !has('terminal') || has('gui_running') + return + endif + let h = winheight(0) + if h < 15 + return + endif + let g:buf = term_start([$VIMPROG, '--clean', '-c', 'set noswapfile'], {'term_rows': h / 3}) + call term_sendkeys(g:buf, (h / 3 - 1)."o\G") + call term_sendkeys(g:buf, "i\") + call term_wait(g:buf, 100) + call term_sendkeys(g:buf, "\") + call term_wait(g:buf, 100) + call assert_match('^!\s*$', term_getline(g:buf, 1)) + exe 'resize +' . (h - 1) + call term_wait(g:buf, 100) + redraw! + call WaitFor('"" == term_getline(g:buf, 1)') + call assert_equal('', term_getline(g:buf, 1)) + sleep 100m + call WaitFor('"^!" =~ term_getline(g:buf, term_getcursor(g:buf)[0] + 1)') + call assert_match('^!\s*$', term_getline(g:buf, term_getcursor(g:buf)[0] + 1)) bwipe! endfunc diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -762,6 +762,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 1161, +/**/ 1160, /**/ 1159,