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;