Patch 8.1.0062
Problem:    Popup menu broken if a callback changes the window layout. (Qiming
            Zhao)
Solution:   Recompute the popup menu position if needed.  Redraw the ruler
            even when the popup menu is displayed.
Files:      src/popupmnu.c, src/proto/popupmnu.pro, src/screen.c


*** ../vim-8.1.0061/src/popupmnu.c      2018-05-14 23:05:31.000000000 +0200
--- src/popupmnu.c      2018-06-17 14:41:52.487403691 +0200
***************
*** 29,34 ****
--- 29,40 ----
  static int pum_row;                   /* top row of pum */
  static int pum_col;                   /* left column of pum */
  
+ static int pum_win_row;
+ static int pum_win_height;
+ static int pum_win_col;
+ static int pum_win_wcol;
+ static int pum_win_width;
+ 
  static int pum_do_redraw = FALSE;     /* do redraw anyway */
  
  static int pum_set_selected(int n, int repeat);
***************
*** 81,87 ****
  {
      int               def_width;
      int               max_width;
-     int               row;
      int               context_lines;
      int               cursor_col;
      int               above_row;
--- 87,92 ----
***************
*** 103,109 ****
        validate_cursor_col();
        pum_array = NULL;
  
!       row = curwin->w_wrow + W_WINROW(curwin);
  
  #if defined(FEAT_QUICKFIX)
        FOR_ALL_WINDOWS(pvwin)
--- 108,120 ----
        validate_cursor_col();
        pum_array = NULL;
  
!       // Remember the essential parts of the window position and size, so we
!       // can decide when to reposition the popup menu.
!       pum_win_row = curwin->w_wrow + W_WINROW(curwin);
!       pum_win_height = curwin->w_height;
!       pum_win_col = curwin->w_wincol;
!       pum_win_wcol = curwin->w_wcol;
!       pum_win_width = curwin->w_width;
  
  #if defined(FEAT_QUICKFIX)
        FOR_ALL_WINDOWS(pvwin)
***************
*** 128,139 ****
        if (p_ph > 0 && pum_height > p_ph)
            pum_height = p_ph;
  
!       /* Put the pum below "row" if possible.  If there are few lines decide
         * on where there is more room. */
!       if (row + 2 >= below_row - pum_height
!                             && row - above_row > (below_row - above_row) / 2)
        {
!           /* pum above "row" */
  
            /* Leave two lines of context if possible */
            if (curwin->w_wrow - curwin->w_cline_row >= 2)
--- 139,150 ----
        if (p_ph > 0 && pum_height > p_ph)
            pum_height = p_ph;
  
!       /* Put the pum below "pum_win_row" if possible.  If there are few lines 
decide
         * on where there is more room. */
!       if (pum_win_row + 2 >= below_row - pum_height
!                     && pum_win_row - above_row > (below_row - above_row) / 2)
        {
!           /* pum above "pum_win_row" */
  
            /* Leave two lines of context if possible */
            if (curwin->w_wrow - curwin->w_cline_row >= 2)
***************
*** 141,155 ****
            else
                context_lines = curwin->w_wrow - curwin->w_cline_row;
  
!           if (row >= size + context_lines)
            {
!               pum_row = row - size - context_lines;
                pum_height = size;
            }
            else
            {
                pum_row = 0;
!               pum_height = row - context_lines;
            }
            if (p_ph > 0 && pum_height > p_ph)
            {
--- 152,166 ----
            else
                context_lines = curwin->w_wrow - curwin->w_cline_row;
  
!           if (pum_win_row >= size + context_lines)
            {
!               pum_row = pum_win_row - size - context_lines;
                pum_height = size;
            }
            else
            {
                pum_row = 0;
!               pum_height = pum_win_row - context_lines;
            }
            if (p_ph > 0 && pum_height > p_ph)
            {
***************
*** 159,165 ****
        }
        else
        {
!           /* pum below "row" */
  
            /* Leave two lines of context if possible */
            if (curwin->w_cline_row
--- 170,176 ----
        }
        else
        {
!           /* pum below "pum_win_row" */
  
            /* Leave two lines of context if possible */
            if (curwin->w_cline_row
***************
*** 169,175 ****
                context_lines = curwin->w_cline_row
                                    + curwin->w_cline_height - curwin->w_wrow;
  
!           pum_row = row + context_lines;
            if (size > below_row - pum_row)
                pum_height = below_row - pum_row;
            else
--- 180,186 ----
                context_lines = curwin->w_cline_row
                                    + curwin->w_cline_height - curwin->w_wrow;
  
!           pum_row = pum_win_row + context_lines;
            if (size > below_row - pum_row)
                pum_height = below_row - pum_row;
            else
***************
*** 823,828 ****
--- 834,875 ----
  }
  
  /*
+  * Reposition the popup menu to adjust for window layout changes.
+  */
+     void
+ pum_may_redraw(void)
+ {
+     pumitem_T *array = pum_array;
+     int               len = pum_size;
+     int               selected = pum_selected;
+ 
+     if (!pum_visible())
+       return;  // nothing to do
+ 
+     if (pum_win_row == curwin->w_wrow + W_WINROW(curwin)
+           && pum_win_height == curwin->w_height
+           && pum_win_col == curwin->w_wincol
+           && pum_win_width == curwin->w_width)
+     {
+       // window position didn't change, redraw in the same position
+       pum_redraw();
+     }
+     else
+     {
+       int wcol = curwin->w_wcol;
+ 
+       // Window layout changed, recompute the position.
+       // Use the remembered w_wcol value, the cursor may have moved when a
+       // completion was inserted, but we want the menu in the same position.
+       pum_undisplay();
+       curwin->w_wcol = pum_win_wcol;
+       curwin->w_valid |= VALID_WCOL;
+       pum_display(array, len, selected);
+       curwin->w_wcol = wcol;
+     }
+ }
+ 
+ /*
   * Return the height of the popup menu, the number of entries visible.
   * Only valid when pum_visible() returns TRUE!
   */
*** ../vim-8.1.0061/src/proto/popupmnu.pro      2018-05-17 13:52:48.000000000 
+0200
--- src/proto/popupmnu.pro      2018-06-17 14:12:56.177812770 +0200
***************
*** 4,9 ****
--- 4,10 ----
  void pum_undisplay(void);
  void pum_clear(void);
  int pum_visible(void);
+ void pum_may_redraw(void);
  int pum_get_height(void);
  int split_message(char_u *mesg, pumitem_T **array);
  void ui_remove_balloon(void);
*** ../vim-8.1.0061/src/screen.c        2018-06-16 16:20:48.768597967 +0200
--- src/screen.c        2018-06-17 14:37:49.760753642 +0200
***************
*** 171,177 ****
  static void win_redr_custom(win_T *wp, int draw_ruler);
  #endif
  #ifdef FEAT_CMDL_INFO
! static void win_redr_ruler(win_T *wp, int always);
  #endif
  
  /* Ugly global: overrule attribute used by screen_char() */
--- 171,177 ----
  static void win_redr_custom(win_T *wp, int draw_ruler);
  #endif
  #ifdef FEAT_CMDL_INFO
! static void win_redr_ruler(win_T *wp, int always, int ignore_pum);
  #endif
  
  /* Ugly global: overrule attribute used by screen_char() */
***************
*** 783,790 ****
  #endif
  #ifdef FEAT_INS_EXPAND
      /* May need to redraw the popup menu. */
!     if (pum_visible())
!       pum_redraw();
  #endif
  
      /* Reset b_mod_set flags.  Going through all windows is probably faster
--- 783,789 ----
  #endif
  #ifdef FEAT_INS_EXPAND
      /* May need to redraw the popup menu. */
!     pum_may_redraw();
  #endif
  
      /* Reset b_mod_set flags.  Going through all windows is probably faster
***************
*** 7002,7008 ****
                                                   - 1 + wp->w_wincol), attr);
  
  #ifdef FEAT_CMDL_INFO
!       win_redr_ruler(wp, TRUE);
  #endif
      }
  
--- 7001,7007 ----
                                                   - 1 + wp->w_wincol), attr);
  
  #ifdef FEAT_CMDL_INFO
!       win_redr_ruler(wp, TRUE, ignore_pum);
  #endif
      }
  
***************
*** 10455,10461 ****
      /* If the last window has no status line, the ruler is after the mode
       * message and must be redrawn */
      if (redrawing() && lastwin->w_status_height == 0)
!       win_redr_ruler(lastwin, TRUE);
  #endif
      redraw_cmdline = FALSE;
      clear_cmdline = FALSE;
--- 10454,10460 ----
      /* If the last window has no status line, the ruler is after the mode
       * message and must be redrawn */
      if (redrawing() && lastwin->w_status_height == 0)
!       win_redr_ruler(lastwin, TRUE, FALSE);
  #endif
      redraw_cmdline = FALSE;
      clear_cmdline = FALSE;
***************
*** 10874,10879 ****
--- 10873,10879 ----
                                                     (int)wp->w_width, FALSE);
  }
  #endif
+ 
  /*
   * Show current status info in ruler and various other places
   * If always is FALSE, only show ruler if position has changed.
***************
*** 10899,10905 ****
      else
  #endif
  #ifdef FEAT_CMDL_INFO
!       win_redr_ruler(curwin, always);
  #endif
  
  #ifdef FEAT_TITLE
--- 10899,10905 ----
      else
  #endif
  #ifdef FEAT_CMDL_INFO
!       win_redr_ruler(curwin, always, FALSE);
  #endif
  
  #ifdef FEAT_TITLE
***************
*** 10918,10924 ****
  
  #ifdef FEAT_CMDL_INFO
      static void
! win_redr_ruler(win_T *wp, int always)
  {
  #define RULER_BUF_LEN 70
      char_u    buffer[RULER_BUF_LEN];
--- 10918,10924 ----
  
  #ifdef FEAT_CMDL_INFO
      static void
! win_redr_ruler(win_T *wp, int always, int ignore_pum)
  {
  #define RULER_BUF_LEN 70
      char_u    buffer[RULER_BUF_LEN];
***************
*** 10951,10958 ****
      if (wp == lastwin && lastwin->w_status_height == 0)
        if (edit_submode != NULL)
            return;
!     /* Don't draw the ruler when the popup menu is visible, it may overlap. */
!     if (pum_visible())
        return;
  #endif
  
--- 10951,10959 ----
      if (wp == lastwin && lastwin->w_status_height == 0)
        if (edit_submode != NULL)
            return;
!     // Don't draw the ruler when the popup menu is visible, it may overlap.
!     // Except when the popup menu will be redrawn anyway.
!     if (!ignore_pum && pum_visible())
        return;
  #endif
  
*** ../vim-8.1.0061/src/version.c       2018-06-16 22:58:11.791025515 +0200
--- src/version.c       2018-06-17 14:39:53.964061772 +0200
***************
*** 763,764 ****
--- 763,766 ----
  {   /* Add new patch number below this line */
+ /**/
+     62,
  /**/

-- 
hundred-and-one symptoms of being an internet addict:
58. You turn on your computer and turn off your wife.

 /// 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].
For more options, visit https://groups.google.com/d/optout.

Raspunde prin e-mail lui