Patch 8.1.2265
Problem:    When popup with "botleft" does not fit it flips incorrectly.
Solution:   Only flip when there is more space on the other side.  Add the
            "posinvert" option to disable flipping and do it in both
            directions if enabled.  (closes #5151)
Files:      src/popupwin.c, src/testdir/test_popupwin.vim, src/vim.h,
            src/testdir/dumps/Test_popupwin_nospace.dump


*** ../vim-8.1.2264/src/popupwin.c      2019-11-03 22:29:19.469793561 +0100
--- src/popupwin.c      2019-11-06 19:17:46.571609017 +0100
***************
*** 673,678 ****
--- 673,688 ----
            wp->w_popup_flags &= ~POPF_DRAG;
      }
  
+     di = dict_find(dict, (char_u *)"posinvert", -1);
+     if (di != NULL)
+     {
+       nr = dict_get_number(dict, (char_u *)"posinvert");
+       if (nr)
+           wp->w_popup_flags |= POPF_POSINVERT;
+       else
+           wp->w_popup_flags &= ~POPF_POSINVERT;
+     }
+ 
      di = dict_find(dict, (char_u *)"resize", -1);
      if (di != NULL)
      {
***************
*** 1383,1397 ****
            wp->w_winrow = 0;
      }
      else if (wp->w_popup_pos == POPPOS_BOTRIGHT
!           || wp->w_popup_pos == POPPOS_BOTLEFT)
      {
        if ((wp->w_height + extra_height) <= wantline)
            // bottom aligned: may move down
            wp->w_winrow = wantline - (wp->w_height + extra_height);
        else
!           // Not enough space, make top aligned.
            wp->w_winrow = (wantline < 0 ? 0 : wantline) + 1;
      }
      if (wp->w_winrow >= Rows)
        wp->w_winrow = Rows - 1;
      else if (wp->w_winrow < 0)
--- 1393,1427 ----
            wp->w_winrow = 0;
      }
      else if (wp->w_popup_pos == POPPOS_BOTRIGHT
!               || wp->w_popup_pos == POPPOS_BOTLEFT)
      {
        if ((wp->w_height + extra_height) <= wantline)
            // bottom aligned: may move down
            wp->w_winrow = wantline - (wp->w_height + extra_height);
+       else if (wantline * 2 >= Rows || !(wp->w_popup_flags & POPF_POSINVERT))
+       {
+           // Bottom aligned but does not fit, and less space on the other
+           // side or "posinvert" is off: reduce height.
+           wp->w_winrow = 0;
+           wp->w_height = wantline - extra_height;
+       }
        else
!           // Not enough space and more space on the other side: make top
!           // aligned.
            wp->w_winrow = (wantline < 0 ? 0 : wantline) + 1;
      }
+     else if (wp->w_popup_pos == POPPOS_TOPRIGHT
+               || wp->w_popup_pos == POPPOS_TOPLEFT)
+     {
+       if (wantline + (wp->w_height + extra_height) - 1 > Rows
+               && wantline * 2 > Rows
+               && (wp->w_popup_flags & POPF_POSINVERT))
+           // top aligned and not enough space below but there is space above:
+           // make bottom aligned
+           wp->w_winrow = wantline - 2 - wp->w_height - extra_height;
+       else
+           wp->w_winrow = wantline - 1;
+     }
      if (wp->w_winrow >= Rows)
        wp->w_winrow = Rows - 1;
      else if (wp->w_winrow < 0)
***************
*** 1730,1736 ****
      if (rettv != NULL)
        rettv->vval.v_number = wp->w_id;
      wp->w_popup_pos = POPPOS_TOPLEFT;
