summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2019-05-26 22:17:52 +0200
committerBram Moolenaar <Bram@vim.org>2019-05-26 22:17:52 +0200
commit2cd0dce898995a2b05f7285a70efec3f67f579f5 (patch)
treed0f53338a226bedd3730e5a143bc226aff64cdb4
parent68e6560b84f196c82e27a72669684d5506a3a837 (diff)
patch 8.1.1406: popup_hide() and popup_show() not implemented yetv8.1.1406
Problem: popup_hide() and popup_show() not implemented yet. Solution: Implement the functions.
-rw-r--r--runtime/doc/popup.txt13
-rw-r--r--src/evalfunc.c2
-rw-r--r--src/popupwin.c77
-rw-r--r--src/proto/popupwin.pro3
-rw-r--r--src/screen.c12
-rw-r--r--src/structs.h1
-rw-r--r--src/testdir/test_popupwin.vim38
-rw-r--r--src/version.c2
-rw-r--r--src/vim.h5
9 files changed, 135 insertions, 18 deletions
diff --git a/runtime/doc/popup.txt b/runtime/doc/popup.txt
index 3b17f77953..bbab6d03da 100644
--- 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_menu()*
"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_move()*
{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
index 3256b22c9d..b15e74d438 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 e39ee67d48..0857f6b0a3 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 172c0794d2..64fca5ff56 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 30e1bb21ab..40cff9acc2 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 ca7c540703..925bf0363b 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 04c67a227a..73efe0a738 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 04de1af85a..5df9639743 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,
diff --git a/src/vim.h b/src/vim.h
index 3389ef5a1d..a52ba5e64c 100644
--- a/src/vim.h
+++ b/src/vim.h
@@ -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.