Skip to content

Commit

Permalink
patch 8.2.4982: colors in terminal window are not 100% correct
Browse files Browse the repository at this point in the history
Problem:    Colors in terminal window are not 100% correct.
Solution:   Use g:terminal_ansi_colors as documented. (closes #10429,
            closes #7227 closes #10347)
  • Loading branch information
LemonBoy authored and brammool committed May 20, 2022
1 parent 1755a91 commit b2b3acb
Show file tree
Hide file tree
Showing 9 changed files with 204 additions and 49 deletions.
4 changes: 2 additions & 2 deletions src/job.c
Original file line number Diff line number Diff line change
Expand Up @@ -548,13 +548,13 @@ get_job_options(typval_T *tv, jobopt_T *opt, int supported, int supported2)
break;

if (item == NULL || item->v_type != VAR_LIST
|| item->vval.v_list == NULL)
|| item->vval.v_list == NULL
|| item->vval.v_list->lv_first == &range_list_item)
{
semsg(_(e_invalid_value_for_argument_str), "ansi_colors");
return FAIL;
}

CHECK_LIST_MATERIALIZE(item->vval.v_list);
li = item->vval.v_list->lv_first;
for (; li != NULL && n < 16; li = li->li_next, n++)
{
Expand Down
1 change: 1 addition & 0 deletions src/option.c
Original file line number Diff line number Diff line change
Expand Up @@ -3255,6 +3255,7 @@ set_bool_option(
# endif
# ifdef FEAT_TERMINAL
term_update_colors_all();
term_update_palette_all();
term_update_wincolor_all();
# endif
}
Expand Down
1 change: 1 addition & 0 deletions src/proto/term.pro
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ void show_termcodes(int flags);
int show_one_termcode(char_u *name, char_u *code, int printit);
void update_tcap(int attr);
void swap_tcap(void);
void ansi_color2rgb(int nr, char_u *r, char_u *g, char_u *b, char_u *ansi_idx);
void cterm_color2rgb(int nr, char_u *r, char_u *g, char_u *b, char_u *ansi_idx);
void term_replace_bs_del_keycode(char_u *ta_buf, int ta_len, int len);
/* vim: set ft=c : */
1 change: 1 addition & 0 deletions src/proto/terminal.pro
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ int term_get_attr(win_T *wp, linenr_T lnum, int col);
void term_reset_wincolor(win_T *wp);
void term_update_wincolor(win_T *wp);
void term_update_wincolor_all(void);
void term_update_palette_all(void);
void term_update_colors_all(void);
char_u *term_get_status_text(term_T *term);
void term_clear_status_text(term_T *term);
Expand Down
21 changes: 20 additions & 1 deletion src/term.c
Original file line number Diff line number Diff line change
Expand Up @@ -6730,7 +6730,7 @@ static int grey_ramp[] = {
0x80, 0x8A, 0x94, 0x9E, 0xA8, 0xB2, 0xBC, 0xC6, 0xD0, 0xDA, 0xE4, 0xEE
};

static char_u ansi_table[16][3] = {
static const char_u ansi_table[16][3] = {
// R G B
{ 0, 0, 0}, // black
{224, 0, 0}, // dark red
Expand Down Expand Up @@ -6760,6 +6760,25 @@ static const char_u cterm_ansi_idx[] = {

#define ANSI_INDEX_NONE 0

void
ansi_color2rgb(int nr, char_u *r, char_u *g, char_u *b, char_u *ansi_idx)
{
if (nr < 16)
{
*r = ansi_table[nr][0];
*g = ansi_table[nr][1];
*b = ansi_table[nr][2];
*ansi_idx = nr;
}
else
{
*r = 0;
*g = 0;
*b = 0;
*ansi_idx = ANSI_INDEX_NONE;
}
}

void
cterm_color2rgb(int nr, char_u *r, char_u *g, char_u *b, char_u *ansi_idx)
{
Expand Down
207 changes: 163 additions & 44 deletions src/terminal.c
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,8 @@ struct terminal_S {
int tl_cursor_shape; // 1: block, 2: underline, 3: bar
char_u *tl_cursor_color; // NULL or allocated

long_u *tl_palette; // array of 16 colors specified by term_start, can
// be NULL
int tl_using_altscreen;
garray_T tl_osc_buf; // incomplete OSC string
};
Expand Down Expand Up @@ -242,6 +244,25 @@ cursor_color_get(char_u *color)
return (color == NULL) ? (char_u *)"" : color;
}

/*
* Return TRUE if the user-defined palette (either g:terminal_ansi_colors or the
* "ansi_colors" argument in term_start()) shall be applied.
*/
static int
term_use_palette()
{
if (0
#ifdef FEAT_GUI
|| gui.in_use
#endif
#ifdef FEAT_TERMGUICOLORS
|| p_tgc
#endif
)
return TRUE;
return FALSE;
}


/*
* Parse 'termwinsize' and set "rows" and "cols" for the terminal size in the
Expand Down Expand Up @@ -705,6 +726,18 @@ term_start(
if (opt->jo_set2 & JO2_TERM_HIGHLIGHT)
term->tl_highlight_name = vim_strsave(opt->jo_term_highlight);

// Save the user-defined palette, it is only used in GUI (or 'tgc' is on).
if (opt->jo_set2 & JO2_ANSI_COLORS)
{
term->tl_palette = ALLOC_MULT(long_u, 16);
if (term->tl_palette == NULL)
{
vim_free(term);
return NULL;
}
memcpy(term->tl_palette, opt->jo_ansi_colors, sizeof(long_u) * 16);
}

// System dependent: setup the vterm and maybe start the job in it.
if (argv == NULL
&& argvar->v_type == VAR_STRING
Expand Down Expand Up @@ -1118,6 +1151,7 @@ free_unused_terminals()
#endif
vim_free(term->tl_highlight_name);
vim_free(term->tl_cursor_color);
vim_free(term->tl_palette);
vim_free(term);
}
}
Expand Down Expand Up @@ -2795,31 +2829,24 @@ color2index(VTermColor *color, int fg, int *boldp)
int blue = color->blue;
int green = color->green;

*boldp = FALSE;

if (VTERM_COLOR_IS_INVALID(color))
return 0;

if (VTERM_COLOR_IS_INDEXED(color))
{
// The first 16 colors and default: use the ANSI index.
switch (color->index + 1)
// Use the color as-is if possible, give up otherwise.
if (color->index < t_colors)
return color->index + 1;
// 8-color terminals can actually display twice as many colors by
// setting the high-intensity/bold bit.
else if (t_colors == 8 && fg && color->index < 16)
{
case 0: return 0;
case 1: return lookup_color( 0, fg, boldp) + 1; // black
case 2: return lookup_color( 4, fg, boldp) + 1; // dark red
case 3: return lookup_color( 2, fg, boldp) + 1; // dark green
case 4: return lookup_color( 7, fg, boldp) + 1; // dark yellow
case 5: return lookup_color( 1, fg, boldp) + 1; // dark blue
case 6: return lookup_color( 5, fg, boldp) + 1; // dark magenta
case 7: return lookup_color( 3, fg, boldp) + 1; // dark cyan
case 8: return lookup_color( 8, fg, boldp) + 1; // light grey
case 9: return lookup_color(12, fg, boldp) + 1; // dark grey
case 10: return lookup_color(20, fg, boldp) + 1; // red
case 11: return lookup_color(16, fg, boldp) + 1; // green
case 12: return lookup_color(24, fg, boldp) + 1; // yellow
case 13: return lookup_color(14, fg, boldp) + 1; // blue
case 14: return lookup_color(22, fg, boldp) + 1; // magenta
case 15: return lookup_color(18, fg, boldp) + 1; // cyan
case 16: return lookup_color(26, fg, boldp) + 1; // white
*boldp = TRUE;
return (color->index & 7) + 1;
}
return 0;
}

if (t_colors >= 256)
Expand Down Expand Up @@ -4251,11 +4278,13 @@ init_vterm_ansi_colors(VTerm *vterm)
{
dictitem_T *var = find_var((char_u *)"g:terminal_ansi_colors", NULL, TRUE);

if (var != NULL
&& (var->di_tv.v_type != VAR_LIST
|| var->di_tv.vval.v_list == NULL
|| var->di_tv.vval.v_list->lv_first == &range_list_item
|| set_ansi_colors_list(vterm, var->di_tv.vval.v_list) == FAIL))
if (var == NULL)
return;

if (var->di_tv.v_type != VAR_LIST
|| var->di_tv.vval.v_list == NULL
|| var->di_tv.vval.v_list->lv_first == &range_list_item
|| set_ansi_colors_list(vterm, var->di_tv.vval.v_list) == FAIL)
semsg(_(e_invalid_argument_str), "g:terminal_ansi_colors");
}
#endif
Expand Down Expand Up @@ -4689,6 +4718,62 @@ create_vterm(term_T *term, int rows, int cols)
return OK;
}

/*
* Reset the terminal palette to its default value.
*/
static void
term_reset_palette(VTerm *vterm)
{
VTermState *state = vterm_obtain_state(vterm);
int index;

for (index = 0; index < 16; index++)
{
VTermColor color;

color.type = VTERM_COLOR_INDEXED;
ansi_color2rgb(index, &color.red, &color.green, &color.blue,
&color.index);
// The first valid index starts at 1.
color.index -= 1;

vterm_state_set_palette_color(state, index, &color);
}
}

static void
term_update_palette(term_T *term)
{
if (term_use_palette()
&& (term->tl_palette != NULL
|| find_var((char_u *)"g:terminal_ansi_colors", NULL, TRUE)
!= NULL))
{
if (term->tl_palette != NULL)
set_vterm_palette(term->tl_vterm, term->tl_palette);
else
init_vterm_ansi_colors(term->tl_vterm);
}
else
term_reset_palette(term->tl_vterm);
}

/*
* Called when option 'termguicolors' is changed.
*/
void
term_update_palette_all()
{
term_T *term;

FOR_ALL_TERMS(term)
{
if (term->tl_vterm == NULL)
continue;
term_update_palette(term);
}
}

/*
* Called when option 'background' or 'termguicolors' was set,
* or when any highlight is changed.
Expand Down Expand Up @@ -6346,6 +6431,8 @@ f_term_setansicolors(typval_T *argvars, typval_T *rettv UNUSED)
{
buf_T *buf;
term_T *term;
listitem_T *li;
int n = 0;

if (in_vim9script()
&& (check_for_buffer_arg(argvars, 0) == FAIL
Expand All @@ -6364,9 +6451,38 @@ f_term_setansicolors(typval_T *argvars, typval_T *rettv UNUSED)
emsg(_(e_list_required));
return;
}

if (set_ansi_colors_list(term->tl_vterm, argvars[1].vval.v_list) == FAIL)
if (argvars[1].vval.v_list->lv_first == &range_list_item
|| argvars[1].vval.v_list->lv_len != 16)
{
emsg(_(e_invalid_argument));
return;
}

if (term->tl_palette == NULL)
term->tl_palette = ALLOC_MULT(long_u, 16);
if (term->tl_palette == NULL)
return;

FOR_ALL_LIST_ITEMS(argvars[1].vval.v_list, li)
{
char_u *color_name;
guicolor_T guicolor;

color_name = tv_get_string_chk(&li->li_tv);
if (color_name == NULL)
return;

guicolor = GUI_GET_COLOR(color_name);
if (guicolor == INVALCOLOR)
{
semsg(_(e_cannot_allocate_color_str), color_name);
return;
}

term->tl_palette[n++] = GUI_MCH_GET_RGB(guicolor);
}

term_update_palette(term);
}
#endif

Expand Down Expand Up @@ -6823,12 +6939,13 @@ conpty_term_and_job_init(
if (create_vterm(term, term->tl_rows, term->tl_cols) == FAIL)
goto failed;

#if defined(FEAT_GUI) || defined(FEAT_TERMGUICOLORS)
if (opt->jo_set2 & JO2_ANSI_COLORS)
set_vterm_palette(term->tl_vterm, opt->jo_ansi_colors);
else
init_vterm_ansi_colors(term->tl_vterm);
#endif
if (term_use_palette())
{
if (term->tl_palette != NULL)
set_vterm_palette(term->tl_vterm, term->tl_palette);
else
init_vterm_ansi_colors(term->tl_vterm);
}

channel_set_job(channel, job, opt);
job_set_options(job, opt);
Expand Down Expand Up @@ -7154,12 +7271,13 @@ winpty_term_and_job_init(
if (create_vterm(term, term->tl_rows, term->tl_cols) == FAIL)
goto failed;

#if defined(FEAT_GUI) || defined(FEAT_TERMGUICOLORS)
if (opt->jo_set2 & JO2_ANSI_COLORS)
set_vterm_palette(term->tl_vterm, opt->jo_ansi_colors);
else
init_vterm_ansi_colors(term->tl_vterm);
#endif
if (term_use_palette())
{
if (term->tl_palette != NULL)
set_vterm_palette(term->tl_vterm, term->tl_palette);
else
init_vterm_ansi_colors(term->tl_vterm);
}

channel_set_job(channel, job, opt);
job_set_options(job, opt);
Expand Down Expand Up @@ -7413,12 +7531,13 @@ term_and_job_init(
if (create_vterm(term, term->tl_rows, term->tl_cols) == FAIL)
return FAIL;

#if defined(FEAT_GUI) || defined(FEAT_TERMGUICOLORS)
if (opt->jo_set2 & JO2_ANSI_COLORS)
set_vterm_palette(term->tl_vterm, opt->jo_ansi_colors);
else
init_vterm_ansi_colors(term->tl_vterm);
#endif
if (term_use_palette())
{
if (term->tl_palette != NULL)
set_vterm_palette(term->tl_vterm, term->tl_palette);
else
init_vterm_ansi_colors(term->tl_vterm);
}

// This may change a string in "argvar".
term->tl_job = job_start(argvar, argv, opt, &term->tl_job);
Expand Down
4 changes: 2 additions & 2 deletions src/testdir/test_functions.vim
Original file line number Diff line number Diff line change
Expand Up @@ -2679,8 +2679,8 @@ func Test_range()
else
let cmd = "ls"
endif
call assert_fails('call term_start("' .. cmd .. '", #{term_finish: "close"})', 'E475:')
unlet g:terminal_ansi_colors
call assert_fails('call term_start("' .. cmd .. '", #{term_finish: "close"'
\ .. ', ansi_colors: range(16)})', 'E475:')
endif

" type()
Expand Down

0 comments on commit b2b3acb

Please sign in to comment.