]> git.ipfire.org Git - thirdparty/vim.git/commitdiff
patch 8.1.1452: line and col property of popup windows not properly checked v8.1.1452
authorBram Moolenaar <Bram@vim.org>
Sun, 2 Jun 2019 14:51:21 +0000 (16:51 +0200)
committerBram Moolenaar <Bram@vim.org>
Sun, 2 Jun 2019 14:51:21 +0000 (16:51 +0200)
Problem:    Line and col property of popup windows not properly checked.
Solution:   Check for "+" or "-" sign.

src/dict.c
src/popupwin.c
src/proto/dict.pro
src/testdir/test_popupwin.vim
src/version.c
src/window.c

index d6b3b189a638987cbaaa53f05ec6a15417077552..c67eb42c5870999b74f24ff911d3c36f353f1500 100644 (file)
@@ -604,6 +604,27 @@ dict_get_number(dict_T *d, char_u *key)
     return tv_get_number(&di->di_tv);
 }
 
+/*
+ * Get a number item from a dictionary.
+ * Returns 0 if the entry doesn't exist.
+ * Give an error if the entry is not a number.
+ */
+    varnumber_T
+dict_get_number_check(dict_T *d, char_u *key)
+{
+    dictitem_T *di;
+
+    di = dict_find(d, key, -1);
+    if (di == NULL)
+       return 0;
+    if (di->di_tv.v_type != VAR_NUMBER)
+    {
+       semsg(_(e_invarg2), tv_get_string(&di->di_tv));
+       return 0;
+    }
+    return tv_get_number(&di->di_tv);
+}
+
 /*
  * Return an allocated string with the string representation of a Dictionary.
  * May return NULL.
index 4a67e241edbeeff39d637152def94b178afa8e1c..357b7611d065d9e531fa46b000d2a0f859444240 100644 (file)
@@ -29,7 +29,7 @@ static poppos_entry_T poppos_entries[] = {
 };
 
 /*
- * Get option value for"key", which is "line" or "col".
+ * Get option value for "key", which is "line" or "col".
  * Handles "cursor+N" and "cursor-N".
  */
     static int
@@ -47,13 +47,15 @@ popup_options_one(dict_T *dict, char_u *key)
 
     val = tv_get_string(&di->di_tv);
     if (STRNCMP(val, "cursor", 6) != 0)
-       return dict_get_number(dict, key);
+       return dict_get_number_check(dict, key);
 
     setcursor_mayforce(TRUE);
     s = val + 6;
     if (*s != NUL)
     {
-       n = strtol((char *)s, (char **)&endp, 10);
+       endp = s;
+       if (*skipwhite(s) == '+' || *skipwhite(s) == '-')
+           n = strtol((char *)s, (char **)&endp, 10);
        if (endp != NULL && *skipwhite(endp) != NUL)
        {
            semsg(_(e_invexpr2), val);
@@ -902,7 +904,7 @@ f_popup_getpos(typval_T *argvars, typval_T *rettv)
        dict_add_number(dict, "core_height", wp->w_height);
 
        dict_add_number(dict, "visible",
-                                      (wp->w_popup_flags & POPF_HIDDEN) == 0);
+                     win_valid(wp) && (wp->w_popup_flags & POPF_HIDDEN) == 0);
     }
 }
 
index 688255cc1351d713a484c1dcc53fc6272db56a7c..d4820256d1222c7d1a2650dc817440c665c767d5 100644 (file)
@@ -25,6 +25,7 @@ long dict_len(dict_T *d);
 dictitem_T *dict_find(dict_T *d, char_u *key, int len);
 char_u *dict_get_string(dict_T *d, char_u *key, int save);
 varnumber_T dict_get_number(dict_T *d, char_u *key);
+varnumber_T dict_get_number_check(dict_T *d, char_u *key);
 char_u *dict2string(typval_T *tv, int copyID, int restore_copyID);
 int dict_get_tv(char_u **arg, typval_T *rettv, int evaluate);
 void dict_extend(dict_T *d1, dict_T *d2, char_u *action);
index 73f53a23a4f7319f13b23da2bd043fb437f88d13..ca95977a7673266c908df0ae57d165fa1526d5e0 100644 (file)
@@ -224,6 +224,92 @@ func Test_popup_all_corners()
   call delete('XtestPopupCorners')
 endfunc
 
