From 7429791106cc8109010656bd6fe024dbc5456e53 Mon Sep 17 00:00:00 2001 From: Nobuhiro Takasaki Date: Wed, 27 Sep 2017 08:13:58 +0900 Subject: [PATCH 1/2] Integration of past patches --- runtime/doc/options.txt | 5 +- src/misc1.c | 15 + src/option.c | 14 + src/os_win32.c | 632 +++++++++++++++++++++++++++++------ src/proto/os_win32.pro | 3 + src/proto/term.pro | 1 - src/screen.c | 19 ++ src/syntax.c | 21 ++ src/term.c | 61 +--- src/testdir/gen_opt_test.vim | 1 + 10 files changed, 630 insertions(+), 142 deletions(-) diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt index f279de6aefc76..7e03bd327e021 100644 --- a/runtime/doc/options.txt +++ b/runtime/doc/options.txt @@ -7872,7 +7872,7 @@ A jump table for the options with a short description can be found at |Q_op|. :set encoding=utf-8 < You need to do this when your system has no locale support for UTF-8. - *'termguicolors'* *'tgc'* + *'termguicolors'* *'tgc'* *E949* 'termguicolors' 'tgc' boolean (default off) global {not in Vi} @@ -7880,7 +7880,8 @@ A jump table for the options with a short description can be found at |Q_op|. |+termguicolors| feature} When on, uses |highlight-guifg| and |highlight-guibg| attributes in the terminal (thus using 24-bit color). Requires a ISO-8613-3 - compatible terminal. + compatible terminal. For Win32 console, Windows 10 version 1703 + (Creators Update) or later is required. If setting this option does not work (produces a colorless UI) reading |xterm-true-color| might help. Note that the "cterm" attributes are still used, not the "gui" ones. diff --git a/src/misc1.c b/src/misc1.c index 2d635d677faaf..e9ca85d5f57f7 100644 --- a/src/misc1.c +++ b/src/misc1.c @@ -3701,7 +3701,22 @@ vim_beep( && !(gui.in_use && gui.starting) #endif ) + { out_str_cf(T_VB); +#if defined(WIN3264) && !defined(FEAT_GUI) + /* No restore color information, refresh the screen. */ + if (vtp_get_stat() != 0 +# ifdef FEAT_TERMGUICOLORS + && p_tgc +# endif + ) + { + redraw_later(CLEAR); + update_screen(0); + redrawcmd(); + } +#endif + } else out_char(BELL); #ifdef ELAPSED_FUNC diff --git a/src/option.c b/src/option.c index 08fb789dad19b..4d8bb640cf11c 100644 --- a/src/option.c +++ b/src/option.c @@ -8654,10 +8654,24 @@ set_bool_option( /* 'termguicolors' */ else if ((int *)varp == &p_tgc) { +# if !defined(FEAT_GUI) && defined(WIN3264) + /* Do not turn on 'tgc' when 24-bit colors are not supported. */ + if (!vtp_get_stat()) + { + p_tgc = 0; + return (char_u*)N_("E949: 24-bit colors are not supported on this environment"); + } +# endif # ifdef FEAT_GUI if (!gui.in_use && !gui.starting) # endif highlight_gui_started(); +# if !defined(FEAT_GUI) && defined(WIN3264) + control_console_color_rgb(); + /* reset t_Co */ + if (STRCMP(T_NAME, "win32") == 0) + set_termname(T_NAME); +# endif } #endif diff --git a/src/os_win32.c b/src/os_win32.c index d356c7ed6873c..45bb2187697ac 100644 --- a/src/os_win32.c +++ b/src/os_win32.c @@ -182,6 +182,11 @@ static void delete_lines(unsigned cLines); static void gotoxy(unsigned x, unsigned y); static void normvideo(void); static void textattr(WORD wAttr); +static void textattr_normal(void); +static void textattr_reverse(void); +static void textattr_bold(void); +static void textattr_italic(void); +static void textattr_underscore(void); static void textcolor(WORD wAttr); static void textbackground(WORD wAttr); static void standout(void); @@ -202,6 +207,32 @@ static int win32_getattrs(char_u *name); static int win32_setattrs(char_u *name, int attrs); static int win32_set_archive(char_u *name); +#ifndef FEAT_GUI_W32 +static int has_vtp = 0; +static void vtp_init(); +static void vtp_exit(); +static int vtp_printf(char *format, ...); +static void vtp_sgr_bulk(int arg); +static void vtp_sgr_bulks(int argc, int *argv); + +static guicolor_T save_console_bg_rgb; +static guicolor_T save_console_fg_rgb; + +# ifdef FEAT_TERMGUICOLORS +# define USE_VTP (has_vtp && p_tgc) +# else +# define USE_VTP 0 +# endif + +static void set_console_color_rgb(void); +static void reset_console_color_rgb(void); +#endif + +/* This flag is newly created from Windows 10 */ +#ifndef ENABLE_VIRTUAL_TERMINAL_PROCESSING +# define ENABLE_VIRTUAL_TERMINAL_PROCESSING 0x0004 +#endif + #ifndef FEAT_GUI_W32 static int suppress_winsize = 1; /* don't fiddle with console */ #endif @@ -211,6 +242,54 @@ static char_u *exe_path = NULL; static BOOL win8_or_later = FALSE; #ifndef FEAT_GUI_W32 +/* Dynamic loading for portability */ +typedef struct _DYN_CONSOLE_SCREEN_BUFFER_INFOEX +{ + ULONG cbSize; + COORD dwSize; + COORD dwCursorPosition; + WORD wAttributes; + SMALL_RECT srWindow; + COORD dwMaximumWindowSize; + WORD wPopupAttributes; + BOOL bFullscreenSupported; + COLORREF ColorTable[16]; +} DYN_CONSOLE_SCREEN_BUFFER_INFOEX, *PDYN_CONSOLE_SCREEN_BUFFER_INFOEX; +typedef BOOL (WINAPI *PfnGetConsoleScreenBufferInfoEx)(HANDLE, PDYN_CONSOLE_SCREEN_BUFFER_INFOEX); +static PfnGetConsoleScreenBufferInfoEx pGetConsoleScreenBufferInfoEx; +typedef BOOL (WINAPI *PfnSetConsoleScreenBufferInfoEx)(HANDLE, PDYN_CONSOLE_SCREEN_BUFFER_INFOEX); +static PfnSetConsoleScreenBufferInfoEx pSetConsoleScreenBufferInfoEx; +static BOOL has_csbiex = FALSE; + +/* + * Get version number including build number + */ +typedef BOOL (WINAPI *PfnRtlGetVersion)(LPOSVERSIONINFOW); +# define MAKE_VER(major, minor, build) \ + (((major) << 24) | ((minor) << 16) | (build)) + + static DWORD +get_build_number(void) +{ + OSVERSIONINFOW osver = {sizeof(OSVERSIONINFOW)}; + HMODULE hNtdll; + PfnRtlGetVersion pRtlGetVersion; + DWORD ver = MAKE_VER(0, 0, 0); + + hNtdll = GetModuleHandle("ntdll.dll"); + if (hNtdll != NULL) + { + pRtlGetVersion = + (PfnRtlGetVersion)GetProcAddress(hNtdll, "RtlGetVersion"); + pRtlGetVersion(&osver); + ver = MAKE_VER(min(osver.dwMajorVersion, 255), + min(osver.dwMinorVersion, 255), + min(osver.dwBuildNumber, 32767)); + } + return ver; +} + + /* * Version of ReadConsoleInput() that works with IME. * Works around problems on Windows 8. @@ -2532,9 +2611,6 @@ mch_init(void) if (cterm_normal_bg_color == 0) cterm_normal_bg_color = ((g_attrCurrent >> 4) & 0xf) + 1; - /* set termcap codes to current text attributes */ - update_tcap(g_attrCurrent); - GetConsoleCursorInfo(g_hConOut, &g_cci); GetConsoleMode(g_hConIn, &g_cmodein); GetConsoleMode(g_hConOut, &g_cmodeout); @@ -2574,6 +2650,8 @@ mch_init(void) #ifdef FEAT_CLIPBOARD win_clip_init(); #endif + + vtp_init(); } /* @@ -2586,6 +2664,8 @@ mch_exit(int r) { exiting = TRUE; + vtp_exit(); + stoptermcap(); if (g_fWindInitCalled) settmode(TMODE_COOK); @@ -3798,7 +3878,15 @@ mch_settmode(int tmode) if (g_fMouseActive) cmodein |= ENABLE_MOUSE_INPUT; #endif - cmodeout &= ~(ENABLE_PROCESSED_OUTPUT | ENABLE_WRAP_AT_EOL_OUTPUT); + cmodeout &= ~( +#ifdef FEAT_TERMGUICOLORS + /* Do not turn off the ENABLE_PROCESSRD_OUTPUT flag when using + * VTP. */ + ((has_vtp) ? 0 : ENABLE_PROCESSED_OUTPUT) | +#else + ENABLE_PROCESSED_OUTPUT | +#endif + ENABLE_WRAP_AT_EOL_OUTPUT); bEnableHandler = TRUE; } else /* cooked */ @@ -5445,6 +5533,7 @@ termcap_mode_start(void) * to restore the actual contents of the buffer. */ RestoreConsoleBuffer(&g_cbTermcap, FALSE); + reset_console_color_rgb(); SetConsoleWindowInfo(g_hConOut, TRUE, &g_cbTermcap.Info.srWindow); Rows = g_cbTermcap.Info.dwSize.Y; Columns = g_cbTermcap.Info.dwSize.X; @@ -5457,6 +5546,7 @@ termcap_mode_start(void) * size. We will use this as the size of our editing environment. */ ClearConsoleBuffer(g_attrCurrent); + set_console_color_rgb(); ResizeConBufAndWindow(g_hConOut, Columns, Rows); } @@ -5505,6 +5595,7 @@ termcap_mode_end(void) cb = &g_cbNonTermcap; #endif RestoreConsoleBuffer(cb, p_rs); + reset_console_color_rgb(); SetConsoleCursorInfo(g_hConOut, &g_cci); if (p_rs || exiting) @@ -5559,7 +5650,11 @@ clear_chars( DWORD dwDummy; FillConsoleOutputCharacter(g_hConOut, ' ', n, coord, &dwDummy); - FillConsoleOutputAttribute(g_hConOut, g_attrCurrent, n, coord, &dwDummy); + + if (!USE_VTP) + FillConsoleOutputAttribute(g_hConOut, g_attrCurrent, n, coord, &dwDummy); + else + FillConsoleOutputAttribute(g_hConOut, 0, n, coord, &dwDummy); } @@ -5570,7 +5665,15 @@ clear_chars( clear_screen(void) { g_coord.X = g_coord.Y = 0; - clear_chars(g_coord, Rows * Columns); + + if (!USE_VTP) + clear_chars(g_coord, Rows * Columns); + else + { + set_console_color_rgb(); + gotoxy(1, 1); + vtp_printf("\033[2J"); + } } @@ -5580,8 +5683,20 @@ clear_screen(void) static void clear_to_end_of_display(void) { - clear_chars(g_coord, (Rows - g_coord.Y - 1) + COORD save = g_coord; + + if (!USE_VTP) + clear_chars(g_coord, (Rows - g_coord.Y - 1) * Columns + (Columns - g_coord.X)); + else + { + set_console_color_rgb(); + gotoxy(g_coord.X + 1, g_coord.Y + 1); + vtp_printf("\033[0J"); + + gotoxy(save.X + 1, save.Y + 1); + g_coord = save; + } } @@ -5591,7 +5706,19 @@ clear_to_end_of_display(void) static void clear_to_end_of_line(void) { - clear_chars(g_coord, Columns - g_coord.X); + COORD save = g_coord; + + if (!USE_VTP) + clear_chars(g_coord, Columns - g_coord.X); + else + { + set_console_color_rgb(); + gotoxy(g_coord.X + 1, g_coord.Y + 1); + vtp_printf("\033[0K"); + + gotoxy(save.X + 1, save.Y + 1); + g_coord = save; + } } @@ -5630,6 +5757,9 @@ set_scroll_region( g_srScrollRegion.Top = top; g_srScrollRegion.Right = right; g_srScrollRegion.Bottom = bottom; + + if (USE_VTP) + vtp_printf("\033[%d;%dr", top + 1, bottom + 1); } @@ -5651,10 +5781,20 @@ insert_lines(unsigned cLines) source.Right = g_srScrollRegion.Right; source.Bottom = g_srScrollRegion.Bottom - cLines; - fill.Char.AsciiChar = ' '; - fill.Attributes = g_attrCurrent; + if (!USE_VTP) + { + fill.Char.AsciiChar = ' '; + fill.Attributes = g_attrCurrent; - ScrollConsoleScreenBuffer(g_hConOut, &source, NULL, dest, &fill); + ScrollConsoleScreenBuffer(g_hConOut, &source, NULL, dest, &fill); + } + else + { + set_console_color_rgb(); + + gotoxy(1, source.Top + 1); + vtp_printf("\033[%dT", cLines); + } /* Here we have to deal with a win32 console flake: If the scroll * region looks like abc and we scroll c to a and fill with d we get @@ -5693,10 +5833,20 @@ delete_lines(unsigned cLines) source.Right = g_srScrollRegion.Right; source.Bottom = g_srScrollRegion.Bottom; - fill.Char.AsciiChar = ' '; - fill.Attributes = g_attrCurrent; + if (!USE_VTP) + { + fill.Char.AsciiChar = ' '; + fill.Attributes = g_attrCurrent; - ScrollConsoleScreenBuffer(g_hConOut, &source, NULL, dest, &fill); + ScrollConsoleScreenBuffer(g_hConOut, &source, NULL, dest, &fill); + } + else + { + set_console_color_rgb(); + + gotoxy(1, source.Top + 1); + vtp_printf("\033[%dS", cLines); + } /* Here we have to deal with a win32 console flake: If the scroll * region looks like abc and we scroll c to a and fill with d we get @@ -5732,7 +5882,11 @@ gotoxy( /* external cursor coords are 1-based; internal are 0-based */ g_coord.X = x - 1; g_coord.Y = y - 1; - SetConsoleCursorPosition(g_hConOut, g_coord); + + if (!USE_VTP) + SetConsoleCursorPosition(g_hConOut, g_coord); + else + vtp_printf("\033[%d;%dH", y, x); } @@ -5749,12 +5903,74 @@ textattr(WORD wAttr) } + static void +textattr_normal(void) +{ + if (!USE_VTP) + SetConsoleTextAttribute(g_hConOut, g_attrCurrent & 0xff); + else + vtp_printf("\033[0m"); /* default color */ +} + + + static void +textattr_reverse(void) +{ + g_attrCurrent = (((g_attrCurrent & 0x0f) << 4) + | ((g_attrCurrent & 0xf0) >> 4)) & 0xff; + + if (!USE_VTP) + SetConsoleTextAttribute(g_hConOut, g_attrCurrent); + else + vtp_printf("\033[7m"); /* reverse */ +} + + + static void +textattr_bold(void) +{ + g_attrCurrent = (g_attrCurrent | 0x08) & 0xff; /* FOREGROUND_INTENSITY */ + + if (!USE_VTP) + SetConsoleTextAttribute(g_hConOut, g_attrCurrent); + else + vtp_printf("\033[1m"); /* bold */ +} + + + static void +textattr_italic(void) +{ + g_attrCurrent = 225; /* blue text on yellow */ + + if (!USE_VTP) + SetConsoleTextAttribute(g_hConOut, g_attrCurrent); + else + vtp_printf("\033[95m"); /* bright magenta text */ +} + + + static void +textattr_underscore(void) +{ + g_attrCurrent = 67; /* cyan text on red */ + + if (!USE_VTP) + SetConsoleTextAttribute(g_hConOut, g_attrCurrent); + else + vtp_printf("\033[4m"); /* underscore */ +} + + static void textcolor(WORD wAttr) { g_attrCurrent = (g_attrCurrent & 0xf0) + (wAttr & 0x0f); - SetConsoleTextAttribute(g_hConOut, g_attrCurrent); + if (!USE_VTP) + SetConsoleTextAttribute(g_hConOut, g_attrCurrent); + else + vtp_sgr_bulk(wAttr); } @@ -5763,7 +5979,10 @@ textbackground(WORD wAttr) { g_attrCurrent = (g_attrCurrent & 0x0f) + ((wAttr & 0x0f) << 4); - SetConsoleTextAttribute(g_hConOut, g_attrCurrent); + if (!USE_VTP) + SetConsoleTextAttribute(g_hConOut, g_attrCurrent); + else + vtp_sgr_bulk(wAttr); } @@ -5773,7 +5992,10 @@ textbackground(WORD wAttr) static void normvideo(void) { - textattr(g_attrDefault); + if (!USE_VTP) + textattr(g_attrDefault); + else + vtp_sgr_bulk(0); } @@ -5786,7 +6008,11 @@ static WORD g_attrPreStandout = 0; standout(void) { g_attrPreStandout = g_attrCurrent; - textattr((WORD) (g_attrCurrent|FOREGROUND_INTENSITY|BACKGROUND_INTENSITY)); + + if (!USE_VTP) + textattr((WORD) (g_attrCurrent|FOREGROUND_INTENSITY|BACKGROUND_INTENSITY)); + else + vtp_printf("\033[91m"); /* bright red text */ } @@ -5796,35 +6022,30 @@ standout(void) static void standend(void) { - if (g_attrPreStandout) + if (!USE_VTP) { - textattr(g_attrPreStandout); - g_attrPreStandout = 0; + if (g_attrPreStandout) + textattr(g_attrPreStandout); } + else + vtp_printf("\033[39m"); /* default color */ + + g_attrPreStandout = 0; } /* - * Set normal fg/bg color, based on T_ME. Called when t_me has been set. + * Set normal fg/bg color */ void mch_set_normal_colors(void) { - char_u *p; - int n; - - cterm_normal_fg_color = (g_attrDefault & 0xf) + 1; - cterm_normal_bg_color = ((g_attrDefault >> 4) & 0xf) + 1; - if (T_ME[0] == ESC && T_ME[1] == '|') - { - p = T_ME + 2; - n = getdigits(&p); - if (*p == 'm' && n > 0) - { - cterm_normal_fg_color = (n & 0xf) + 1; - cterm_normal_bg_color = ((n >> 4) & 0xf) + 1; - } - } + cterm_normal_fg_color = (g_attrDefault & 0x0f) + 1; + cterm_normal_bg_color = ((g_attrDefault >> 4) & 0x0f) + 1; +#ifdef FEAT_TERMGUICOLORS + cterm_normal_fg_gui_color = INVALCOLOR; + cterm_normal_bg_gui_color = INVALCOLOR; +#endif } @@ -5848,7 +6069,8 @@ visual_bell(void) coordOrigin, &dwDummy); Sleep(15); /* wait for 15 msec */ - WriteConsoleOutputAttribute(g_hConOut, oldattrs, Rows * Columns, + if (!USE_VTP) + WriteConsoleOutputAttribute(g_hConOut, oldattrs, Rows * Columns, coordOrigin, &dwDummy); vim_free(oldattrs); } @@ -5898,14 +6120,24 @@ write_chars( unicodebuf, unibuflen); cells = mb_string2cells(pchBuf, cbToWrite); - FillConsoleOutputAttribute(g_hConOut, g_attrCurrent, cells, - coord, &written); - /* When writing fails or didn't write a single character, pretend one - * character was written, otherwise we get stuck. */ - if (WriteConsoleOutputCharacterW(g_hConOut, unicodebuf, length, - coord, &cchwritten) == 0 - || cchwritten == 0) - cchwritten = 1; + + if (!USE_VTP) + { + FillConsoleOutputAttribute(g_hConOut, g_attrCurrent, cells, + coord, &written); + /* When writing fails or didn't write a single character, pretend one + * character was written, otherwise we get stuck. */ + if (WriteConsoleOutputCharacterW(g_hConOut, unicodebuf, length, + coord, &cchwritten) == 0 + || cchwritten == 0) + cchwritten = 1; + } + else + { + if (WriteConsoleW(g_hConOut, unicodebuf, length, &cchwritten, + NULL) == 0 || cchwritten == 0) + cchwritten = 1; + } if (cchwritten == length) { @@ -5924,14 +6156,23 @@ write_chars( else #endif { - FillConsoleOutputAttribute(g_hConOut, g_attrCurrent, cbToWrite, - coord, &written); - /* When writing fails or didn't write a single character, pretend one - * character was written, otherwise we get stuck. */ - if (WriteConsoleOutputCharacter(g_hConOut, (LPCSTR)pchBuf, cbToWrite, - coord, &written) == 0 - || written == 0) - written = 1; + if (!USE_VTP) + { + FillConsoleOutputAttribute(g_hConOut, g_attrCurrent, cbToWrite, + coord, &written); + /* When writing fails or didn't write a single character, pretend one + * character was written, otherwise we get stuck. */ + if (WriteConsoleOutputCharacter(g_hConOut, (LPCSTR)pchBuf, cbToWrite, + coord, &written) == 0 + || written == 0) + written = 1; + } + else + { + if (WriteConsole(g_hConOut, (LPCSTR)pchBuf, cbToWrite, &written, + NULL) == 0 || written == 0) + written = 1; + } g_coord.X += (SHORT) written; } @@ -6057,67 +6298,94 @@ mch_write( char_u *old_s = s; #endif char_u *p; - int arg1 = 0, arg2 = 0; + int arg1 = 0, arg2 = 0, argc = 0, args[16]; switch (s[2]) { - /* one or two numeric arguments, separated by ';' */ - case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': - p = s + 2; - arg1 = getdigits(&p); /* no check for length! */ - if (p > s + len) - break; - - if (*p == ';') + p = s + 1; + do { ++p; - arg2 = getdigits(&p); /* no check for length! */ + args[argc] = getdigits(&p); + argc += (argc < 15) ? 1 : 0; if (p > s + len) break; + } while (*p == ';'); + + if (p > s + len) + break; - if (*p == 'H') - gotoxy(arg2, arg1); - else if (*p == 'r') - set_scroll_region(0, arg1 - 1, Columns - 1, arg2 - 1); + arg1 = args[0]; + arg2 = args[1]; + if (*p == 'm') + { + if (argc == 1 && args[0] == 0) + normvideo(); + else if (argc == 1) + textcolor((WORD) arg1); + else if (USE_VTP) + vtp_sgr_bulks(argc, args); + } + else if (argc == 2 && *p == 'H') + { + gotoxy(arg2, arg1); } - else if (*p == 'A') + else if (argc == 2 && *p == 'r') + { + set_scroll_region(0, arg1 - 1, Columns - 1, arg2 - 1); + } + else if (argc == 1 && *p == 'A') { - /* move cursor up arg1 lines in same column */ gotoxy(g_coord.X + 1, max(g_srScrollRegion.Top, g_coord.Y - arg1) + 1); } - else if (*p == 'C') + else if (argc == 1 && *p == 'B') { - /* move cursor right arg1 columns in same line */ - gotoxy(min(g_srScrollRegion.Right, g_coord.X + arg1) + 1, - g_coord.Y + 1); + if (args[0] == 0) + { + textattr_normal(); + } + else if (args[0] == 1) + { + textattr_reverse(); + } + else if (args[0] == 2) + { + textattr_bold(); + } + else if (args[0] == 3) + { + textattr_italic(); + } + else if (args[0] == 4) + { + textattr_underscore(); + } } - else if (*p == 'H') + else if (argc == 1 && *p == 'b') { - gotoxy(1, arg1); + textbackground((WORD) arg1); } - else if (*p == 'L') + else if (argc == 1 && *p == 'C') { - insert_lines(arg1); + gotoxy(min(g_srScrollRegion.Right, g_coord.X + arg1) + 1, + g_coord.Y + 1); } - else if (*p == 'm') + else if (argc == 1 && *p == 'f') { - if (arg1 == 0) - normvideo(); - else - textattr((WORD) arg1); + textcolor((WORD) arg1); } - else if (*p == 'f') + else if (argc == 1 && *p == 'H') { - textcolor((WORD) arg1); + gotoxy(1, arg1); } - else if (*p == 'b') + else if (argc == 1 && *p == 'L') { - textbackground((WORD) arg1); + insert_lines(arg1); } - else if (*p == 'M') + else if (argc == 1 && *p == 'M') { delete_lines(arg1); } @@ -6126,11 +6394,7 @@ mch_write( s = p + 1; break; - - /* Three-character escape sequences */ - case 'A': - /* move cursor up one line in same column */ gotoxy(g_coord.X + 1, max(g_srScrollRegion.Top, g_coord.Y - 1) + 1); goto got3; @@ -6140,7 +6404,6 @@ mch_write( goto got3; case 'C': - /* move cursor right one column in same line */ gotoxy(min(g_srScrollRegion.Right, g_coord.X + 1) + 1, g_coord.Y + 1); goto got3; @@ -7239,3 +7502,184 @@ mch_setenv(char *var, char *value, int x) return 0; } + +#ifndef FEAT_GUI_W32 + +/* Support for 256 colors and 24-bit colors was added in Windows 10 + * version 1703 (Creators update). */ +# define VTP_FIRST_SUPPORT_BUILD MAKE_VER(10, 0, 15063) + + static void +vtp_init(void) +{ + DWORD ver, mode; + HMODULE hKerneldll; + DYN_CONSOLE_SCREEN_BUFFER_INFOEX csbi; + + ver = get_build_number(); + has_vtp = (ver >= VTP_FIRST_SUPPORT_BUILD) ? 1 : 0; + GetConsoleMode(g_hConOut, &mode); + mode |= (ENABLE_PROCESSED_OUTPUT | ENABLE_VIRTUAL_TERMINAL_PROCESSING); + if (SetConsoleMode(g_hConOut, mode) == 0) + has_vtp = 0; + + /* Use functions supported from Vista */ + hKerneldll = GetModuleHandle("kernel32.dll"); + if (hKerneldll != NULL) + { + pGetConsoleScreenBufferInfoEx = + (PfnGetConsoleScreenBufferInfoEx)GetProcAddress( + hKerneldll, "GetConsoleScreenBufferInfoEx"); + pSetConsoleScreenBufferInfoEx = + (PfnSetConsoleScreenBufferInfoEx)GetProcAddress( + hKerneldll, "SetConsoleScreenBufferInfoEx"); + if (pGetConsoleScreenBufferInfoEx != NULL + && pSetConsoleScreenBufferInfoEx != NULL) + has_csbiex = TRUE; + } + + csbi.cbSize = sizeof(csbi); + if (has_csbiex) + pGetConsoleScreenBufferInfoEx(g_hConOut, &csbi); + save_console_bg_rgb = (guicolor_T)csbi.ColorTable[0]; + save_console_fg_rgb = (guicolor_T)csbi.ColorTable[7]; + + set_console_color_rgb(); +} + + static void +vtp_exit(void) +{ + reset_console_color_rgb(); +} + + static int +vtp_printf( + char *format, + ...) +{ + char_u buf[100]; + va_list list; + DWORD result; + + va_start(list, format); + vim_vsnprintf((char *)buf, 100, (char *)format, list); + va_end(list); + WriteConsoleA(g_hConOut, buf, (DWORD)STRLEN(buf), &result, NULL); + return (int)result; +} + + static void +vtp_sgr_bulk( + int arg) +{ + int args[1]; + + args[0] = arg; + vtp_sgr_bulks(1, args); +} + + static void +vtp_sgr_bulks( + int argc, + int *args +) +{ + /* 2('\033[') + 4('255.') * 16 + NUL */ + char_u buf[2 + (4 * 16) + 1]; + char_u *p; + int i; + + p = buf; + *p++ = '\033'; + *p++ = '['; + + for (i = 0; i < argc; ++i) + { + p += vim_snprintf((char *)p, 4, "%d", args[i] & 0xff); + *p++ = ';'; + } + p--; + *p++ = 'm'; + *p = NUL; + vtp_printf((char *)buf); +} + + static void +set_console_color_rgb(void) +{ +# ifdef FEAT_TERMGUICOLORS + DYN_CONSOLE_SCREEN_BUFFER_INFOEX csbi; + int id; + guicolor_T fg = INVALCOLOR; + guicolor_T bg = INVALCOLOR; + + if (!USE_VTP) + return; + + id = syn_name2id((char_u *)"Normal"); + if (id > 0) + syn_id2colors(id, &fg, &bg); + if (fg == INVALCOLOR) + fg = 0xc0c0c0; /* white text */ + if (bg == INVALCOLOR) + bg = 0x000000; /* black background */ + fg = (GetRValue(fg) << 16) | (GetGValue(fg) << 8) | GetBValue(fg); + bg = (GetRValue(bg) << 16) | (GetGValue(bg) << 8) | GetBValue(bg); + + csbi.cbSize = sizeof(csbi); + if (has_csbiex) + pGetConsoleScreenBufferInfoEx(g_hConOut, &csbi); + + csbi.cbSize = sizeof(csbi); + csbi.srWindow.Right += 1; + csbi.srWindow.Bottom += 1; + csbi.ColorTable[0] = (COLORREF)bg; + csbi.ColorTable[7] = (COLORREF)fg; + if (has_csbiex) + pSetConsoleScreenBufferInfoEx(g_hConOut, &csbi); +# endif +} + + static void +reset_console_color_rgb(void) +{ +# ifdef FEAT_TERMGUICOLORS + DYN_CONSOLE_SCREEN_BUFFER_INFOEX csbi; + + csbi.cbSize = sizeof(csbi); + if (has_csbiex) + pGetConsoleScreenBufferInfoEx(g_hConOut, &csbi); + + csbi.cbSize = sizeof(csbi); + csbi.srWindow.Right += 1; + csbi.srWindow.Bottom += 1; + csbi.ColorTable[0] = (COLORREF)save_console_bg_rgb; + csbi.ColorTable[7] = (COLORREF)save_console_fg_rgb; + if (has_csbiex) + pSetConsoleScreenBufferInfoEx(g_hConOut, &csbi); +# endif +} + + void +control_console_color_rgb(void) +{ + if (USE_VTP) + set_console_color_rgb(); + else + reset_console_color_rgb(); +} + + int +vtp_get_stat(void) +{ + return has_vtp; +} + + int +vtp_use_stat(void) +{ + return (USE_VTP); +} + +#endif diff --git a/src/proto/os_win32.pro b/src/proto/os_win32.pro index a87d8b7673167..7b0ed3e969642 100644 --- a/src/proto/os_win32.pro +++ b/src/proto/os_win32.pro @@ -68,4 +68,7 @@ void set_alist_count(void); void fix_arg_enc(void); int mch_setenv(char *var, char *value, int x); void win32_build_env(dict_T *l, garray_T *gap, int is_terminal); +void control_console_color_rgb(void); +int vtp_get_stat(void); +int vtp_use_stat(void); /* vim: set ft=c : */ diff --git a/src/proto/term.pro b/src/proto/term.pro index ef74f5647c6cb..8f5b78028c55a 100644 --- a/src/proto/term.pro +++ b/src/proto/term.pro @@ -71,7 +71,6 @@ int find_term_bykeys(char_u *src); void show_termcodes(void); int show_one_termcode(char_u *name, char_u *code, int printit); char_u *translate_mapping(char_u *str, int expmap); -void update_tcap(int attr); guicolor_T gui_get_color_cmn(char_u *name); guicolor_T gui_get_rgb_color_cmn(int r, int g, int b); /* vim: set ft=c : */ diff --git a/src/screen.c b/src/screen.c index 6b69d13b630e9..58eb90d87cc27 100644 --- a/src/screen.c +++ b/src/screen.c @@ -2170,6 +2170,25 @@ win_update(win_T *wp) * End of loop over all window lines. */ +#if !defined(FEAT_GUI) && defined(WIN3264) + /* Rewrite the character at the end of the screen line. */ + if (vtp_use_stat()) + { + int i; + + for (i = 0; i < Rows; ++i) +# ifdef FEAT_MBYTE + if (enc_utf8) + if ((*mb_off2cells)(LineOffset[i] + Columns - 2, + LineOffset[i] + screen_Columns) > 1) + screen_draw_rectangle(i, Columns - 2, 1, 2, FALSE); + else + screen_draw_rectangle(i, Columns - 1, 1, 1, FALSE); + else +# endif + screen_char(LineOffset[i] + Columns - 1, i, Columns - 1); + } +#endif if (idx > wp->w_lines_valid) wp->w_lines_valid = idx; diff --git a/src/syntax.c b/src/syntax.c index d247e0d16f30e..7b9057c13326a 100644 --- a/src/syntax.c +++ b/src/syntax.c @@ -8939,6 +8939,10 @@ get_cterm_attr_idx(int attr, int fg, int bg) attrentry_T at_en; vim_memset(&at_en, 0, sizeof(attrentry_T)); +#ifdef FEAT_TERMGUICOLORS + at_en.ae_u.cterm.fg_rgb = INVALCOLOR; + at_en.ae_u.cterm.bg_rgb = INVALCOLOR; +#endif at_en.ae_attr = attr; at_en.ae_u.cterm.fg_color = fg; at_en.ae_u.cterm.bg_color = bg; @@ -9578,6 +9582,23 @@ set_hl_attr( at_en.ae_u.cterm.fg_color = sgp->sg_cterm_fg; at_en.ae_u.cterm.bg_color = sgp->sg_cterm_bg; # ifdef FEAT_TERMGUICOLORS +# ifdef WIN3264 + { + int id; + guicolor_T fg, bg; + + id = syn_name2id((char_u *)"Normal"); + if (id > 0) + { + syn_id2colors(id, &fg, &bg); + if (sgp->sg_gui_fg == INVALCOLOR) + sgp->sg_gui_fg = fg; + if (sgp->sg_gui_bg == INVALCOLOR) + sgp->sg_gui_bg = bg; + } + + } +# endif at_en.ae_u.cterm.fg_rgb = GUI_MCH_GET_RGB2(sgp->sg_gui_fg); at_en.ae_u.cterm.bg_rgb = GUI_MCH_GET_RGB2(sgp->sg_gui_bg); # endif diff --git a/src/term.c b/src/term.c index ffa3944d69fa5..07f17ae15dc7b 100644 --- a/src/term.c +++ b/src/term.c @@ -560,20 +560,15 @@ static struct builtin_term builtin_termcaps[] = {(int)KS_VI, "\033|v"}, /* cursor invisible */ {(int)KS_VE, "\033|V"}, /* cursor visible */ - {(int)KS_ME, "\033|0m"}, /* normal */ - {(int)KS_MR, "\033|112m"}, /* reverse: black on lightgray */ - {(int)KS_MD, "\033|15m"}, /* bold: white on black */ -#if 1 - {(int)KS_SO, "\033|31m"}, /* standout: white on blue */ - {(int)KS_SE, "\033|0m"}, /* standout end */ -#else - {(int)KS_SO, "\033|F"}, /* standout: high intensity */ + {(int)KS_ME, "\033|0B"}, /* normal */ + {(int)KS_MR, "\033|1B"}, /* reverse */ + {(int)KS_MD, "\033|2B"}, /* bold */ + {(int)KS_SO, "\033|F"}, /* standout */ {(int)KS_SE, "\033|f"}, /* standout end */ -#endif - {(int)KS_CZH, "\033|225m"}, /* italic: blue text on yellow */ + {(int)KS_CZH, "\033|3B"}, /* italic */ {(int)KS_CZR, "\033|0m"}, /* italic end */ - {(int)KS_US, "\033|67m"}, /* underscore: cyan text on red */ - {(int)KS_UE, "\033|0m"}, /* underscore end */ + {(int)KS_US, "\033|4B"}, /* underscore */ + {(int)KS_UE, "\033|24m"}, /* underscore end */ {(int)KS_CCO, "16"}, /* allow 16 colors */ # ifdef TERMINFO {(int)KS_CAB, "\033|%p1%db"}, /* set background color */ @@ -600,6 +595,10 @@ static struct builtin_term builtin_termcaps[] = # else {(int)KS_CS, "\033|%i%d;%dr"},/* scroll region */ # endif +# ifdef FEAT_TERMGUICOLORS + {(int)KS_8F, "\033|38;2;%lu;%lu;%lum"}, + {(int)KS_8B, "\033|48;2;%lu;%lu;%lum"}, +# endif {K_UP, "\316H"}, {K_DOWN, "\316P"}, @@ -2007,6 +2006,11 @@ set_termname(char_u *term) may_req_termresponse(); #endif +#if defined(WIN3264) && !defined(FEAT_GUI) && defined(FEAT_TERMGUICOLORS) + if (STRCMP(term, "win32") == 0) + set_color_count((p_tgc) ? 256 : 16); +#endif + return OK; } @@ -6562,39 +6566,6 @@ translate_mapping( } #endif -#if (defined(WIN3264) && !defined(FEAT_GUI)) || defined(PROTO) -static char ksme_str[20]; -static char ksmr_str[20]; -static char ksmd_str[20]; - -/* - * For Win32 console: update termcap codes for existing console attributes. - */ - void -update_tcap(int attr) -{ - struct builtin_term *p; - - p = find_builtin_term(DEFAULT_TERM); - sprintf(ksme_str, IF_EB("\033|%dm", ESC_STR "|%dm"), attr); - sprintf(ksmd_str, IF_EB("\033|%dm", ESC_STR "|%dm"), - attr | 0x08); /* FOREGROUND_INTENSITY */ - sprintf(ksmr_str, IF_EB("\033|%dm", ESC_STR "|%dm"), - ((attr & 0x0F) << 4) | ((attr & 0xF0) >> 4)); - - while (p->bt_string != NULL) - { - if (p->bt_entry == (int)KS_ME) - p->bt_string = &ksme_str[0]; - else if (p->bt_entry == (int)KS_MR) - p->bt_string = &ksmr_str[0]; - else if (p->bt_entry == (int)KS_MD) - p->bt_string = &ksmd_str[0]; - ++p; - } -} -#endif - #if defined(FEAT_GUI) || defined(FEAT_TERMGUICOLORS) || defined(PROTO) static int hex_digit(int c) diff --git a/src/testdir/gen_opt_test.vim b/src/testdir/gen_opt_test.vim index 4edf44aafd2d2..e781a0d2a8518 100644 --- a/src/testdir/gen_opt_test.vim +++ b/src/testdir/gen_opt_test.vim @@ -129,6 +129,7 @@ let test_values = { \ 'switchbuf': [['', 'useopen', 'split,newtab'], ['xxx']], \ 'tagcase': [['smart', 'match'], ['', 'xxx', 'smart,match']], \ 'term': [[], []], + \ 'termguicolors': [[], []], \ 'termsize': [['', '24x80', '0x80', '32x0', '0x0'], ['xxx', '80', '8ax9', '24x80b']], \ 'termencoding': [has('gui_gtk') ? [] : ['', 'utf-8'], ['xxx']], \ 'toolbar': [['', 'icons', 'text'], ['xxx']], From 0ecc1b6eb479ffa8aaddb86a528b221c15faa250 Mon Sep 17 00:00:00 2001 From: Nobuhiro Takasaki Date: Sun, 31 Dec 2017 15:55:46 +0900 Subject: [PATCH 2/2] "dos-colors" fully compatible --- src/option.c | 1 + src/os_win32.c | 135 ++++++++++------------------------------ src/proto/term.pro | 2 + src/term.c | 152 ++++++++++++++++++++++++++++++++++++++++++--- 4 files changed, 181 insertions(+), 109 deletions(-) diff --git a/src/option.c b/src/option.c index 4d8bb640cf11c..3d900eb62593f 100644 --- a/src/option.c +++ b/src/option.c @@ -8661,6 +8661,7 @@ set_bool_option( p_tgc = 0; return (char_u*)N_("E949: 24-bit colors are not supported on this environment"); } + swap_tcap(); # endif # ifdef FEAT_GUI if (!gui.in_use && !gui.starting) diff --git a/src/os_win32.c b/src/os_win32.c index 45bb2187697ac..b85b0f44f8003 100644 --- a/src/os_win32.c +++ b/src/os_win32.c @@ -182,11 +182,6 @@ static void delete_lines(unsigned cLines); static void gotoxy(unsigned x, unsigned y); static void normvideo(void); static void textattr(WORD wAttr); -static void textattr_normal(void); -static void textattr_reverse(void); -static void textattr_bold(void); -static void textattr_italic(void); -static void textattr_underscore(void); static void textcolor(WORD wAttr); static void textbackground(WORD wAttr); static void standout(void); @@ -2611,6 +2606,10 @@ mch_init(void) if (cterm_normal_bg_color == 0) cterm_normal_bg_color = ((g_attrCurrent >> 4) & 0xf) + 1; + /* set termcap codes to current text attributes */ + update_tcap(g_attrCurrent); + swap_tcap(); + GetConsoleCursorInfo(g_hConOut, &g_cci); GetConsoleMode(g_hConIn, &g_cmodein); GetConsoleMode(g_hConOut, &g_cmodeout); @@ -5903,65 +5902,6 @@ textattr(WORD wAttr) } - static void -textattr_normal(void) -{ - if (!USE_VTP) - SetConsoleTextAttribute(g_hConOut, g_attrCurrent & 0xff); - else - vtp_printf("\033[0m"); /* default color */ -} - - - static void -textattr_reverse(void) -{ - g_attrCurrent = (((g_attrCurrent & 0x0f) << 4) - | ((g_attrCurrent & 0xf0) >> 4)) & 0xff; - - if (!USE_VTP) - SetConsoleTextAttribute(g_hConOut, g_attrCurrent); - else - vtp_printf("\033[7m"); /* reverse */ -} - - - static void -textattr_bold(void) -{ - g_attrCurrent = (g_attrCurrent | 0x08) & 0xff; /* FOREGROUND_INTENSITY */ - - if (!USE_VTP) - SetConsoleTextAttribute(g_hConOut, g_attrCurrent); - else - vtp_printf("\033[1m"); /* bold */ -} - - - static void -textattr_italic(void) -{ - g_attrCurrent = 225; /* blue text on yellow */ - - if (!USE_VTP) - SetConsoleTextAttribute(g_hConOut, g_attrCurrent); - else - vtp_printf("\033[95m"); /* bright magenta text */ -} - - - static void -textattr_underscore(void) -{ - g_attrCurrent = 67; /* cyan text on red */ - - if (!USE_VTP) - SetConsoleTextAttribute(g_hConOut, g_attrCurrent); - else - vtp_printf("\033[4m"); /* underscore */ -} - - static void textcolor(WORD wAttr) { @@ -6009,10 +5949,7 @@ standout(void) { g_attrPreStandout = g_attrCurrent; - if (!USE_VTP) - textattr((WORD) (g_attrCurrent|FOREGROUND_INTENSITY|BACKGROUND_INTENSITY)); - else - vtp_printf("\033[91m"); /* bright red text */ + textattr((WORD) (g_attrCurrent|FOREGROUND_INTENSITY|BACKGROUND_INTENSITY)); } @@ -6022,26 +5959,38 @@ standout(void) static void standend(void) { - if (!USE_VTP) - { - if (g_attrPreStandout) - textattr(g_attrPreStandout); - } - else - vtp_printf("\033[39m"); /* default color */ + if (g_attrPreStandout) + textattr(g_attrPreStandout); g_attrPreStandout = 0; } /* - * Set normal fg/bg color + * Set normal fg/bg color, based on T_ME. Called when t_me has been set. */ void mch_set_normal_colors(void) { - cterm_normal_fg_color = (g_attrDefault & 0x0f) + 1; - cterm_normal_bg_color = ((g_attrDefault >> 4) & 0x0f) + 1; + char_u *p; + int n; + + cterm_normal_fg_color = (g_attrDefault & 0xf) + 1; + cterm_normal_bg_color = ((g_attrDefault >> 4) & 0xf) + 1; + if ( +#ifdef FEAT_TERMGUICOLORS + !p_tgc && +#endif + T_ME[0] == ESC && T_ME[1] == '|') + { + p = T_ME + 2; + n = getdigits(&p); + if (*p == 'm' && n > 0) + { + cterm_normal_fg_color = (n & 0xf) + 1; + cterm_normal_bg_color = ((n >> 4) & 0xf) + 1; + } + } #ifdef FEAT_TERMGUICOLORS cterm_normal_fg_gui_color = INVALCOLOR; cterm_normal_bg_gui_color = INVALCOLOR; @@ -6324,7 +6273,12 @@ mch_write( if (argc == 1 && args[0] == 0) normvideo(); else if (argc == 1) - textcolor((WORD) arg1); + { + if (USE_VTP) + textcolor((WORD) arg1); + else + textattr((WORD) arg1); + } else if (USE_VTP) vtp_sgr_bulks(argc, args); } @@ -6341,29 +6295,6 @@ mch_write( gotoxy(g_coord.X + 1, max(g_srScrollRegion.Top, g_coord.Y - arg1) + 1); } - else if (argc == 1 && *p == 'B') - { - if (args[0] == 0) - { - textattr_normal(); - } - else if (args[0] == 1) - { - textattr_reverse(); - } - else if (args[0] == 2) - { - textattr_bold(); - } - else if (args[0] == 3) - { - textattr_italic(); - } - else if (args[0] == 4) - { - textattr_underscore(); - } - } else if (argc == 1 && *p == 'b') { textbackground((WORD) arg1); diff --git a/src/proto/term.pro b/src/proto/term.pro index 8f5b78028c55a..8e9938995ef28 100644 --- a/src/proto/term.pro +++ b/src/proto/term.pro @@ -71,6 +71,8 @@ int find_term_bykeys(char_u *src); void show_termcodes(void); int show_one_termcode(char_u *name, char_u *code, int printit); char_u *translate_mapping(char_u *str, int expmap); +void update_tcap(int attr); +void swap_tcap(void); guicolor_T gui_get_color_cmn(char_u *name); guicolor_T gui_get_rgb_color_cmn(int r, int g, int b); /* vim: set ft=c : */ diff --git a/src/term.c b/src/term.c index 07f17ae15dc7b..c9b20b5149220 100644 --- a/src/term.c +++ b/src/term.c @@ -560,15 +560,20 @@ static struct builtin_term builtin_termcaps[] = {(int)KS_VI, "\033|v"}, /* cursor invisible */ {(int)KS_VE, "\033|V"}, /* cursor visible */ - {(int)KS_ME, "\033|0B"}, /* normal */ - {(int)KS_MR, "\033|1B"}, /* reverse */ - {(int)KS_MD, "\033|2B"}, /* bold */ - {(int)KS_SO, "\033|F"}, /* standout */ + {(int)KS_ME, "\033|0m"}, /* normal */ + {(int)KS_MR, "\033|112m"}, /* reverse: black on lightgray */ + {(int)KS_MD, "\033|15m"}, /* bold: white on black */ +#if 1 + {(int)KS_SO, "\033|31m"}, /* standout: white on blue */ + {(int)KS_SE, "\033|0m"}, /* standout end */ +#else + {(int)KS_SO, "\033|F"}, /* standout: high intensity */ {(int)KS_SE, "\033|f"}, /* standout end */ - {(int)KS_CZH, "\033|3B"}, /* italic */ +#endif + {(int)KS_CZH, "\033|225m"}, /* italic: blue text on yellow */ {(int)KS_CZR, "\033|0m"}, /* italic end */ - {(int)KS_US, "\033|4B"}, /* underscore */ - {(int)KS_UE, "\033|24m"}, /* underscore end */ + {(int)KS_US, "\033|67m"}, /* underscore: cyan text on red */ + {(int)KS_UE, "\033|0m"}, /* underscore end */ {(int)KS_CCO, "16"}, /* allow 16 colors */ # ifdef TERMINFO {(int)KS_CAB, "\033|%p1%db"}, /* set background color */ @@ -6566,6 +6571,139 @@ translate_mapping( } #endif +#if (defined(WIN3264) && !defined(FEAT_GUI)) || defined(PROTO) +static char ksme_str[20]; +static char ksmr_str[20]; +static char ksmd_str[20]; + +/* + * For Win32 console: update termcap codes for existing console attributes. + */ + void +update_tcap(int attr) +{ + struct builtin_term *p; + + p = find_builtin_term(DEFAULT_TERM); + sprintf(ksme_str, IF_EB("\033|%dm", ESC_STR "|%dm"), attr); + sprintf(ksmd_str, IF_EB("\033|%dm", ESC_STR "|%dm"), + attr | 0x08); /* FOREGROUND_INTENSITY */ + sprintf(ksmr_str, IF_EB("\033|%dm", ESC_STR "|%dm"), + ((attr & 0x0F) << 4) | ((attr & 0xF0) >> 4)); + + while (p->bt_string != NULL) + { + if (p->bt_entry == (int)KS_ME) + p->bt_string = &ksme_str[0]; + else if (p->bt_entry == (int)KS_MR) + p->bt_string = &ksmr_str[0]; + else if (p->bt_entry == (int)KS_MD) + p->bt_string = &ksmd_str[0]; + ++p; + } +} + +struct ks_tbl_s +{ + int code; /* value of KS_ */ + char *vtp; /* code in vtp mode */ + char *buf; /* buffer in non-vtp mode */ + char *vbuf; /* buffer in vtp mode */ +}; + +static struct ks_tbl_s ks_tbl[] = +{ + {(int)KS_ME, "\033|0m" }, /* normal */ + {(int)KS_MR, "\033|7m" }, /* reverse */ + {(int)KS_MD, "\033|1m" }, /* bold */ + {(int)KS_SO, "\033|91m"}, /* standout: bright red text */ + {(int)KS_SE, "\033|39m"}, /* standout end: default color */ + {(int)KS_CZH, "\033|95m"}, /* italic: bright magenta text */ + {(int)KS_CZR, "\033|0m",}, /* italic end */ + {(int)KS_US, "\033|4m",}, /* underscore */ + {(int)KS_UE, "\033|24m"}, /* underscore end */ + {(int)KS_NAME, NULL} +}; + + static struct builtin_term * +find_first_tcap( + char_u *name, + int code) +{ + struct builtin_term *p; + + p = find_builtin_term(name); + while (p->bt_string != NULL) + { + if (p->bt_entry == code) + return p; + p++; + } + return NULL; +} + +/* + * For Win32 console: replace the sequence immediately after termguicolors. + */ + void +swap_tcap(void) +{ +# ifdef FEAT_TERMGUICOLORS + static int init = 0; + static int last_tgc; + struct ks_tbl_s *ks; + struct builtin_term *bt; + + /* buffer initialization */ + if (init == 0) + { + ks = ks_tbl; + while (ks->vtp != NULL) + { + bt = find_first_tcap(DEFAULT_TERM, ks->code); + ks->buf = bt->bt_string; + ks->vbuf = ks->vtp; + ks++; + } + init++; + last_tgc = p_tgc; + return; + } + + if (last_tgc != p_tgc) + { + if (p_tgc) + { + /* switch to special character sequence */ + ks = ks_tbl; + while (ks->vtp != NULL) + { + bt = find_first_tcap(DEFAULT_TERM, ks->code); + ks->buf = bt->bt_string; + bt->bt_string = ks->vbuf; + ks++; + } + } + else + { + /* switch to index color */ + ks = ks_tbl; + while (ks->vtp != NULL) + { + bt = find_first_tcap(DEFAULT_TERM, ks->code); + ks->vbuf = bt->bt_string; + bt->bt_string = ks->buf; + ks++; + } + } + + last_tgc = p_tgc; + } +# endif +} + +#endif + #if defined(FEAT_GUI) || defined(FEAT_TERMGUICOLORS) || defined(PROTO) static int hex_digit(int c)