diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/evalfunc.c | 2 | ||||
-rw-r--r-- | src/popupwin.c | 77 | ||||
-rw-r--r-- | src/proto/popupwin.pro | 3 | ||||
-rw-r--r-- | src/screen.c | 12 | ||||
-rw-r--r-- | src/structs.h | 1 | ||||
-rw-r--r-- | src/testdir/test_popupwin.vim | 38 | ||||
-rw-r--r-- | src/version.c | 2 | ||||
-rw-r--r-- | src/vim.h | 5 |
8 files changed, 128 insertions, 12 deletions
diff --git a/src/evalfunc.c b/src/evalfunc.c index 3256b22c9..b15e74d43 100644 --- 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 index e39ee67d4..0857f6b0a 100644 --- a/src/popupwin.c +++ b/src/popupwin.c @@ -195,18 +195,85 @@ f_popup_create(typval_T *argvars, typval_T *rettv) } /* + * 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_close(nr); +/* + * 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); + + 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 id) *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 index 172c0794d..64fca5ff5 100644 --- 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 index 30e1bb21a..40cff9acc 100644 --- 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 index ca7c54070..925bf0363 100644 --- 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 index 04c67a227..73efe0a73 100644 --- 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 index 04de1af85..5df963974 100644 --- 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, @@ -612,7 +612,10 @@ extern int (*dyn_libintl_wputenv)(const wchar_t *envstring); #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. |