changeset 17119:b439e096a011 v8.1.1559

patch 8.1.1559: popup window title property not implemented yet commit https://github.com/vim/vim/commit/eb2310d47d83764a61d63cd5c2788870d7f6eddf Author: Bram Moolenaar <Bram@vim.org> Date: Sun Jun 16 20:09:10 2019 +0200 patch 8.1.1559: popup window title property not implemented yet Problem: Popup window title property not implemented yet. Solution: Implement the title property.
author Bram Moolenaar <Bram@vim.org>
date Sun, 16 Jun 2019 20:15:05 +0200
parents 27642fa6eeee
children d6f065ba684d
files runtime/doc/popup.txt src/popupwin.c src/structs.h src/testdir/dumps/Test_popupwin_menu_01.dump src/testdir/dumps/Test_popupwin_menu_02.dump src/testdir/dumps/Test_popupwin_title.dump src/testdir/test_popupwin.vim src/version.c src/window.c
diffstat 9 files changed, 98 insertions(+), 26 deletions(-) [+]
line wrap: on
line diff
--- a/runtime/doc/popup.txt
+++ b/runtime/doc/popup.txt
@@ -112,7 +112,6 @@ TODO:
 	popup_setoptions({id}, {options})
 	hidden option
 	tabpage option with number
-	title option
 	flip option
 	transparent text property
 
@@ -452,8 +451,8 @@ The second argument of |popup_create()| 
 	title		Text to be displayed above the first item in the
 			popup, on top of any border.  If there is no top
 			border one line of padding is added to put the title
-			on.
-			{not implemented yet}
+			on.  You might want to add one or more spaces at the
+			start and end as padding.
 	wrap		TRUE to make the lines wrap (default TRUE).
 	drag		TRUE to allow the popup to be dragged with the mouse
 			by grabbing at at the border.  Has no effect if the
--- a/src/popupwin.c
+++ b/src/popupwin.c
@@ -294,6 +294,13 @@ apply_options(win_T *wp, buf_T *buf UNUS
 	set_string_option_direct_in_win(wp, (char_u *)"wincolor", -1,
 						   str, OPT_FREE|OPT_LOCAL, 0);
 
+    str = dict_get_string(dict, (char_u *)"title", FALSE);
+    if (str != NULL)
+    {
+	vim_free(wp->w_popup_title);
+	wp->w_popup_title = vim_strsave(str);
+    }
+
     wp->w_firstline = dict_get_number(dict, (char_u *)"firstline");
     if (wp->w_firstline < 1)
 	wp->w_firstline = 1;
@@ -532,6 +539,19 @@ popup_width(win_T *wp)
 }
 
 /*
+ * Get the padding plus border at the top, adjusted to 1 if there is a title.
+ */
+    static int
+popup_top_extra(win_T *wp)
+{
+    int	extra = wp->w_popup_border[0] + wp->w_popup_padding[0];
+
+    if (extra == 0 && wp->w_popup_title != NULL && *wp->w_popup_title != NUL)
+	return 1;
+    return extra;
+}
+
+/*
  * Adjust the position and size of the popup to fit on the screen.
  */
     void
@@ -543,7 +563,7 @@ popup_adjust_position(win_T *wp)
     int		center_vert = FALSE;
     int		center_hor = FALSE;
     int		allow_adjust_left = !wp->w_popup_fixed;
-    int		top_extra = wp->w_popup_border[0] + wp->w_popup_padding[0];
+    int		top_extra = popup_top_extra(wp);
     int		right_extra = wp->w_popup_border[1] + wp->w_popup_padding[1];
     int		bot_extra = wp->w_popup_border[2] + wp->w_popup_padding[2];
     int		left_extra = wp->w_popup_border[3] + wp->w_popup_padding[3];
@@ -553,6 +573,7 @@ popup_adjust_position(win_T *wp)
     int		org_wincol = wp->w_wincol;
     int		org_width = wp->w_width;
     int		org_height = wp->w_height;
+    int		minwidth;
 
     wp->w_winrow = 0;
     wp->w_wincol = 0;
