changeset 16809:5ff14f96f1c9 v8.1.1406

patch 8.1.1406: popup_hide() and popup_show() not implemented yet commit https://github.com/vim/vim/commit/2cd0dce898995a2b05f7285a70efec3f67f579f5 Author: Bram Moolenaar <Bram@vim.org> 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.
author Bram Moolenaar <Bram@vim.org>
date Sun, 26 May 2019 22:30:05 +0200
parents c002c4899529
children 53b2302072d2
files runtime/doc/popup.txt src/evalfunc.c src/popupwin.c src/proto/popupwin.pro src/screen.c src/structs.h src/testdir/test_popupwin.vim src/version.c src/vim.h
diffstat 9 files changed, 135 insertions(+), 18 deletions(-) [+]
line wrap: on
line diff
--- 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()*
--- 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},
--- 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;
 	}
 }
--- 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);
--- 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
--- 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
--- 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
--- 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,
--- 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.