]> git.ipfire.org Git - thirdparty/vim.git/commitdiff
patch 8.1.1410: popup_move() is not implemented yet v8.1.1410
authorBram Moolenaar <Bram@vim.org>
Mon, 27 May 2019 19:54:10 +0000 (21:54 +0200)
committerBram Moolenaar <Bram@vim.org>
Mon, 27 May 2019 19:54:10 +0000 (21:54 +0200)
Problem:    Popup_move() is not implemented yet.
Solution:   Implement it. (Yasuhiro Matsumoto, closes #4441)  Improve the
            positioning and resizing.

runtime/doc/popup.txt
src/evalfunc.c
src/popupwin.c
src/proto/popupwin.pro
src/screen.c
src/structs.h
src/testdir/dumps/Test_popupwin_05.dump [new file with mode: 0644]
src/testdir/test_popupwin.vim
src/version.c

index 5697edec996e1e07b11890be42b1c29ee8305c54..b92871506f04a8e67d9b2e8b8a516b6f073cd6b7 100644 (file)
@@ -84,7 +84,7 @@ Probably 2. is the best choice.
 
 IMPLEMENTATION:
 - Code is in popupwin.c
-- Implement list of lines with text properties
+- implement popup_getposition({id}), use in tests
 - Implement filter.
 - Handle screen resize in screenalloc().
 - Make redrawing more efficient and avoid flicker.
@@ -190,7 +190,6 @@ popup_show({id})                                            *popup_show()*
                For {id} see `popup_hide()`.
 
 popup_move({id}, {options})                                    *popup_move()*
-               {not implemented yet}
                Move popup {id} to the position speficied with {options}.
                {options} may contain the items from |popup_create()| that
                specify the popup position: "line", "col", "pos", "maxheight",
@@ -310,10 +309,8 @@ The second argument of |popup_create()| is a dictionary with options:
                        {not implemented yet}
        maxheight       maximum height
        minheight       minimum height
-                       {not implemented yet}
        maxwidth        maximum width
        minwidth        minimum width
-                       {not implemented yet}
        hidden          when TRUE the popup exists but is not displayed; use
                        `popup_show()` to unhide it.
                        {not implemented yet}
index b15e74d438b6ac3ed89709d73813824bdeeb657a..03e326024439ecd097266dbcf4ded5af73992ac4 100644 (file)
@@ -811,6 +811,7 @@ static struct fst
     {"popup_close",    1, 1, f_popup_close},
     {"popup_create",   2, 2, f_popup_create},
     {"popup_hide",     1, 1, f_popup_hide},
+    {"popup_move",     2, 2, f_popup_move},
     {"popup_show",     1, 1, f_popup_show},
 #endif
 #ifdef FEAT_FLOAT
index 9222119445b8f4dc248617d3554024e6565eeecf..9970c5afe9957480774c7a14a19cfe4f448cbd4c 100644 (file)
@@ -25,10 +25,14 @@ apply_options(win_T *wp, buf_T *buf UNUSED, dict_T *dict)
     int            nr;
     char_u  *str;
 
+    wp->w_minwidth = dict_get_number(dict, (char_u *)"minwidth");
+    wp->w_minheight = dict_get_number(dict, (char_u *)"minheight");
     wp->w_maxwidth = dict_get_number(dict, (char_u *)"maxwidth");
     wp->w_maxheight = dict_get_number(dict, (char_u *)"maxheight");
-    wp->w_winrow = dict_get_number(dict, (char_u *)"line");
-    wp->w_wincol = dict_get_number(dict, (char_u *)"col");
+
+    wp->w_wantline = dict_get_number(dict, (char_u *)"line");
+    wp->w_wantcol = dict_get_number(dict, (char_u *)"col");
+
     wp->w_zindex = dict_get_number(dict, (char_u *)"zindex");
 
 #if defined(FEAT_TIMERS)
@@ -144,6 +148,49 @@ add_popup_dicts(buf_T *buf, list_T *l)
     }
 }
 
