mirror of
https://github.com/vim/vim.git
synced 2026-05-28 00:21:37 +02:00
patch 9.1.2006: MS-Windows: ANSI colors not correct in terminal
Problem: ANSI escape colors are not displayed correctly in
non-termguicolors in vim (cli) on Windows. The red and blue
channels seem to be swapped.
Cause: When converting VTerm ANSI index colors to cterm colors in
terminal.c, the Windows case equivalent to NR-16 (:help
cterm-colors) is ignored.
Solution: Created and used a table to convert ANSI indexed colors to
cterm's NR-16 representation (Windows only). This table
corresponds to the inverse conversion of cterm_ansi_idx in
term.c. The values in both tables are exactly the same, but
the meanings are opposite, so they are separate tables
(Muraoka Taro).
closes: #18931
Signed-off-by: Muraoka Taro <koron.kaoriya@gmail.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
This commit is contained in:
committed by
Christian Brabandt
parent
3913f13a7d
commit
86855ea8ee
+1
-1
@@ -7642,7 +7642,7 @@ static const char_u ansi_table[16][3] = {
|
||||
|
||||
# if defined(MSWIN)
|
||||
// Mapping between cterm indices < 16 and their counterpart in the ANSI palette.
|
||||
static const char_u cterm_ansi_idx[] = {
|
||||
const char_u cterm_ansi_idx[] = {
|
||||
0, 4, 2, 6, 1, 5, 3, 7, 8, 12, 10, 14, 9, 13, 11, 15
|
||||
};
|
||||
# endif
|
||||
|
||||
@@ -233,3 +233,8 @@ typedef enum {
|
||||
TMODE_RAW, // terminal mode for Normal and Insert mode
|
||||
TMODE_UNKNOWN // after executing a shell
|
||||
} tmode_T;
|
||||
|
||||
#if defined(MSWIN)
|
||||
// Mapping between cterm indices < 16 and their counterpart in the ANSI palette.
|
||||
extern const char_u cterm_ansi_idx[];
|
||||
#endif
|
||||
|
||||
+14
-1
@@ -3033,7 +3033,20 @@ color2index(VTermColor *color, int fg, int *boldp)
|
||||
{
|
||||
// Use the color as-is if possible, give up otherwise.
|
||||
if (color->index < t_colors)
|
||||
return color->index + 1;
|
||||
{
|
||||
uint8_t index = color->index;
|
||||
#ifdef MSWIN
|
||||
// Convert ANSI palette to cterm color index.
|
||||
// cterm_ansi_idx is a table for the reverse conversion from cterm
|
||||
// color index to ANSI palette. However, the current table can
|
||||
// be used for this conversion as well.
|
||||
// Note: If the contents of cterm_ansi_idx change in the future, a
|
||||
// different table may be needed for this purpose.
|
||||
if (index < 16)
|
||||
index = cterm_ansi_idx[index];
|
||||
#endif
|
||||
return 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)
|
||||
|
||||
@@ -1037,4 +1037,55 @@ func Test_terminal_visual_empty_listchars()
|
||||
call StopVimInTerminal(buf)
|
||||
endfunc
|
||||
|
||||
func Test_terminal_ansi_color_windows_cui()
|
||||
if !has('win32') || has('gui_running')
|
||||
throw 'Skipped: only for the Windows CUI'
|
||||
endif
|
||||
if exists('$APPVEYOR')
|
||||
throw 'Skipped: this test cannot be performed because AppVeyor does not support ANSI escape sequences'
|
||||
endif
|
||||
|
||||
call assert_equal('dark', &background)
|
||||
|
||||
" Outputs 16 ANSI colors as background colors
|
||||
let ansi = ''
|
||||
for i in range(16)
|
||||
let ansi ..= printf("\e[%dm%X", i + (i < 8 ? 40 : 92), i)
|
||||
endfor
|
||||
let ansi ..= "\e[40m\n"
|
||||
call writefile([ansi], 'XANSIcolor', 'D')
|
||||
|
||||
let expected_chars = '0123456789ABCDEF'
|
||||
let expected_colors = [
|
||||
\ '#000000', '#e00000', '#00e000', '#e0e000',
|
||||
\ '#0000e0', '#e000e0', '#00e0e0', '#e0e0e0',
|
||||
\ '#808080', '#ff4040', '#40ff40', '#ffff40',
|
||||
\ '#4040ff', '#ff40ff', '#40ffff', '#ffffff',
|
||||
\ ]
|
||||
|
||||
" Ideally, 16 colors should be checked. However, in the current CI
|
||||
" environment, the 16th color is something other than white, and we don't
|
||||
" know the cause nor solution. After discussion, we decided to check only 15
|
||||
" colors for the time being.
|
||||
" FIXME: Check all 16 colors in the future.
|
||||
let len_to_check = 15
|
||||
let expected_colors = expected_colors[:len_to_check-1]
|
||||
|
||||
" First, make sure vim can display correct ANSI color text in terminal.
|
||||
let buf = term_start("cmd /C type XANSIcolor")
|
||||
call WaitForAssert({-> assert_equal(expected_chars, term_scrape(buf, 1)[:15]->map({_, v -> v['chars']})->join(''))})
|
||||
call assert_equal(expected_colors, term_scrape(buf, 1)[:len_to_check-1]->map({_, v -> v['bg']}))
|
||||
bwipeout!
|
||||
|
||||
" Next, check if vim can do the same thing in the vim terminal in terminal.
|
||||
let lines = [
|
||||
\ 'call term_start("cmd /C type XANSIcolor")'
|
||||
\ ]
|
||||
call writefile(lines, 'XloadANSI', 'D')
|
||||
let cmd = GetVimCommandCleanTerm()
|
||||
let buf = term_start(cmd .. '-S XloadANSI')
|
||||
call WaitForAssert({-> assert_equal(expected_chars, term_scrape(buf, 1)[:15]->map({_, v -> v['chars']})->join(''))})
|
||||
call assert_equal(expected_colors, term_scrape(buf, 1)[:len_to_check-1]->map({_, v -> v['bg']}))
|
||||
endfunc
|
||||
|
||||
" vim: shiftwidth=2 sts=2 expandtab
|
||||
|
||||
@@ -734,6 +734,8 @@ static char *(features[]) =
|
||||
|
||||
static int included_patches[] =
|
||||
{ /* Add new patch number below this line */
|
||||
/**/
|
||||
2006,
|
||||
/**/
|
||||
2005,
|
||||
/**/
|
||||
|
||||
Reference in New Issue
Block a user