mirror of
				https://github.com/vim/vim.git
				synced 2025-10-29 09:37:35 -04:00 
			
		
		
		
	patch 9.1.1856: cannot style popup window (border, shadow, etc)
Problem:  cannot style popup window (border, shadow, etc)
Solution: Extend the 'completepopup' option with additional properties
          (Girish Palya)
This patch extends the 'completepopup' option with additional settings
to allow more configuration of info popup window.
New values:
```
- close           "on" (default) or "off"
- resize          "on" (default) or "off"
- borderchars     specify eight characters (separated by semicolons) to
                  draw the popup border: top, right, bottom, left,
                  topleft, topright, botright, botleft.
- borderhighlight highlight group for the popup border characters
- shadow          pum shadow
```
closes: #18487
Signed-off-by: Girish Palya <girishji@gmail.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
			
			
This commit is contained in:
		
				
					committed by
					
						 Christian Brabandt
						Christian Brabandt
					
				
			
			
				
	
			
			
			
						parent
						
							e15cd0f065
						
					
				
				
					commit
					1a09f11f5d
				
			
							
								
								
									
										205
									
								
								src/popupwin.c
									
									
									
									
									
								
							
							
						
						
									
										205
									
								
								src/popupwin.c
									
									
									
									
									
								
							| @@ -1219,8 +1219,10 @@ popup_adjust_position(win_T *wp) | ||||