+/*
+ * Adjust the position and size of the popup to fit on the screen.
+ */
+    static void
+popup_adjust_position(win_T *wp)
+{
+    // TODO: Compute the size and position properly.
+    if (wp->w_wantline > 0)
+       wp->w_winrow = wp->w_wantline - 1;
+    else
+       // TODO: better default
+       wp->w_winrow = Rows > 5 ? Rows / 2 - 2 : 0;
+    if (wp->w_winrow >= Rows)
+       wp->w_winrow = Rows - 1;
+
+    if (wp->w_wantcol > 0)
+       wp->w_wincol = wp->w_wantcol - 1;
+    else
+       // TODO: better default
+       wp->w_wincol = Columns > 20 ? Columns / 2 - 10 : 0;
+    if (wp->w_wincol >= Columns - 3)
+       wp->w_wincol = Columns - 3;
+
+    // TODO: set width based on longest text line and the 'wrap' option
+    wp->w_width = vim_strsize(ml_get_buf(wp->w_buffer, 1, FALSE));
+    if (wp->w_minwidth > 0 && wp->w_width < wp->w_minwidth)
+       wp->w_width = wp->w_minwidth;
+    if (wp->w_maxwidth > 0 && wp->w_width > wp->w_maxwidth)
+       wp->w_width = wp->w_maxwidth;
+    if (wp->w_width > Columns - wp->w_wincol)
+       wp->w_width = Columns - wp->w_wincol;
+
+    if (wp->w_height <= 1)
+       // TODO: adjust height for wrapped lines
+       wp->w_height = wp->w_buffer->b_ml.ml_line_count;
+    if (wp->w_minheight > 0 && wp->w_height < wp->w_minheight)
+       wp->w_height = wp->w_minheight;
+    if (wp->w_maxheight > 0 && wp->w_height > wp->w_maxheight)
+       wp->w_height = wp->w_maxheight;
+    if (wp->w_height > Rows - wp->w_winrow)
+       wp->w_height = Rows - wp->w_winrow;
+}
+
 /*
  * popup_create({text}, {options})
  */
@@ -241,32 +288,7 @@ f_popup_create(typval_T *argvars, typval_T *rettv)
     if (wp->w_zindex == 0)
        wp->w_zindex = 50;
 
-    // TODO: Compute the size and position properly.
-
-    // Default position is in middle of the screen, assuming a small popup
-    if (wp->w_winrow == 0)
-       wp->w_winrow = Rows > 5 ? Rows / 2 - 2 : 0;
-    else
-       --wp->w_winrow;  // option value is one-based
-    if (wp->w_wincol == 0)
-       wp->w_wincol = Columns > 20 ? Columns / 2 - 10 : 0;
-    else
-       --wp->w_wincol;  // option value is one-based
-
-
-    // TODO: set width based on longest text line and the 'wrap' option
-    wp->w_width = wp->w_maxwidth == 0 ? 20 : wp->w_maxwidth;
-    if (wp->w_maxwidth > 0 && wp->w_width > wp->w_maxwidth)
-       wp->w_width = wp->w_maxwidth;
-    if (wp->w_width > Columns - wp->w_wincol)
-       wp->w_width = Columns - wp->w_wincol;
-
-    // TODO: adjust height for wrapped lines
-    wp->w_height = buf->b_ml.ml_line_count;
-    if (wp->w_maxheight > 0 && wp->w_height > wp->w_maxheight)
-       wp->w_height = wp->w_maxheight;
-    if (wp->w_height > Rows - wp->w_winrow)
-       wp->w_height = Rows - wp->w_winrow;
+    popup_adjust_position(wp);
 
     wp->w_vsep_width = 0;
 
@@ -424,4 +446,45 @@ ex_popupclear(exarg_T *eap UNUSED)
     close_all_popups();
 }
 
