# HG changeset patch # User Bram Moolenaar # Date 1558902605 -7200 # Node ID 5ff14f96f1c9462cdd63b7f1e0b504b364d27eb6 # Parent c002c48995297860d8c31372b844ae8b24744e52 patch 8.1.1406: popup_hide() and popup_show() not implemented yet commit https://github.com/vim/vim/commit/2cd0dce898995a2b05f7285a70efec3f67f579f5 Author: Bram Moolenaar Date: Sun May 26 22:17:52 2019 +0200 patch 8.1.1406: popup_hide() and popup_show() not implemented yet Problem: popup_hide() and popup_show() not implemented yet. Solution: Implement the functions. diff --git a/runtime/doc/popup.txt b/runtime/doc/popup.txt --- a/runtime/doc/popup.txt +++ b/runtime/doc/popup.txt @@ -85,7 +85,6 @@ Probably 2. is the best choice. IMPLEMENTATION: - Code is in popupwin.c - Implement list of lines with text properties -- Implement popup_hide() and popup_show() - Implement filter. - Handle screen resize in screenalloc(). - Make redrawing more efficient and avoid flicker. @@ -179,15 +178,16 @@ popup_menu({text}, {options}) *popup "callback" to a function that handles the selected item. -popup_show({id}) *popup_show()* - {not implemented yet} - If {id} is a hidden popup, show it now. - popup_hide({id}) *popup_hide()* - {not implemented yet} If {id} is a displayed popup, hide it now. If the popup has a filter it will not be invoked for so long as the popup is hidden. + If window {id} does not exist nothing happens. If window {id} + exists but is not a popup window an error is given. *E993* + +popup_show({id}) *popup_show()* + If {id} is a hidden popup, show it now. + For {id} see `popup_hide()`. popup_move({id}, {options}) *popup_move()* {not implemented yet} @@ -195,6 +195,7 @@ popup_move({id}, {options}) *popup_m {options} may contain the items from |popup_create()| that specify the popup position: "line", "col", "pos", "maxheight", "minheight", "maxwidth" and "minwidth". + For {id} see `popup_hide()`. popup_filter_menu({id}, {key}) *popup_filter_menu()* diff --git a/src/evalfunc.c b/src/evalfunc.c --- a/src/evalfunc.c +++ b/src/evalfunc.c @@ -810,6 +810,8 @@ static struct fst #ifdef FEAT_TEXT_PROP {"popup_close", 1, 1, f_popup_close}, {"popup_create", 2, 2, f_popup_create}, + {"popup_hide", 1, 1, f_popup_hide}, + {"popup_show", 1, 1, f_popup_show}, #endif #ifdef FEAT_FLOAT {"pow", 2, 2, f_pow}, diff --git a/src/popupwin.c b/src/popupwin.c --- a/src/popupwin.c +++ b/src/popupwin.c @@ -195,18 +195,85 @@ f_popup_create(typval_T *argvars, typval } /* + * Find the popup window with window-ID "id". + * If the popup window does not exist NULL is returned. + * If the window is not a popup window, and error message is given. + */ + static win_T * +find_popup_win(int id) +{ + win_T *wp = win_id2wp(id); + + if (wp != NULL && !bt_popup(wp->w_buffer)) + { + semsg(_("E993: window %d is not a popup window"), id); + return NULL; + } + return wp; +} + +/* + * Return TRUE if there any popups that are not hidden. + */ + int +popup_any_visible(void) +{ + win_T *wp; + + for (wp = first_popupwin; wp != NULL; wp = wp->w_next) + if ((wp->w_popup_flags & PFL_HIDDEN) == 0) + return TRUE; + for (wp = curtab->tp_first_popupwin; wp != NULL; wp = wp->w_next) + if ((wp->w_popup_flags & PFL_HIDDEN) == 0) + return TRUE; + return FALSE; +} + +/* * popup_close({id}) */ void f_popup_close(typval_T *argvars, typval_T *rettv UNUSED) { - int nr = (int)tv_get_number(argvars); + int id = (int)tv_get_number(argvars); + + popup_close(id); +} + +/* + * popup_hide({id}) + */ + void +f_popup_hide(typval_T *argvars, typval_T *rettv UNUSED) +{ + int id = (int)tv_get_number(argvars); + win_T *wp = find_popup_win(id); - popup_close(nr); + if (wp != NULL && (wp->w_popup_flags & PFL_HIDDEN) == 0) + { + wp->w_popup_flags |= PFL_HIDDEN; + redraw_all_later(NOT_VALID); + } +} + +/* + * popup_show({id}) + */ + void +f_popup_show(typval_T *argvars, typval_T *rettv UNUSED) +{ + int id = (int)tv_get_number(argvars); + win_T *wp = find_popup_win(id); + + if (wp != NULL && (wp->w_popup_flags & PFL_HIDDEN) != 0) + { + wp->w_popup_flags &= ~PFL_HIDDEN; + redraw_all_later(NOT_VALID); + } } static void -popup_undisplay(win_T *wp) +popup_free(win_T *wp) { if (wp->w_winrow + wp->w_height >= cmdline_row) clear_cmdline = TRUE; @@ -232,7 +299,7 @@ popup_close(int id) first_popupwin = wp->w_next; else prev->w_next = wp->w_next; - popup_undisplay(wp); + popup_free(wp); return; } @@ -258,7 +325,7 @@ popup_close_tabpage(tabpage_T *tp, int i *root = wp->w_next; else prev->w_next = wp->w_next; - popup_undisplay(wp); + popup_free(wp); return; } } diff --git a/src/proto/popupwin.pro b/src/proto/popupwin.pro --- a/src/proto/popupwin.pro +++ b/src/proto/popupwin.pro @@ -1,6 +1,9 @@ /* popupwin.c */ void f_popup_create(typval_T *argvars, typval_T *rettv); +int popup_any_visible(void); void f_popup_close(typval_T *argvars, typval_T *rettv); +void f_popup_hide(typval_T *argvars, typval_T *rettv); +void f_popup_show(typval_T *argvars, typval_T *rettv); void popup_close(int id); void popup_close_tabpage(tabpage_T *tp, int id); void close_all_popups(void); diff --git a/src/screen.c b/src/screen.c --- a/src/screen.c +++ b/src/screen.c @@ -610,7 +610,7 @@ update_screen(int type_arg) } #ifdef FEAT_TEXT_PROP // TODO: avoid redrawing everything when there is a popup window. - if (first_popupwin != NULL || curtab->tp_first_popupwin != NULL) + if (popup_any_visible()) type = NOT_VALID; #endif @@ -999,9 +999,9 @@ update_popups(void) // Reset all the VALID_POPUP flags. for (wp = first_popupwin; wp != NULL; wp = wp->w_next) - wp->w_valid &= ~VALID_POPUP; + wp->w_popup_flags &= ~PFL_REDRAWN; for (wp = curtab->tp_first_popupwin; wp != NULL; wp = wp->w_next) - wp->w_valid &= ~VALID_POPUP; + wp->w_popup_flags &= ~PFL_REDRAWN; // TODO: don't redraw every popup every time. for (;;) @@ -1012,14 +1012,14 @@ update_popups(void) lowest_zindex = INT_MAX; lowest_wp = NULL; for (wp = first_popupwin; wp != NULL; wp = wp->w_next) - if ((wp->w_valid & VALID_POPUP) == 0 + if ((wp->w_popup_flags & (PFL_REDRAWN|PFL_HIDDEN)) == 0 && wp->w_zindex < lowest_zindex) { lowest_zindex = wp->w_zindex; lowest_wp = wp; } for (wp = curtab->tp_first_popupwin; wp != NULL; wp = wp->w_next) - if ((wp->w_valid & VALID_POPUP) == 0 + if ((wp->w_popup_flags & (PFL_REDRAWN|PFL_HIDDEN)) == 0 && wp->w_zindex < lowest_zindex) { lowest_zindex = wp->w_zindex; @@ -1029,7 +1029,7 @@ update_popups(void) if (lowest_wp == NULL) break; win_update(lowest_wp); - lowest_wp->w_valid |= VALID_POPUP; + lowest_wp->w_popup_flags |= PFL_REDRAWN; } } #endif diff --git a/src/structs.h b/src/structs.h --- a/src/structs.h +++ b/src/structs.h @@ -2871,6 +2871,7 @@ struct window_S int w_vsep_width; /* Number of separator columns (0 or 1). */ pos_save_T w_save_cursor; /* backup of cursor pos and topline */ #ifdef FEAT_TEXT_PROP + int w_popup_flags; // PFL_ values int w_zindex; int w_maxheight; // "maxheight" for popup window int w_maxwidth; // "maxwidth" for popup window 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 @@ -76,3 +76,41 @@ func Test_popup_time() bwipe! endfunc + +func Test_popup_hide() + topleft vnew + call setline(1, 'hello') + + let winid = popup_create('world', { + \ 'line': 1, + \ 'col': 1, + \}) + redraw + let line = join(map(range(1, 5), 'screenstring(1, v:val)'), '') + call assert_equal('world', line) + + call popup_hide(winid) + redraw + let line = join(map(range(1, 5), 'screenstring(1, v:val)'), '') + call assert_equal('hello', line) + + call popup_show(winid) + redraw + let line = join(map(range(1, 5), 'screenstring(1, v:val)'), '') + call assert_equal('world', line) + + + call popup_close(winid) + redraw + let line = join(map(range(1, 5), 'screenstring(1, v:val)'), '') + call assert_equal('hello', line) + + " error is given for existing non-popup window + call assert_fails('call popup_hide(win_getid())', 'E993:') + + " no error non-existing window + call popup_hide(1234234) + call popup_show(41234234) + + bwipe! +endfunc diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -768,6 +768,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 1406, +/**/ 1405, /**/ 1404, diff --git a/src/vim.h b/src/vim.h --- a/src/vim.h +++ b/src/vim.h @@ -612,7 +612,10 @@ extern int (*dyn_libintl_wputenv)(const #define VALID_BOTLINE 0x20 // w_botine and w_empty_rows are valid #define VALID_BOTLINE_AP 0x40 // w_botine is approximated #define VALID_TOPLINE 0x80 // w_topline is valid (for cursor position) -#define VALID_POPUP 0x100 // popup has been redrawn + +// Values for w_popup_flags. +#define PFL_HIDDEN 1 // popup is not displayed +#define PFL_REDRAWN 2 // popup was just redrawn /* * Terminal highlighting attribute bits.