!     wp->w_popup_flags = POPF_IS_POPUP | POPF_MAPPING;
  
      if (buf != NULL)
      {
--- 1760,1766 ----
      if (rettv != NULL)
        rettv->vval.v_number = wp->w_id;
      wp->w_popup_pos = POPPOS_TOPLEFT;
!     wp->w_popup_flags = POPF_IS_POPUP | POPF_MAPPING | POPF_POSINVERT;
  
      if (buf != NULL)
      {
***************
*** 2670,2675 ****
--- 2700,2707 ----
        dict_add_number(dict, "mapping",
                                      (wp->w_popup_flags & POPF_MAPPING) != 0);
        dict_add_number(dict, "resize", (wp->w_popup_flags & POPF_RESIZE) != 0);
+       dict_add_number(dict, "posinvert",
+                                   (wp->w_popup_flags & POPF_POSINVERT) != 0);
        dict_add_number(dict, "cursorline",
                                   (wp->w_popup_flags & POPF_CURSORLINE) != 0);
        dict_add_string(dict, "highlight", wp->w_p_wcr);
***************
*** 2830,2836 ****
  
      argv[2].v_type = VAR_UNKNOWN;
  
!     // NOTE: The callback might close the popup, thus 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);
--- 2862,2868 ----
  
      argv[2].v_type = VAR_UNKNOWN;
  
!     // 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);
*** ../vim-8.1.2264/src/testdir/test_popupwin.vim       2019-11-03 
22:29:19.469793561 +0100
--- src/testdir/test_popupwin.vim       2019-11-06 19:20:35.974855239 +0100
***************
*** 323,328 ****
--- 323,420 ----
    call delete('XtestPopupCorners')
  endfunc
  
+ func Test_popup_nospace()
+   CheckScreendump
+ 
+   let lines =<< trim END
+       call setline(1, repeat([repeat('-', 60)], 15))
+       set so=0
+ 
+       " cursor in a line in top half, using "botleft" with popup that
+       " does fit
+       normal 5G2|r@
+       let winid1 = popup_create(['one', 'two'], #{
+             \ line: 'cursor-1',
+             \ col: 'cursor',
+             \ pos: 'botleft',
+             \ border: [],
+             \ })
+       " cursor in a line in top half, using "botleft" with popup that
+       " doesn't fit: gets truncated
+       normal 5G9|r#
+       let winid1 = popup_create(['one', 'two', 'tee'], #{
+             \ line: 'cursor-1',
+             \ col: 'cursor',
+             \ pos: 'botleft',
+             \ posinvert: 0,
+             \ border: [],
+             \ })
+       " cursor in a line in top half, using "botleft" with popup that
+       " doesn't fit and 'posinvert' set: flips to below.
+       normal 5G16|r%
+       let winid1 = popup_create(['one', 'two', 'tee'], #{
+             \ line: 'cursor-1',
+             \ col: 'cursor',
+             \ pos: 'botleft',
+             \ border: [],
+             \ })
+       " cursor in a line in bottom half, using "botleft" with popup that
+       " doesn't fit: does not flip.
+       normal 8G23|r*
+       let winid1 = popup_create(['aaa', 'bbb', 'ccc', 'ddd', 'eee', 'fff'], #{
+             \ line: 'cursor-1',
+             \ col: 'cursor',
+             \ pos: 'botleft',
+             \ border: [],
+             \ })
+ 
+       " cursor in a line in bottom half, using "topleft" with popup that
+       " does fit
+       normal 8G30|r@
+       let winid1 = popup_create(['one', 'two'], #{
+             \ line: 'cursor+1',
+             \ col: 'cursor',
+             \ pos: 'topleft',
+             \ border: [],
+             \ })
+       " cursor in a line in top half, using "topleft" with popup that
+       " doesn't fit: truncated
+       normal 8G37|r#
+       let winid1 = popup_create(['one', 'two', 'tee'], #{
+             \ line: 'cursor+1',
+             \ col: 'cursor',
+             \ pos: 'topleft',
+             \ posinvert: 0,
+             \ border: [],
+             \ })
+       " cursor in a line in top half, using "topleft" with popup that
+       " doesn't fit and "posinvert" set: flips to below.
+       normal 8G44|r%
+       let winid1 = popup_create(['one', 'two', 'tee'], #{
+             \ line: 'cursor+1',
+             \ col: 'cursor',
+             \ pos: 'topleft',
+             \ border: [],
+             \ })
+       " cursor in a line in top half, using "topleft" with popup that
+       " doesn't fit: does not flip.
+       normal 5G51|r*
+       let winid1 = popup_create(['aaa', 'bbb', 'ccc', 'ddd', 'eee', 'fff'], #{
+             \ line: 'cursor+1',
+             \ col: 'cursor',
+             \ pos: 'topleft',
+             \ border: [],
+             \ })
+   END
+   call writefile(lines, 'XtestPopupNospace')
+   let buf = RunVimInTerminal('-S XtestPopupNospace', #{rows: 12})
+   call VerifyScreenDump(buf, 'Test_popupwin_nospace', {})
+ 
+   " clean up
+   call StopVimInTerminal(buf)
+   call delete('XtestPopupNospace')
+ endfunc
+ 
  func Test_popup_firstline()
    CheckScreendump
  
***************
*** 586,591 ****
--- 678,684 ----
            \], #{
            \ line: 1,
            \ col: 10,
+           \ posinvert: 0,
            \ wrap: 0,
            \ fixed: 1,
            \ zindex: 90,
***************
*** 604,609 ****
--- 697,703 ----
            \], #{
            \ line: 7,
            \ col: 10,
+           \ posinvert: 0,
            \ wrap: 0,
            \ fixed: 1,
            \ close: 'button',
*** ../vim-8.1.2264/src/vim.h   2019-11-02 22:54:37.409188799 +0100
--- src/vim.h   2019-11-06 18:30:24.227318430 +0100
***************
*** 632,637 ****
--- 632,638 ----
  #define POPF_MAPPING  0x80    // mapping keys
  #define POPF_INFO     0x100   // used for info of popup menu
  #define POPF_INFO_MENU        0x200   // align info popup with popup menu
+ #define POPF_POSINVERT        0x400   // vertical position can be inverted
  
  #ifdef FEAT_TEXT_PROP
  # define WIN_IS_POPUP(wp) ((wp)->w_popup_flags != 0)