+/*
+ * popup_move({id}, {options})
+ */
+    void
+f_popup_move(typval_T *argvars, typval_T *rettv UNUSED)
+{
+    dict_T     *d;
+    int                nr;
+    int                id = (int)tv_get_number(argvars);
+    win_T      *wp = find_popup_win(id);
+
+    if (wp == NULL)
+       return;  // invalid {id}
+
+    if (argvars[1].v_type != VAR_DICT || argvars[1].vval.v_dict == NULL)
+    {
+       emsg(_(e_dictreq));
+       return;
+    }
+    d = argvars[1].vval.v_dict;
+
+    if ((nr = dict_get_number(d, (char_u *)"minwidth")) > 0)
+       wp->w_minwidth = nr;
+    if ((nr = dict_get_number(d, (char_u *)"minheight")) > 0)
+       wp->w_minheight = nr;
+    if ((nr = dict_get_number(d, (char_u *)"maxwidth")) > 0)
+       wp->w_maxwidth = nr;
+    if ((nr = dict_get_number(d, (char_u *)"maxheight")) > 0)
+       wp->w_maxheight = nr;
+    if ((nr = dict_get_number(d, (char_u *)"line")) > 0)
+       wp->w_wantline = nr;
+    if ((nr = dict_get_number(d, (char_u *)"col")) > 0)
+       wp->w_wantcol = nr;
+    // TODO: "pos"
+
+    if (wp->w_winrow + wp->w_height >= cmdline_row)
+       clear_cmdline = TRUE;
+    popup_adjust_position(wp);
+    redraw_all_later(NOT_VALID);
+}
+
 #endif // FEAT_TEXT_PROP
index 64fca5ff56bc4c53f9fa24e1f420a00a14cce7c5..f4d476095cf9e45494ba01c3c38c959c6f3c3f2d 100644 (file)
@@ -8,4 +8,5 @@ void popup_close(int id);
 void popup_close_tabpage(tabpage_T *tp, int id);
 void close_all_popups(void);
 void ex_popupclear(exarg_T *eap);
+void f_popup_move(typval_T *argvars, typval_T *rettv);
 /* vim: set ft=c : */
index 02cd172a90077860b251a8f4e8f6cd7de24b0f99..d5272236f44e269b605b24222adc10bf8aafb37a 100644 (file)
@@ -1034,6 +1034,24 @@ update_popups(void)
 }
 #endif
 
+/*
+ * Get 'wincolor' attribute for window "wp".  If not set and "wp" is a popup
+ * window then get the "Pmenu" highlight attribute.
+ */
+    static int
+get_wcr_attr(win_T *wp)
+{
+    int wcr_attr = 0;
+
+    if (*wp->w_p_wcr != NUL)
+       wcr_attr = syn_name2attr(wp->w_p_wcr);
+#ifdef FEAT_TEXT_PROP
+    if (bt_popup(wp->w_buffer) && wcr_attr == 0)
+       wcr_attr = HL_ATTR(HLF_PNI);
+#endif
+    return wcr_attr;
+}
+
 #if defined(FEAT_GUI) || defined(PROTO)
 /*
  * Update a single window, its status line and maybe the command line msg.
@@ -2419,13 +2437,9 @@ win_draw_end(
 {
     int                n = 0;
     int                attr = HL_ATTR(hl);
-    int                wcr_attr = 0;
+    int                wcr_attr = get_wcr_attr(wp);
 
-    if (*wp->w_p_wcr != NUL)
-    {
-       wcr_attr = syn_name2attr(wp->w_p_wcr);
-       attr = hl_combine_attr(wcr_attr, attr);
-    }
+    attr = hl_combine_attr(wcr_attr, attr);
 
     if (draw_margin)
     {
@@ -3115,6 +3129,8 @@ win_line(
     int                vi_attr = 0;            // attributes for Visual and incsearch
                                        // highlighting
     int                wcr_attr = 0;           // attributes from 'wincolor'
+    int                win_attr = 0;           // background for whole window, except
+                                       // margins and "~" lines.
     int                area_attr = 0;          // attributes desired by highlighting
     int                search_attr = 0;        // attributes desired by 'hlsearch'
 #ifdef FEAT_SYN_HL
@@ -3196,7 +3212,6 @@ win_line(
 #ifdef FEAT_TERMINAL
     int                get_term_attr = FALSE;
 #endif
-    int                win_attr = 0;           // background for whole window
 
     /* draw_state: items that are drawn in sequence: */
 #define WL_START       0               /* nothing done yet */
