attrentry_T *char_aep = NULL;
attrentry_T *popup_aep;
attrentry_T new_en;
+ attrentry_T tmp_en;
#ifdef FEAT_GUI
if (gui.in_use)
if (char_attr <= HL_ALL)
new_en.ae_attr = char_attr;
}
- if (popup_attr > HL_ALL)
+
+ // initialize an empty entry if no highlight set for popup
+ if (popup_attr <= HL_ALL)
{
+ CLEAR_FIELD(tmp_en);
+ tmp_en.ae_u.gui.fg_color = INVALCOLOR;
+ tmp_en.ae_u.gui.bg_color = INVALCOLOR;
+ tmp_en.ae_u.gui.sp_color = INVALCOLOR;
+ // preserve attributes other than color
+ tmp_en.ae_attr = popup_attr;
+ popup_aep = &tmp_en;
+
+ popup_aep->ae_u.gui.bg_color = fallback_bg_rgb;
+ }
+ else
popup_aep = syn_gui_attr2entry(popup_attr);
- if (popup_aep != NULL)
+
+ if (popup_aep != NULL)
+ {
+ guicolor_T popup_bg_rgb = popup_aep->ae_u.gui.bg_color;
+ if (COLOR_INVALID(popup_bg_rgb))
+ popup_bg_rgb = fallback_bg_rgb;
+
+ // Blend fg: pum_bg toward underlying_fg.
+ // blend=0 (opaque): fg = pum_bg (text hidden)
+ // blend=100 (transparent): fg = underlying_fg (text visible)
{
- // Blend fg: pum_bg toward underlying_fg.
- // blend=0 (opaque): fg = pum_bg (text hidden)
- // blend=100 (transparent): fg = underlying_fg (text visible)
- if (popup_aep->ae_u.gui.bg_color != INVALCOLOR)
- {
- int base_fg = fallback_fg_rgb;
- if (char_aep != NULL
- && char_aep->ae_u.gui.fg_color != INVALCOLOR)
- base_fg = char_aep->ae_u.gui.fg_color;
- new_en.ae_u.gui.fg_color = blend_colors(
- popup_aep->ae_u.gui.bg_color, base_fg, blend);
- }
- // Blend bg: popup bg toward underlying bg.
- if (popup_aep->ae_u.gui.bg_color != INVALCOLOR)
- {
- guicolor_T underlying_bg = fallback_bg_rgb;
- if (char_aep != NULL)
- underlying_bg = char_aep->ae_u.gui.bg_color;
- new_en.ae_u.gui.bg_color = blend_colors(
- popup_aep->ae_u.gui.bg_color,
- underlying_bg, blend);
- }
+ int base_fg = fallback_fg_rgb;
+ if (char_aep != NULL
+ && char_aep->ae_u.gui.fg_color != INVALCOLOR)
+ base_fg = char_aep->ae_u.gui.fg_color;
+ new_en.ae_u.gui.fg_color = blend_colors(
+ popup_bg_rgb, base_fg, blend);
+ }
+ // Blend background color: blend popup bg toward underlying bg
+ {
+ guicolor_T underlying_bg = fallback_bg_rgb;
+ if (char_aep != NULL
+ && !COLOR_INVALID(char_aep->ae_u.gui.bg_color))
+ underlying_bg = char_aep->ae_u.gui.bg_color;
+ new_en.ae_u.gui.bg_color = blend_colors(
+ popup_bg_rgb,
+ underlying_bg, blend);
}
}
return get_attr_entry(&gui_attr_table, &new_en);
if (char_attr <= HL_ALL)
new_en.ae_attr = char_attr;
}
- if (popup_attr > HL_ALL)
+
+ // initialize an empty entry if no highlight set for popup
+ if (popup_attr <= HL_ALL)
{
+ CLEAR_FIELD(tmp_en);
+#ifdef FEAT_TERMGUICOLORS
+ tmp_en.ae_u.cterm.fg_rgb = INVALCOLOR;
+ tmp_en.ae_u.cterm.ul_rgb = INVALCOLOR;
+ // allow blending with termguicolors
+ tmp_en.ae_u.cterm.bg_rgb = fallback_bg_rgb;
+#endif
+ // preserve attributes other than color
+ tmp_en.ae_attr = popup_attr;
+ popup_aep = &tmp_en;
+
+ // allow blending with notermguicolors
+ popup_aep->ae_u.cterm.bg_color = cterm_normal_bg_color;
+ }
+ else
popup_aep = syn_cterm_attr2entry(popup_attr);
- if (popup_aep != NULL)
+
+ if (popup_aep != NULL)
+ {
+ guicolor_T popup_bg_rgb = INVALCOLOR;
+#ifdef FEAT_TERMGUICOLORS
+ // Fall back to cterm color converted to RGB when gui color is not set.
+ popup_bg_rgb = popup_aep->ae_u.cterm.bg_rgb;
+ if (COLOR_INVALID(popup_bg_rgb)
+ && popup_aep->ae_u.cterm.bg_color > 0)
+ popup_bg_rgb = cterm_color_to_rgb(
+ popup_aep->ae_u.cterm.bg_color);
+#endif
+ // assign default color if guibg and ctermbg are not set for popup
+ if (COLOR_INVALID(popup_bg_rgb)
+ && popup_aep->ae_u.cterm.bg_color == 0)
+ popup_bg_rgb = fallback_bg_rgb;
+
+ // Blend cterm fg: pum_bg toward underlying_fg in the
+ // 256-color palette (mirrors the fg_rgb blend below).
{
- // Blend cterm fg: pum_bg toward underlying_fg in the
- // 256-color palette (mirrors the fg_rgb blend below).
- {
- int under_fg = (char_aep != NULL)
- ? char_aep->ae_u.cterm.fg_color : 0;
- guicolor_T under_fg_rgb = INVALCOLOR;
- guicolor_T popup_bg_rgb = INVALCOLOR;
+ int under_fg = (char_aep != NULL)
+ ? char_aep->ae_u.cterm.fg_color : 0;
+ guicolor_T under_fg_rgb = INVALCOLOR;
#ifdef FEAT_TERMGUICOLORS
- if (char_aep != NULL)
- under_fg_rgb = char_aep->ae_u.cterm.fg_rgb;
- popup_bg_rgb = popup_aep->ae_u.cterm.bg_rgb;
+ if (char_aep != NULL)
+ under_fg_rgb = char_aep->ae_u.cterm.fg_rgb;
#endif
- new_en.ae_u.cterm.fg_color = blend_cterm_colors(
- popup_aep->ae_u.cterm.fg_color, popup_bg_rgb,
- under_fg, under_fg_rgb, fallback_fg_rgb, blend);
- }
- // Approximate cterm bg by blending with the underlying bg
- // in the 256-color palette and mapping to the nearest entry.
- {
- int under_bg = (char_aep != NULL)
- ? char_aep->ae_u.cterm.bg_color : 0;
- guicolor_T under_bg_rgb = INVALCOLOR;
- guicolor_T popup_bg_rgb = INVALCOLOR;
+ new_en.ae_u.cterm.fg_color = blend_cterm_colors(
+ popup_aep->ae_u.cterm.fg_color, popup_bg_rgb,
+ under_fg, under_fg_rgb, fallback_fg_rgb, blend);
+ }
+ // Approximate cterm bg by blending with the underlying bg
+ // in the 256-color palette and mapping to the nearest entry.
+ {
+ int under_bg = (char_aep != NULL)
+ ? char_aep->ae_u.cterm.bg_color : 0;
+ guicolor_T under_bg_rgb = INVALCOLOR;
#ifdef FEAT_TERMGUICOLORS
- if (char_aep != NULL)
- under_bg_rgb = char_aep->ae_u.cterm.bg_rgb;
- popup_bg_rgb = popup_aep->ae_u.cterm.bg_rgb;
+ if (char_aep != NULL)
+ under_bg_rgb = char_aep->ae_u.cterm.bg_rgb;
#endif
- new_en.ae_u.cterm.bg_color = blend_cterm_colors(
- popup_aep->ae_u.cterm.bg_color, popup_bg_rgb,
- under_bg, under_bg_rgb, fallback_bg_rgb, blend);
- }
+ new_en.ae_u.cterm.bg_color = blend_cterm_colors(
+ popup_aep->ae_u.cterm.bg_color, popup_bg_rgb,
+ under_bg, under_bg_rgb, fallback_bg_rgb, blend);
+ }
#ifdef FEAT_TERMGUICOLORS
- // Blend fg_rgb: pum_bg toward underlying_fg.
- // CTERMCOLOR is a sentinel meaning "use the cterm color";
- // treat it as no underlying color so it is not blended in
- // as a real near-white pixel.
- if (popup_aep->ae_u.cterm.bg_rgb != INVALCOLOR)
- {
- int base_fg = fallback_fg_rgb;
- if (char_aep != NULL
- && !COLOR_INVALID(char_aep->ae_u.cterm.fg_rgb))
- base_fg = char_aep->ae_u.cterm.fg_rgb;
- new_en.ae_u.cterm.fg_rgb = blend_colors(
- popup_aep->ae_u.cterm.bg_rgb, base_fg, blend);
- }
+ // Blend fg_rgb: pum_bg toward underlying_fg.
+ // Fall back to cterm color converted to RGB when
+ // gui color is not set.
+ // CTERMCOLOR is a sentinel meaning "use the cterm color";
+ // treat it as no underlying color so it is not blended in
+ // as a real near-white pixel.
+ if (popup_bg_rgb != INVALCOLOR)
+ {
+ int base_fg = fallback_fg_rgb;
+ if (char_aep != NULL
+ && !COLOR_INVALID(char_aep->ae_u.cterm.fg_rgb))
+ base_fg = char_aep->ae_u.cterm.fg_rgb;
+ new_en.ae_u.cterm.fg_rgb = blend_colors(
+ popup_bg_rgb, base_fg, blend);
+ }
+ if (popup_bg_rgb != INVALCOLOR)
+ {
// Blend bg_rgb.
- if (popup_aep->ae_u.cterm.bg_rgb != INVALCOLOR)
- {
- guicolor_T underlying_bg = fallback_bg_rgb;
- if (char_aep != NULL
- && !COLOR_INVALID(char_aep->ae_u.cterm.bg_rgb))
- underlying_bg = char_aep->ae_u.cterm.bg_rgb;
- new_en.ae_u.cterm.bg_rgb = blend_colors(
- popup_aep->ae_u.cterm.bg_rgb,
- underlying_bg, blend);
- }
-#endif
+ guicolor_T underlying_bg = fallback_bg_rgb;
+ if (char_aep != NULL
+ && !COLOR_INVALID(char_aep->ae_u.cterm.bg_rgb))
+ underlying_bg = char_aep->ae_u.cterm.bg_rgb;
+ new_en.ae_u.cterm.bg_rgb = blend_colors(
+ popup_bg_rgb, underlying_bg, blend);
}
+#endif
}
return get_attr_entry(&cterm_attr_table, &new_en);
}
if (char_attr <= HL_ALL)
new_en.ae_attr = char_attr;
}
+
return get_attr_entry(&term_attr_table, &new_en);
}
call StopVimInTerminal(buf)
endfunc
+" Test pumopt opacity when Pmenu highlight groups are cleared
+func Test_pumopt_opacity_pmenu_cleared()
+ CheckScreendump
+ let lines =<< trim END
+ set pumopt=opacity:50,border:round
+ set completeopt=menu
+ highlight clear
+ highlight clear Pmenu
+ highlight clear PmenuSel
+ highlight Underbg ctermbg=red guibg=red
+ highlight Underfg ctermfg=green guifg=green
+ call setline(1, '')
+ for i in range(10)
+ call append(line('$'), ' X YYY ZZZ X YYY X X X X X X')
+ endfor
+ call matchadd('Underbg', 'YYY')
+ call matchadd('Underfg', 'ZZZ')
+ normal gg
+ inoremap <F5> <Cmd>call complete(col('.'),
+ \ ['item', 'another item', 'and a last one'])<CR>
+ END
+ call writefile(lines, 'Xpumopacitypmenucleared', 'D')
+ let buf = RunVimInTerminal('-S Xpumopacitypmenucleared', {})
+ call TermWait(buf)
+ " light background
+ call term_sendkeys(buf, "i\<F5>")
+ call TermWait(buf, 100)
+ call VerifyScreenDump(buf, 'Test_pumopt_opacity_pmenu_cleared', {})
+ call term_sendkeys(buf, "\<C-E>\<Esc>u")
+ call TermWait(buf)
+ " light termguicolors
+ call term_sendkeys(buf, ":set termguicolors\<CR>")
+ call term_sendkeys(buf, "i\<F5>")
+ call TermWait(buf, 100)
+ call VerifyScreenDump(buf, 'Test_pumopt_opacity_pmenu_cleared_2', {})
+ call term_sendkeys(buf, "\<C-E>\<Esc>u")
+ call TermWait(buf)
+ " dark termguicolors
+ call term_sendkeys(buf, ":set background=dark\<CR>")
+ call term_sendkeys(buf, ":highlight clear Pmenu\<CR>")
+ call term_sendkeys(buf, ":highlight clear PmenuSel\<CR>")
+ call term_sendkeys(buf, "i\<F5>")
+ call TermWait(buf, 100)
+ call VerifyScreenDump(buf, 'Test_pumopt_opacity_pmenu_cleared_3', {})
+ call term_sendkeys(buf, "\<C-E>\<Esc>u")
+ call TermWait(buf)
+ " dark background
+ call term_sendkeys(buf, ":set notermguicolors\<CR>")
+ call term_sendkeys(buf, "i\<F5>")
+ call TermWait(buf, 100)
+ call VerifyScreenDump(buf, 'Test_pumopt_opacity_pmenu_cleared_4', {})
+ call term_sendkeys(buf, "\<C-E>\<Esc>u")
+ call TermWait(buf)
+ call StopVimInTerminal(buf)
+endfunc
+
func Test_popup_sandbox()
call assert_fails('sandbox call popup_create("hello", {})', 'E48:')
call assert_fails('sandbox call popup_setoptions(1, {})', 'E48:')