Patch 8.1.1453
Problem:    Popup window "moved" property not implemented yet.
Solution:   Implement it.
Files:      src/main.c, src/edit.c, src/gui.c, src/globals.h, src/structs.h,
            src/screen.c, src/popupwin.c, src/proto/popupwin.pro,
            src/testdir/test_popupwin.vim, runtime/doc/popup.txt


*** ../vim-8.1.1452/src/main.c  2019-05-24 18:48:36.762128482 +0200
--- src/main.c  2019-06-02 17:03:56.230707184 +0200
***************
*** 1159,1164 ****
--- 1159,1167 ----
            /* Trigger CursorMoved if the cursor moved. */
            if (!finish_op && (
                        has_cursormoved()
+ #ifdef FEAT_TEXT_PROP
+                       || popup_visible
+ #endif
  #ifdef FEAT_CONCEAL
                        || curwin->w_p_cole > 0
  #endif
***************
*** 1168,1181 ****
                if (has_cursormoved())
                    apply_autocmds(EVENT_CURSORMOVED, NULL, NULL,
                                                               FALSE, curbuf);
! # ifdef FEAT_CONCEAL
                if (curwin->w_p_cole > 0)
                {
                    conceal_old_cursor_line = last_cursormoved.lnum;
                    conceal_new_cursor_line = curwin->w_cursor.lnum;
                    conceal_update_lines = TRUE;
                }
! # endif
                last_cursormoved = curwin->w_cursor;
            }
  
--- 1171,1188 ----
                if (has_cursormoved())
                    apply_autocmds(EVENT_CURSORMOVED, NULL, NULL,
                                                               FALSE, curbuf);
! #ifdef FEAT_TEXT_PROP
!               if (popup_visible)
!                   popup_check_cursor_pos();
! #endif
! #ifdef FEAT_CONCEAL
                if (curwin->w_p_cole > 0)
                {
                    conceal_old_cursor_line = last_cursormoved.lnum;
                    conceal_new_cursor_line = curwin->w_cursor.lnum;
                    conceal_update_lines = TRUE;
                }
! #endif
                last_cursormoved = curwin->w_cursor;
            }
  
*** ../vim-8.1.1452/src/edit.c  2019-05-24 19:38:59.096545552 +0200
--- src/edit.c  2019-06-02 18:12:32.244392562 +0200
***************
*** 1456,1463 ****
   * inserting sequences of characters (e.g., for CTRL-R).
   */
      void