+func Test_popup_in_tab()
+  " default popup is local to tab, not visible when in other tab
+  let winid = popup_create("text", {})
+  call assert_equal(1, popup_getpos(winid).visible)
+  tabnew
+  call assert_equal(0, popup_getpos(winid).visible)
+  quit
+  call assert_equal(1, popup_getpos(winid).visible)
+  popupclear
+
+  " global popup is visible in any tab
+  let winid = popup_create("text", {'tab': -1})
+  call assert_equal(1, popup_getpos(winid).visible)
+  tabnew
+  call assert_equal(1, popup_getpos(winid).visible)
+  quit
+  call assert_equal(1, popup_getpos(winid).visible)
+  popupclear
+endfunc
+
+func Test_popup_valid_arguments()
+  " Zero value is like the property wasn't there
+  let winid = popup_create("text", {"col": 0})
+  let pos = popup_getpos(winid)
+  call assert_inrange(&columns / 2 - 1, &columns / 2 + 1, pos.col)
+  popupclear
+
+  " using cursor column has minimum value of 1
+  let winid = popup_create("text", {"col": 'cursor-100'})
+  let pos = popup_getpos(winid)
+  call assert_equal(1, pos.col)
+  popupclear
+
+  " center
+  let winid = popup_create("text", {"pos": 'center'})
+  let pos = popup_getpos(winid)
+  let around = (&columns - pos.width) / 2
+  call assert_inrange(around - 1, around + 1, pos.col)
+  let around = (&lines - pos.height) / 2
+  call assert_inrange(around - 1, around + 1, pos.line)
+  popupclear
+endfunc
+
+func Test_popup_invalid_arguments()
+  call assert_fails('call popup_create(666, {})', 'E714:')
+  popupclear
+  call assert_fails('call popup_create("text", "none")', 'E715:')
+  popupclear
+
+  call assert_fails('call popup_create("text", {"col": "xxx"})', 'E475:')
+  popupclear
+  call assert_fails('call popup_create("text", {"col": "cursor8"})', 'E15:')
+  popupclear
+  call assert_fails('call popup_create("text", {"col": "cursor+x"})', 'E15:')
+  popupclear
+  call assert_fails('call popup_create("text", {"col": "cursor+8x"})', 'E15:')
+  popupclear
+
+  call assert_fails('call popup_create("text", {"line": "xxx"})', 'E475:')
+  popupclear
+  call assert_fails('call popup_create("text", {"line": "cursor8"})', 'E15:')
+  popupclear
+  call assert_fails('call popup_create("text", {"line": "cursor+x"})', 'E15:')
+  popupclear
+  call assert_fails('call popup_create("text", {"line": "cursor+8x"})', 'E15:')
+  popupclear
+
+  call assert_fails('call popup_create("text", {"pos": "there"})', 'E475:')
+  popupclear
+  call assert_fails('call popup_create("text", {"padding": "none"})', 'E714:')
+  popupclear
+  call assert_fails('call popup_create("text", {"border": "none"})', 'E714:')
+  popupclear
+  call assert_fails('call popup_create("text", {"borderhighlight": "none"})', 'E714:')
+  popupclear
+  call assert_fails('call popup_create("text", {"borderchars": "none"})', 'E714:')
+  popupclear
+
+  call assert_fails('call popup_create([{"text": "text"}, 666], {})', 'E715:')
+  popupclear
+  call assert_fails('call popup_create([{"text": "text", "props": "none"}], {})', 'E714:')
+  popupclear
+  call assert_fails('call popup_create([{"text": "text", "props": ["none"]}], {})', 'E715:')
+  popupclear
+endfunc
+
 func Test_win_execute_closing_curwin()
   split
   let winid = popup_create('some text', {})
@@ -593,6 +679,15 @@ func Test_popup_atcursor()
   call assert_equal(4, pos.line)
   call popup_close(winid)
 
+  " cursor in first line, popup in line 2
+  call cursor(1, 1)
+  redraw
+  let winid = popup_atcursor(['vim', 'is', 'great'], {})
+  redraw
+  let pos = popup_getpos(winid)
+  call assert_equal(2, pos.line)
+  call popup_close(winid)
+
   bwipe!
 endfunc
 
index 6e04c071789ba459bf0cdf1384e4de52b6e28ea4..33eb93c36bacf9f5b44858b61dcc61d207aa1627 100644 (file)
@@ -767,6 +767,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    1452,
 /**/
     1451,
 /**/
index f4ef983c6ddff6875d5cc5da60371ef73a138369..d293bad44188255948834c2315e75aded8f50c8f 100644 (file)
@@ -1368,6 +1368,9 @@ win_init_some(win_T *newp, win_T *oldp)
     win_copy_options(oldp, newp);
 }
 
+/*
+ * Return TRUE if "win" is a global popup or a popup in the current tab page.
+ */
     static int
 win_valid_popup(win_T *win UNUSED)
 {
@@ -1418,6 +1421,11 @@ win_valid_any_tab(win_T *win)
            if (wp == win)
                return TRUE;
        }
+#ifdef FEAT_TEXT_PROP
+       for (wp = tp->tp_first_popupwin; wp != NULL; wp = wp->w_next)
+           if (wp == win)
+               return TRUE;
+#endif
     }
     return win_valid_popup(win);
 }