Mercurial > vim
comparison src/terminal.c @ 28919:99c1356f4210 v8.2.4982
patch 8.2.4982: colors in terminal window are not 100% correct
Commit: https://github.com/vim/vim/commit/b2b3acbf2b3ae29ecf517f03b46fbeadf0c1a905
Author: LemonBoy <thatlemon@gmail.com>
Date: Fri May 20 10:10:34 2022 +0100
patch 8.2.4982: colors in terminal window are not 100% correct
Problem: Colors in terminal window are not 100% correct.
Solution: Use g:terminal_ansi_colors as documented. (closes https://github.com/vim/vim/issues/10429,
closes #7227 closes #10347)
author | Bram Moolenaar <Bram@vim.org> |
---|---|
date | Fri, 20 May 2022 11:15:04 +0200 |
parents | d0241e74bfdb |
children | 983ec746af54 |
comparison
equal
deleted
inserted
replaced
28918:ec2988a3b03c | 28919:99c1356f4210 |
---|---|
160 int tl_cursor_visible; | 160 int tl_cursor_visible; |
161 int tl_cursor_blink; | 161 int tl_cursor_blink; |
162 int tl_cursor_shape; // 1: block, 2: underline, 3: bar | 162 int tl_cursor_shape; // 1: block, 2: underline, 3: bar |
163 char_u *tl_cursor_color; // NULL or allocated | 163 char_u *tl_cursor_color; // NULL or allocated |
164 | 164 |
165 long_u *tl_palette; // array of 16 colors specified by term_start, can | |
166 // be NULL | |
165 int tl_using_altscreen; | 167 int tl_using_altscreen; |
166 garray_T tl_osc_buf; // incomplete OSC string | 168 garray_T tl_osc_buf; // incomplete OSC string |
167 }; | 169 }; |
168 | 170 |
169 #define TMODE_ONCE 1 // CTRL-\ CTRL-N used | 171 #define TMODE_ONCE 1 // CTRL-\ CTRL-N used |
238 | 240 |
239 static char_u * | 241 static char_u * |
240 cursor_color_get(char_u *color) | 242 cursor_color_get(char_u *color) |
241 { | 243 { |
242 return (color == NULL) ? (char_u *)"" : color; | 244 return (color == NULL) ? (char_u *)"" : color; |
245 } | |
246 | |
247 /* | |
248 * Return TRUE if the user-defined palette (either g:terminal_ansi_colors or the | |
249 * "ansi_colors" argument in term_start()) shall be applied. | |
250 */ | |
251 static int | |
252 term_use_palette() | |
253 { | |
254 if (0 | |
255 #ifdef FEAT_GUI | |
256 || gui.in_use | |
257 #endif | |
258 #ifdef FEAT_TERMGUICOLORS | |
259 || p_tgc | |
260 #endif | |
261 ) | |
262 return TRUE; | |
263 return FALSE; | |
243 } | 264 } |
244 | 265 |
245 | 266 |
246 /* | 267 /* |
247 * Parse 'termwinsize' and set "rows" and "cols" for the terminal size in the | 268 * Parse 'termwinsize' and set "rows" and "cols" for the terminal size in the |
702 else | 723 else |
703 term->tl_api = vim_strsave((char_u *)"Tapi_"); | 724 term->tl_api = vim_strsave((char_u *)"Tapi_"); |
704 | 725 |
705 if (opt->jo_set2 & JO2_TERM_HIGHLIGHT) | 726 if (opt->jo_set2 & JO2_TERM_HIGHLIGHT) |
706 term->tl_highlight_name = vim_strsave(opt->jo_term_highlight); | 727 term->tl_highlight_name = vim_strsave(opt->jo_term_highlight); |
728 | |
729 // Save the user-defined palette, it is only used in GUI (or 'tgc' is on). | |
730 if (opt->jo_set2 & JO2_ANSI_COLORS) | |
731 { | |
732 term->tl_palette = ALLOC_MULT(long_u, 16); | |
733 if (term->tl_palette == NULL) | |
734 { | |
735 vim_free(term); | |
736 return NULL; | |
737 } | |
738 memcpy(term->tl_palette, opt->jo_ansi_colors, sizeof(long_u) * 16); | |
739 } | |
707 | 740 |
708 // System dependent: setup the vterm and maybe start the job in it. | 741 // System dependent: setup the vterm and maybe start the job in it. |
709 if (argv == NULL | 742 if (argv == NULL |
710 && argvar->v_type == VAR_STRING | 743 && argvar->v_type == VAR_STRING |
711 && argvar->vval.v_string != NULL | 744 && argvar->vval.v_string != NULL |
1116 if (term->tl_out_fd != NULL) | 1149 if (term->tl_out_fd != NULL) |
1117 fclose(term->tl_out_fd); | 1150 fclose(term->tl_out_fd); |
1118 #endif | 1151 #endif |
1119 vim_free(term->tl_highlight_name); | 1152 vim_free(term->tl_highlight_name); |
1120 vim_free(term->tl_cursor_color); | 1153 vim_free(term->tl_cursor_color); |
1154 vim_free(term->tl_palette); | |
1121 vim_free(term); | 1155 vim_free(term); |
1122 } | 1156 } |
1123 } | 1157 } |
1124 | 1158 |
1125 /* | 1159 /* |
2793 { | 2827 { |
2794 int red = color->red; | 2828 int red = color->red; |
2795 int blue = color->blue; | 2829 int blue = color->blue; |
2796 int green = color->green; | 2830 int green = color->green; |
2797 | 2831 |
2832 *boldp = FALSE; | |
2833 | |
2798 if (VTERM_COLOR_IS_INVALID(color)) | 2834 if (VTERM_COLOR_IS_INVALID(color)) |
2799 return 0; | 2835 return 0; |
2836 | |
2800 if (VTERM_COLOR_IS_INDEXED(color)) | 2837 if (VTERM_COLOR_IS_INDEXED(color)) |
2801 { | 2838 { |
2802 // The first 16 colors and default: use the ANSI index. | 2839 // Use the color as-is if possible, give up otherwise. |
2803 switch (color->index + 1) | 2840 if (color->index < t_colors) |
2804 { | 2841 return color->index + 1; |
2805 case 0: return 0; | 2842 // 8-color terminals can actually display twice as many colors by |
2806 case 1: return lookup_color( 0, fg, boldp) + 1; // black | 2843 // setting the high-intensity/bold bit. |
2807 case 2: return lookup_color( 4, fg, boldp) + 1; // dark red | 2844 else if (t_colors == 8 && fg && color->index < 16) |
2808 case 3: return lookup_color( 2, fg, boldp) + 1; // dark green | 2845 { |
2809 case 4: return lookup_color( 7, fg, boldp) + 1; // dark yellow | 2846 *boldp = TRUE; |
2810 case 5: return lookup_color( 1, fg, boldp) + 1; // dark blue | 2847 return (color->index & 7) + 1; |
2811 case 6: return lookup_color( 5, fg, boldp) + 1; // dark magenta | 2848 } |
2812 case 7: return lookup_color( 3, fg, boldp) + 1; // dark cyan | 2849 return 0; |
2813 case 8: return lookup_color( 8, fg, boldp) + 1; // light grey | |
2814 case 9: return lookup_color(12, fg, boldp) + 1; // dark grey | |
2815 case 10: return lookup_color(20, fg, boldp) + 1; // red | |
2816 case 11: return lookup_color(16, fg, boldp) + 1; // green | |
2817 case 12: return lookup_color(24, fg, boldp) + 1; // yellow | |
2818 case 13: return lookup_color(14, fg, boldp) + 1; // blue | |
2819 case 14: return lookup_color(22, fg, boldp) + 1; // magenta | |
2820 case 15: return lookup_color(18, fg, boldp) + 1; // cyan | |
2821 case 16: return lookup_color(26, fg, boldp) + 1; // white | |
2822 } | |
2823 } | 2850 } |
2824 | 2851 |
2825 if (t_colors >= 256) | 2852 if (t_colors >= 256) |
2826 { | 2853 { |
2827 if (red == blue && red == green) | 2854 if (red == blue && red == green) |
4249 static void | 4276 static void |
4250 init_vterm_ansi_colors(VTerm *vterm) | 4277 init_vterm_ansi_colors(VTerm *vterm) |
4251 { | 4278 { |
4252 dictitem_T *var = find_var((char_u *)"g:terminal_ansi_colors", NULL, TRUE); | 4279 dictitem_T *var = find_var((char_u *)"g:terminal_ansi_colors", NULL, TRUE); |
4253 | 4280 |
4254 if (var != NULL | 4281 if (var == NULL) |
4255 && (var->di_tv.v_type != VAR_LIST | 4282 return; |
4256 || var->di_tv.vval.v_list == NULL | 4283 |
4257 || var->di_tv.vval.v_list->lv_first == &range_list_item | 4284 if (var->di_tv.v_type != VAR_LIST |
4258 || set_ansi_colors_list(vterm, var->di_tv.vval.v_list) == FAIL)) | 4285 || var->di_tv.vval.v_list == NULL |
4286 || var->di_tv.vval.v_list->lv_first == &range_list_item | |
4287 || set_ansi_colors_list(vterm, var->di_tv.vval.v_list) == FAIL) | |
4259 semsg(_(e_invalid_argument_str), "g:terminal_ansi_colors"); | 4288 semsg(_(e_invalid_argument_str), "g:terminal_ansi_colors"); |
4260 } | 4289 } |
4261 #endif | 4290 #endif |
4262 | 4291 |
4263 /* | 4292 /* |
4685 #endif | 4714 #endif |
4686 vterm_state_set_termprop(state, VTERM_PROP_CURSORBLINK, &value); | 4715 vterm_state_set_termprop(state, VTERM_PROP_CURSORBLINK, &value); |
4687 vterm_state_set_unrecognised_fallbacks(state, &state_fallbacks, term); | 4716 vterm_state_set_unrecognised_fallbacks(state, &state_fallbacks, term); |
4688 | 4717 |
4689 return OK; | 4718 return OK; |
4719 } | |
4720 | |
4721 /* | |
4722 * Reset the terminal palette to its default value. | |
4723 */ | |
4724 static void | |
4725 term_reset_palette(VTerm *vterm) | |
4726 { | |
4727 VTermState *state = vterm_obtain_state(vterm); | |
4728 int index; | |
4729 | |
4730 for (index = 0; index < 16; index++) | |
4731 { | |
4732 VTermColor color; | |
4733 | |
4734 color.type = VTERM_COLOR_INDEXED; | |
4735 ansi_color2rgb(index, &color.red, &color.green, &color.blue, | |
4736 &color.index); | |
4737 // The first valid index starts at 1. | |
4738 color.index -= 1; | |
4739 | |
4740 vterm_state_set_palette_color(state, index, &color); | |
4741 } | |
4742 } | |
4743 | |
4744 static void | |
4745 term_update_palette(term_T *term) | |
4746 { | |
4747 if (term_use_palette() | |
4748 && (term->tl_palette != NULL | |
4749 || find_var((char_u *)"g:terminal_ansi_colors", NULL, TRUE) | |
4750 != NULL)) | |
4751 { | |
4752 if (term->tl_palette != NULL) | |
4753 set_vterm_palette(term->tl_vterm, term->tl_palette); | |
4754 else | |
4755 init_vterm_ansi_colors(term->tl_vterm); | |
4756 } | |
4757 else | |
4758 term_reset_palette(term->tl_vterm); | |
4759 } | |
4760 | |
4761 /* | |
4762 * Called when option 'termguicolors' is changed. | |
4763 */ | |
4764 void | |
4765 term_update_palette_all() | |
4766 { | |
4767 term_T *term; | |
4768 | |
4769 FOR_ALL_TERMS(term) | |
4770 { | |
4771 if (term->tl_vterm == NULL) | |
4772 continue; | |
4773 term_update_palette(term); | |
4774 } | |
4690 } | 4775 } |
4691 | 4776 |
4692 /* | 4777 /* |
4693 * Called when option 'background' or 'termguicolors' was set, | 4778 * Called when option 'background' or 'termguicolors' was set, |
4694 * or when any highlight is changed. | 4779 * or when any highlight is changed. |
6344 void | 6429 void |
6345 f_term_setansicolors(typval_T *argvars, typval_T *rettv UNUSED) | 6430 f_term_setansicolors(typval_T *argvars, typval_T *rettv UNUSED) |
6346 { | 6431 { |
6347 buf_T *buf; | 6432 buf_T *buf; |
6348 term_T *term; | 6433 term_T *term; |
6434 listitem_T *li; | |
6435 int n = 0; | |
6349 | 6436 |
6350 if (in_vim9script() | 6437 if (in_vim9script() |
6351 && (check_for_buffer_arg(argvars, 0) == FAIL | 6438 && (check_for_buffer_arg(argvars, 0) == FAIL |
6352 || check_for_list_arg(argvars, 1) == FAIL)) | 6439 || check_for_list_arg(argvars, 1) == FAIL)) |
6353 return; | 6440 return; |
6362 if (argvars[1].v_type != VAR_LIST || argvars[1].vval.v_list == NULL) | 6449 if (argvars[1].v_type != VAR_LIST || argvars[1].vval.v_list == NULL) |
6363 { | 6450 { |
6364 emsg(_(e_list_required)); | 6451 emsg(_(e_list_required)); |
6365 return; | 6452 return; |
6366 } | 6453 } |
6367 | 6454 if (argvars[1].vval.v_list->lv_first == &range_list_item |
6368 if (set_ansi_colors_list(term->tl_vterm, argvars[1].vval.v_list) == FAIL) | 6455 || argvars[1].vval.v_list->lv_len != 16) |
6456 { | |
6369 emsg(_(e_invalid_argument)); | 6457 emsg(_(e_invalid_argument)); |
6458 return; | |
6459 } | |
6460 | |
6461 if (term->tl_palette == NULL) | |
6462 term->tl_palette = ALLOC_MULT(long_u, 16); | |
6463 if (term->tl_palette == NULL) | |
6464 return; | |
6465 | |
6466 FOR_ALL_LIST_ITEMS(argvars[1].vval.v_list, li) | |
6467 { | |
6468 char_u *color_name; | |
6469 guicolor_T guicolor; | |
6470 | |
6471 color_name = tv_get_string_chk(&li->li_tv); | |
6472 if (color_name == NULL) | |
6473 return; | |
6474 | |
6475 guicolor = GUI_GET_COLOR(color_name); | |
6476 if (guicolor == INVALCOLOR) | |
6477 { | |
6478 semsg(_(e_cannot_allocate_color_str), color_name); | |
6479 return; | |
6480 } | |
6481 | |
6482 term->tl_palette[n++] = GUI_MCH_GET_RGB(guicolor); | |
6483 } | |
6484 | |
6485 term_update_palette(term); | |
6370 } | 6486 } |
6371 #endif | 6487 #endif |
6372 | 6488 |
6373 /* | 6489 /* |
6374 * "term_setapi(buf, api)" function | 6490 * "term_setapi(buf, api)" function |
6821 vim_free(env_wchar); | 6937 vim_free(env_wchar); |
6822 | 6938 |
6823 if (create_vterm(term, term->tl_rows, term->tl_cols) == FAIL) | 6939 if (create_vterm(term, term->tl_rows, term->tl_cols) == FAIL) |
6824 goto failed; | 6940 goto failed; |
6825 | 6941 |
6826 #if defined(FEAT_GUI) || defined(FEAT_TERMGUICOLORS) | 6942 if (term_use_palette()) |
6827 if (opt->jo_set2 & JO2_ANSI_COLORS) | 6943 { |
6828 set_vterm_palette(term->tl_vterm, opt->jo_ansi_colors); | 6944 if (term->tl_palette != NULL) |
6829 else | 6945 set_vterm_palette(term->tl_vterm, term->tl_palette); |
6830 init_vterm_ansi_colors(term->tl_vterm); | 6946 else |
6831 #endif | 6947 init_vterm_ansi_colors(term->tl_vterm); |
6948 } | |
6832 | 6949 |
6833 channel_set_job(channel, job, opt); | 6950 channel_set_job(channel, job, opt); |
6834 job_set_options(job, opt); | 6951 job_set_options(job, opt); |
6835 | 6952 |
6836 job->jv_channel = channel; | 6953 job->jv_channel = channel; |
7152 vim_free(env_wchar); | 7269 vim_free(env_wchar); |
7153 | 7270 |
7154 if (create_vterm(term, term->tl_rows, term->tl_cols) == FAIL) | 7271 if (create_vterm(term, term->tl_rows, term->tl_cols) == FAIL) |
7155 goto failed; | 7272 goto failed; |
7156 | 7273 |
7157 #if defined(FEAT_GUI) || defined(FEAT_TERMGUICOLORS) | 7274 if (term_use_palette()) |
7158 if (opt->jo_set2 & JO2_ANSI_COLORS) | 7275 { |
7159 set_vterm_palette(term->tl_vterm, opt->jo_ansi_colors); | 7276 if (term->tl_palette != NULL) |
7160 else | 7277 set_vterm_palette(term->tl_vterm, term->tl_palette); |
7161 init_vterm_ansi_colors(term->tl_vterm); | 7278 else |
7162 #endif | 7279 init_vterm_ansi_colors(term->tl_vterm); |
7280 } | |
7163 | 7281 |
7164 channel_set_job(channel, job, opt); | 7282 channel_set_job(channel, job, opt); |
7165 job_set_options(job, opt); | 7283 job_set_options(job, opt); |
7166 | 7284 |
7167 job->jv_channel = channel; | 7285 job->jv_channel = channel; |
7411 term->tl_arg0_cmd = NULL; | 7529 term->tl_arg0_cmd = NULL; |
7412 | 7530 |
7413 if (create_vterm(term, term->tl_rows, term->tl_cols) == FAIL) | 7531 if (create_vterm(term, term->tl_rows, term->tl_cols) == FAIL) |
7414 return FAIL; | 7532 return FAIL; |
7415 | 7533 |
7416 #if defined(FEAT_GUI) || defined(FEAT_TERMGUICOLORS) | 7534 if (term_use_palette()) |
7417 if (opt->jo_set2 & JO2_ANSI_COLORS) | 7535 { |
7418 set_vterm_palette(term->tl_vterm, opt->jo_ansi_colors); | 7536 if (term->tl_palette != NULL) |
7419 else | 7537 set_vterm_palette(term->tl_vterm, term->tl_palette); |
7420 init_vterm_ansi_colors(term->tl_vterm); | 7538 else |
7421 #endif | 7539 init_vterm_ansi_colors(term->tl_vterm); |
7540 } | |
7422 | 7541 |
7423 // This may change a string in "argvar". | 7542 // This may change a string in "argvar". |
7424 term->tl_job = job_start(argvar, argv, opt, &term->tl_job); | 7543 term->tl_job = job_start(argvar, argv, opt, &term->tl_job); |
7425 if (term->tl_job != NULL) | 7544 if (term->tl_job != NULL) |
7426 ++term->tl_job->jv_refcount; | 7545 ++term->tl_job->jv_refcount; |