Patch 8.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)
Files:      src/job.c, src/option.c, src/proto/term.pro,
            src/terminal.c, src/proto/terminal.pro, src/term.c,
            src/testdir/test_functions.vim, src/testdir/test_terminal.vim


*** ../vim-8.2.4981/src/job.c   2022-05-09 20:09:19.286641426 +0100
--- src/job.c   2022-05-20 09:28:30.147063583 +0100
***************
*** 548,560 ****
                    break;
  
                if (item == NULL || item->v_type != VAR_LIST
!                       || item->vval.v_list == NULL)
                {
                    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++)
                {
--- 548,560 ----
                    break;
  
                if (item == NULL || item->v_type != VAR_LIST
!                       || 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;
                }
  
                li = item->vval.v_list->lv_first;
                for (; li != NULL && n < 16; li = li->li_next, n++)
                {
*** ../vim-8.2.4981/src/option.c        2022-05-09 20:09:19.290641428 +0100
--- src/option.c        2022-05-20 09:34:38.504068577 +0100
***************
*** 3255,3260 ****
--- 3255,3261 ----
  # endif
  # ifdef FEAT_TERMINAL
        term_update_colors_all();
+       term_update_palette_all();
        term_update_wincolor_all();
  # endif
      }
*** ../vim-8.2.4981/src/proto/term.pro  2021-12-03 20:43:20.088234242 +0000
--- src/proto/term.pro  2022-05-20 09:32:40.535766493 +0100
***************
*** 84,89 ****
--- 84,90 ----
  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 : */
*** ../vim-8.2.4981/src/terminal.c      2022-05-09 20:09:19.294641425 +0100
--- src/terminal.c      2022-05-20 09:34:36.096062524 +0100
***************
*** 162,167 ****
--- 162,169 ----
      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,247 ****
--- 244,268 ----
      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,710 ****
--- 726,743 ----
      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,1123 ****
--- 1151,1157 ----
  #endif
        vim_free(term->tl_highlight_name);
        vim_free(term->tl_cursor_color);
+       vim_free(term->tl_palette);
        vim_free(term);
      }
  }
***************
*** 2795,2825 ****
      int blue = color->blue;
      int green = color->green;
  
      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)
        {
!           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
        }
      }
  
      if (t_colors >= 256)
--- 2829,2852 ----
      int blue = color->blue;
      int green = color->green;
  
+     *boldp = FALSE;
+ 
      if (VTERM_COLOR_IS_INVALID(color))
        return 0;
+ 
      if (VTERM_COLOR_IS_INDEXED(color))
      {
!       // 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)
        {
!           *boldp = TRUE;
!           return (color->index & 7) + 1;
        }
+       return 0;
      }
  
      if (t_colors >= 256)
***************
*** 4251,4261 ****
  {
      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))
        semsg(_(e_invalid_argument_str), "g:terminal_ansi_colors");
  }
  #endif
