base_fg, popup_aep->ae_u.gui.bg_color, blend);
}
}
- else if (popup_aep->ae_u.gui.fg_color != INVALCOLOR)
+ else
{
- // blend_fg=FALSE: use popup foreground
+ // blend_fg=FALSE: popup text is opaque. Replace the
+ // underlying cell's attribute flags and fg with the
+ // popup's, so the underlying syntax highlighting does
+ // not bleed through.
+ new_en.ae_attr = popup_aep->ae_attr;
new_en.ae_u.gui.fg_color = popup_aep->ae_u.gui.fg_color;
}
// Blend background color: blend popup bg toward underlying bg
popup_aep = syn_cterm_attr2entry(popup_attr);
if (popup_aep != NULL)
{
- // Blend foreground color
- if (popup_aep->ae_u.cterm.fg_color > 0)
+ if (!blend_fg)
+ {
+ // blend_fg=FALSE: popup text is opaque. Replace the
+ // underlying cell's attribute flags and fg with the
+ // popup's, so the underlying syntax highlighting does
+ // not bleed through.
+ new_en.ae_attr = popup_aep->ae_attr;
+ new_en.ae_u.cterm.fg_color = popup_aep->ae_u.cterm.fg_color;
+ }
+ else if (popup_aep->ae_u.cterm.fg_color > 0)
+ // Blend foreground color
new_en.ae_u.cterm.fg_color = popup_aep->ae_u.cterm.fg_color;
// Use popup background color (cterm colors don't support blending)
if (popup_aep->ae_u.cterm.bg_color > 0)
base_fg, popup_bg, blend);
}
}
- else if (popup_fg != INVALCOLOR)
- // blend_fg=FALSE: use popup foreground
+ else
+ // blend_fg=FALSE: popup text is opaque. Replace fg
+ // with popup's (even INVALCOLOR) so the underlying
+ // syntax highlighting fg does not bleed. ae_attr
+ // was already set above for this branch.
new_en.ae_u.cterm.fg_rgb = popup_fg;
if (popup_bg != INVALCOLOR)
{
force_redraw_this = force_redraw_next;
force_redraw_next = FALSE;
+ // When drawing pum text with opacity, blend the popup bg with the
+ // saved underlying bg so text cells match the padding cells that
+ // use hl_pum_blend_attr. Without this, popup text appears on a
+ // solid bg while padding shows a blended bg, creating a visible
+ // seam.
+ int cell_attr = attr;
+ if (screen_pum_blend > 0 && pum_bg_attrs != NULL
+ && row >= pum_bg_top && row < pum_bg_bot
+ && col < pum_bg_cols)
+ {
+ int soff = (row - pum_bg_top) * pum_bg_cols + col;
+ cell_attr = hl_blend_attr(pum_bg_attrs[soff], attr,
+ screen_pum_blend, FALSE);
+ }
+
need_redraw = ScreenLines[off] != c
|| (mbyte_cells == 2
&& ScreenLines[off + 1] != (enc_dbcs ? ptr[1] : 0))
(u8char_T)(c < 0x80 && u8cc[0] == 0 ? 0 : u8c)
|| (ScreenLinesUC[off] != 0
&& screen_comp_differs(off, u8cc))))
- || ScreenAttrs[off] != attr
+ || ScreenAttrs[off] != cell_attr
|| exmode_active;
if ((need_redraw || force_redraw_this) && !skip_for_popup(row, col))
&& (*mb_off2cells)(off + 1, max_off) > 1)))
ScreenLines[off + mbyte_blen] = 0;
ScreenLines[off] = c;
- ScreenAttrs[off] = attr;
+ ScreenAttrs[off] = cell_attr;
ScreenCols[off] = -1;
if (enc_utf8)
{
if (mbyte_cells == 2)
{
ScreenLines[off + 1] = 0;
- ScreenAttrs[off + 1] = attr;
+ ScreenLinesUC[off + 1] = 0;
+ for (int ci = 0; ci < Screen_mco; ++ci)
+ ScreenLinesC[ci][off + 1] = 0;
+ ScreenAttrs[off + 1] = cell_attr;
ScreenCols[off + 1] = -1;
}
screen_char(off, row, col);
else if (mbyte_cells == 2)
{
ScreenLines[off + 1] = ptr[1];
- ScreenAttrs[off + 1] = attr;
+ ScreenAttrs[off + 1] = cell_attr;
ScreenCols[off + 1] = -1;
screen_char_2(off, row, col);
}
&& col < pum_bg_cols)
{
int soff = (row - pum_bg_top) * pum_bg_cols + col;
+
+ // Skip the trailing cell of a wide background char: its
+ // leading cell already emitted the full wide glyph via
+ // screen_char(); drawing here would clobber the right half.
+ // Only applies when the previous cell was actually processed
+ // in this fill range -- if the fill starts here (col ==
+ // start_col), the "wide lead" is outside our range (e.g.,
+ // popup text wrote a narrow cell there), so we fall through
+ // to the regular blend path which renders a blended space.
+ if (enc_utf8 && pum_bg_linesUC != NULL
+ && col > start_col
+ && pum_bg_linesUC[soff] == 0
+ && pum_bg_linesUC[soff - 1] != 0
+ && utf_char2cells(pum_bg_linesUC[soff - 1]) == 2)
+ {
+ ScreenLines[off] = 0;
+ if (ScreenLinesUC != NULL)
+ ScreenLinesUC[off] = 0;
+ ScreenAttrs[off] = ScreenAttrs[off - 1];
+ goto next_col;
+ }
+
int underlying_attr = pum_bg_attrs[soff];
+ // If restoring the leading cell of a wide background char
+ // would extend past the end of the fill range (e.g. into a
+ // popup border cell on the right edge), render a blended
+ // space instead so the border at col+1 is preserved.
+ // Likewise, if this cell is the trailing half of a wide
+ // background char whose leading cell is outside the fill
+ // range (e.g., popup text wrote a narrow cell there),
+ // restoring the trailing alone would emit a stray NUL.
+ if (enc_utf8 && pum_bg_linesUC != NULL
+ && ((pum_bg_linesUC[soff] != 0
+ && utf_char2cells(pum_bg_linesUC[soff]) == 2
+ && col + 1 >= end_col)
+ || (col == start_col
+ && pum_bg_linesUC[soff] == 0
+ && col > 0
+ && pum_bg_linesUC[soff - 1] != 0
+ && utf_char2cells(pum_bg_linesUC[soff - 1])
+ == 2)))
+ {
+ ScreenLines[off] = ' ';
+ if (ScreenLinesUC != NULL)
+ ScreenLinesUC[off] = 0;
+ ScreenAttrs[off] = hl_pum_blend_attr(underlying_attr,
+ attr, screen_pum_blend);
+ screen_char(off, row, col);
+ goto next_col;
+ }
+
// Restore underlying character so text shows through.
ScreenLines[off] = pum_bg_lines[soff];
if (enc_utf8 && pum_bg_linesUC != NULL
--- /dev/null
+|ほ*0&#ffffff0|げ> +&@70
+|ほ*0#0000001#ffff4012|げ|ほ|げ|ほ|げ|漢*4&&| +&| +4#e000e06#ffffff0|テ*&|ス|ト|あ*0#0000000&|い|う|え|お|カ|タ|カ|ナ| +&@34
+|ふ*0#ffffff16#0000e05|が|漢|字|ほ|げ|漢*4&&| +&| +4#e000e06#ffffff0|テ*&|ス|ト|あ*0#0000000&|い|う|え|お|カ|タ|カ|ナ| +&@34
+|カ*0#ffffff16#0000e05|タ|カ|ナ|候|補|漢*4&&| +&| +4#e000e06#ffffff0|テ*&|ス|ト|あ*0#0000000&|い|う|え|お|カ|タ|カ|ナ| +&@34
+|ほ*&|げ|ほ|げ|ほ|げ|漢*4#e000e06&|字|テ|ス|ト|あ*0#0000000&|い|う|え|お|カ|タ|カ|ナ| +&@34
+|ほ*&|げ|ほ|げ|ほ|げ|漢*4#e000e06&|字|テ|ス|ト|あ*0#0000000&|い|う|え|お|カ|タ|カ|ナ| +&@34
+|ほ*&|げ|ほ|げ|ほ|げ|漢*4#e000e06&|字|テ|ス|ト|あ*0#0000000&|い|う|え|お|カ|タ|カ|ナ| +&@34
+|ほ*&|げ|ほ|げ|ほ|げ|漢*4#e000e06&|字|テ|ス|ト|あ*0#0000000&|い|う|え|お|カ|タ|カ|ナ| +&@34
+|ほ*&|げ|ほ|げ|ほ|げ|漢*4#e000e06&|字|テ|ス|ト|あ*0#0000000&|い|う|え|お|カ|タ|カ|ナ| +&@34
+|ほ*&|げ|ほ|げ|ほ|げ|漢*4#e000e06&|字|テ|ス|ト|あ*0#0000000&|い|う|え|お|カ|タ|カ|ナ| +&@34
+|ほ*&|げ|ほ|げ|ほ|げ|漢*4#e000e06&|字|テ|ス|ト|あ*0#0000000&|い|う|え|お|カ|タ|カ|ナ| +&@34
+|ほ*&|げ|ほ|げ|ほ|げ|漢*4#e000e06&|字|テ|ス|ト|あ*0#0000000&|い|う|え|お|カ|タ|カ|ナ| +&@34
+|ほ*&|げ|ほ|げ|ほ|げ|漢*4#e000e06&|字|テ|ス|ト|あ*0#0000000&|い|う|え|お|カ|タ|カ|ナ| +&@34
+|ほ*&|げ|ほ|げ|ほ|げ|漢*4#e000e06&|字|テ|ス|ト|あ*0#0000000&|い|う|え|お|カ|タ|カ|ナ| +&@34
+|ほ*&|げ|ほ|げ|ほ|げ|漢*4#e000e06&|字|テ|ス|ト|あ*0#0000000&|い|う|え|お|カ|タ|カ|ナ| +&@34
+|ほ*&|げ|ほ|げ|ほ|げ|漢*4#e000e06&|字|テ|ス|ト|あ*0#0000000&|い|う|え|お|カ|タ|カ|ナ| +&@34
+|ほ*&|げ|ほ|げ|ほ|げ|漢*4#e000e06&|字|テ|ス|ト|あ*0#0000000&|い|う|え|お|カ|タ|カ|ナ| +&@34
+|ほ*&|げ|ほ|げ|ほ|げ|漢*4#e000e06&|字|テ|ス|ト|あ*0#0000000&|い|う|え|お|カ|タ|カ|ナ| +&@34
+|ほ*&|げ|ほ|げ|ほ|げ|漢*4#e000e06&|字|テ|ス|ト|あ*0#0000000&|い|う|え|お|カ|タ|カ|ナ| +&@34
+|-+2&&@1| |I|N|S|E|R|T| |-@1| +0&&@44|1|,|1| @10|T|o|p|
--- /dev/null
+|ほ*0&#ffffff0|げ> +&@70
+|╭+0#0000001#ffd7ff255|─@15|╮|ス*0#0000000#ffffff0|ト|あ|い|う|え|お|カ|タ|カ|ナ| +&@34
+|│+0#0000001#ffd7ff255| +0&#e0e0e08|ほ*&|げ@1|ほ|げ|漢|字| +&|│+0&#ffd7ff255|ス*0#0000000#ffffff0|ト|あ|い|う|え|お|カ|タ|カ|ナ| +&@34
+|│+0#0000001#ffd7ff255| |ふ*&|が|漢|字|げ|漢|字| +&|│|ス*0#0000000#ffffff0|ト|あ|い|う|え|お|カ|タ|カ|ナ| +&@34
+|│+0#0000001#ffd7ff255| |カ*&|タ|カ|ナ|候|補|字| +&|│|ス*0#0000000#ffffff0|ト|あ|い|う|え|お|カ|タ|カ|ナ| +&@34
+|╰+0#0000001#ffd7ff255|─@15|╯|ス*0#0000000#ffffff0|ト|あ|い|う|え|お|カ|タ|カ|ナ| +&@34
+|ほ*&|げ|ほ|げ|ほ|げ|漢|字|テ|ス|ト|あ|い|う|え|お|カ|タ|カ|ナ| +&@34
+|ほ*&|げ|ほ|げ|ほ|げ|漢|字|テ|ス|ト|あ|い|う|え|お|カ|タ|カ|ナ| +&@34
+|ほ*&|げ|ほ|げ|ほ|げ|漢|字|テ|ス|ト|あ|い|う|え|お|カ|タ|カ|ナ| +&@34
+|ほ*&|げ|ほ|げ|ほ|げ|漢|字|テ|ス|ト|あ|い|う|え|お|カ|タ|カ|ナ| +&@34
+|ほ*&|げ|ほ|げ|ほ|げ|漢|字|テ|ス|ト|あ|い|う|え|お|カ|タ|カ|ナ| +&@34
+|ほ*&|げ|ほ|げ|ほ|げ|漢|字|テ|ス|ト|あ|い|う|え|お|カ|タ|カ|ナ| +&@34
+|ほ*&|げ|ほ|げ|ほ|げ|漢|字|テ|ス|ト|あ|い|う|え|お|カ|タ|カ|ナ| +&@34
+|ほ*&|げ|ほ|げ|ほ|げ|漢|字|テ|ス|ト|あ|い|う|え|お|カ|タ|カ|ナ| +&@34
+|ほ*&|げ|ほ|げ|ほ|げ|漢|字|テ|ス|ト|あ|い|う|え|お|カ|タ|カ|ナ| +&@34
+|ほ*&|げ|ほ|げ|ほ|げ|漢|字|テ|ス|ト|あ|い|う|え|お|カ|タ|カ|ナ| +&@34
+|ほ*&|げ|ほ|げ|ほ|げ|漢|字|テ|ス|ト|あ|い|う|え|お|カ|タ|カ|ナ| +&@34
+|ほ*&|げ|ほ|げ|ほ|げ|漢|字|テ|ス|ト|あ|い|う|え|お|カ|タ|カ|ナ| +&@34
+|ほ*&|げ|ほ|げ|ほ|げ|漢|字|テ|ス|ト|あ|い|う|え|お|カ|タ|カ|ナ| +&@34
+|-+2&&@1| |I|N|S|E|R|T| |-@1| +0&&@44|1|,|1| @10|T|o|p|
--- /dev/null
+|ほ*0&#ffffff0|げ> +&@70
+|╭+0#0000001#ffd7ff255|─@15|╮|ス*0#0000000#ffffff0|ト|あ|い|う|え|お|カ|タ|カ|ナ| +&@34
+|│+0#0000001#ffd7ff255| +0&#e0e0e08|ほ*&|げ| +&|げ*&|ほ|げ|漢|字|│+0&#ffd7ff255| +0#0000000#ffffff0|ス*&|ト|あ|い|う|え|お|カ|タ|カ|ナ| +&@33
+|│+0#0000001#ffd7ff255| |ふ*&|が|漢|字|げ|漢|字| +&|│|ス*0#0000000#ffffff0|ト|あ|い|う|え|お|カ|タ|カ|ナ| +&@34
+|│+0#0000001#ffd7ff255| |カ*&|タ|カ|ナ|候|補| +&|字*&|│+&| +0#0000000#ffffff0|ス*&|ト|あ|い|う|え|お|カ|タ|カ|ナ| +&@33
+|╰+0#0000001#ffd7ff255|─@15|╯|ス*0#0000000#ffffff0|ト|あ|い|う|え|お|カ|タ|カ|ナ| +&@34
+|a|ほ*&|げ|ほ|げ|ほ|げ|漢|字|テ|ス|ト|あ|い|う|え|お|カ|タ|カ|ナ| +&@33
+|ほ*&|げ|ほ|げ|ほ|げ|漢|字|テ|ス|ト|あ|い|う|え|お|カ|タ|カ|ナ| +&@34
+|a|ほ*&|げ|ほ|げ|ほ|げ|漢|字|テ|ス|ト|あ|い|う|え|お|カ|タ|カ|ナ| +&@33
+|ほ*&|げ|ほ|げ|ほ|げ|漢|字|テ|ス|ト|あ|い|う|え|お|カ|タ|カ|ナ| +&@34
+|a|ほ*&|げ|ほ|げ|ほ|げ|漢|字|テ|ス|ト|あ|い|う|え|お|カ|タ|カ|ナ| +&@33
+|ほ*&|げ|ほ|げ|ほ|げ|漢|字|テ|ス|ト|あ|い|う|え|お|カ|タ|カ|ナ| +&@34
+|a|ほ*&|げ|ほ|げ|ほ|げ|漢|字|テ|ス|ト|あ|い|う|え|お|カ|タ|カ|ナ| +&@33
+|ほ*&|げ|ほ|げ|ほ|げ|漢|字|テ|ス|ト|あ|い|う|え|お|カ|タ|カ|ナ| +&@34
+|a|ほ*&|げ|ほ|げ|ほ|げ|漢|字|テ|ス|ト|あ|い|う|え|お|カ|タ|カ|ナ| +&@33
+|ほ*&|げ|ほ|げ|ほ|げ|漢|字|テ|ス|ト|あ|い|う|え|お|カ|タ|カ|ナ| +&@34
+|a|ほ*&|げ|ほ|げ|ほ|げ|漢|字|テ|ス|ト|あ|い|う|え|お|カ|タ|カ|ナ| +&@33
+|ほ*&|げ|ほ|げ|ほ|げ|漢|字|テ|ス|ト|あ|い|う|え|お|カ|タ|カ|ナ| +&@34
+|a|ほ*&|げ|ほ|げ|ほ|げ|漢|字|テ|ス|ト|あ|い|う|え|お|カ|タ|カ|ナ| +&@33
+|-+2&&@1| |I|N|S|E|R|T| |-@1| +0&&@44|1|,|1| @10|T|o|p|
call StopVimInTerminal(buf)
endfunc
+" Test pumopt opacity with multibyte background text and multibyte popup
+" items. Exercises the wide-character alignment in the blend path:
+" - a wide background character whose trailing cell falls inside the pum
+" fill range must not be re-emitted after screen_char() has already drawn
+" the full glyph (would clobber the right half);
+" - a wide background character at the right edge of the fill range must
+" not spill into the adjacent border cell.
+func Test_pumopt_opacity_wide_bg()
+ CheckScreendump
+ let lines =<< trim END
+ set pumopt=opacity:50,border:round
+ set completeopt=menu
+ call setline(1, '')
+ for i in range(20)
+ call append(line('$'), 'ほげほげほげ漢字テストあいうえおカタカナ')
+ endfor
+ normal gg
+ inoremap <F5> <Cmd>call complete(col('.'),
+ \ ['ほげ', 'ふが漢字', 'カタカナ候補'])<CR>
+ END
+ call writefile(lines, 'Xpumoptopacitywide', 'D')
+ let buf = RunVimInTerminal('-S Xpumoptopacitywide', {})
+ call TermWait(buf)
+ call term_sendkeys(buf, "i\<F5>")
+ call TermWait(buf, 100)
+ call VerifyScreenDump(buf, 'Test_pumopt_opacity_wide_bg', {})
+ call term_sendkeys(buf, "\<C-E>\<Esc>u")
+ call TermWait(buf)
+ call StopVimInTerminal(buf)
+endfunc
+
+" Test pumopt opacity when every other background line is shifted by one
+" narrow cell, so the background's wide-character boundaries do not align
+" with the popup's wide-character grid. Exercises the blend path when:
+" - pum_bg has the trailing half of a wide character at col == start_col
+" (its leading half was overwritten by the popup text's clear_next_cell
+" narrow space), where restoring the trailing alone would emit a stray
+" NUL; a blended space must be rendered instead.
+" - clearing of ScreenLinesUC[off + 1] when screen_puts_len writes a wide
+" character on a cell whose trailing previously held a different wide
+" char's leading codepoint.
+func Test_pumopt_opacity_wide_bg_shifted()
+ CheckScreendump
+ let lines =<< trim END
+ set pumopt=opacity:50,border:round
+ set completeopt=menu
+ call setline(1, '')
+ let base = 'ほげほげほげ漢字テストあいうえおカタカナ'
+ for i in range(20)
+ call append(line('$'), (i % 2 == 0 ? '' : 'a') .. base)
+ endfor
+ normal gg
+ inoremap <F5> <Cmd>call complete(col('.'),
+ \ ['ほげ', 'ふが漢字', 'カタカナ候補'])<CR>
+ END
+ call writefile(lines, 'Xpumoptopacityshifted', 'D')
+ let buf = RunVimInTerminal('-S Xpumoptopacityshifted', {})
+ call TermWait(buf)
+ call term_sendkeys(buf, "i\<F5>")
+ call TermWait(buf, 100)
+ call VerifyScreenDump(buf, 'Test_pumopt_opacity_wide_bg_shifted', {})
+ call term_sendkeys(buf, "\<C-E>\<Esc>u")
+ call TermWait(buf)
+ call StopVimInTerminal(buf)
+endfunc
+
+" Test that opaque popup text uses the popup's own attributes (fg and flags
+" like italic) rather than inheriting them from the syntax-highlighted
+" multibyte background cell underneath. Without this guard, popup text
+" picks up the fg/italic of whatever buffer text happened to sit under
+" each cell.
+func Test_pumopt_opacity_text_attrs()
+ CheckScreendump
+ let lines =<< trim END
+ set pumopt=opacity:50
+ set completeopt=menu
+ hi clear
+ hi Pmenu guifg=#ffffff guibg=#004488 ctermfg=white ctermbg=darkblue
+ hi PmenuSel guifg=#000000 guibg=#ffcc00 ctermfg=black ctermbg=yellow
+ hi Special guifg=#ff66cc cterm=italic gui=italic
+ call setline(1, '')
+ for i in range(20)
+ call append(line('$'), 'ほげほげほげ漢字テストあいうえおカタカナ')
+ endfor
+ call matchadd('Special', '漢字\|テスト')
+ normal gg
+ inoremap <F5> <Cmd>call complete(col('.'),
+ \ ['ほげ', 'ふが漢字', 'カタカナ候補'])<CR>
+ END
+ call writefile(lines, 'Xpumoptopacityattrs', 'D')
+ let buf = RunVimInTerminal('-S Xpumoptopacityattrs', {})
+ call TermWait(buf)
+ call term_sendkeys(buf, "i\<F5>")
+ call TermWait(buf, 100)
+ call VerifyScreenDump(buf, 'Test_pumopt_opacity_text_attrs', {})
+ call term_sendkeys(buf, "\<C-E>\<Esc>u")
+ call TermWait(buf)
+ call StopVimInTerminal(buf)
+endfunc
+
" Test pumopt opacity:100 (fully opaque, same as default)
func Test_pumopt_opacity_100()
CheckScreendump
static int included_patches[] =
{ /* Add new patch number below this line */
+/**/
+ 372,
/**/
371,
/**/