Patch 8.1.1410
Problem:    Popup_move() is not implemented yet.
Solution:   Implement it. (Yasuhiro Matsumoto, closes #4441)  Improve the
            positioning and resizing.
Files:      runtime/doc/popup.txt, src/evalfunc.c, src/popupwin.c,
            src/screen.c, src/structs.h, src/proto/popupwin.pro,
            src/testdir/test_popupwin.vim,
            src/testdir/dumps/Test_popupwin_05.dump


*** ../vim-8.1.1409/runtime/doc/popup.txt       2019-05-26 23:32:03.179678024 
+0200
--- runtime/doc/popup.txt       2019-05-27 20:15:57.224591812 +0200
***************
*** 84,90 ****
  
  IMPLEMENTATION:
  - Code is in popupwin.c
! - Implement list of lines with text properties
  - Implement filter.
  - Handle screen resize in screenalloc().
  - Make redrawing more efficient and avoid flicker.
--- 84,90 ----
  
  IMPLEMENTATION:
  - Code is in popupwin.c
! - implement popup_getposition({id}), use in tests
  - Implement filter.
  - Handle screen resize in screenalloc().
  - Make redrawing more efficient and avoid flicker.
***************
*** 190,196 ****
                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",
--- 190,195 ----
***************
*** 310,319 ****
                        {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}
--- 309,316 ----
*** ../vim-8.1.1409/src/evalfunc.c      2019-05-26 22:17:31.736315033 +0200
--- src/evalfunc.c      2019-05-27 20:06:05.751964764 +0200
***************
*** 811,816 ****
--- 811,817 ----
      {"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
*** ../vim-8.1.1409/src/popupwin.c      2019-05-27 10:04:37.530426996 +0200
--- src/popupwin.c      2019-05-27 20:44:15.611540280 +0200
***************
*** 25,34 ****
      int           nr;
      char_u  *str;
  
      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_zindex = dict_get_number(dict, (char_u *)"zindex");
  
  #if defined(FEAT_TIMERS)
--- 25,38 ----
      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_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)
***************
*** 145,150 ****
--- 149,197 ----
  }
  
  /*
+  * 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})
   */
      void
***************
*** 241,272 ****
      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;
  
      wp->w_vsep_width = 0;
  
--- 288,294 ----
      if (wp->w_zindex == 0)
        wp->w_zindex = 50;
  
!     popup_adjust_position(wp);
  
      wp->w_vsep_width = 0;
  
***************
*** 424,427 ****
--- 446,490 ----
      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
*** ../vim-8.1.1409/src/screen.c        2019-05-27 10:04:37.530426996 +0200
--- src/screen.c        2019-05-27 21:48:09.115958231 +0200
***************
*** 1034,1039 ****
--- 1034,1057 ----
  }
  #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,2431 ****
  {
      int               n = 0;
      int               attr = HL_ATTR(hl);
!     int               wcr_attr = 0;
  
!     if (*wp->w_p_wcr != NUL)
!     {
!       wcr_attr = syn_name2attr(wp->w_p_wcr);
!       attr = hl_combine_attr(wcr_attr, attr);
!     }
  
      if (draw_margin)
      {
--- 2437,2445 ----
  {
      int               n = 0;
      int               attr = HL_ATTR(hl);
!     int               wcr_attr = get_wcr_attr(wp);
  
!     attr = hl_combine_attr(wcr_attr, attr);
  
      if (draw_margin)
      {
***************
*** 3115,3120 ****
--- 3129,3136 ----
      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,3202 ****
  #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 */
--- 3212,3217 ----
***************
*** 3566,3593 ****
        }
      }
  
!     if (*wp->w_p_wcr != NUL)
      {
!       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;
!       }
      }
  #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
  
      /*
--- 3581,3595 ----
        }
      }
  
!     wcr_attr = get_wcr_attr(wp);
!     if (wcr_attr != 0)
      {
!       win_attr = wcr_attr;
!       area_highlighting = TRUE;
      }
  #ifdef FEAT_TEXT_PROP
      if (bt_popup(wp->w_buffer))
        screen_line_flags |= SLF_POPUP;
  #endif
  
      /*
*** ../vim-8.1.1409/src/structs.h       2019-05-26 22:17:31.736315033 +0200
--- src/structs.h       2019-05-27 20:30:23.054166540 +0200
***************
*** 2873,2880 ****
--- 2873,2884 ----
  #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
*** ../vim-8.1.1409/src/proto/popupwin.pro      2019-05-26 22:17:31.736315033 
+0200
--- src/proto/popupwin.pro      2019-05-27 20:24:05.974256691 +0200
***************
*** 8,11 ****
--- 8,12 ----
  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 : */
*** ../vim-8.1.1409/src/testdir/test_popupwin.vim       2019-05-26 
23:32:03.175678045 +0200
--- src/testdir/test_popupwin.vim       2019-05-27 21:50:29.651252234 +0200
***************
*** 16,23 ****
        \ "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})",
        \ "call setwinvar(winid2, '&wincolor', 'PopupColor2')",
        \], 'XtestPopup')
    let buf = RunVimInTerminal('-S XtestPopup', {'rows': 10})
