Patch 8.1.2304
Problem:    Cannot get the mouse position when getting a mouse click.
Solution:   Add getmousepos().
Files:      runtime/doc/eval.txt, runtime/doc/popup.txt, src/mouse.c
            src/proto/mouse.pro, src/evalfunc.c, src/popupwin.c,
            src/popupwin.pro, src/testdir/test_popupwin.vim,
            src/testdir/test_functions.vim


*** ../vim-8.1.2303/runtime/doc/eval.txt        2019-10-29 04:12:38.620582834 
+0100
--- runtime/doc/eval.txt        2019-11-16 18:20:29.431251620 +0100
***************
*** 2480,2485 ****
--- 2480,2486 ----
  getline({lnum}, {end})                List    lines {lnum} to {end} of 
current buffer
  getloclist({nr} [, {what}])   List    list of location list items
  getmatches([{win}])           List    list of current matches
+ getmousepos()                 Dict    last known mouse position
  getpid()                      Number  process ID of Vim
  getpos({expr})                        List    position of cursor, mark, etc.
  getqflist([{what}])           List    list of quickfix items
***************
*** 4912,4919 ****
  
                When the user clicks a mouse button, the mouse event will be
                returned.  The position can then be found in |v:mouse_col|,
!               |v:mouse_lnum|, |v:mouse_winid| and |v:mouse_win|.  This
!               example positions the mouse as it would normally happen: >
                        let c = getchar()
                        if c == "\<LeftMouse>" && v:mouse_win > 0
                          exe v:mouse_win . "wincmd w"
--- 4919,4927 ----
  
                When the user clicks a mouse button, the mouse event will be
                returned.  The position can then be found in |v:mouse_col|,
!               |v:mouse_lnum|, |v:mouse_winid| and |v:mouse_win|.
!               |getmousepos()| can also be used.  This example positions the
!               mouse as it would normally happen: >
                        let c = getchar()
                        if c == "\<LeftMouse>" && v:mouse_win > 0
                          exe v:mouse_win . "wincmd w"
***************
*** 5323,5328 ****
--- 5331,5365 ----
                        'pattern': 'FIXME', 'priority': 10, 'id': 2}] >
                        :unlet m
  <
+ getmousepos()                                         *getmousepos()*
+               Returns a Dictionary with the last known position of the
+               mouse.  This can be used in a mapping for a mouse click or in
+               a filter of a popup window.  The items are:
+                       screenrow       screen row
+                       screencol       screen column
+                       winid           Window ID of the click
+                       winrow          row inside "winid"
+                       wincol          column inside "winid"
+                       line            text line inside "winid"
+                       column          text column inside "winid"
+               All numbers are 1-based.
+ 
+               If not over a window, e.g. when in the command line, then only
+               "screenrow" and "screencol" are valid, the others are zero.
+ 
+               When on the status line below a window or the vertical
+               separater right of a window, the "line" and "column" values
+               are zero.
+ 
+               When the position is after the text then "column" is the
+               length of the text in bytes.
+ 
+               If the mouse is over a popup window then that window is used.
+ 
+ 
+               When using |getchar()| the Vim variables |v:mouse_lnum|,
+               |v:mouse_col| and |v:mouse_winid| also provide these values.
+ 
                                                        *getpid()*
  getpid()      Return a Number which is the process ID of the Vim process.
                On Unix and MS-Windows this is a unique number, until Vim
*** ../vim-8.1.2303/runtime/doc/popup.txt       2019-11-11 21:45:01.925407125 
+0100
--- runtime/doc/popup.txt       2019-11-16 15:57:02.558631367 +0100
***************
*** 862,871 ****
        cursor keys     select another entry
        Tab             accept current suggestion
  
! A mouse click arrives as <LeftMouse>.  The coordinates are in |v:mouse_col|
! and |v:mouse_lnum|.  |v:mouse_winid| holds the window ID, |v:mouse_win| is
! always zero.  The top-left screen cell of the popup is col 1, row 1 (not
! counting the border).
  
  Vim provides standard filters |popup_filter_menu()| and
  |popup_filter_yesno()|.
--- 862,869 ----
        cursor keys     select another entry
        Tab             accept current suggestion
  
! A mouse click arrives as <LeftMouse>.  The coordinates can be obtained with
! |mousegetpos()|.
  
  Vim provides standard filters |popup_filter_menu()| and
  |popup_filter_yesno()|.
*** ../vim-8.1.2303/src/mouse.c 2019-11-13 22:35:15.759521804 +0100
--- src/mouse.c 2019-11-16 18:12:11.385526875 +0100
***************
*** 2822,2827 ****
--- 2822,2828 ----
      int               retval = FALSE;
      int               off;
      int               count;
