diff src/popupwin.c @ 18542:244b336b94ce v8.1.2265

patch 8.1.2265: when popup with "botleft" does not fit it flips incorrectly Commit: https://github.com/vim/vim/commit/638a4a7508082f8700b135953e4f9465f675a0f5 Author: Bram Moolenaar <Bram@vim.org> Date: Wed Nov 6 19:25:22 2019 +0100 patch 8.1.2265: when popup with "botleft" does not fit it flips incorrectly 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)
author Bram Moolenaar <Bram@vim.org>
date Wed, 06 Nov 2019 19:30:03 +0100
parents e855058e0c23
children a6dbbedddce1
line wrap: on
line diff
--- a/src/popupwin.c
+++ b/src/popupwin.c
@@ -673,6 +673,16 @@ apply_general_options(win_T *wp, dict_T 
 	    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,15 +1393,35 @@ popup_adjust_position(win_T *wp)
 	    wp->w_winrow = 0;
     }
     else if (wp->w_popup_pos == POPPOS_BOTRIGHT
-	    || wp->w_popup_pos == POPPOS_BOTLEFT)
+		|| 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, make top aligned.
+	    // 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,7 +1760,7 @@ popup_create(typval_T *argvars, typval_T
     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;
+    wp->w_popup_flags = POPF_IS_POPUP | POPF_MAPPING | POPF_POSINVERT;
 
     if (buf != NULL)
     {
@@ -2670,6 +2700,8 @@ f_popup_getoptions(typval_T *argvars, ty
 	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,7 +2862,7 @@ invoke_popup_filter(win_T *wp, int c)
 
     argv[2].v_type = VAR_UNKNOWN;
 
-    // NOTE: The callback might close the popup, thus make "wp" invalid.
+    // 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);