--- 16,23 ----
        \ "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, 
'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,36 ****
  
    " Add a tabpage
    call term_sendkeys(buf, ":tabnew\<CR>")
!   call term_sendkeys(buf, ":call popup_create(["
        \ .. "{'text': 'other tab'},"
        \ .. "{'text': 'a comment line', 'props': [{"
!       \ .. "'col': 3, 'length': 7, 'type': 'comment'"
        \ .. "}]},"
!       \ .. "], {'line': 4, 'col': 9})\<CR>")
    call VerifyScreenDump(buf, 'Test_popupwin_02', {})
  
    " switch back to first tabpage
--- 25,36 ----
  
    " Add a tabpage
    call term_sendkeys(buf, ":tabnew\<CR>")
!   call term_sendkeys(buf, ":let popupwin = popup_create(["
        \ .. "{'text': 'other tab'},"
        \ .. "{'text': 'a comment line', 'props': [{"
!       \ .. "'col': 3, 'length': 7, 'minwidth': 20, 'type': 'comment'"
        \ .. "}]},"
!       \ .. "], {'line': 4, 'col': 9, 'minwidth': 20})\<CR>")
    call VerifyScreenDump(buf, 'Test_popupwin_02', {})
  
    " switch back to first tabpage
***************
*** 41,46 ****
--- 41,51 ----
    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,61 ****
--- 61,67 ----
    call popup_create('world', {
        \ 'line': 1,
        \ 'col': 1,
+       \ 'minwidth': 20,
        \ 'time': 500,
        \})
    redraw
***************
*** 70,75 ****
--- 76,82 ----
    call popup_create('on the command line', {
        \ 'line': &lines,
        \ 'col': 10,
+       \ 'minwidth': 20,
        \ 'time': 500,
        \})
    redraw
***************
*** 91,96 ****
--- 98,104 ----
    let winid = popup_create('world', {
        \ 'line': 1,
        \ 'col': 1,
+       \ 'minwidth': 20,
        \})
    redraw
    let line = join(map(range(1, 5), 'screenstring(1, v:val)'), '')
***************
*** 121,123 ****
--- 129,161 ----
  
    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
*** ../vim-8.1.1409/src/testdir/dumps/Test_popupwin_05.dump     2019-05-27 
21:51:37.350912887 +0200
--- src/testdir/dumps/Test_popupwin_05.dump     2019-05-27 21:48:42.687789379 
+0200
***************
*** 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| 
*** ../vim-8.1.1409/src/version.c       2019-05-27 20:01:38.121491973 +0200
--- src/version.c       2019-05-27 21:51:48.102859037 +0200
***************
*** 769,770 ****
--- 769,772 ----
  {   /* Add new patch number below this line */
+ /**/
+     1410,
  /**/

-- 
The users that I support would double-click on a landmine to find out
what happens.                           -- A system administrator

 /// Bram Moolenaar -- [email protected] -- http://www.Moolenaar.net   \\\
///        sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\
\\\  an exciting new programming language -- http://www.Zimbu.org        ///
 \\\            help me help AIDS victims -- http://ICCF-Holland.org    ///

-- 
-- 
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

--- 
You received this message because you are subscribed to the Google Groups 
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/vim_dev/201905271954.x4RJsSOJ028834%40masaka.moolenaar.net.
For more options, visit https://groups.google.com/d/optout.

Raspunde prin e-mail lui