+     char_u    *p;
  
  #ifdef FEAT_RIGHTLEFT
      if (win->w_p_rl)
***************
*** 2881,2886 ****
--- 2882,2892 ----
        col += row * (win->w_width - off);
        // add skip column (for long wrapping line)
        col += win->w_skipcol;
+       // limit to text length plus one
+       p = ml_get_buf(win->w_buffer, lnum, FALSE);
+       count = STRLEN(p);
+       if (col > count)
+           col = count;
      }
  
      if (!win->w_p_wrap)
***************
*** 3001,3003 ****
--- 3007,3067 ----
      return (int)(ptr - line);
  }
  #endif
+ 
+ #if defined(FEAT_EVAL) || defined(PROTO)
+     void
+ f_getmousepos(typval_T *argvars UNUSED, typval_T *rettv)
+ {
+     dict_T    *d;
+     win_T     *wp;
+     int               row = mouse_row;
+     int               col = mouse_col;
+     varnumber_T winid = 0;
+     varnumber_T winrow = 0;
+     varnumber_T wincol = 0;
+     varnumber_T line = 0;
+     varnumber_T column = 0;
+ 
+     if (rettv_dict_alloc(rettv) != OK)
+       return;
+     d = rettv->vval.v_dict;
+ 
+     dict_add_number(d, "screenrow", (varnumber_T)mouse_row + 1);
+     dict_add_number(d, "screencol", (varnumber_T)mouse_col + 1);
+ 
+     wp = mouse_find_win(&row, &col, FIND_POPUP);
+     if (wp != NULL)
+     {
+       int     top_off = 0;
+       int     left_off = 0;
+       int     height = wp->w_height + wp->w_status_height;
+ 
+ #ifdef FEAT_TEXT_PROP
+       if (WIN_IS_POPUP(wp))
+       {
+           top_off = popup_top_extra(wp);
+           left_off = popup_left_extra(wp);
+           height = popup_height(wp);
+       }
+ #endif
+       if (row < height)
+       {
+           winid = wp->w_id;
+           winrow = row + 1;
+           wincol = col + 1;
+           row -= top_off;
+           col -= left_off;
+           if (row >= 0 && row < wp->w_height && col >= 0 && col < wp->w_width)
+           {
+               mouse_comp_pos(wp, &row, &col, &line, NULL);
+               column = col + 1;
+           }
+       }
+     }
+     dict_add_number(d, "winid", winid);
+     dict_add_number(d, "winrow", winrow);
+     dict_add_number(d, "wincol", wincol);
+     dict_add_number(d, "line", line);
+     dict_add_number(d, "column", column);
+ }
+ #endif
*** ../vim-8.1.2303/src/proto/mouse.pro 2019-09-23 21:16:51.387544361 +0200
--- src/proto/mouse.pro 2019-11-16 16:20:57.037027736 +0100
***************
*** 17,20 ****
--- 17,21 ----
  int mouse_comp_pos(win_T *win, int *rowp, int *colp, linenr_T *lnump, int 
*plines_cache);
  win_T *mouse_find_win(int *rowp, int *colp, mouse_find_T popup);
  int vcol2col(win_T *wp, linenr_T lnum, int vcol);
+ void f_getmousepos(typval_T *argvars, typval_T *rettv);
  /* vim: set ft=c : */
*** ../vim-8.1.2303/src/evalfunc.c      2019-11-10 00:13:46.434916175 +0100
--- src/evalfunc.c      2019-11-16 16:08:14.380168924 +0100
***************
*** 465,470 ****
--- 465,471 ----
      {"getline",               1, 2, FEARG_1,    f_getline},
      {"getloclist",    1, 2, 0,          f_getloclist},
      {"getmatches",    0, 1, 0,          f_getmatches},
+     {"getmousepos",   0, 0, 0,          f_getmousepos},
      {"getpid",                0, 0, 0,          f_getpid},
      {"getpos",                1, 1, FEARG_1,    f_getpos},
      {"getqflist",     0, 1, 0,          f_getqflist},
*** ../vim-8.1.2303/src/popupwin.c      2019-11-13 22:35:15.755521778 +0100
--- src/popupwin.c      2019-11-16 16:52:16.180901037 +0100
***************
*** 1047,1052 ****
--- 1047,1061 ----
  }
  
  /*
+  * Get the padding plus border at the left.
+  */
+     int
+ popup_left_extra(win_T *wp)
+ {
+     return wp->w_popup_border[3] + wp->w_popup_padding[3];
+ }
+ 
+ /*
   * Return the height of popup window "wp", including border and padding.
   */
      int
***************
*** 2908,2940 ****
  
      argv[2].v_type = VAR_UNKNOWN;
  