! ins_redraw(
!     int               ready UNUSED)       /* not busy with something */
  {
  #ifdef FEAT_CONCEAL
      linenr_T  conceal_old_cursor_line = 0;
--- 1456,1462 ----
   * inserting sequences of characters (e.g., for CTRL-R).
   */
      void
! ins_redraw(int ready)     // not busy with something
  {
  #ifdef FEAT_CONCEAL
      linenr_T  conceal_old_cursor_line = 0;
***************
*** 1468,1477 ****
      if (char_avail())
        return;
  
- #if defined(FEAT_CONCEAL)
      /* Trigger CursorMoved if the cursor moved.  Not when the popup menu is
       * visible, the command might delete it. */
      if (ready && (has_cursormovedI()
  # if defined(FEAT_CONCEAL)
                || curwin->w_p_cole > 0
  # endif
--- 1467,1478 ----
      if (char_avail())
        return;
  
      /* Trigger CursorMoved if the cursor moved.  Not when the popup menu is
       * visible, the command might delete it. */
      if (ready && (has_cursormovedI()
+ # ifdef FEAT_TEXT_PROP
+               || popup_visible
+ # endif
  # if defined(FEAT_CONCEAL)
                || curwin->w_p_cole > 0
  # endif
***************
*** 1497,1502 ****
--- 1498,1507 ----
            update_curswant();
            ins_apply_autocmds(EVENT_CURSORMOVEDI);
        }
+ #ifdef FEAT_TEXT_PROP
+       if (popup_visible)
+           popup_check_cursor_pos();
+ #endif
  # ifdef FEAT_CONCEAL
        if (curwin->w_p_cole > 0)
        {
***************
*** 1507,1513 ****
  # endif
        last_cursormoved = curwin->w_cursor;
      }
- #endif
  
      /* Trigger TextChangedI if b_changedtick differs. */
      if (ready && has_textchangedI()
--- 1512,1517 ----
***************
*** 3859,3865 ****
      if (replace_stack_len <= replace_stack_nr)
      {
        replace_stack_len += 50;
!       p = alloc(sizeof(char_u) * replace_stack_len);
        if (p == NULL)      /* out of memory */
        {
            replace_stack_len -= 50;
--- 3863,3869 ----
      if (replace_stack_len <= replace_stack_nr)
      {
        replace_stack_len += 50;
!       p = ALLOC_MULT(char_u, replace_stack_len);
        if (p == NULL)      /* out of memory */
        {
            replace_stack_len -= 50;
*** ../vim-8.1.1452/src/gui.c   2019-05-24 18:48:36.758128504 +0200
--- src/gui.c   2019-06-02 17:03:51.394743342 +0200
***************
*** 5117,5122 ****
--- 5117,5125 ----
  
      /* Trigger CursorMoved if the cursor moved. */
      if (!finish_op && (has_cursormoved()
+ # ifdef FEAT_TEXT_PROP
+               || popup_visible
+ # endif
  # ifdef FEAT_CONCEAL
                || curwin->w_p_cole > 0
  # endif
***************
*** 5124,5129 ****
--- 5127,5136 ----
      {
        if (has_cursormoved())
            apply_autocmds(EVENT_CURSORMOVED, NULL, NULL, FALSE, curbuf);
+ #ifdef FEAT_TEXT_PROP
+       if (popup_visible)
+           popup_check_cursor_pos();
+ #endif
  # ifdef FEAT_CONCEAL
        if (curwin->w_p_cole > 0)
        {
*** ../vim-8.1.1452/src/globals.h       2019-05-26 18:48:09.402542633 +0200
--- src/globals.h       2019-06-02 17:04:22.518512240 +0200
***************
*** 558,581 ****
  EXTERN win_T  *firstwin;              /* first window */
  EXTERN win_T  *lastwin;               /* last window */
  EXTERN win_T  *prevwin INIT(= NULL);  /* previous window */
! # define ONE_WINDOW (firstwin == lastwin)
! # define W_NEXT(wp) ((wp)->w_next)
! # define FOR_ALL_WINDOWS(wp) for (wp = firstwin; wp != NULL; wp = wp->w_next)
! # define FOR_ALL_FRAMES(frp, first_frame) \
      for (frp = first_frame; frp != NULL; frp = frp->fr_next)
! # define FOR_ALL_TABPAGES(tp) for (tp = first_tabpage; tp != NULL; tp = 
tp->tp_next)
! # define FOR_ALL_WINDOWS_IN_TAB(tp, wp) \
      for ((wp) = ((tp) == NULL || (tp) == curtab) \
            ? firstwin : (tp)->tp_firstwin; (wp); (wp) = (wp)->w_next)
  /*
   * When using this macro "break" only breaks out of the inner loop. Use "goto"
   * to break out of the tabpage loop.
   */
! # define FOR_ALL_TAB_WINDOWS(tp, wp) \
      for ((tp) = first_tabpage; (tp) != NULL; (tp) = (tp)->tp_next) \
        for ((wp) = ((tp) == curtab) \
                ? firstwin : (tp)->tp_firstwin; (wp); (wp) = (wp)->w_next)
  
  EXTERN win_T  *curwin;        /* currently active window */
  
  EXTERN win_T  *aucmd_win;     /* window used in aucmd_prepbuf() */
--- 558,582 ----
  EXTERN win_T  *firstwin;              /* first window */
  EXTERN win_T  *lastwin;               /* last window */
  EXTERN win_T  *prevwin INIT(= NULL);  /* previous window */
! #define ONE_WINDOW (firstwin == lastwin)
! #define W_NEXT(wp) ((wp)->w_next)
! #define FOR_ALL_WINDOWS(wp) for (wp = firstwin; wp != NULL; wp = wp->w_next)
! #define FOR_ALL_FRAMES(frp, first_frame) \
      for (frp = first_frame; frp != NULL; frp = frp->fr_next)
! #define FOR_ALL_TABPAGES(tp) for (tp = first_tabpage; tp != NULL; tp = 
tp->tp_next)
! #define FOR_ALL_WINDOWS_IN_TAB(tp, wp) \
      for ((wp) = ((tp) == NULL || (tp) == curtab) \
            ? firstwin : (tp)->tp_firstwin; (wp); (wp) = (wp)->w_next)
  /*
   * When using this macro "break" only breaks out of the inner loop. Use "goto"
   * to break out of the tabpage loop.
   */
! #define FOR_ALL_TAB_WINDOWS(tp, wp) \
      for ((tp) = first_tabpage; (tp) != NULL; (tp) = (tp)->tp_next) \
        for ((wp) = ((tp) == curtab) \
                ? firstwin : (tp)->tp_firstwin; (wp); (wp) = (wp)->w_next)
  
+ 
  EXTERN win_T  *curwin;        /* currently active window */
  
  EXTERN win_T  *aucmd_win;     /* window used in aucmd_prepbuf() */
***************
*** 1663,1666 ****
--- 1664,1668 ----
  
  #ifdef FEAT_TEXT_PROP
  EXTERN int text_prop_frozen INIT(= 0);
+ EXTERN int popup_visible INIT(= FALSE);
  #endif
*** ../vim-8.1.1452/src/structs.h       2019-06-02 14:49:52.372891128 +0200
--- src/structs.h       2019-06-02 17:09:32.012375995 +0200
***************
*** 2897,2902 ****
--- 2897,2908 ----
                                          // computed
      callback_T        w_close_cb;         // popup close callback
      callback_T        w_filter_cb;        // popup filter callback
+ 
+     win_T     *w_popup_curwin;    // close popup if curwin differs
+     linenr_T  w_popup_lnum;       // close popup if cursor not on this line
+     colnr_T   w_popup_mincol;     // close popup if cursor before this col
+     colnr_T   w_popup_maxcol;     // close popup if cursor after this col
+ 
  # if defined(FEAT_TIMERS)
      timer_T   *w_popup_timer;     // timer for closing popup window
  # endif
*** ../vim-8.1.1452/src/screen.c        2019-06-02 15:56:11.839730143 +0200
--- src/screen.c        2019-06-02 17:05:40.501948236 +0200
***************
*** 1050,1055 ****
--- 1050,1056 ----
      // so that the window with a higher zindex is drawn later, thus goes on
      // top.
      // TODO: don't redraw every popup every time.
+     popup_visible = FALSE;
      popup_reset_handled();
      while ((wp = find_next_popup(TRUE)) != NULL)
      {
***************
*** 1066,1071 ****
--- 1067,1073 ----
  
        // Draw the popup text.
        win_update(wp);
+       popup_visible = TRUE;
  
        wp->w_winrow -= top_off;
        wp->w_wincol -= left_off;
*** ../vim-8.1.1452/src/popupwin.c      2019-06-02 16:51:18.011257964 +0200
--- src/popupwin.c      2019-06-02 17:58:17.393963233 +0200
***************
*** 285,290 ****
--- 285,333 ----
            }
        }
      }
+ 
+     di = dict_find(dict, (char_u *)"moved", -1);
+     if (di != NULL)
+     {
+       wp->w_popup_curwin = curwin;
+       wp->w_popup_lnum = curwin->w_cursor.lnum;
+       wp->w_popup_mincol = curwin->w_cursor.col;
+       wp->w_popup_maxcol = curwin->w_cursor.col;
+       if (di->di_tv.v_type == VAR_STRING && di->di_tv.vval.v_string != NULL)
+       {
+           char_u  *s = di->di_tv.vval.v_string;
+           int     flags = 0;
+ 
+           if (STRCMP(s, "word") == 0)
+               flags = FIND_IDENT | FIND_STRING;
+           else if (STRCMP(s, "WORD") == 0)
+               flags = FIND_STRING;
+           else if (STRCMP(s, "any") != 0)
+               semsg(_(e_invarg2), s);
+           if (flags != 0)
+           {
+               char_u  *ptr;
+               int     len = find_ident_under_cursor(&ptr, flags);
+ 
+               if (len > 0)
+               {
+                   wp->w_popup_mincol = (int)(ptr - ml_get_curline());
+                   wp->w_popup_maxcol = wp->w_popup_mincol + len - 1;
+               }
+           }
+       }
+       else if (di->di_tv.v_type == VAR_LIST
+               && di->di_tv.vval.v_list != NULL
+               && di->di_tv.vval.v_list->lv_len == 2)
+       {
+           list_T *l = di->di_tv.vval.v_list;
+ 
+           wp->w_popup_mincol = tv_get_number(&l->lv_first->li_tv);
+           wp->w_popup_maxcol = tv_get_number(&l->lv_first->li_next->li_tv);
+       }
+       else
+           semsg(_(e_invarg2), tv_get_string(&di->di_tv));
+     }
  }
  
  /*
***************
*** 708,713 ****
--- 751,771 ----
  }
  
  /*
+  * Close popup "wp" and invoke any close callback for it.
+  */
+     static void
+ popup_close_and_callback(win_T *wp, typval_T *arg)
+ {
+     int id = wp->w_id;
+ 
+     if (wp->w_close_cb.cb_name != NULL)
+       // Careful: This may make "wp" invalid.
+       invoke_popup_callback(wp, arg);
+ 
+     popup_close(id);
+ }
+ 
+ /*
   * popup_close({id})
   */
      void
***************
*** 717,729 ****
      win_T     *wp = find_popup_win(id);
  
      if (wp != NULL)
!     {
!       if (wp->w_close_cb.cb_name != NULL)
!           // Careful: This may make "wp" invalid.
!           invoke_popup_callback(wp, &argvars[1]);
! 
!       popup_close(id);
!     }
  }
  
  /*
--- 775,781 ----
      win_T     *wp = find_popup_win(id);
  
      if (wp != NULL)
!       popup_close_and_callback(wp, &argvars[1]);
  }
  
  /*
***************
*** 1066,1069 ****
--- 1118,1145 ----
      return res;
  }
  
+ /*
+  * Called when the cursor moved: check if any popup needs to be closed if the
+  * cursor moved far enough.
+  */
+     void
+ popup_check_cursor_pos()
+ {
+     win_T *wp;
+     typval_T tv;
+ 
+     popup_reset_handled();
+     while ((wp = find_next_popup(TRUE)) != NULL)
+       if (wp->w_popup_curwin != NULL
+               && (curwin != wp->w_popup_curwin
+                   || curwin->w_cursor.lnum != wp->w_popup_lnum
+                   || curwin->w_cursor.col < wp->w_popup_mincol
+                   || curwin->w_cursor.col > wp->w_popup_maxcol))
+       {
+           tv.v_type = VAR_NUMBER;
+           tv.vval.v_number = -1;
+           popup_close_and_callback(wp, &tv);
+       }
+ }
+ 
  #endif // FEAT_TEXT_PROP
*** ../vim-8.1.1452/src/proto/popupwin.pro      2019-06-01 17:13:15.880517743 
+0200
--- src/proto/popupwin.pro      2019-06-02 17:15:02.082311611 +0200
***************
*** 17,20 ****
--- 17,21 ----
  void popup_reset_handled(void);
  win_T *find_next_popup(int lowest);
  int popup_do_filter(int c);
+ void popup_check_cursor_pos(void);
  /* vim: set ft=c : */
*** ../vim-8.1.1452/src/testdir/test_popupwin.vim       2019-06-02 
16:51:18.011257964 +0200
--- src/testdir/test_popupwin.vim       2019-06-02 18:37:10.534590921 +0200
***************
*** 909,915 ****
    %bwipe!
  endfunc
  
! function Test_adjust_left_past_screen_width()
    " width of screen
    let X = join(map(range(&columns), {->'X'}), '')
  
--- 909,915 ----
    %bwipe!
  endfunc
  
! func Test_adjust_left_past_screen_width()
    " width of screen
    let X = join(map(range(&columns), {->'X'}), '')
  
***************
*** 973,976 ****
  
    popupclear
    %bwipe!
! endfunction
--- 973,1037 ----
  
    popupclear
    %bwipe!
! endfunc
! 
! func Test_popup_moved()
!   new
!   call test_override('char_avail', 1)
!   call setline(1, ['one word to move around', 'a WORD.and->some thing'])
! 
!   exe "normal gg0/word\<CR>"
!   let winid = popup_atcursor('text', {'moved': 'any'})
!   redraw
!   call assert_equal(1, popup_getpos(winid).visible)
!   " trigger the check for last_cursormoved by going into insert mode
!   call feedkeys("li\<Esc>", 'xt')
!   call assert_equal({}, popup_getpos(winid))
!   popupclear
! 
!   exe "normal gg0/word\<CR>"
!   let winid = popup_atcursor('text', {'moved': 'word'})
!   redraw
!   call assert_equal(1, popup_getpos(winid).visible)
!   call feedkeys("hi\<Esc>", 'xt')
!   call assert_equal({}, popup_getpos(winid))
!   popupclear
! 
!   exe "normal gg0/word\<CR>"
!   let winid = popup_atcursor('text', {'moved': 'word'})
!   redraw
!   call assert_equal(1, popup_getpos(winid).visible)
!   call feedkeys("li\<Esc>", 'xt')
!   call assert_equal(1, popup_getpos(winid).visible)
!   call feedkeys("ei\<Esc>", 'xt')
!   call assert_equal(1, popup_getpos(winid).visible)
!   call feedkeys("eli\<Esc>", 'xt')
!   call assert_equal({}, popup_getpos(winid))
!   popupclear
! 
!   exe "normal gg0/WORD\<CR>"
!   let winid = popup_atcursor('text', {'moved': 'WORD'})
!   redraw
!   call assert_equal(1, popup_getpos(winid).visible)
!   call feedkeys("eli\<Esc>", 'xt')
!   call assert_equal(1, popup_getpos(winid).visible)
!   call feedkeys("wi\<Esc>", 'xt')
!   call assert_equal(1, popup_getpos(winid).visible)
!   call feedkeys("Eli\<Esc>", 'xt')
!   call assert_equal({}, popup_getpos(winid))
!   popupclear
! 
!   exe "normal gg0/word\<CR>"
!   let winid = popup_atcursor('text', {'moved': [5, 10]})
!   redraw
!   call assert_equal(1, popup_getpos(winid).visible)
!   call feedkeys("eli\<Esc>", 'xt')
!   call feedkeys("ei\<Esc>", 'xt')
!   call assert_equal(1, popup_getpos(winid).visible)
!   call feedkeys("eli\<Esc>", 'xt')
!   call assert_equal({}, popup_getpos(winid))
!   popupclear
! 
!   bwipe!
!   call test_override('ALL', 0)
! endfunc
*** ../vim-8.1.1452/runtime/doc/popup.txt       2019-06-02 14:49:52.368891150 
+0200
--- runtime/doc/popup.txt       2019-06-02 17:30:33.520955494 +0200
***************
*** 90,96 ****
  
  IMPLEMENTATION:
  - Code is in popupwin.c
- - Fix positioning with border and padding.
  - Why does 'nrformats' leak from the popup window buffer???
  - Make redrawing more efficient and avoid flicker.
      First draw popups, creating a mask, use the mask in screen_line() when
--- 90,95 ----
***************
*** 410,422 ****
        zindex          Priority for the popup, default 50.
        time            Time in milliseconds after which the popup will close.
                        When omitted |popup_close()| must be used.
!       moved           "cell": close the popup if the cursor moved at least
!                       one screen cell.
!                       "word" allows for moving the cursor within |<cword>|
!                       "WORD" allows for moving the cursor within |<cWORD>|
!                       a list with two numbers specifies the start and end
!                       column outside of which the popup will close
!                       {not implemented yet}
        filter          A callback that can filter typed characters, see 
                        |popup-filter|.
        callback        A callback that is called when the popup closes, e.g.
--- 409,422 ----
        zindex          Priority for the popup, default 50.
        time            Time in milliseconds after which the popup will close.
                        When omitted |popup_close()| must be used.
!       moved           Specifies to close the popup if the cursor moved:
!                       - "any": if the cursor moved at all
!                       - "word": if the cursor moved outside |<cword>|
!                       - "WORD": if the cursor moved outside |<cWORD>|
!                       - [{start}, {end}]: if the cursor moved before column
!                         {start} or after {end}
!                       The popup also closes if the cursor moves to another
!                       line or to another window.
        filter          A callback that can filter typed characters, see 
                        |popup-filter|.
        callback        A callback that is called when the popup closes, e.g.
***************
*** 510,515 ****
--- 510,518 ----
  result, which could be an index in the popup lines, or whatever was passed as
  the second argument of `popup_close()`.
  
+ If the popup is closed because the cursor moved, the number -1 is passed to
+ the callback.
+ 
  ==============================================================================
  3. Examples                                           *popup-examples*
  
*** ../vim-8.1.1452/src/version.c       2019-06-02 16:51:18.011257964 +0200
--- src/version.c       2019-06-02 18:37:36.630426619 +0200
***************
*** 769,770 ****
--- 769,772 ----
  {   /* Add new patch number below this line */
+ /**/
+     1453,
  /**/

-- 
>From "know your smileys":
¯\_(ツ)_/¯   Shrug

 /// 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/201906021640.x52GeLm6000686%40masaka.moolenaar.net.
For more options, visit https://groups.google.com/d/optout.

Raspunde prin e-mail lui