@@ -3566,28 +3581,15 @@ win_line(
        }
     }
 
-    if (*wp->w_p_wcr != NUL)
+    wcr_attr = get_wcr_attr(wp);
+    if (wcr_attr != 0)
     {
-       wcr_attr = syn_name2attr(wp->w_p_wcr);
-
-       // 'wincolor' highlighting for the whole window
-       if (wcr_attr != 0)
-       {
-           win_attr = wcr_attr;
-           area_highlighting = TRUE;
-       }
+       win_attr = wcr_attr;
+       area_highlighting = TRUE;
     }
 #ifdef FEAT_TEXT_PROP
     if (bt_popup(wp->w_buffer))
-    {
        screen_line_flags |= SLF_POPUP;
-
-       if (win_attr == 0)
-       {
-           win_attr = HL_ATTR(HLF_PNI);
-           area_highlighting = TRUE;
-       }
-    }
 #endif
 
     /*
index 925bf0363bb3731927e35832b815b9fcb22e5dae..07dc7e3befe807a2a6753a269e2971e575ab59ab 100644 (file)
@@ -2873,8 +2873,12 @@ struct window_S
 #ifdef FEAT_TEXT_PROP
     int                w_popup_flags;      // PFL_ values
     int                w_zindex;
+    int                w_minheight;        // "minheight" for popup window
+    int                w_minwidth;         // "minwidth" for popup window
     int                w_maxheight;        // "maxheight" for popup window
     int                w_maxwidth;         // "maxwidth" for popup window
+    int                w_wantline;         // "line" for popup window
+    int                w_wantcol;          // "col" for popup window
 # if defined(FEAT_TIMERS)
     timer_T    *w_popup_timer;     // timer for closing popup window
 # endif
diff --git a/src/testdir/dumps/Test_popupwin_05.dump b/src/testdir/dumps/Test_popupwin_05.dump
new file mode 100644 (file)
index 0000000..bfb50f0
--- /dev/null
@@ -0,0 +1,10 @@
+> +0&#ffffff0@74
+|~+0#4040ff13&| @73
+|~| @73
+|~| @6|o+0#0000001#ffd7ff255|t|h|e|r| |t|a|b| @5| +0#4040ff13#ffffff0@51
+|~| @6|a+0#0000001#ffd7ff255| |c+0#ff404010&|o|m@1|e|n|t| +0#0000001&|l|i|n|e| | +0#4040ff13#ffffff0@51
+|~| @6|~+0&#ffd7ff255| @13| +0&#ffffff0@51
+|~| @73
+|~| @73
+|~| @73
+|:+0#0000000&|r|e|d|r|a|w| @49|0|,|0|-|1| @8|A|l@1| 
index f1394fbf872d8ed6341d6e14505ed309139aac1b..756ad68c4dc19f375238648ae307cc362fc04438 100644 (file)
@@ -16,8 +16,8 @@ func Test_simple_popup()
        \ "hi PopupColor2 ctermbg=lightcyan",
        \ "hi Comment ctermfg=red",
        \ "call prop_type_add('comment', {'highlight': 'Comment'})",
-       \ "let winid = popup_create('hello there', {'line': 3, 'col': 11, 'highlight': 'PopupColor1'})",
-       \ "let winid2 = popup_create(['another one', 'another two', 'another three'], {'line': 3, 'col': 25})",
+       \ "let winid = popup_create('hello there', {'line': 3, 'col': 11, 'minwidth': 20, 'highlight': 'PopupColor1'})",
+       \ "let winid2 = popup_create(['another one', 'another two', 'another three'], {'line': 3, 'col': 25, 'minwidth': 20})",
        \ "call setwinvar(winid2, '&wincolor', 'PopupColor2')",
        \], 'XtestPopup')
   let buf = RunVimInTerminal('-S XtestPopup', {'rows': 10})
@@ -25,12 +25,12 @@ func Test_simple_popup()
 
   " Add a tabpage
   call term_sendkeys(buf, ":tabnew\<CR>")
-  call term_sendkeys(buf, ":call popup_create(["
+  call term_sendkeys(buf, ":let popupwin = popup_create(["
        \ .. "{'text': 'other tab'},"
        \ .. "{'text': 'a comment line', 'props': [{"
-       \ .. "'col': 3, 'length': 7, 'type': 'comment'"
+       \ .. "'col': 3, 'length': 7, 'minwidth': 20, 'type': 'comment'"
        \ .. "}]},"
-       \ .. "], {'line': 4, 'col': 9})\<CR>")
+       \ .. "], {'line': 4, 'col': 9, 'minwidth': 20})\<CR>")
   call VerifyScreenDump(buf, 'Test_popupwin_02', {})
 
   " switch back to first tabpage
@@ -41,6 +41,11 @@ func Test_simple_popup()
   call term_sendkeys(buf, ":quit!\<CR>")
   call VerifyScreenDump(buf, 'Test_popupwin_04', {})
 
+  " resize popup
+  call term_sendkeys(buf, ":call popup_move(popupwin, {'minwidth': 15, 'maxwidth': 25, 'minheight': 3, 'maxheight': 5})\<CR>")
+  call term_sendkeys(buf, ":redraw\<CR>")
+  call VerifyScreenDump(buf, 'Test_popupwin_05', {})
+
   " clean up
   call StopVimInTerminal(buf)
   call delete('XtestPopup')
@@ -56,6 +61,7 @@ func Test_popup_time()
   call popup_create('world', {
        \ 'line': 1,
        \ 'col': 1,
+       \ 'minwidth': 20,
        \ 'time': 500,
        \})
   redraw
@@ -70,6 +76,7 @@ func Test_popup_time()
   call popup_create('on the command line', {
        \ 'line': &lines,
        \ 'col': 10,
+       \ 'minwidth': 20,
        \ 'time': 500,
        \})
   redraw
@@ -91,6 +98,7 @@ func Test_popup_hide()
   let winid = popup_create('world', {
        \ 'line': 1,
        \ 'col': 1,
+       \ 'minwidth': 20,
        \})
   redraw
   let line = join(map(range(1, 5), 'screenstring(1, v:val)'), '')
@@ -121,3 +129,33 @@ func Test_popup_hide()
 
   bwipe!
 endfunc
+
+func Test_popup_move()
+  topleft vnew
+  call setline(1, 'hello')
+
+  let winid = popup_create('world', {
+       \ 'line': 1,
+       \ 'col': 1,
+       \ 'minwidth': 20,
+       \})
+  redraw
+  let line = join(map(range(1, 6), 'screenstring(1, v:val)'), '')
+  call assert_equal('world ', line)
+
+  call popup_move(winid, {'line': 2, 'col': 2})
+  redraw
+  let line = join(map(range(1, 6), 'screenstring(1, v:val)'), '')
+  call assert_equal('hello ', line)
+  let line = join(map(range(1, 6), 'screenstring(2, v:val)'), '')
+  call assert_equal('~world', line)
+
+  call popup_move(winid, {'line': 1})
+  redraw
+  let line = join(map(range(1, 6), 'screenstring(1, v:val)'), '')
+  call assert_equal('hworld', line)
+
+  call popup_close(winid)
+
+  bwipe!
+endfunc
index b0068641235a0941124a3aa0abbe988a41ca4100..1fa7db403e3311b6884e95e8858cd980221a4010 100644 (file)
@@ -767,6 +767,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    1410,
 /**/
     1409,
 /**/