To: vim_dev@googlegroups.com Subject: Patch 8.1.1410 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 8.1.1410 Problem: Popup_move() is not implemented yet. Solution: Implement it. (Yasuhiro Matsumoto, closes #4441) Improve the positioning and resizing. Files: runtime/doc/popup.txt, src/evalfunc.c, src/popupwin.c, src/screen.c, src/structs.h, src/proto/popupwin.pro, src/testdir/test_popupwin.vim, src/testdir/dumps/Test_popupwin_05.dump *** ../vim-8.1.1409/runtime/doc/popup.txt 2019-05-26 23:32:03.179678024 +0200 --- runtime/doc/popup.txt 2019-05-27 20:15:57.224591812 +0200 *************** *** 84,90 **** IMPLEMENTATION: - Code is in popupwin.c ! - Implement list of lines with text properties - Implement filter. - Handle screen resize in screenalloc(). - Make redrawing more efficient and avoid flicker. --- 84,90 ---- IMPLEMENTATION: - Code is in popupwin.c ! - implement popup_getposition({id}), use in tests - Implement filter. - Handle screen resize in screenalloc(). - Make redrawing more efficient and avoid flicker. *************** *** 190,196 **** For {id} see `popup_hide()`. popup_move({id}, {options}) *popup_move()* - {not implemented yet} Move popup {id} to the position speficied with {options}. {options} may contain the items from |popup_create()| that specify the popup position: "line", "col", "pos", "maxheight", --- 190,195 ---- *************** *** 310,319 **** {not implemented yet} maxheight maximum height minheight minimum height - {not implemented yet} maxwidth maximum width minwidth minimum width - {not implemented yet} hidden when TRUE the popup exists but is not displayed; use `popup_show()` to unhide it. {not implemented yet} --- 309,316 ---- *** ../vim-8.1.1409/src/evalfunc.c 2019-05-26 22:17:31.736315033 +0200 --- src/evalfunc.c 2019-05-27 20:06:05.751964764 +0200 *************** *** 811,816 **** --- 811,817 ---- {"popup_close", 1, 1, f_popup_close}, {"popup_create", 2, 2, f_popup_create}, {"popup_hide", 1, 1, f_popup_hide}, + {"popup_move", 2, 2, f_popup_move}, {"popup_show", 1, 1, f_popup_show}, #endif #ifdef FEAT_FLOAT *** ../vim-8.1.1409/src/popupwin.c 2019-05-27 10:04:37.530426996 +0200 --- src/popupwin.c 2019-05-27 20:44:15.611540280 +0200 *************** *** 25,34 **** int nr; char_u *str; wp->w_maxwidth = dict_get_number(dict, (char_u *)"maxwidth"); wp->w_maxheight = dict_get_number(dict, (char_u *)"maxheight"); ! wp->w_winrow = dict_get_number(dict, (char_u *)"line"); ! wp->w_wincol = dict_get_number(dict, (char_u *)"col"); wp->w_zindex = dict_get_number(dict, (char_u *)"zindex"); #if defined(FEAT_TIMERS) --- 25,38 ---- int nr; char_u *str; + wp->w_minwidth = dict_get_number(dict, (char_u *)"minwidth"); + wp->w_minheight = dict_get_number(dict, (char_u *)"minheight"); wp->w_maxwidth = dict_get_number(dict, (char_u *)"maxwidth"); wp->w_maxheight = dict_get_number(dict, (char_u *)"maxheight"); ! ! wp->w_wantline = dict_get_number(dict, (char_u *)"line"); ! wp->w_wantcol = dict_get_number(dict, (char_u *)"col"); ! wp->w_zindex = dict_get_number(dict, (char_u *)"zindex"); #if defined(FEAT_TIMERS) *************** *** 145,150 **** --- 149,197 ---- } /* + * Adjust the position and size of the popup to fit on the screen. + */ + static void + popup_adjust_position(win_T *wp) + { + // TODO: Compute the size and position properly. + if (wp->w_wantline > 0) + wp->w_winrow = wp->w_wantline - 1; + else + // TODO: better default + wp->w_winrow = Rows > 5 ? Rows / 2 - 2 : 0; + if (wp->w_winrow >= Rows) + wp->w_winrow = Rows - 1; + + if (wp->w_wantcol > 0) + wp->w_wincol = wp->w_wantcol - 1; + else + // TODO: better default + wp->w_wincol = Columns > 20 ? Columns / 2 - 10 : 0; + if (wp->w_wincol >= Columns - 3) + wp->w_wincol = Columns - 3; + + // TODO: set width based on longest text line and the 'wrap' option + wp->w_width = vim_strsize(ml_get_buf(wp->w_buffer, 1, FALSE)); + if (wp->w_minwidth > 0 && wp->w_width < wp->w_minwidth) + wp->w_width = wp->w_minwidth; + if (wp->w_maxwidth > 0 && wp->w_width > wp->w_maxwidth) + wp->w_width = wp->w_maxwidth; + if (wp->w_width > Columns - wp->w_wincol) + wp->w_width = Columns - wp->w_wincol; + + if (wp->w_height <= 1) + // TODO: adjust height for wrapped lines + wp->w_height = wp->w_buffer->b_ml.ml_line_count; + if (wp->w_minheight > 0 && wp->w_height < wp->w_minheight) + wp->w_height = wp->w_minheight; + if (wp->w_maxheight > 0 && wp->w_height > wp->w_maxheight) + wp->w_height = wp->w_maxheight; + if (wp->w_height > Rows - wp->w_winrow) + wp->w_height = Rows - wp->w_winrow; + } + + /* * popup_create({text}, {options}) */ void *************** *** 241,272 **** if (wp->w_zindex == 0) wp->w_zindex = 50; ! // TODO: Compute the size and position properly. ! ! // Default position is in middle of the screen, assuming a small popup ! if (wp->w_winrow == 0) ! wp->w_winrow = Rows > 5 ? Rows / 2 - 2 : 0; ! else ! --wp->w_winrow; // option value is one-based ! if (wp->w_wincol == 0) ! wp->w_wincol = Columns > 20 ? Columns / 2 - 10 : 0; ! else ! --wp->w_wincol; // option value is one-based ! ! ! // TODO: set width based on longest text line and the 'wrap' option ! wp->w_width = wp->w_maxwidth == 0 ? 20 : wp->w_maxwidth; ! if (wp->w_maxwidth > 0 && wp->w_width > wp->w_maxwidth) ! wp->w_width = wp->w_maxwidth; ! if (wp->w_width > Columns - wp->w_wincol) ! wp->w_width = Columns - wp->w_wincol; ! ! // TODO: adjust height for wrapped lines ! wp->w_height = buf->b_ml.ml_line_count; ! if (wp->w_maxheight > 0 && wp->w_height > wp->w_maxheight) ! wp->w_height = wp->w_maxheight; ! if (wp->w_height > Rows - wp->w_winrow) ! wp->w_height = Rows - wp->w_winrow; wp->w_vsep_width = 0; --- 288,294 ---- if (wp->w_zindex == 0) wp->w_zindex = 50; ! popup_adjust_position(wp); wp->w_vsep_width = 0; *************** *** 424,427 **** --- 446,490 ---- close_all_popups(); } + /* + * popup_move({id}, {options}) + */ + void + f_popup_move(typval_T *argvars, typval_T *rettv UNUSED) + { + dict_T *d; + int nr; + int id = (int)tv_get_number(argvars); + win_T *wp = find_popup_win(id); + + if (wp == NULL) + return; // invalid {id} + + if (argvars[1].v_type != VAR_DICT || argvars[1].vval.v_dict == NULL) + { + emsg(_(e_dictreq)); + return; + } + d = argvars[1].vval.v_dict; + + if ((nr = dict_get_number(d, (char_u *)"minwidth")) > 0) + wp->w_minwidth = nr; + if ((nr = dict_get_number(d, (char_u *)"minheight")) > 0) + wp->w_minheight = nr; + if ((nr = dict_get_number(d, (char_u *)"maxwidth")) > 0) + wp->w_maxwidth = nr; + if ((nr = dict_get_number(d, (char_u *)"maxheight")) > 0) + wp->w_maxheight = nr; + if ((nr = dict_get_number(d, (char_u *)"line")) > 0) + wp->w_wantline = nr; + if ((nr = dict_get_number(d, (char_u *)"col")) > 0) + wp->w_wantcol = nr; + // TODO: "pos" + + if (wp->w_winrow + wp->w_height >= cmdline_row) + clear_cmdline = TRUE; + popup_adjust_position(wp); + redraw_all_later(NOT_VALID); + } + #endif // FEAT_TEXT_PROP *** ../vim-8.1.1409/src/screen.c 2019-05-27 10:04:37.530426996 +0200 --- src/screen.c 2019-05-27 21:48:09.115958231 +0200 *************** *** 1034,1039 **** --- 1034,1057 ---- } #endif + /* + * Get 'wincolor' attribute for window "wp". If not set and "wp" is a popup + * window then get the "Pmenu" highlight attribute. + */ + static int + get_wcr_attr(win_T *wp) + { + int wcr_attr = 0; + + if (*wp->w_p_wcr != NUL) + wcr_attr = syn_name2attr(wp->w_p_wcr); + #ifdef FEAT_TEXT_PROP + if (bt_popup(wp->w_buffer) && wcr_attr == 0) + wcr_attr = HL_ATTR(HLF_PNI); + #endif + return wcr_attr; + } + #if defined(FEAT_GUI) || defined(PROTO) /* * Update a single window, its status line and maybe the command line msg. *************** *** 2419,2431 **** { int n = 0; int attr = HL_ATTR(hl); ! int wcr_attr = 0; ! if (*wp->w_p_wcr != NUL) ! { ! wcr_attr = syn_name2attr(wp->w_p_wcr); ! attr = hl_combine_attr(wcr_attr, attr); ! } if (draw_margin) { --- 2437,2445 ---- { int n = 0; int attr = HL_ATTR(hl); ! int wcr_attr = get_wcr_attr(wp); ! attr = hl_combine_attr(wcr_attr, attr); if (draw_margin) { *************** *** 3115,3120 **** --- 3129,3136 ---- int vi_attr = 0; // attributes for Visual and incsearch // highlighting int wcr_attr = 0; // attributes from 'wincolor' + int win_attr = 0; // background for whole window, except + // margins and "~" lines. int area_attr = 0; // attributes desired by highlighting int search_attr = 0; // attributes desired by 'hlsearch' #ifdef FEAT_SYN_HL *************** *** 3196,3202 **** #ifdef FEAT_TERMINAL int get_term_attr = FALSE; #endif - int win_attr = 0; // background for whole window /* draw_state: items that are drawn in sequence: */ #define WL_START 0 /* nothing done yet */ --- 3212,3217 ---- *************** *** 3566,3593 **** } } ! if (*wp->w_p_wcr != NUL) { ! wcr_attr = syn_name2attr(wp->w_p_wcr); ! ! // 'wincolor' highlighting for the whole window ! if (wcr_attr != 0) ! { ! win_attr = wcr_attr; ! area_highlighting = TRUE; ! } } #ifdef FEAT_TEXT_PROP if (bt_popup(wp->w_buffer)) - { screen_line_flags |= SLF_POPUP; - - if (win_attr == 0) - { - win_attr = HL_ATTR(HLF_PNI); - area_highlighting = TRUE; - } - } #endif /* --- 3581,3595 ---- } } ! wcr_attr = get_wcr_attr(wp); ! if (wcr_attr != 0) { ! win_attr = wcr_attr; ! area_highlighting = TRUE; } #ifdef FEAT_TEXT_PROP if (bt_popup(wp->w_buffer)) screen_line_flags |= SLF_POPUP; #endif /* *** ../vim-8.1.1409/src/structs.h 2019-05-26 22:17:31.736315033 +0200 --- src/structs.h 2019-05-27 20:30:23.054166540 +0200 *************** *** 2873,2880 **** --- 2873,2884 ---- #ifdef FEAT_TEXT_PROP int w_popup_flags; // PFL_ values int w_zindex; + int w_minheight; // "minheight" for popup window + int w_minwidth; // "minwidth" for popup window int w_maxheight; // "maxheight" for popup window int w_maxwidth; // "maxwidth" for popup window + int w_wantline; // "line" for popup window + int w_wantcol; // "col" for popup window # if defined(FEAT_TIMERS) timer_T *w_popup_timer; // timer for closing popup window # endif *** ../vim-8.1.1409/src/proto/popupwin.pro 2019-05-26 22:17:31.736315033 +0200 --- src/proto/popupwin.pro 2019-05-27 20:24:05.974256691 +0200 *************** *** 8,11 **** --- 8,12 ---- void popup_close_tabpage(tabpage_T *tp, int id); void close_all_popups(void); void ex_popupclear(exarg_T *eap); + void f_popup_move(typval_T *argvars, typval_T *rettv); /* vim: set ft=c : */ *** ../vim-8.1.1409/src/testdir/test_popupwin.vim 2019-05-26 23:32:03.175678045 +0200 --- src/testdir/test_popupwin.vim 2019-05-27 21:50:29.651252234 +0200 *************** *** 16,23 **** \ "hi PopupColor2 ctermbg=lightcyan", \ "hi Comment ctermfg=red", \ "call prop_type_add('comment', {'highlight': 'Comment'})", ! \ "let winid = popup_create('hello there', {'line': 3, 'col': 11, 'highlight': 'PopupColor1'})", ! \ "let winid2 = popup_create(['another one', 'another two', 'another three'], {'line': 3, 'col': 25})", \ "call setwinvar(winid2, '&wincolor', 'PopupColor2')", \], 'XtestPopup') let buf = RunVimInTerminal('-S XtestPopup', {'rows': 10}) --- 16,23 ---- \ "hi PopupColor2 ctermbg=lightcyan", \ "hi Comment ctermfg=red", \ "call prop_type_add('comment', {'highlight': 'Comment'})", ! \ "let winid = popup_create('hello there', {'line': 3, 'col': 11, 'minwidth': 20, 'highlight': 'PopupColor1'})", ! \ "let winid2 = popup_create(['another one', 'another two', 'another three'], {'line': 3, 'col': 25, 'minwidth': 20})", \ "call setwinvar(winid2, '&wincolor', 'PopupColor2')", \], 'XtestPopup') let buf = RunVimInTerminal('-S XtestPopup', {'rows': 10}) *************** *** 25,36 **** " Add a tabpage call term_sendkeys(buf, ":tabnew\") ! call term_sendkeys(buf, ":call popup_create([" \ .. "{'text': 'other tab'}," \ .. "{'text': 'a comment line', 'props': [{" ! \ .. "'col': 3, 'length': 7, 'type': 'comment'" \ .. "}]}," ! \ .. "], {'line': 4, 'col': 9})\") call VerifyScreenDump(buf, 'Test_popupwin_02', {}) " switch back to first tabpage --- 25,36 ---- " Add a tabpage call term_sendkeys(buf, ":tabnew\") ! call term_sendkeys(buf, ":let popupwin = popup_create([" \ .. "{'text': 'other tab'}," \ .. "{'text': 'a comment line', 'props': [{" ! \ .. "'col': 3, 'length': 7, 'minwidth': 20, 'type': 'comment'" \ .. "}]}," ! \ .. "], {'line': 4, 'col': 9, 'minwidth': 20})\") call VerifyScreenDump(buf, 'Test_popupwin_02', {}) " switch back to first tabpage *************** *** 41,46 **** --- 41,51 ---- call term_sendkeys(buf, ":quit!\") call VerifyScreenDump(buf, 'Test_popupwin_04', {}) + " resize popup + call term_sendkeys(buf, ":call popup_move(popupwin, {'minwidth': 15, 'maxwidth': 25, 'minheight': 3, 'maxheight': 5})\") + call term_sendkeys(buf, ":redraw\") + call VerifyScreenDump(buf, 'Test_popupwin_05', {}) + " clean up call StopVimInTerminal(buf) call delete('XtestPopup') *************** *** 56,61 **** --- 61,67 ---- call popup_create('world', { \ 'line': 1, \ 'col': 1, + \ 'minwidth': 20, \ 'time': 500, \}) redraw *************** *** 70,75 **** --- 76,82 ---- call popup_create('on the command line', { \ 'line': &lines, \ 'col': 10, + \ 'minwidth': 20, \ 'time': 500, \}) redraw *************** *** 91,96 **** --- 98,104 ---- let winid = popup_create('world', { \ 'line': 1, \ 'col': 1, + \ 'minwidth': 20, \}) redraw let line = join(map(range(1, 5), 'screenstring(1, v:val)'), '') *************** *** 121,123 **** --- 129,161 ---- bwipe! endfunc + + func Test_popup_move() + topleft vnew + call setline(1, 'hello') + + let winid = popup_create('world', { + \ 'line': 1, + \ 'col': 1, + \ 'minwidth': 20, + \}) + redraw + let line = join(map(range(1, 6), 'screenstring(1, v:val)'), '') + call assert_equal('world ', line) + + call popup_move(winid, {'line': 2, 'col': 2}) + redraw + let line = join(map(range(1, 6), 'screenstring(1, v:val)'), '') + call assert_equal('hello ', line) + let line = join(map(range(1, 6), 'screenstring(2, v:val)'), '') + call assert_equal('~world', line) + + call popup_move(winid, {'line': 1}) + redraw + let line = join(map(range(1, 6), 'screenstring(1, v:val)'), '') + call assert_equal('hworld', line) + + call popup_close(winid) + + bwipe! + endfunc *** ../vim-8.1.1409/src/testdir/dumps/Test_popupwin_05.dump 2019-05-27 21:51:37.350912887 +0200 --- src/testdir/dumps/Test_popupwin_05.dump 2019-05-27 21:48:42.687789379 +0200 *************** *** 0 **** --- 1,10 ---- + > +0&#ffffff0@74 + |~+0#4040ff13&| @73 + |~| @73 + |~| @6|o+0#0000001#ffd7ff255|t|h|e|r| |t|a|b| @5| +0#4040ff13#ffffff0@51 + |~| @6|a+0#0000001#ffd7ff255| |c+0#ff404010&|o|m@1|e|n|t| +0#0000001&|l|i|n|e| | +0#4040ff13#ffffff0@51 + |~| @6|~+0&#ffd7ff255| @13| +0&#ffffff0@51 + |~| @73 + |~| @73 + |~| @73 + |:+0#0000000&|r|e|d|r|a|w| @49|0|,|0|-|1| @8|A|l@1| *** ../vim-8.1.1409/src/version.c 2019-05-27 20:01:38.121491973 +0200 --- src/version.c 2019-05-27 21:51:48.102859037 +0200 *************** *** 769,770 **** --- 769,772 ---- { /* Add new patch number below this line */ + /**/ + 1410, /**/ -- The users that I support would double-click on a landmine to find out what happens. -- A system administrator /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\ /// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\ \\\ an exciting new programming language -- http://www.Zimbu.org /// \\\ help me help AIDS victims -- http://ICCF-Holland.org ///