*** ../vim-8.1.2264/src/testdir/dumps/Test_popupwin_nospace.dump        
2019-11-06 19:24:23.249873836 +0100
--- src/testdir/dumps/Test_popupwin_nospace.dump        2019-11-06 
19:01:00.531770824 +0100
***************
*** 0 ****
--- 1,12 ----
+ 
|-+0&#ffffff0|╔+0#0000001#ffd7ff255|═@2|╗|-+0#0000000#ffffff0@1|╔+0#0000001#ffd7ff255|═@2|╗|-+0#0000000#ffffff0@8|╔+0#0000001#ffd7ff255|═@2|╗|-+0#0000000#ffffff0@32|
 @14
+ 
|-|║+0#0000001#ffd7ff255|o|n|e|║|-+0#0000000#ffffff0@1|║+0#0000001#ffd7ff255|o|n|e|║|-+0#0000000#ffffff0@8|║+0#0000001#ffd7ff255|a@2|║|-+0#0000000#ffffff0@32|
 @14
+ 
|-|║+0#0000001#ffd7ff255|t|w|o|║|-+0#0000000#ffffff0@1|║+0#0000001#ffd7ff255|t|w|o|║|-+0#0000000#ffffff0@8|║+0#0000001#ffd7ff255|b@2|║|-+0#0000000#ffffff0@15|╔+0#0000001#ffd7ff255|═@2|╗|-+0#0000000#ffffff0@11|
 @14
+ 
|-|╚+0#0000001#ffd7ff255|═@2|╝|-+0#0000000#ffffff0@1|╚+0#0000001#ffd7ff255|═@2|╝|-+0#0000000#ffffff0@8|║+0#0000001#ffd7ff255|c@2|║|-+0#0000000#ffffff0@15|║+0#0000001#ffd7ff255|o|n|e|║|-+0#0000000#ffffff0@11|
 @14
+ 
|-|@|-@5|#|-@5|%|-@5|║+0#0000001#ffd7ff255|d@2|║|-+0#0000000#ffffff0@15|║+0#0000001#ffd7ff255|t|w|o|║|-+0#0000000#ffffff0@1>*|-@8|
 @14
+ 
|-@14|╔+0#0000001#ffd7ff255|═@2|╗|-+0#0000000#ffffff0@1|║+0#0000001#ffd7ff255|e@2|║|-+0#0000000#ffffff0@15|║+0#0000001#ffd7ff255|t|e@1|║|-+0#0000000#ffffff0@1|╔+0#0000001#ffd7ff255|═@2|╗|-+0#0000000#ffffff0@4|
 @14
+ 
|-@14|║+0#0000001#ffd7ff255|o|n|e|║|-+0#0000000#ffffff0@1|╚+0#0000001#ffd7ff255|═@2|╝|-+0#0000000#ffffff0@15|╚+0#0000001#ffd7ff255|═@2|╝|-+0#0000000#ffffff0@1|║+0#0000001#ffd7ff255|a@2|║|-+0#0000000#ffffff0@4|
 @14
+ 
|-@14|║+0#0000001#ffd7ff255|t|w|o|║|-+0#0000000#ffffff0@1|*|-@5|@|-@5|#|-@5|%|-@5|║+0#0000001#ffd7ff255|b@2|║|-+0#0000000#ffffff0@4|
 @14
+ 
|-@14|║+0#0000001#ffd7ff255|t|e@1|║|-+0#0000000#ffffff0@8|╔+0#0000001#ffd7ff255|═@2|╗|-+0#0000000#ffffff0@1|╔+0#0000001#ffd7ff255|═@2|╗|-+0#0000000#ffffff0@8|║+0#0000001#ffd7ff255|c@2|║|-+0#0000000#ffffff0@4|
 @14
+ 
|-@14|╚+0#0000001#ffd7ff255|═@2|╝|-+0#0000000#ffffff0@8|║+0#0000001#ffd7ff255|o|n|e|║|-+0#0000000#ffffff0@1|║+0#0000001#ffd7ff255|o|n|e|║|-+0#0000000#ffffff0@8|║+0#0000001#ffd7ff255|d@2|║|-+0#0000000#ffffff0@4|
 @14
+ 
|-@28|║+0#0000001#ffd7ff255|t|w|o|║|-+0#0000000#ffffff0@1|║+0#0000001#ffd7ff255|t|w|o|║|-+0#0000000#ffffff0@8|║+0#0000001#ffd7ff255|e@2|║|-+0#0000000#ffffff0@4|
 @14
+ @29|╚+0#0000001#ffd7ff255|═@2|╝| 
+0#0000000#ffffff0@1|║+0#0000001#ffd7ff255|t|e@1|║| 
+0#0000000#ffffff0@8|║+0#0000001#ffd7ff255|f@2|║| +0#0000000#ffffff0@1|5|,|5|1| 
@9|T|o|p| 
*** ../vim-8.1.2264/src/version.c       2019-11-06 15:21:56.720396416 +0100
--- src/version.c       2019-11-06 19:03:12.831241148 +0100
***************
*** 743,744 ****
--- 743,746 ----
  {   /* Add new patch number below this line */
+ /**/
+     2265,
  /**/

-- 
A day without sunshine is like, well, night.

 /// 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/201911061826.xA6IQKE2013802%40masaka.moolenaar.net.

Raspunde prin e-mail lui