@@ -646,8 +667,17 @@ popup_adjust_position(win_T *wp)
 	    break;
     }
 
-    if (wp->w_minwidth > 0 && wp->w_width < wp->w_minwidth)
-	wp->w_width = wp->w_minwidth;
+    minwidth = wp->w_minwidth;
+    if (wp->w_popup_title != NULL && *wp->w_popup_title != NUL)
+    {
+	int title_len = vim_strsize(wp->w_popup_title) + 2 - extra_width;
+
+	if (minwidth < title_len)
+	    minwidth = title_len;
+    }
+
+    if (minwidth > 0 && wp->w_width < minwidth)
+	wp->w_width = minwidth;
     if (wp->w_width > maxwidth)
 	wp->w_width = maxwidth;
     if (center_hor)
@@ -1384,7 +1414,7 @@ f_popup_getpos(typval_T *argvars, typval
     {
 	if (wp == NULL)
 	    return;  // invalid {id}
-	top_extra = wp->w_popup_border[0] + wp->w_popup_padding[0];
+	top_extra = popup_top_extra(wp);
 	left_extra = wp->w_popup_border[3] + wp->w_popup_padding[3];
 
 	dict = rettv->vval.v_dict;
@@ -1750,6 +1780,7 @@ update_popups(void (*win_update)(win_T *
     int	    left_off;
     int	    total_width;
     int	    total_height;
+    int	    top_padding;
     int	    popup_attr;
     int	    border_attr[4];
     int	    border_char[8];
@@ -1770,7 +1801,7 @@ update_popups(void (*win_update)(win_T *
 
 	// adjust w_winrow and w_wincol for border and padding, since
 	// win_update() doesn't handle them.
-	top_off = wp->w_popup_padding[0] + wp->w_popup_border[0];
+	top_off = popup_top_extra(wp);
 	left_off = wp->w_popup_padding[3] + wp->w_popup_border[3];
 	wp->w_winrow += top_off;
 	wp->w_wincol += left_off;
@@ -1783,7 +1814,7 @@ update_popups(void (*win_update)(win_T *
 
 	total_width = wp->w_popup_border[3] + wp->w_popup_padding[3]
 		+ wp->w_width + wp->w_popup_padding[1] + wp->w_popup_border[1];
-	total_height = wp->w_popup_border[0] + wp->w_popup_padding[0]
+	total_height = popup_top_extra(wp)
 		+ wp->w_height + wp->w_popup_padding[2] + wp->w_popup_border[2];
 	popup_attr = get_wcr_attr(wp);
 
@@ -1816,6 +1847,7 @@ update_popups(void (*win_update)(win_T *
 		border_attr[i] = syn_name2attr(wp->w_border_highlight[i]);
 	}
 
+	top_padding = wp->w_popup_padding[0];
 	if (wp->w_popup_border[0] > 0)
 	{
 	    // top border
@@ -1832,17 +1864,24 @@ update_popups(void (*win_update)(win_T *
 			       wp->w_wincol + total_width - 1, border_attr[1]);
 	    }
 	}
+	else if (wp->w_popup_padding[0] == 0 && popup_top_extra(wp) > 0)
+	    top_padding = 1;
 
-	if (wp->w_popup_padding[0] > 0)
+	if (top_padding > 0)
 	{
 	    // top padding
 	    row = wp->w_winrow + wp->w_popup_border[0];
-	    screen_fill(row, row + wp->w_popup_padding[0],
+	    screen_fill(row, row + top_padding,
 		    wp->w_wincol + wp->w_popup_border[3],
 		    wp->w_wincol + total_width - wp->w_popup_border[1],
 							 ' ', ' ', popup_attr);
 	}
 
+	// Title goes on top of border or padding.
+	if (wp->w_popup_title != NULL)
+	    screen_puts(wp->w_popup_title, wp->w_winrow, wp->w_wincol + 1,
+		    wp->w_popup_border[0] > 0 ? border_attr[0] : popup_attr);
+
 	for (row = wp->w_winrow + wp->w_popup_border[0];
 		row < wp->w_winrow + total_height - wp->w_popup_border[2];
 		    ++row)
--- a/src/structs.h
+++ b/src/structs.h
@@ -2891,6 +2891,7 @@ struct window_S
     pos_save_T	w_save_cursor;	    /* backup of cursor pos and topline */
 #ifdef FEAT_TEXT_PROP
     int		w_popup_flags;	    // POPF_ values
+    char_u	*w_popup_title;
     poppos_T	w_popup_pos;
     int		w_popup_fixed;	    // do not shift popup to fit on screen
     int		w_zindex;
--- a/src/testdir/dumps/Test_popupwin_menu_01.dump
+++ b/src/testdir/dumps/Test_popupwin_menu_01.dump
@@ -1,10 +1,10 @@
 >1+0&#ffffff0| @73
-|2| @30|╔+0#0000001#ffd7ff255|═@8|╗| +0#0000000#ffffff0@31
-|3| @30|║+0#0000001#ffd7ff255| @8|║| +0#0000000#ffffff0@31
-|4| @30|║+0#0000001#ffd7ff255| |o+0#0000000#5fd7ff255|n|e| +0#0000001#ffd7ff255@4|║| +0#0000000#ffffff0@31
-|5| @30|║+0#0000001#ffd7ff255| |t|w|o| @4|║| +0#0000000#ffffff0@31
-|6| @30|║+0#0000001#ffd7ff255| |a|n|o|t|h|e|r| |║| +0#0000000#ffffff0@31
-|7| @30|║+0#0000001#ffd7ff255| @8|║| +0#0000000#ffffff0@31
-|8| @30|╚+0#0000001#ffd7ff255|═@8|╝| +0#0000000#ffffff0@31
+|2| @20|╔+0#0000001#ffd7ff255| |m|a|k|e| |a| |c|h|o|i|c|e| |f|r|o|m| |t|h|e| |l|i|s|t| |╗| +0#0000000#ffffff0@21
+|3| @20|║+0#0000001#ffd7ff255| @28|║| +0#0000000#ffffff0@21
+|4| @20|║+0#0000001#ffd7ff255| |o+0#0000000#5fd7ff255|n|e| +0#0000001#ffd7ff255@24|║| +0#0000000#ffffff0@21
+|5| @20|║+0#0000001#ffd7ff255| |t|w|o| @24|║| +0#0000000#ffffff0@21
+|6| @20|║+0#0000001#ffd7ff255| |a|n|o|t|h|e|r| @20|║| +0#0000000#ffffff0@21
+|7| @20|║+0#0000001#ffd7ff255| @28|║| +0#0000000#ffffff0@21
+|8| @20|╚+0#0000001#ffd7ff255|═@28|╝| +0#0000000#ffffff0@21
 |9| @73
 @57|1|,|1| @10|T|o|p| 
--- a/src/testdir/dumps/Test_popupwin_menu_02.dump
+++ b/src/testdir/dumps/Test_popupwin_menu_02.dump
@@ -1,10 +1,10 @@
 >1+0&#ffffff0| @73
-|2| @30|╔+0#0000001#ffd7ff255|═@8|╗| +0#0000000#ffffff0@31
-|3| @30|║+0#0000001#ffd7ff255| @8|║| +0#0000000#ffffff0@31
-|4| @30|║+0#0000001#ffd7ff255| |o|n|e| @4|║| +0#0000000#ffffff0@31
-|5| @30|║+0#0000001#ffd7ff255| |t|w|o| @4|║| +0#0000000#ffffff0@31
-|6| @30|║+0#0000001#ffd7ff255| |a+0#0000000#5fd7ff255|n|o|t|h|e|r| +0#0000001#ffd7ff255|║| +0#0000000#ffffff0@31
-|7| @30|║+0#0000001#ffd7ff255| @8|║| +0#0000000#ffffff0@31
-|8| @30|╚+0#0000001#ffd7ff255|═@8|╝| +0#0000000#ffffff0@31
+|2| @20|╔+0#0000001#ffd7ff255| |m|a|k|e| |a| |c|h|o|i|c|e| |f|r|o|m| |t|h|e| |l|i|s|t| |╗| +0#0000000#ffffff0@21
+|3| @20|║+0#0000001#ffd7ff255| @28|║| +0#0000000#ffffff0@21
+|4| @20|║+0#0000001#ffd7ff255| |o|n|e| @24|║| +0#0000000#ffffff0@21
+|5| @20|║+0#0000001#ffd7ff255| |t|w|o| @24|║| +0#0000000#ffffff0@21
+|6| @20|║+0#0000001#ffd7ff255| |a+0#0000000#5fd7ff255|n|o|t|h|e|r| +0#0000001#ffd7ff255@20|║| +0#0000000#ffffff0@21
+|7| @20|║+0#0000001#ffd7ff255| @28|║| +0#0000000#ffffff0@21
+|8| @20|╚+0#0000001#ffd7ff255|═@28|╝| +0#0000000#ffffff0@21
 |9| @73
 @57|1|,|1| @10|T|o|p| 
new file mode 100644
--- /dev/null
+++ b/src/testdir/dumps/Test_popupwin_title.dump
@@ -0,0 +1,10 @@
+>1+0&#ffffff0| @73
+|2| @73
+|3| @73
+|4| @28| +0#0000001#ffd7ff255|T|i|t|l|e| |S|t|r|i|n|g| | +0#0000000#ffffff0@30
+|5| @28|o+0#0000001#ffd7ff255|n|e| @10| +0#0000000#ffffff0@30
+|6| @28|t+0#0000001#ffd7ff255|w|o| @10| +0#0000000#ffffff0@30
+|7| @28|a+0#0000001#ffd7ff255|n|o|t|h|e|r| @6| +0#0000000#ffffff0@30
+|8| @73
+|9| @73
+@57|1|,|1| @10|T|o|p| 
--- a/src/testdir/test_popupwin.vim
+++ b/src/testdir/test_popupwin.vim
@@ -940,7 +940,7 @@ func Test_popup_menu_screenshot()
   let lines =<< trim END
 	call setline(1, range(1, 20))
 	hi PopupSelected ctermbg=lightblue
-	call popup_menu(['one', 'two', 'another'], {'callback': 'MenuDone'})
+	call popup_menu(['one', 'two', 'another'], {'callback': 'MenuDone', 'title': ' make a choice from the list '})
 	func MenuDone(id, res)
 	  echomsg "selected " .. a:res
 	endfunc
@@ -960,6 +960,26 @@ func Test_popup_menu_screenshot()
   call delete('XtestPopupMenu')
 endfunc
 
+func Test_popup_title()
+  if !CanRunVimInTerminal()
+    throw 'Skipped: cannot make screendumps'
+  endif
+
+  " Create a popup without title or border, a line of padding will be added to
+  " put the title on.
+  let lines =<< trim END
+	call setline(1, range(1, 20))
+	call popup_create(['one', 'two', 'another'], {'title': 'Title String'})
+  END
+  call writefile(lines, 'XtestPopupTitle')
+  let buf = RunVimInTerminal('-S XtestPopupTitle', {'rows': 10})
+  call VerifyScreenDump(buf, 'Test_popupwin_title', {})
+
+  " clean up
+  call StopVimInTerminal(buf)
+  call delete('XtestPopupTitle')
+endfunc
+
 func Test_popup_close_callback()
   func PopupDone(id, result)
     let g:result = a:result
--- a/src/version.c
+++ b/src/version.c
@@ -778,6 +778,8 @@ static char *(features[]) =
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    1559,
+/**/
     1558,
 /**/
     1557,
--- a/src/window.c
+++ b/src/window.c
@@ -4857,6 +4857,7 @@ win_free(
     free_callback(&wp->w_filter_cb);
     for (i = 0; i < 4; ++i)
 	VIM_CLEAR(wp->w_border_highlight[i]);
+    vim_free(wp->w_popup_title);
 #endif
 
 #ifdef FEAT_SYN_HL