--- 4278,4290 ----
  {
      dictitem_T        *var = find_var((char_u *)"g:terminal_ansi_colors", 
NULL, TRUE);
  
!     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,4695 ****
--- 4719,4780 ----
  }
  
  /*
+  * 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,6351 ****
--- 6431,6438 ----
  {
      buf_T     *buf;
      term_T    *term;
+     listitem_T        *li;
+     int               n = 0;
  
      if (in_vim9script()
            && (check_for_buffer_arg(argvars, 0) == FAIL
***************
*** 6364,6372 ****
        emsg(_(e_list_required));
        return;
      }
! 
!     if (set_ansi_colors_list(term->tl_vterm, argvars[1].vval.v_list) == FAIL)
        emsg(_(e_invalid_argument));
  }
  #endif
  
--- 6451,6488 ----
        emsg(_(e_list_required));
        return;
      }
!     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,6834 ****
      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
  
      channel_set_job(channel, job, opt);
      job_set_options(job, opt);
--- 6939,6951 ----
      if (create_vterm(term, term->tl_rows, term->tl_cols) == FAIL)
        goto failed;
  
!     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,7165 ****
      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
  
      channel_set_job(channel, job, opt);
      job_set_options(job, opt);
--- 7271,7283 ----
      if (create_vterm(term, term->tl_rows, term->tl_cols) == FAIL)
        goto failed;
  
!     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,7424 ****
      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
  
      // This may change a string in "argvar".
      term->tl_job = job_start(argvar, argv, opt, &term->tl_job);
--- 7531,7543 ----
      if (create_vterm(term, term->tl_rows, term->tl_cols) == FAIL)
        return FAIL;
  
!     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);
*** ../vim-8.2.4981/src/proto/terminal.pro      2021-12-13 21:59:04.895993159 
+0000
--- src/proto/terminal.pro      2022-05-20 09:34:11.155999571 +0100
***************
*** 34,39 ****
--- 34,40 ----
  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);
*** ../vim-8.2.4981/src/term.c  2022-05-09 20:09:19.294641425 +0100
--- src/term.c  2022-05-20 09:28:30.151063595 +0100
***************
*** 6730,6736 ****
      0x80, 0x8A, 0x94, 0x9E, 0xA8, 0xB2, 0xBC, 0xC6, 0xD0, 0xDA, 0xE4, 0xEE
  };
  
! static char_u ansi_table[16][3] = {
  //   R    G    B
    {  0,   0,   0}, // black
    {224,   0,   0}, // dark red
--- 6730,6736 ----
      0x80, 0x8A, 0x94, 0x9E, 0xA8, 0xB2, 0xBC, 0xC6, 0xD0, 0xDA, 0xE4, 0xEE
  };
  
! static const char_u ansi_table[16][3] = {
  //   R    G    B
    {  0,   0,   0}, // black
    {224,   0,   0}, // dark red
***************
*** 6761,6766 ****
--- 6761,6785 ----
  #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)
  {
      int idx;
*** ../vim-8.2.4981/src/testdir/test_functions.vim      2022-05-05 
20:18:12.408138480 +0100
--- src/testdir/test_functions.vim      2022-05-20 09:28:30.155063608 +0100
***************
*** 2679,2686 ****
      else
        let cmd = "ls"
      endif
!     call assert_fails('call term_start("' .. cmd .. '", #{term_finish: 
"close"})', 'E475:')
!     unlet g:terminal_ansi_colors
    endif
  
    " type()
--- 2679,2686 ----
      else
        let cmd = "ls"
      endif
!     call assert_fails('call term_start("' .. cmd .. '", #{term_finish: 
"close"'
!         \ .. ', ansi_colors: range(16)})', 'E475:')
    endif
  
    " type()
*** ../vim-8.2.4981/src/testdir/test_terminal.vim       2022-03-31 
12:33:56.485701120 +0100
--- src/testdir/test_terminal.vim       2022-05-20 09:28:30.155063608 +0100
***************
*** 2012,2021 ****
--- 2012,2027 ----
    CheckFeature termguicolors
    CheckFunction term_getansicolors
  
+   if has('vtp') && !has('vcon') && !has('gui_running')
+     throw 'Skipped: does not support termguicolors'
+   endif
+ 
+   set tgc
    let g:terminal_ansi_colors = reverse(copy(s:test_colors))
    let buf = Run_shell_in_terminal({})
    call assert_equal(g:terminal_ansi_colors, term_getansicolors(buf))
    call StopShellInTerminal(buf)
+   set tgc&
  
    exe buf . 'bwipe'
    unlet g:terminal_ansi_colors
***************
*** 2025,2030 ****
--- 2031,2041 ----
    CheckFeature termguicolors
    CheckFunction term_getansicolors
  
+   if has('vtp') && !has('vcon') && !has('gui_running')
+     throw 'Skipped: does not support termguicolors'
+   endif
+ 
+   set tgc
    let g:terminal_ansi_colors = reverse(copy(s:test_colors))
    let buf = Run_shell_in_terminal({'ansi_colors': s:test_colors})
    call assert_equal(s:test_colors, term_getansicolors(buf))
***************
*** 2047,2052 ****
--- 2058,2064 ----
    let colors[4] = 'Invalid'
    call assert_fails('call term_setansicolors(buf, colors)', 'E254:')
    call assert_fails('call term_setansicolors(buf, {})', 'E714:')
+   set tgc&
  
    call StopShellInTerminal(buf)
    call assert_equal(0, term_setansicolors(buf, []))
*** ../vim-8.2.4981/src/version.c       2022-05-19 10:31:06.969630503 +0100
--- src/version.c       2022-05-20 09:30:53.815480276 +0100
***************
*** 748,749 ****
--- 748,751 ----
  {   /* Add new patch number below this line */
+ /**/
+     4982,
  /**/

-- 
hundred-and-one symptoms of being an internet addict:
237. You tattoo your email address on your forehead.

 /// Bram Moolenaar -- [email protected] -- http://www.Moolenaar.net   \\\
///                                                                      \\\
\\\        sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ ///
 \\\            help me help AIDS victims -- http://ICCF-Holland.org    ///

-- 
-- 
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

--- 
You received this message because you are subscribed to the Google Groups 
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/vim_dev/20220520091155.4B21A1C10A7%40moolenaar.net.

Raspunde prin e-mail lui