|     int		center_hor = FALSE; | ||||
|     int		allow_adjust_left = !wp->w_popup_fixed; | ||||
|     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		right_extra = wp->w_popup_border[1] + wp->w_popup_padding[1] | ||||
| 		    + (wp->w_popup_shadow ? 2 : 0); | ||||
|     int		bot_extra = wp->w_popup_border[2] + wp->w_popup_padding[2] | ||||
| 		    + wp->w_popup_shadow; | ||||
|     int		left_extra = wp->w_popup_border[3] + wp->w_popup_padding[3]; | ||||
|     int		extra_height = top_extra + bot_extra; | ||||
|     int		extra_width = left_extra + right_extra; | ||||
| @@ -1782,6 +1784,21 @@ popup_set_buffer_text(buf_T *buf, typval_T text) | ||||
|     curbuf = curwin->w_buffer; | ||||
| } | ||||
|  | ||||
| #define SET_BORDER_CHARS(a0, a1, a2, a3, a4, a5, a6, a7)    \ | ||||
|     do {						    \ | ||||
| 	if (wp != NULL)					    \ | ||||
| 	{						    \ | ||||
| 	    wp->w_border_char[0] = (a0);		    \ | ||||
| 	    wp->w_border_char[1] = (a1);		    \ | ||||
| 	    wp->w_border_char[2] = (a2);		    \ | ||||
| 	    wp->w_border_char[3] = (a3);		    \ | ||||
| 	    wp->w_border_char[4] = (a4);		    \ | ||||
| 	    wp->w_border_char[5] = (a5);		    \ | ||||
| 	    wp->w_border_char[6] = (a6);		    \ | ||||
| 	    wp->w_border_char[7] = (a7);		    \ | ||||
| 	}						    \ | ||||
|     } while (0) | ||||
|  | ||||
| /* | ||||
|  * Parse the 'previewpopup' or 'completepopup' option and apply the values to | ||||
|  * window "wp" if it is not NULL. | ||||
| @@ -1795,6 +1812,7 @@ parse_popup_option(win_T *wp, int is_preview) | ||||
| 	!is_preview ? p_cpp : | ||||
| #endif | ||||
| 	p_pvp; | ||||
|     int	    border_enabled = FALSE; | ||||
|  | ||||
|     if (wp != NULL) | ||||
| 	wp->w_popup_flags &= ~POPF_INFO_MENU; | ||||
| @@ -1847,28 +1865,159 @@ parse_popup_option(win_T *wp, int is_preview) | ||||
|  | ||||
| 		*p = NUL; | ||||
| 		set_string_option_direct_in_win(wp, (char_u *)"wincolor", -1, | ||||
| 						s + 10, OPT_FREE|OPT_LOCAL, 0); | ||||
| 			s + 10, OPT_FREE|OPT_LOCAL, 0); | ||||
| 		*p = c; | ||||
| 	    } | ||||
| 	} | ||||
| 	else if (STRNCMP(s, "borderhighlight:", 16) == 0) | ||||
| 	{ | ||||
| 	    char_u	*arg = s + 16; | ||||
|  | ||||
| 	    if (*arg == NUL || *arg == ',') | ||||
| 		return FAIL; | ||||
| 	    if (wp != NULL) | ||||
| 	    { | ||||
| 		for (int i = 0; i < 4; ++i) | ||||
| 		{ | ||||
| 		    VIM_CLEAR(wp->w_border_highlight[i]); | ||||
| 		    wp->w_border_highlight[i] = vim_strnsave(arg, p - arg); | ||||
| 		} | ||||
| 	    } | ||||
| 	} | ||||
| 	else if (STRNCMP(s, "border:", 7) == 0) | ||||
| 	{ | ||||
| 	    // Note: Keep this in sync with p_popup_option_border_values. | ||||
| 	    char_u	*arg = s + 7; | ||||
| 	    int		on = STRNCMP(arg, "on", 2) == 0 && arg + 2 == p; | ||||
| 	    int		off = STRNCMP(arg, "off", 3) == 0 && arg + 3 == p; | ||||
| 	    int		i; | ||||
| 	    int		token_len = p - arg; | ||||
| 	    char_u	*token; | ||||
| 	    // Use box-drawing characters only when 'encoding' is "utf-8" and | ||||
| 	    // 'ambiwidth' is "single". | ||||
| 	    int		can_use_box_chars = (enc_utf8 && *p_ambw == 's'); | ||||
|  | ||||
| 	    if (!on && !off) | ||||
| 	    if (token_len == 0 | ||||
| 			|| (STRNCMP(arg, "off", 3) == 0 && arg + 3 == p)) | ||||
| 	    { | ||||
| 		if (wp != NULL) | ||||
| 		{ | ||||
| 		    for (i = 0; i < 4; ++i) | ||||
| 			wp->w_popup_border[i] = 0; | ||||
| 		    SET_BORDER_CHARS(0, 0, 0, 0, 0, 0, 0, 0); | ||||
| 		    // only show the X for close when there is a border | ||||
| 		    wp->w_popup_close = POPCLOSE_NONE; | ||||
| 		} | ||||
| 		continue; | ||||
| 	    } | ||||
|  | ||||
| 	    token = vim_strnsave(arg, token_len); | ||||
| 	    if (token == NULL) | ||||
| 		return FAIL; | ||||
|  | ||||
| 	    if ((can_use_box_chars && (STRCMP(token, "single") == 0 | ||||
| 			    || STRCMP(token, "double") == 0 | ||||
| 			    || STRCMP(token, "on") == 0 | ||||
| 			    || STRCMP(token, "round") == 0)) | ||||
| 		    || STRCMP(token, "ascii") == 0 | ||||
| 		    || (STRNCMP(token, "custom:", 7) == 0)) | ||||
| 	    { | ||||
| 		if (STRCMP(token, "single") == 0) | ||||
| 		    SET_BORDER_CHARS(0x2500, 0x2502, 0x2500, 0x2502, // ─ │ ─ │ | ||||
| 			    0x250c, 0x2510, 0x2518, 0x2514); // ┌ ┐ ┘ └ | ||||
| 		else if (STRCMP(token, "double") == 0) | ||||
| 		    SET_BORDER_CHARS(0x2550, 0x2551, 0x2550, 0x2551, // ═ ║ ═ ║ | ||||
| 			    0x2554, 0x2557, 0x255D, 0x255A); // ╔ ╗ ╝  ╚ | ||||
| 		else if (STRCMP(token, "round") == 0) | ||||
| 		    SET_BORDER_CHARS(0x2500, 0x2502, 0x2500, 0x2502, // ─ │ ─ │ | ||||
| 			    0x256d, 0x256e, 0x256f, 0x2570); // ╭ ╮ ╯ ╰ | ||||
| 		else if (STRCMP(token, "on") == 0) | ||||
| 		    SET_BORDER_CHARS(0, 0, 0, 0, 0, 0, 0, 0); | ||||
| 		else if (STRCMP(token, "ascii") == 0) | ||||
| 		    SET_BORDER_CHARS('-', '|', '-', '|', '+', '+', '+', '+'); | ||||
| 		else if (STRNCMP(token, "custom:", 7) == 0) | ||||
| 		{ | ||||
| 		    char_u	*q = token + 7; | ||||
| 		    int		out[8]; | ||||
| 		    int		failed = FALSE; | ||||
|  | ||||
| 		    SET_BORDER_CHARS(0, 0, 0, 0, 0, 0, 0, 0); | ||||
|  | ||||
| 		    for (i = 0; i < 8 && !failed; i++) | ||||
| 		    { | ||||
| 			if (*q == NUL) | ||||
| 			    failed = TRUE; | ||||
| 			else | ||||
| 			{ | ||||
| 			    out[i] = mb_ptr2char(q); | ||||
| 			    mb_ptr2char_adv(&q); | ||||
| 			    if (i < 7) | ||||
| 			    { | ||||
| 				if (*q != ';') | ||||
| 				    failed = TRUE; // must be semicolon | ||||
| 				q++; | ||||
| 			    } | ||||
| 			} | ||||
| 		    } | ||||
| 		    if (failed || *q != NUL) // must end exactly after the 8th char | ||||
| 		    { | ||||
| 			vim_free(token); | ||||
| 			return FAIL; | ||||
| 		    } | ||||
| 		    SET_BORDER_CHARS(out[0], out[1], out[2], out[3], out[4], | ||||
| 			    out[5], out[6], out[7]); | ||||
| 		} | ||||
| 	    } | ||||
| 	    else | ||||
| 	    { | ||||
| 		vim_free(token); | ||||
| 		return FAIL; | ||||
| 	    } | ||||
|  | ||||
| 	    if (wp != NULL) | ||||
| 	    { | ||||
| 		for (i = 0; i < 4; ++i) | ||||
| 		    wp->w_popup_border[i] = on ? 1 : 0; | ||||
| 		if (off) | ||||
| 		    // only show the X for close when there is a border | ||||
| 		    wp->w_popup_close = POPCLOSE_NONE; | ||||
| 		    wp->w_popup_border[i] = 1; | ||||
| 	    } | ||||
| 	    border_enabled = TRUE; | ||||
|  | ||||
| 	    vim_free(token); | ||||
| 	} | ||||
| 	else if (STRNCMP(s, "close:", 6) == 0) | ||||
| 	{ | ||||
| 	    char_u	*arg = s + 6; | ||||
| 	    int		on = STRNCMP(arg, "on", 2) == 0 && arg + 2 == p; | ||||
| 	    int		off = STRNCMP(arg, "off", 3) == 0 && arg + 3 == p; | ||||
|  | ||||
| 	    if ((!on && !off) || is_preview) | ||||
| 		return FAIL; | ||||
| 	    on = on && mouse_has(MOUSE_INSERT) && border_enabled; | ||||
| 	    if (wp != NULL) | ||||
| 		wp->w_popup_close = on ? POPCLOSE_BUTTON : POPCLOSE_NONE; | ||||
| 	} | ||||
| 	else if (STRNCMP(s, "resize:", 7) == 0) | ||||
| 	{ | ||||
| 	    char_u	*arg = s + 7; | ||||
| 	    int		on = STRNCMP(arg, "on", 2) == 0 && arg + 2 == p; | ||||
| 	    int		off = STRNCMP(arg, "off", 3) == 0 && arg + 3 == p; | ||||
|  | ||||
| 	    if ((!on && !off) || is_preview) | ||||
| 		return FAIL; | ||||
| 	    if (wp != NULL) | ||||
| 	    { | ||||
| 		if (on && mouse_has(MOUSE_INSERT)) | ||||
| 		    wp->w_popup_flags |= POPF_RESIZE; | ||||
| 		else | ||||
| 		    wp->w_popup_flags &= ~POPF_RESIZE; | ||||
| 	    } | ||||
| 	} | ||||
| 	else if (STRNCMP(s, "shadow:", 7) == 0) | ||||
| 	{ | ||||
| 	    char_u	*arg = s + 7; | ||||
| 	    int		on = STRNCMP(arg, "on", 2) == 0 && arg + 2 == p; | ||||
| 	    int		off = STRNCMP(arg, "off", 3) == 0 && arg + 3 == p; | ||||
|  | ||||
| 	    if ((!on && !off) || is_preview) | ||||
| 		return FAIL; | ||||
| 	    if (wp != NULL) | ||||
| 		wp->w_popup_shadow = on ? 1 : 0; | ||||
| 	} | ||||
| 	else if (STRNCMP(s, "align:", 6) == 0) | ||||
| 	{ | ||||
| @@ -2297,6 +2446,12 @@ popup_create(typval_T *argvars, typval_T *rettv, create_type_T type) | ||||
| 	parse_previewpopup(wp); | ||||
| 	popup_set_wantpos_cursor(wp, wp->w_minwidth, d); | ||||
|     } | ||||
|  | ||||
|     for (i = 0; i < 4; ++i) | ||||
| 	VIM_CLEAR(wp->w_border_highlight[i]); | ||||
|     for (i = 0; i < 8; ++i) | ||||
| 	wp->w_border_char[i] = 0; | ||||
|  | ||||
| # ifdef FEAT_QUICKFIX | ||||
|     if (type == TYPE_INFO) | ||||
|     { | ||||
| @@ -2311,10 +2466,6 @@ popup_create(typval_T *argvars, typval_T *rettv, create_type_T type) | ||||
|     } | ||||
| # endif | ||||
|  | ||||
|     for (i = 0; i < 4; ++i) | ||||
| 	VIM_CLEAR(wp->w_border_highlight[i]); | ||||
|     for (i = 0; i < 8; ++i) | ||||
| 	wp->w_border_char[i] = 0; | ||||
|     wp->w_want_scrollbar = 1; | ||||
|     wp->w_popup_fixed = 0; | ||||
|     wp->w_filter_mode = MODE_ALL; | ||||
| @@ -4151,7 +4302,6 @@ update_popups(void (*win_update)(win_T *wp)) | ||||
| 	else | ||||
| 	    wp->w_popup_flags &= ~POPF_ON_CMDLINE; | ||||
|  | ||||
|  | ||||
| 	// We can only use these line drawing characters when 'encoding' is | ||||
| 	// "utf-8" and 'ambiwidth' is "single". | ||||
| 	if (enc_utf8 && *p_ambw == 's') | ||||
| @@ -4374,6 +4524,18 @@ update_popups(void (*win_update)(win_T *wp)) | ||||
| 			popup_attr); | ||||
| 	} | ||||
|  | ||||
| 	// right shadow | ||||
| 	if (wp->w_popup_shadow) | ||||
| 	{ | ||||
| 	    int col = wincol + total_width; | ||||
| 	    for (i = 0; i < total_height; ++i) | ||||
| 	    { | ||||
| 		row = wp->w_winrow + i + 1; | ||||
| 		put_shadow_char(row, col); | ||||
| 		put_shadow_char(row, col + 1); | ||||
| 	    } | ||||
| 	} | ||||
|  | ||||
| 	if (wp->w_popup_padding[2] > 0) | ||||
| 	{ | ||||
| 	    // bottom padding | ||||
| @@ -4387,7 +4549,7 @@ update_popups(void (*win_update)(win_T *wp)) | ||||
| 	{ | ||||
| 	    // bottom border | ||||
| 	    row = wp->w_winrow + total_height - 1; | ||||
| 	    screen_fill(row , row + 1, | ||||
| 	    screen_fill(row, row + 1, | ||||
| 		    wincol < 0 ? 0 : wincol, | ||||
| 		    wincol + total_width, | ||||
| 		    wp->w_popup_border[3] != 0 && wp->w_popup_leftoff == 0 | ||||
| @@ -4400,6 +4562,15 @@ update_popups(void (*win_update)(win_T *wp)) | ||||
| 	    } | ||||
| 	} | ||||
|  | ||||
| 	if (wp->w_popup_shadow) | ||||
| 	{ | ||||
| 	    // bottom shadow | ||||
| 	    row = wp->w_winrow + total_height; | ||||
| 	    for (int col = 2 + (wincol < 0 ? 0 : wincol); | ||||
| 		    col < wincol + total_width; col++) | ||||
| 		put_shadow_char(row, col); | ||||
| 	} | ||||
|  | ||||
| 	if (wp->w_popup_close == POPCLOSE_BUTTON) | ||||
| 	{ | ||||
| 	    // close button goes on top of anything at the top-right corner | ||||
|   | ||||
		Reference in New Issue
	
	Block a user