# HG changeset patch # User Bram Moolenaar # Date 1559421005 -7200 # Node ID ec61b6b79865b8a2adda1a80b3d62038451a0b3e # Parent a8aa4c4ffa4ada581908b468c73395c668de08ef patch 8.1.1445: popup window border highlight not implemented yet commit https://github.com/vim/vim/commit/790498b509443f96f39431d2bc87b777efbe250f Author: Bram Moolenaar Date: Sat Jun 1 22:15:29 2019 +0200 patch 8.1.1445: popup window border highlight not implemented yet Problem: Popup window border highlight not implemented yet. Solution: Implement the "borderhighlight" option. diff --git a/runtime/doc/popup.txt b/runtime/doc/popup.txt --- a/runtime/doc/popup.txt +++ b/runtime/doc/popup.txt @@ -368,15 +368,19 @@ The second argument of |popup_create()| border list with numbers, defining the border thickness above/right/below/left of the popup (similar to CSS); only values of zero and non-zero are recognized; - an empty list uses a border of 1 all around - borderhighlight highlight group name to use for the border - {not implemented yet} + an empty list uses a border all around + borderhighlight list of highlight group names to use for the border; + when one entry it is used for all borders, otherwise + the highlight for the top/right/bottom/left border borderchars list with characters, defining the character to use for the top/right/bottom/left border; optionally followed by the character to use for the - topright/botright/botleft/topleft corner; an empty - list can be used to show a double line all around - {not implemented yet} + topleft/topright/botright/botleft corner; when the + list has one character it is used for all; when + the list has two characters the first is used for the + border lines, the second for the corners; by default + a double line is used all around when 'encoding' is + "utf-8", otherwise ASCII characters are used. zindex priority for the popup, default 50 time time in milliseconds after which the popup will close; when omitted |popup_close()| must be used. diff --git a/src/popupwin.c b/src/popupwin.c --- a/src/popupwin.c +++ b/src/popupwin.c @@ -144,6 +144,7 @@ apply_options(win_T *wp, buf_T *buf UNUS int nr; char_u *str; dictitem_T *di; + int i; wp->w_minwidth = dict_get_number(dict, (char_u *)"minwidth"); wp->w_minheight = dict_get_number(dict, (char_u *)"minheight"); @@ -211,6 +212,66 @@ apply_options(win_T *wp, buf_T *buf UNUS get_padding_border(dict, wp->w_popup_padding, "padding", 999); get_padding_border(dict, wp->w_popup_border, "border", 1); + + for (i = 0; i < 4; ++i) + VIM_CLEAR(wp->w_border_highlight[i]); + di = dict_find(dict, (char_u *)"borderhighlight", -1); + if (di != NULL) + { + if (di->di_tv.v_type != VAR_LIST) + emsg(_(e_listreq)); + else + { + list_T *list = di->di_tv.vval.v_list; + listitem_T *li; + + if (list != NULL) + for (i = 0, li = list->lv_first; i < 4 && i < list->lv_len; + ++i, li = li->li_next) + { + str = tv_get_string(&li->li_tv); + if (*str != NUL) + wp->w_border_highlight[i] = vim_strsave(str); + } + if (list->lv_len == 1 && wp->w_border_highlight[0] != NULL) + for (i = 1; i < 4; ++i) + wp->w_border_highlight[i] = + vim_strsave(wp->w_border_highlight[0]); + } + } + + for (i = 0; i < 8; ++i) + wp->w_border_char[i] = 0; + di = dict_find(dict, (char_u *)"borderchars", -1); + if (di != NULL) + { + if (di->di_tv.v_type != VAR_LIST) + emsg(_(e_listreq)); + else + { + list_T *list = di->di_tv.vval.v_list; + listitem_T *li; + + if (list != NULL) + for (i = 0, li = list->lv_first; i < 8 && i < list->lv_len; + ++i, li = li->li_next) + { + str = tv_get_string(&li->li_tv); + if (*str != NUL) + wp->w_border_char[i] = mb_ptr2char(str); + } + if (list->lv_len == 1) + for (i = 1; i < 8; ++i) + wp->w_border_char[i] = wp->w_border_char[0]; + if (list->lv_len == 2) + { + for (i = 4; i < 8; ++i) + wp->w_border_char[i] = wp->w_border_char[1]; + for (i = 1; i < 4; ++i) + wp->w_border_char[i] = wp->w_border_char[0]; + } + } + } } /* diff --git a/src/screen.c b/src/screen.c --- a/src/screen.c +++ b/src/screen.c @@ -1030,13 +1030,11 @@ update_popups(void) int total_width; int total_height; int popup_attr; + int border_attr[4]; + int border_char[8] = {'-', '|', '-', '|', '+', '+', '+', '+', }; + char_u buf[MB_MAXBYTES]; int row; - int tl_corner_char = '+'; - char *tr_corner_str = "+"; - int bl_corner_char = '+'; - char *br_corner_str = "+"; - int hor_line_char = '-'; - char *ver_line_str = "|"; + int i; // Find the window with the lowest zindex that hasn't been updated yet, // so that the window with a higher zindex is drawn later, thus goes on @@ -1070,12 +1068,22 @@ update_popups(void) if (enc_utf8) { - tl_corner_char = 0x2554; - tr_corner_str = "\xe2\x95\x97"; - bl_corner_char = 0x255a; - br_corner_str = "\xe2\x95\x9d"; - hor_line_char = 0x2550; - ver_line_str = "\xe2\x95\x91"; + border_char[0] = border_char[2] = 0x2550; + border_char[1] = border_char[3] = 0x2551; + border_char[4] = 0x2554; + border_char[5] = 0x2557; + border_char[6] = 0x255d; + border_char[7] = 0x255a; + } + for (i = 0; i < 8; ++i) + if (wp->w_border_char[i] != 0) + border_char[i] = wp->w_border_char[i]; + + for (i = 0; i < 4; ++i) + { + border_attr[i] = popup_attr; + if (wp->w_border_highlight[i] != NULL) + border_attr[i] = syn_name2attr(wp->w_border_highlight[i]); } if (wp->w_popup_border[0] > 0) @@ -1085,11 +1093,14 @@ update_popups(void) wp->w_wincol, wp->w_wincol + total_width, wp->w_popup_border[3] != 0 - ? tl_corner_char : hor_line_char, - hor_line_char, popup_attr); + ? border_char[4] : border_char[0], + border_char[0], border_attr[0]); if (wp->w_popup_border[1] > 0) - screen_puts((char_u *)tr_corner_str, wp->w_winrow, - wp->w_wincol + total_width - 1, popup_attr); + { + buf[mb_char2bytes(border_char[5], buf)] = NUL; + screen_puts(buf, wp->w_winrow, + wp->w_wincol + total_width - 1, border_attr[1]); + } } if (wp->w_popup_padding[0] > 0) @@ -1108,15 +1119,21 @@ update_popups(void) { // left border if (wp->w_popup_border[3] > 0) - screen_puts((char_u *)ver_line_str, row, wp->w_wincol, popup_attr); + { + buf[mb_char2bytes(border_char[3], buf)] = NUL; + screen_puts(buf, row, wp->w_wincol, border_attr[3]); + } // left padding if (wp->w_popup_padding[3] > 0) screen_puts(get_spaces(wp->w_popup_padding[3]), row, wp->w_wincol + wp->w_popup_border[3], popup_attr); // right border if (wp->w_popup_border[1] > 0) - screen_puts((char_u *)ver_line_str, row, - wp->w_wincol + total_width - 1, popup_attr); + { + buf[mb_char2bytes(border_char[1], buf)] = NUL; + screen_puts(buf, row, + wp->w_wincol + total_width - 1, border_attr[1]); + } // right padding if (wp->w_popup_padding[1] > 0) screen_puts(get_spaces(wp->w_popup_padding[1]), row, @@ -1142,11 +1159,15 @@ update_popups(void) screen_fill(row , row + 1, wp->w_wincol, wp->w_wincol + total_width, - wp->w_popup_border[3] != 0 ? bl_corner_char : hor_line_char, - hor_line_char, popup_attr); + wp->w_popup_border[3] != 0 + ? border_char[7] : border_char[2], + border_char[2], border_attr[2]); if (wp->w_popup_border[1] > 0) - screen_puts((char_u *)br_corner_str, row, - wp->w_wincol + total_width - 1, popup_attr); + { + buf[mb_char2bytes(border_char[6], buf)] = NUL; + screen_puts(buf, row, + wp->w_wincol + total_width - 1, border_attr[2]); + } } } } diff --git a/src/structs.h b/src/structs.h --- a/src/structs.h +++ b/src/structs.h @@ -2890,6 +2890,8 @@ struct window_S int w_wantcol; // "col" for popup window int w_popup_padding[4]; // popup padding top/right/bot/left int w_popup_border[4]; // popup border top/right/bot/left + char_u *w_border_highlight[4]; // popup border highlight + int w_border_char[8]; // popup border characters varnumber_T w_popup_last_changedtick; // b:changedtick when position was // computed callback_T w_filter_cb; // popup filter callback diff --git a/src/testdir/dumps/Test_popupwin_22.dump b/src/testdir/dumps/Test_popupwin_22.dump new file mode 100644 --- /dev/null +++ b/src/testdir/dumps/Test_popupwin_22.dump @@ -0,0 +1,12 @@ +>1+0&#ffffff0| @73 +|2| |╔+0fd7ff255|═@11|╗| +0&#ffffff0@5|╔+0&#dadada255|═@11|╗+0a8a8a255| +0&#ffffff0@5|x+0fd7ff255@13| +0&#ffffff0@2|#+0fd7ff255|x@11|#| +0&#ffffff0@1 +|3| |║+0fd7ff255|h+0#0000001#ffd7ff255|e|l@1|o| |b|o|r|d|e|r|║+0#0000000#5fd7ff255| +0&#ffffff0@5|║+0&#a8a8a8255|h+0#0000001#ffd7ff255|e|l@1|o| |b|o|r|d|e|r|║+0#0000000#8a8a8a255| +0&#ffffff0@5|x+0fd7ff255|h+0#0000001#ffd7ff255|e|l@1|o| |b|o|r|d|e|r|x+0#0000000#5fd7ff255| +0&#ffffff0@2|x+0fd7ff255|h+0#0000001#ffd7ff255|e|l@1|o| |b|o|r|d|e|r|x+0#0000000#5fd7ff255| +0&#ffffff0@1 +|4| |╚+0fd7ff255|═@11|╝| +0&#ffffff0@5|║+0&#a8a8a8255|a+0#0000001#ffd7ff255|n|d| |m|o|r|e| @3|║+0#0000000#8a8a8a255| +0&#ffffff0@5|x+0fd7ff255|l+0#0000001#ffd7ff255|i|n|e|s| |o|n|l|y| @1|x+0#0000000#5fd7ff255| +0&#ffffff0@2|x+0fd7ff255|w+0#0000001#ffd7ff255|i|t|h| |c|o|r|n|e|r|s|x+0#0000000#5fd7ff255| +0&#ffffff0@1 +|5| @20|╚+0�|═@11|╝| +0&#ffffff0@5|x+0fd7ff255@13| +0&#ffffff0@2|#+0fd7ff255|x@11|#| +0&#ffffff0@1 +|6| |4+0fd7ff255|0@11|5| +0&#ffffff0@58 +|7| |3+0fd7ff255|h+0#0000001#ffd7ff255|e|l@1|o| |b|o|r|d|e|r|1+0#0000000#5fd7ff255| +0&#ffffff0@5| +0fd7ff255@13| +0&#ffffff0@38 +|8| |3+0fd7ff255|w+0#0000001#ffd7ff255|i|t|h| |n|u|m|b|e|r|s|1+0#0000000#5fd7ff255| +0&#ffffff0@5| +0fd7ff255|h+0#0000001#ffd7ff255|e|l@1|o| |b|o|r|d|e|r| +0#0000000#5fd7ff255| +0&#ffffff0@38 +|9| |7+0fd7ff255|2@11|6| +0&#ffffff0@5| +0fd7ff255|j+0#0000001#ffd7ff255|u|s|t| |b|l|a|n|k|s| | +0#0000000#5fd7ff255| +0&#ffffff0@38 +|1|0| @19| +0fd7ff255@13| +0&#ffffff0@38 +|1@1| @72 +@57|1|,|1| @10|T|o|p| diff --git a/src/testdir/test_popupwin.vim b/src/testdir/test_popupwin.vim --- a/src/testdir/test_popupwin.vim +++ b/src/testdir/test_popupwin.vim @@ -77,6 +77,26 @@ func Test_popup_with_border_and_padding( call delete('XtestPopupBorder') endfor + call writefile([ + \ "call setline(1, range(1, 100))", + \ "hi BlueColor ctermbg=lightblue", + \ "hi TopColor ctermbg=253", + \ "hi RightColor ctermbg=245", + \ "hi BottomColor ctermbg=240", + \ "hi LeftColor ctermbg=248", + \ "call popup_create('hello border', {'line': 2, 'col': 3, 'border': [], 'borderhighlight': ['BlueColor']})", + \ "call popup_create(['hello border', 'and more'], {'line': 2, 'col': 23, 'border': [], 'borderhighlight': ['TopColor', 'RightColor', 'BottomColor', 'LeftColor']})", + \ "call popup_create(['hello border', 'lines only'], {'line': 2, 'col': 43, 'border': [], 'borderhighlight': ['BlueColor'], 'borderchars': ['x']})", + \ "call popup_create(['hello border', 'with corners'], {'line': 2, 'col': 60, 'border': [], 'borderhighlight': ['BlueColor'], 'borderchars': ['x', '#']})", + \ "call popup_create(['hello border', 'with numbers'], {'line': 6, 'col': 3, 'border': [], 'borderhighlight': ['BlueColor'], 'borderchars': ['0', '1', '2', '3', '4', '5', '6', '7']})", + \ "call popup_create(['hello border', 'just blanks'], {'line': 7, 'col': 23, 'border': [], 'borderhighlight': ['BlueColor'], 'borderchars': [' ']})", + \], 'XtestPopupBorder') + let buf = RunVimInTerminal('-S XtestPopupBorder', {'rows': 12}) + call VerifyScreenDump(buf, 'Test_popupwin_22', {}) + + call StopVimInTerminal(buf) + call delete('XtestPopupBorder') + let with_border_or_padding = { \ 'line': 2, \ 'core_line': 3, diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -768,6 +768,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 1445, +/**/ 1444, /**/ 1443, diff --git a/src/window.c b/src/window.c --- a/src/window.c +++ b/src/window.c @@ -4846,6 +4846,8 @@ win_free( #endif #ifdef FEAT_TEXT_PROP free_callback(&wp->w_filter_cb); + for (i = 0; i < 4; ++i) + VIM_CLEAR(wp->w_border_highlight[i]); #endif #ifdef FEAT_SYN_HL