-     if (is_mouse_key(c))
-     {
-       int             row = mouse_row - wp->w_winrow;
-       int             col = mouse_col - wp->w_wincol;
-       linenr_T        lnum;
- 
-       if (row >= 0 && col >= 0)
-       {
-           (void)mouse_comp_pos(wp, &row, &col, &lnum, NULL);
-           set_vim_var_nr(VV_MOUSE_LNUM, lnum);
-           set_vim_var_nr(VV_MOUSE_COL, col + 1);
-           set_vim_var_nr(VV_MOUSE_WINID, wp->w_id);
-       }
-     }
- 
      // NOTE: The callback might close the popup and make "wp" invalid.
      call_callback(&wp->w_filter_cb, -1, &rettv, 2, argv);
      if (win_valid_popup(wp) && old_lnum != wp->w_cursor.lnum)
        popup_highlight_curline(wp);
      res = tv_get_number(&rettv);
  
-     if (is_mouse_key(c))
-     {
-       set_vim_var_nr(VV_MOUSE_LNUM, 0);
-       set_vim_var_nr(VV_MOUSE_COL, 0);
-       set_vim_var_nr(VV_MOUSE_WINID, wp->w_id);
-     }
      vim_free(argv[1].vval.v_string);
      clear_tv(&rettv);
      return res;
--- 2917,2928 ----
*** ../vim-8.1.2303/src/testdir/test_popupwin.vim       2019-11-13 
22:35:15.759521804 +0100
--- src/testdir/test_popupwin.vim       2019-11-16 18:12:59.365307098 +0100
***************
*** 2205,2246 ****
  
  func Test_popupwin_filter_mouse()
    func MyPopupFilter(winid, c)
!     let g:got_mouse_col = v:mouse_col
!     let g:got_mouse_lnum = v:mouse_lnum
!     let g:got_mouse_winid = v:mouse_winid
      return 0
    endfunc
  
!   let winid = popup_create(['short', 'long line that will wrap', 'short'], #{
!       \ line: 4,
!       \ col: 8,
        \ maxwidth: 12,
        \ filter: 'MyPopupFilter',
        \ })
    redraw
!   call test_setmouse(4, 8)
!   call feedkeys("\<LeftMouse>", 'xt')
!   call assert_equal(1, g:got_mouse_col)
!   call assert_equal(1, g:got_mouse_lnum)
!   call assert_equal(winid, g:got_mouse_winid)
! 
!   call test_setmouse(5, 8)
!   call feedkeys("\<LeftMouse>", 'xt')
!   call assert_equal(1, g:got_mouse_col)
!   call assert_equal(2, g:got_mouse_lnum)
! 
!   call test_setmouse(6, 8)
!   call feedkeys("\<LeftMouse>", 'xt')
!   call assert_equal(13, g:got_mouse_col)
!   call assert_equal(2, g:got_mouse_lnum)
! 
!   call test_setmouse(7, 20)
!   call feedkeys("\<LeftMouse>", 'xt')
!   call assert_equal(13, g:got_mouse_col)
!   call assert_equal(3, g:got_mouse_lnum)
!   call assert_equal(winid, g:got_mouse_winid)
  
    call popup_close(winid)
    delfunc MyPopupFilter
  endfunc
  
--- 2205,2310 ----
  
  func Test_popupwin_filter_mouse()
    func MyPopupFilter(winid, c)
!     let g:got_mousepos = getmousepos()
      return 0
    endfunc
  
!   call setline(1, ['.'->repeat(25)]->repeat(10))
!   let winid = popup_create(['short', 'long line that will wrap', 'other'], #{
!       \ line: 2,
!       \ col: 4,
        \ maxwidth: 12,
+       \ padding: [],
+       \ border: [],
        \ filter: 'MyPopupFilter',
        \ })
    redraw
