summaryrefslogtreecommitdiff
path: root/src/terminal.c
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2021-11-20 13:47:45 +0000
committerBram Moolenaar <Bram@vim.org>2021-11-20 13:47:45 +0000
commit87fd0924e2d85213cc111ee7a5122f92216a37c7 (patch)
treef2338c0fc69e65e11e66590514a2b6eb40e2e26d /src/terminal.c
parentcdf5fdb2948ecdd24c6a1e27ed33dfa847c2b3e4 (diff)
downloadvim-git-87fd0924e2d85213cc111ee7a5122f92216a37c7.tar.gz
patch 8.2.3628: looking terminal colors is a bit slowv8.2.3628
Problem: Looking terminal colors is a bit slow. Solution: Cache the terminal colors. (closes #9130, closes #9058)
Diffstat (limited to 'src/terminal.c')
-rw-r--r--src/terminal.c383
1 files changed, 202 insertions, 181 deletions
diff --git a/src/terminal.c b/src/terminal.c
index c00302d2b..24779d9c2 100644
--- a/src/terminal.c
+++ b/src/terminal.c
@@ -2319,14 +2319,21 @@ terminal_is_active()
}
/*
- * Return the highight group name for the terminal; "Terminal" if not set.
+ * Return the highight group ID for the terminal and the window.
*/
- static char_u *
-term_get_highlight_name(term_T *term)
+ static int
+term_get_highlight_id(term_T *term, win_T *wp)
{
- if (term->tl_highlight_name == NULL)
- return (char_u *)"Terminal";
- return term->tl_highlight_name;
+ char_u *name;
+
+ if (wp != NULL && *wp->w_p_wcr != NUL)
+ name = wp->w_p_wcr;
+ else if (term->tl_highlight_name != NULL)
+ name = term->tl_highlight_name;
+ else
+ name = (char_u*)"Terminal";
+
+ return syn_name2id(name);
}
#if defined(FEAT_GUI) || defined(PROTO)
@@ -2336,7 +2343,8 @@ term_get_cursor_shape(guicolor_T *fg, guicolor_T *bg)
term_T *term = in_terminal_loop;
static cursorentry_T entry;
int id;
- guicolor_T term_fg, term_bg;
+ guicolor_T term_fg = INVALCOLOR;
+ guicolor_T term_bg = INVALCOLOR;
CLEAR_FIELD(entry);
entry.shape = entry.mshape =
@@ -2352,18 +2360,17 @@ term_get_cursor_shape(guicolor_T *fg, guicolor_T *bg)
}
// The highlight group overrules the defaults.
- id = syn_name2id(term_get_highlight_name(term));
+ id = term_get_highlight_id(term, curwin);
if (id != 0)
- {
syn_id2colors(id, &term_fg, &term_bg);
+ if (term_bg != INVALCOLOR)
*fg = term_bg;
- }
else
*fg = gui.back_pixel;
if (term->tl_cursor_color == NULL)
{
- if (id != 0)
+ if (term_fg != INVALCOLOR)
*bg = term_fg;
else
*bg = gui.norm_pixel;
@@ -2743,8 +2750,7 @@ color2index(VTermColor *color, int fg, int *boldp)
int blue = color->blue;
int green = color->green;
- if (VTERM_COLOR_IS_DEFAULT_FG(color)
- || VTERM_COLOR_IS_DEFAULT_BG(color))
+ if (VTERM_COLOR_IS_INVALID(color))
return 0;
if (VTERM_COLOR_IS_INDEXED(color))
{
@@ -2815,19 +2821,19 @@ color2index(VTermColor *color, int fg, int *boldp)
* Convert Vterm attributes to highlight flags.
*/
static int
-vtermAttr2hl(VTermScreenCellAttrs cellattrs)
+vtermAttr2hl(VTermScreenCellAttrs *cellattrs)
{
int attr = 0;
- if (cellattrs.bold)
+ if (cellattrs->bold)
attr |= HL_BOLD;
- if (cellattrs.underline)
+ if (cellattrs->underline)
attr |= HL_UNDERLINE;
- if (cellattrs.italic)
+ if (cellattrs->italic)
attr |= HL_ITALIC;
- if (cellattrs.strike)
+ if (cellattrs->strike)
attr |= HL_STRIKETHROUGH;
- if (cellattrs.reverse)
+ if (cellattrs->reverse)
attr |= HL_INVERSE;
return attr;
}
@@ -2858,88 +2864,66 @@ hl2vtermAttr(int attr, cellattr_T *cell)
cell2attr(
term_T *term,
win_T *wp,
- VTermScreenCellAttrs cellattrs,
- VTermColor cellfg,
- VTermColor cellbg)
+ VTermScreenCellAttrs *cellattrs,
+ VTermColor *cellfg,
+ VTermColor *cellbg)
{
int attr = vtermAttr2hl(cellattrs);
+ VTermColor *fg = cellfg;
+ VTermColor *bg = cellbg;
+ int is_default_fg = VTERM_COLOR_IS_DEFAULT_FG(fg);
+ int is_default_bg = VTERM_COLOR_IS_DEFAULT_BG(bg);
+
+ if (is_default_fg || is_default_bg)
+ {
+ if (wp != NULL && *wp->w_p_wcr != NUL)
+ {
+ if (is_default_fg)
+ fg = &wp->w_term_wincolor.fg;
+ if (is_default_bg)
+ bg = &wp->w_term_wincolor.bg;
+ }
+ else
+ {
+ if (is_default_fg)
+ fg = &term->tl_default_color.fg;
+ if (is_default_bg)
+ bg = &term->tl_default_color.bg;
+ }
+ }
#ifdef FEAT_GUI
if (gui.in_use)
{
- guicolor_T fg, bg;
-
- fg = gui_mch_get_rgb_color(cellfg.red, cellfg.green, cellfg.blue);
- bg = gui_mch_get_rgb_color(cellbg.red, cellbg.green, cellbg.blue);
- return get_gui_attr_idx(attr, fg, bg);
+ guicolor_T guifg = gui_mch_get_rgb_color(fg->red, fg->green, fg->blue);
+ guicolor_T guibg = gui_mch_get_rgb_color(bg->red, bg->green, bg->blue);
+ return get_gui_attr_idx(attr, guifg, guibg);
}
else
#endif
#ifdef FEAT_TERMGUICOLORS
if (p_tgc)
{
- guicolor_T fg = INVALCOLOR;
- guicolor_T bg = INVALCOLOR;
-
- // Use the 'wincolor' or "Terminal" highlighting for the default
- // colors.
- if (VTERM_COLOR_IS_DEFAULT_FG(&cellfg)
- || VTERM_COLOR_IS_DEFAULT_BG(&cellbg))
- {
- int id = 0;
-
- if (wp != NULL && *wp->w_p_wcr != NUL)
- id = syn_name2id(wp->w_p_wcr);
- if (id == 0)
- id = syn_name2id(term_get_highlight_name(term));
- if (id > 0)
- syn_id2colors(id, &fg, &bg);
- if (!VTERM_COLOR_IS_DEFAULT_FG(&cellfg))
- fg = gui_get_rgb_color_cmn(cellfg.red, cellfg.green,
- cellfg.blue);
- if (!VTERM_COLOR_IS_DEFAULT_BG(&cellbg))
- bg = gui_get_rgb_color_cmn(cellbg.red, cellbg.green,
- cellbg.blue);
- }
- else
- {
- fg = gui_get_rgb_color_cmn(cellfg.red, cellfg.green, cellfg.blue);
- bg = gui_get_rgb_color_cmn(cellbg.red, cellbg.green, cellbg.blue);
- }
-
- return get_tgc_attr_idx(attr, fg, bg);
+ guicolor_T tgcfg = VTERM_COLOR_IS_INVALID(fg)
+ ? INVALCOLOR
+ : gui_get_rgb_color_cmn(fg->red, fg->green, fg->blue);
+ guicolor_T tgcbg = VTERM_COLOR_IS_INVALID(bg)
+ ? INVALCOLOR
+ : gui_get_rgb_color_cmn(bg->red, bg->green, bg->blue);
+ return get_tgc_attr_idx(attr, tgcfg, tgcbg);
}
else
#endif
{
int bold = MAYBE;
- int fg = color2index(&cellfg, TRUE, &bold);
- int bg = color2index(&cellbg, FALSE, &bold);
-
- // Use the 'wincolor' or "Terminal" highlighting for the default
- // colors.
- if ((fg == 0 || bg == 0) && t_colors >= 16)
- {
- int cterm_fg = -1;
- int cterm_bg = -1;
- int id = 0;
-
- if (wp != NULL && *wp->w_p_wcr != NUL)
- id = syn_name2id(wp->w_p_wcr);
- if (id == 0)
- id = syn_name2id(term_get_highlight_name(term));
- if (id > 0)
- syn_id2cterm_bg(id, &cterm_fg, &cterm_bg);
- if (fg == 0 && cterm_fg >= 0)
- fg = cterm_fg + 1;
- if (bg == 0 && cterm_bg >= 0)
- bg = cterm_bg + 1;
- }
+ int ctermfg = color2index(fg, TRUE, &bold);
+ int ctermbg = color2index(bg, FALSE, &bold);
// with 8 colors set the bold attribute to get a bright foreground
if (bold == TRUE)
attr |= HL_BOLD;
- return get_cterm_attr_idx(attr, fg, bg);
+
+ return get_cterm_attr_idx(attr, ctermfg, ctermbg);
}
return 0;
}
@@ -2988,7 +2972,7 @@ term_scroll_up(term_T *term, int start_row, int count)
// Set the color to clear lines with.
vterm_state_get_default_colors(vterm_obtain_state(term->tl_vterm),
&fg, &bg);
- clear_attr = cell2attr(term, wp, attr, fg, bg);
+ clear_attr = cell2attr(term, wp, &attr, &fg, &bg);
win_del_lines(wp, start_row, count, FALSE, FALSE, clear_attr);
}
}
@@ -3633,7 +3617,8 @@ term_line2screenline(
// This will only store the lower byte of "c".
ScreenLines[off] = c;
}
- ScreenAttrs[off] = cell2attr(term, wp, cell.attrs, cell.fg, cell.bg);
+ ScreenAttrs[off] = cell2attr(term, wp, &cell.attrs, &cell.fg,
+ &cell.bg);
++pos->col;
++off;
@@ -3893,7 +3878,7 @@ term_get_attr(win_T *wp, linenr_T lnum, int col)
else
cellattr = line->sb_cells + col;
}
- return cell2attr(term, wp, cellattr->attrs, cellattr->fg, cellattr->bg);
+ return cell2attr(term, wp, &cellattr->attrs, &cellattr->fg, &cellattr->bg);
}
/*
@@ -3914,45 +3899,15 @@ cterm_color2vterm(int nr, VTermColor *rgb)
}
/*
- * Initialize term->tl_default_color from the environment.
+ * Initialize vterm color from the synID.
+ * Returns TRUE if color is set to "fg" and "bg".
+ * Otherwise returns FALSE.
*/
- static void
-init_default_colors(term_T *term, win_T *wp)
+ static int
+get_vterm_color_from_synid(int id, VTermColor *fg, VTermColor *bg)
{
- VTermColor *fg, *bg;
- int fgval, bgval;
- int id;
-
- CLEAR_FIELD(term->tl_default_color.attrs);
- term->tl_default_color.width = 1;
- fg = &term->tl_default_color.fg;
- bg = &term->tl_default_color.bg;
-
- // Vterm uses a default black background. Set it to white when
- // 'background' is "light".
- if (*p_bg == 'l')
- {
- fgval = 0;
- bgval = 255;
- }
- else
- {
- fgval = 255;
- bgval = 0;
- }
- fg->red = fg->green = fg->blue = fgval;
- bg->red = bg->green = bg->blue = bgval;
- fg->type = VTERM_COLOR_RGB | VTERM_COLOR_DEFAULT_FG;
- bg->type = VTERM_COLOR_RGB | VTERM_COLOR_DEFAULT_BG;
-
- // The 'wincolor' or the highlight group overrules the defaults.
- if (wp != NULL && *wp->w_p_wcr != NUL)
- id = syn_name2id(wp->w_p_wcr);
- else
- id = syn_name2id(term_get_highlight_name(term));
-
- // Use the actual color for the GUI and when 'termguicolors' is set.
#if defined(FEAT_GUI) || defined(FEAT_TERMGUICOLORS)
+ // Use the actual color for the GUI and when 'termguicolors' is set.
if (0
# ifdef FEAT_GUI
|| gui.in_use
@@ -3966,64 +3921,141 @@ init_default_colors(term_T *term, win_T *wp)
# endif
)
{
- guicolor_T fg_rgb = INVALCOLOR;
- guicolor_T bg_rgb = INVALCOLOR;
+ guicolor_T fg_rgb = INVALCOLOR;
+ guicolor_T bg_rgb = INVALCOLOR;
- if (id != 0)
+ if (id > 0)
syn_id2colors(id, &fg_rgb, &bg_rgb);
-# ifdef FEAT_GUI
- if (gui.in_use)
- {
- if (fg_rgb == INVALCOLOR)
- fg_rgb = gui.norm_pixel;
- if (bg_rgb == INVALCOLOR)
- bg_rgb = gui.back_pixel;
- }
-# ifdef FEAT_TERMGUICOLORS
- else
-# endif
-# endif
-# ifdef FEAT_TERMGUICOLORS
- {
- if (fg_rgb == INVALCOLOR)
- fg_rgb = cterm_normal_fg_gui_color;
- if (bg_rgb == INVALCOLOR)
- bg_rgb = cterm_normal_bg_gui_color;
- }
-# endif
if (fg_rgb != INVALCOLOR)
{
long_u rgb = GUI_MCH_GET_RGB(fg_rgb);
-
fg->red = (unsigned)(rgb >> 16);
fg->green = (unsigned)(rgb >> 8) & 255;
fg->blue = (unsigned)rgb & 255;
+ fg->type = VTERM_COLOR_RGB | VTERM_COLOR_DEFAULT_FG;
}
+ else
+ fg->type = VTERM_COLOR_INVALID | VTERM_COLOR_DEFAULT_FG;
+
if (bg_rgb != INVALCOLOR)
{
long_u rgb = GUI_MCH_GET_RGB(bg_rgb);
-
bg->red = (unsigned)(rgb >> 16);
bg->green = (unsigned)(rgb >> 8) & 255;
bg->blue = (unsigned)rgb & 255;
+ bg->type = VTERM_COLOR_RGB | VTERM_COLOR_DEFAULT_BG;
}
+ else
+ bg->type = VTERM_COLOR_INVALID | VTERM_COLOR_DEFAULT_BG;
+
+ return TRUE;
}
else
#endif
- if (id != 0 && t_colors >= 16)
+ if (t_colors >= 16)
{
int cterm_fg = -1;
int cterm_bg = -1;
- syn_id2cterm_bg(id, &cterm_fg, &cterm_bg);
+
+ if (id > 0)
+ syn_id2cterm_bg(id, &cterm_fg, &cterm_bg);
if (cterm_fg >= 0)
+ {
cterm_color2vterm(cterm_fg, fg);
+ fg->type |= VTERM_COLOR_DEFAULT_FG;
+ }
+ else
+ fg->type = VTERM_COLOR_INVALID | VTERM_COLOR_DEFAULT_FG;
+
if (cterm_bg >= 0)
+ {
cterm_color2vterm(cterm_bg, bg);
+ bg->type |= VTERM_COLOR_DEFAULT_BG;
+ }
+ else
+ bg->type = VTERM_COLOR_INVALID | VTERM_COLOR_DEFAULT_BG;
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+ void
+term_reset_wincolor(win_T *wp)
+{
+ wp->w_term_wincolor.fg.type = VTERM_COLOR_INVALID | VTERM_COLOR_DEFAULT_FG;
+ wp->w_term_wincolor.bg.type = VTERM_COLOR_INVALID | VTERM_COLOR_DEFAULT_BG;
+}
+
+/*
+ * Cache the color of 'wincolor'.
+ */
+ void
+term_update_wincolor(win_T *wp)
+{
+ int id = 0;
+
+ if (*wp->w_p_wcr != NUL)
+ id = syn_name2id(wp->w_p_wcr);
+ if (id == 0 || !get_vterm_color_from_synid(id, &wp->w_term_wincolor.fg,
+ &wp->w_term_wincolor.bg))
+ term_reset_wincolor(wp);
+}
+
+/*
+ * Called when option 'termguicolors' was set,
+ * or when any highlight is changed.
+ */
+ void
+term_update_wincolor_all()
+{
+ win_T *wp = NULL;
+ int did_curwin = FALSE;
+
+ while (for_all_windows_and_curwin(&wp, &did_curwin))
+ term_update_wincolor(wp);
+}
+
+/*
+ * Initialize term->tl_default_color from the environment.
+ */
+ static void
+init_default_colors(term_T *term)
+{
+ VTermColor *fg, *bg;
+ int fgval, bgval;
+ int id;
+
+ CLEAR_FIELD(term->tl_default_color.attrs);
+ term->tl_default_color.width = 1;
+ fg = &term->tl_default_color.fg;
+ bg = &term->tl_default_color.bg;
+
+ // Vterm uses a default black background. Set it to white when
+ // 'background' is "light".
+ if (*p_bg == 'l')
+ {
+ fgval = 0;
+ bgval = 255;
}
else
{
+ fgval = 255;
+ bgval = 0;
+ }
+ fg->red = fg->green = fg->blue = fgval;
+ bg->red = bg->green = bg->blue = bgval;
+ fg->type = VTERM_COLOR_RGB | VTERM_COLOR_DEFAULT_FG;
+ bg->type = VTERM_COLOR_RGB | VTERM_COLOR_DEFAULT_BG;
+
+ // The highlight group overrules the defaults.
+ id = term_get_highlight_id(term, NULL);
+
+ if (!get_vterm_color_from_synid(id, fg, bg))
+ {
#if defined(MSWIN) && (!defined(FEAT_GUI_MSWIN) || defined(VIMDLL))
int tmp;
#endif
@@ -4532,7 +4564,7 @@ create_vterm(term_T *term, int rows, int cols)
// TODO: depends on 'encoding'.
vterm_set_utf8(vterm, 1);
- init_default_colors(term, NULL);
+ init_default_colors(term);
vterm_state_set_default_colors(
state,
@@ -4568,36 +4600,24 @@ create_vterm(term_T *term, int rows, int cols)
}
/*
- * Called when 'wincolor' was set.
- */
- void
-term_update_colors(term_T *term)
-{
- win_T *wp;
-
- if (term->tl_vterm == NULL)
- return;
- init_default_colors(term, curwin);
- vterm_state_set_default_colors(
- vterm_obtain_state(term->tl_vterm),
- &term->tl_default_color.fg,
- &term->tl_default_color.bg);
-
- FOR_ALL_WINDOWS(wp)
- if (wp->w_buffer == term->tl_buffer)
- redraw_win_later(wp, NOT_VALID);
-}
-
-/*
- * Called when 'background' was set.
+ * Called when option 'background' or 'termguicolors' was set,
+ * or when any highlight is changed.
*/
void
term_update_colors_all(void)
{
- term_T *tp;
+ term_T *term;
- FOR_ALL_TERMS(tp)
- term_update_colors(tp);
+ FOR_ALL_TERMS(term)
+ {
+ if (term->tl_vterm == NULL)
+ continue;
+ init_default_colors(term);
+ vterm_state_set_default_colors(
+ vterm_obtain_state(term->tl_vterm),
+ &term->tl_default_color.fg,
+ &term->tl_default_color.bg);
+ }
}
/*
@@ -4692,8 +4712,8 @@ term_get_buf(typval_T *argvars, char *where)
clear_cell(VTermScreenCell *cell)
{
CLEAR_FIELD(*cell);
- cell->fg.type = VTERM_COLOR_DEFAULT_FG;
- cell->bg.type = VTERM_COLOR_DEFAULT_BG;
+ cell->fg.type = VTERM_COLOR_INVALID | VTERM_COLOR_DEFAULT_FG;
+ cell->bg.type = VTERM_COLOR_INVALID | VTERM_COLOR_DEFAULT_BG;
}
static void
@@ -4844,8 +4864,8 @@ f_term_dumpwrite(typval_T *argvars, typval_T *rettv UNUSED)
if (should_break)
break;
}
- same_attr = vtermAttr2hl(cell.attrs)
- == vtermAttr2hl(prev_cell.attrs)
+ same_attr = vtermAttr2hl(&cell.attrs)
+ == vtermAttr2hl(&prev_cell.attrs)
&& vterm_color_is_equal(&cell.fg, &prev_cell.fg)
&& vterm_color_is_equal(&cell.bg, &prev_cell.bg);
if (same_chars && cell.width == prev_cell.width && same_attr
@@ -4893,7 +4913,7 @@ f_term_dumpwrite(typval_T *argvars, typval_T *rettv UNUSED)
}
else
{
- fprintf(fd, "%d", vtermAttr2hl(cell.attrs));
+ fprintf(fd, "%d", vtermAttr2hl(&cell.attrs));
if (vterm_color_is_equal(&cell.fg, &prev_cell.fg))
fputs("&", fd);
else
@@ -5344,7 +5364,7 @@ term_load_dump(typval_T *argvars, typval_T *rettv, int do_diff)
VTermPos cursor_pos1;
VTermPos cursor_pos2;
- init_default_colors(term, NULL);
+ init_default_colors(term);
rettv->vval.v_number = buf->b_fnum;
@@ -5454,8 +5474,8 @@ term_load_dump(typval_T *argvars, typval_T *rettv, int do_diff)
else if (!vterm_color_is_equal(&(cellattr1 + col)->bg,
&(cellattr2 + col)->bg))
textline[col] = 'b';
- else if (vtermAttr2hl((cellattr1 + col)->attrs)
- != vtermAttr2hl(((cellattr2 + col)->attrs)))
+ else if (vtermAttr2hl(&(cellattr1 + col)->attrs)
+ != vtermAttr2hl(&((cellattr2 + col)->attrs)))
textline[col] = 'a';
}
p1 += len1;
@@ -6134,7 +6154,8 @@ f_term_scrape(typval_T *argvars, typval_T *rettv)
bg.red, bg.green, bg.blue);
dict_add_string(dcell, "bg", rgb);
- dict_add_number(dcell, "attr", cell2attr(term, NULL, attrs, fg, bg));
+ dict_add_number(dcell, "attr",
+ cell2attr(term, NULL, &attrs, &fg, &bg));
dict_add_number(dcell, "width", width);
++pos.col;