diff options
author | LemonBoy <thatlemon@gmail.com> | 2022-05-20 10:10:34 +0100 |
---|---|---|
committer | Bram Moolenaar <Bram@vim.org> | 2022-05-20 10:10:34 +0100 |
commit | b2b3acbf2b3ae29ecf517f03b46fbeadf0c1a905 (patch) | |
tree | becd5281fbad0eba88ff2e54211157f4af4a0089 /src/terminal.c | |
parent | 1755a91851f7022fdd3eecfbd2cc0b508a2f2a8f (diff) |
patch 8.2.4982: colors in terminal window are not 100% correctv8.2.4982
Problem: Colors in terminal window are not 100% correct.
Solution: Use g:terminal_ansi_colors as documented. (closes #10429,
closes #7227 closes #10347)
Diffstat (limited to 'src/terminal.c')
-rw-r--r-- | src/terminal.c | 207 |
1 files changed, 163 insertions, 44 deletions
diff --git a/src/terminal.c b/src/terminal.c index 703966a877..4c8ee7feab 100644 --- a/src/terminal.c +++ b/src/terminal.c @@ -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 }; @@ -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 @@ -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 @@ -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); } } @@ -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) @@ -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 @@ -4690,6 +4719,62 @@ create_vterm(term_T *term, int rows, int cols) } /* + * 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. */ @@ -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 @@ -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 @@ -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); @@ -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); @@ -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); |