!   "    123456789012345678901
!   "  1 .....................
!   "  2 ...+--------------+..
!   "  3 ...|              |..
!   "  4 ...| short        |..
!   "  5 ...| long line th |..
!   "  6 ...| at will wrap |..
!   "  7 ...| other        |..
!   "  8 ...|              |..
!   "  9 ...+--------------+..
!   " 10 .....................
!   let tests = []
! 
!   func AddItemOutsidePopup(tests, row, col)
!     eval a:tests->add(#{clickrow: a:row, clickcol: a:col, result: #{
!         \ screenrow: a:row, screencol: a:col,
!         \ winid: win_getid(), winrow: a:row, wincol: a:col,
!         \ line: a:row, column: a:col,
!         \ }})
!   endfunc
!   func AddItemInPopupBorder(tests, winid, row, col)
!     eval a:tests->add(#{clickrow: a:row, clickcol: a:col, result: #{
!         \ screenrow: a:row, screencol: a:col,
!         \ winid: a:winid, winrow: a:row - 1, wincol: a:col - 3,
!         \ line: 0, column: 0,
!         \ }})
!   endfunc
!   func AddItemInPopupText(tests, winid, row, col, textline, textcol)
!     eval a:tests->add(#{clickrow: a:row, clickcol: a:col, result: #{
!         \ screenrow: a:row, screencol: a:col,
!         \ winid: a:winid, winrow: a:row - 1, wincol: a:col - 3,
!         \ line: a:textline, column: a:textcol,
!         \ }})
!   endfunc
! 
!   " above and below popup
!   for c in range(1, 21)
!     call AddItemOutsidePopup(tests, 1, c)
!     call AddItemOutsidePopup(tests, 10, c)
!   endfor
!   " left and right of popup
!   for r in range(1, 10)
!     call AddItemOutsidePopup(tests, r, 3)
!     call AddItemOutsidePopup(tests, r, 20)
!   endfor
!   " top and bottom in popup
!   for c in range(4, 19)
!     call AddItemInPopupBorder(tests, winid, 2, c)
!     call AddItemInPopupBorder(tests, winid, 3, c)
!     call AddItemInPopupBorder(tests, winid, 8, c)
!     call AddItemInPopupBorder(tests, winid, 9, c)
!   endfor
!   " left and right margin in popup
!   for r in range(2, 9)
!     call AddItemInPopupBorder(tests, winid, r, 4)
!     call AddItemInPopupBorder(tests, winid, r, 5)
!     call AddItemInPopupBorder(tests, winid, r, 18)
!     call AddItemInPopupBorder(tests, winid, r, 19)
!   endfor
!   " text "short"
!   call AddItemInPopupText(tests, winid, 4, 6, 1, 1)
!   call AddItemInPopupText(tests, winid, 4, 10, 1, 5)
!   call AddItemInPopupText(tests, winid, 4, 11, 1, 6)
!   call AddItemInPopupText(tests, winid, 4, 17, 1, 6)
!   " text "long line th"
!   call AddItemInPopupText(tests, winid, 5, 6, 2, 1)
!   call AddItemInPopupText(tests, winid, 5, 10, 2, 5)
!   call AddItemInPopupText(tests, winid, 5, 17, 2, 12)
!   " text "at will wrap"
!   call AddItemInPopupText(tests, winid, 6, 6, 2, 13)
!   call AddItemInPopupText(tests, winid, 6, 10, 2, 17)
!   call AddItemInPopupText(tests, winid, 6, 17, 2, 24)
!   " text "other"
!   call AddItemInPopupText(tests, winid, 7, 6, 3, 1)
!   call AddItemInPopupText(tests, winid, 7, 10, 3, 5)
!   call AddItemInPopupText(tests, winid, 7, 11, 3, 6)
!   call AddItemInPopupText(tests, winid, 7, 17, 3, 6)
! 
!   for item in tests
!     call test_setmouse(item.clickrow, item.clickcol)
!     call feedkeys("\<LeftMouse>", 'xt')
!     call assert_equal(item.result, g:got_mousepos)
!   endfor
  
    call popup_close(winid)
+   enew!
    delfunc MyPopupFilter
  endfunc
  
*** ../vim-8.1.2303/src/testdir/test_functions.vim      2019-09-28 
22:11:49.654184756 +0200
--- src/testdir/test_functions.vim      2019-11-16 18:18:14.083868933 +0100
***************
*** 1331,1336 ****
--- 1331,1337 ----
    call feedkeys('a', '')
    call assert_equal(char2nr('a'), getchar())
  
+   call setline(1, 'xxxx')
    call test_setmouse(1, 3)
    let v:mouse_win = 9
    let v:mouse_winid = 9
***************
*** 1342,1347 ****
--- 1343,1349 ----
    call assert_equal(win_getid(1), v:mouse_winid)
    call assert_equal(1, v:mouse_lnum)
    call assert_equal(3, v:mouse_col)
+   enew!
  endfunc
  
  func Test_libcall_libcallnr()
*** ../vim-8.1.2303/src/version.c       2019-11-16 14:19:29.715739224 +0100
--- src/version.c       2019-11-16 18:08:02.754668833 +0100
***************
*** 743,744 ****
--- 743,746 ----
  {   /* Add new patch number below this line */
+ /**/
+     2304,
  /**/

-- 
>From "know your smileys":
 |-P    Reaction to unusually ugly C code

 /// 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/201911161723.xAGHNZ5g003483%40masaka.moolenaar.net.

Raspunde prin e-mail lui