diff options
author | Bram Moolenaar <Bram@vim.org> | 2018-02-22 21:07:09 +0100 |
---|---|---|
committer | Bram Moolenaar <Bram@vim.org> | 2018-02-22 21:07:09 +0100 |
commit | cafafb381a04e33f3ce9cd15dd9f94b73226831f (patch) | |
tree | 39c0444924dc20b2715e102a8e8ea34a11684ab6 /src | |
parent | 19eb6658eced1b1ce3d1097187ee28c28e352f2e (diff) |
patch 8.0.1531: cannot use 24 bit colors in MS-Windows consolev8.0.1531
Problem: Cannot use 24 bit colors in MS-Windows console.
Solution: Add support for vcon. (Nobuhiro Takasaki, Ken Takasaki,
fixes #1270, fixes #2060)
Diffstat (limited to 'src')
-rw-r--r-- | src/evalfunc.c | 8 | ||||
-rw-r--r-- | src/feature.h | 7 | ||||
-rw-r--r-- | src/misc1.c | 15 | ||||
-rw-r--r-- | src/option.c | 15 | ||||
-rw-r--r-- | src/os_win32.c | 529 | ||||
-rw-r--r-- | src/proto/os_win32.pro | 5 | ||||
-rw-r--r-- | src/proto/term.pro | 1 | ||||
-rw-r--r-- | src/screen.c | 19 | ||||
-rw-r--r-- | src/syntax.c | 21 | ||||
-rw-r--r-- | src/term.c | 153 | ||||
-rw-r--r-- | src/testdir/gen_opt_test.vim | 1 | ||||
-rw-r--r-- | src/version.c | 9 |
12 files changed, 680 insertions, 103 deletions
diff --git a/src/evalfunc.c b/src/evalfunc.c index 1fad78a189..5b684bd946 100644 --- a/src/evalfunc.c +++ b/src/evalfunc.c @@ -851,7 +851,7 @@ static struct fst #ifdef FEAT_TERMINAL {"term_dumpdiff", 2, 3, f_term_dumpdiff}, {"term_dumpload", 1, 2, f_term_dumpload}, - {"term_dumpwrite", 2, 4, f_term_dumpwrite}, + {"term_dumpwrite", 2, 3, f_term_dumpwrite}, {"term_getaltscreen", 1, 1, f_term_getaltscreen}, {"term_getattr", 2, 2, f_term_getattr}, {"term_getcursor", 1, 1, f_term_getcursor}, @@ -6323,9 +6323,9 @@ f_has(typval_T *argvars, typval_T *rettv) else if (STRICMP(name, "syntax_items") == 0) n = syntax_present(curwin); #endif -#if defined(WIN3264) - else if (STRICMP(name, "win95") == 0) - n = FALSE; /* Win9x is no more supported. */ +#ifdef FEAT_VTP + else if (STRICMP(name, "vcon") == 0) + n = has_vtp_working(); #endif #ifdef FEAT_NETBEANS_INTG else if (STRICMP(name, "netbeans_enabled") == 0) diff --git a/src/feature.h b/src/feature.h index a0b0f7e1d4..d29e599a9b 100644 --- a/src/feature.h +++ b/src/feature.h @@ -1394,3 +1394,10 @@ || (defined(WIN3264) && defined(FEAT_GUI_W32)) # define FEAT_FILTERPIPE #endif + +/* + * +vtp: Win32 virtual console. + */ +#if !defined(FEAT_GUI) && defined(WIN3264) +# define FEAT_VTP +#endif diff --git a/src/misc1.c b/src/misc1.c index e639fbe41b..32e3c17ae6 100644 --- a/src/misc1.c +++ b/src/misc1.c @@ -3714,7 +3714,22 @@ vim_beep( && !(gui.in_use && gui.starting) #endif ) + { out_str_cf(T_VB); +#ifdef FEAT_VTP + /* No restore color information, refresh the screen. */ + if (has_vtp_working() != 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 21ca0fa48b..9662039510 100644 --- a/src/option.c +++ b/src/option.c @@ -8690,10 +8690,25 @@ set_bool_option( /* 'termguicolors' */ else if ((int *)varp == &p_tgc) { +# ifdef FEAT_VTP + /* Do not turn on 'tgc' when 24-bit colors are not supported. */ + if (!has_vtp_working()) + { + p_tgc = 0; + return (char_u*)N_("E954: 24-bit colors are not supported on this environment"); + } + swap_tcap(); +# endif # ifdef FEAT_GUI if (!gui.in_use && !gui.starting) # endif highlight_gui_started(); +# ifdef FEAT_VTP + 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 02f87102c1..91f453f2e9 100644 --- a/src/os_win32.c +++ b/src/os_win32.c @@ -203,6 +203,32 @@ static int win32_setattrs(char_u *name, int attrs); static int win32_set_archive(char_u *name); #ifndef FEAT_GUI_W32 +static int vtp_working = 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 (vtp_working && 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 +237,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. @@ -2537,6 +2611,7 @@ mch_init(void) /* set termcap codes to current text attributes */ update_tcap(g_attrCurrent); + swap_tcap(); GetConsoleCursorInfo(g_hConOut, &g_cci); GetConsoleMode(g_hConIn, &g_cmodein); @@ -2577,6 +2652,8 @@ mch_init(void) #ifdef FEAT_CLIPBOARD win_clip_init(); #endif + + vtp_init(); } /* @@ -2589,6 +2666,8 @@ mch_exit(int r) { exiting = TRUE; + vtp_exit(); + stoptermcap(); if (g_fWindInitCalled) settmode(TMODE_COOK); @@ -3801,7 +3880,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. */ + ((vtp_working) ? 0 : ENABLE_PROCESSED_OUTPUT) | +#else + ENABLE_PROCESSED_OUTPUT | +#endif + ENABLE_WRAP_AT_EOL_OUTPUT); bEnableHandler = TRUE; } else /* cooked */ @@ -5448,6 +5535,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; @@ -5460,6 +5548,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); } @@ -5508,6 +5597,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) @@ -5562,7 +5652,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); } @@ -5573,7 +5667,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"); + } } @@ -5583,8 +5685,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; + } } @@ -5594,7 +5708,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; + } } @@ -5633,6 +5759,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); } @@ -5654,10 +5783,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 @@ -5696,10 +5835,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 @@ -5735,7 +5884,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); } @@ -5757,7 +5910,10 @@ 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); } @@ -5766,7 +5922,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); } @@ -5776,7 +5935,10 @@ textbackground(WORD wAttr) static void normvideo(void) { - textattr(g_attrDefault); + if (!USE_VTP) + textattr(g_attrDefault); + else + vtp_sgr_bulk(0); } @@ -5789,6 +5951,7 @@ static WORD g_attrPreStandout = 0; standout(void) { g_attrPreStandout = g_attrCurrent; + textattr((WORD) (g_attrCurrent|FOREGROUND_INTENSITY|BACKGROUND_INTENSITY)); } @@ -5800,10 +5963,9 @@ standout(void) standend(void) { if (g_attrPreStandout) - { textattr(g_attrPreStandout); - g_attrPreStandout = 0; - } + + g_attrPreStandout = 0; } @@ -5818,7 +5980,11 @@ mch_set_normal_colors(void) 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] == '|') + if ( +#ifdef FEAT_TERMGUICOLORS + !p_tgc && +#endif + T_ME[0] == ESC && T_ME[1] == '|') { p = T_ME + 2; n = getdigits(&p); @@ -5828,6 +5994,10 @@ mch_set_normal_colors(void) cterm_normal_bg_color = ((n >> 4) & 0xf) + 1; } } +#ifdef FEAT_TERMGUICOLORS + cterm_normal_fg_gui_color = INVALCOLOR; + cterm_normal_bg_gui_color = INVALCOLOR; +#endif } @@ -5851,7 +6021,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); } @@ -5901,14 +6072,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) { @@ -5927,14 +6108,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; } @@ -6060,67 +6250,76 @@ 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) + { + if (USE_VTP) + textcolor((WORD) arg1); + else + textattr((WORD) arg1); + } + else if (USE_VTP) + vtp_sgr_bulks(argc, args); } - else if (*p == 'A') + else if (argc == 2 && *p == 'H') { - /* move cursor up arg1 lines in same column */ - gotoxy(g_coord.X + 1, - max(g_srScrollRegion.Top, g_coord.Y - arg1) + 1); + gotoxy(arg2, arg1); } - else if (*p == 'C') + else if (argc == 2 && *p == 'r') { - /* move cursor right arg1 columns in same line */ - gotoxy(min(g_srScrollRegion.Right, g_coord.X + arg1) + 1, - g_coord.Y + 1); + set_scroll_region(0, arg1 - 1, Columns - 1, arg2 - 1); } - else if (*p == 'H') + else if (argc == 1 && *p == 'A') { - gotoxy(1, arg1); + gotoxy(g_coord.X + 1, + max(g_srScrollRegion.Top, g_coord.Y - arg1) + 1); } - else if (*p == 'L') + else if (argc == 1 && *p == 'b') { - insert_lines(arg1); + textbackground((WORD) arg1); } - else if (*p == 'm') + else if (argc == 1 && *p == 'C') { - if (arg1 == 0) - normvideo(); - else - textattr((WORD) arg1); + gotoxy(min(g_srScrollRegion.Right, g_coord.X + arg1) + 1, + g_coord.Y + 1); } - else if (*p == 'f') + else if (argc == 1 && *p == 'f') { textcolor((WORD) arg1); } - else if (*p == 'b') + else if (argc == 1 && *p == 'H') { - textbackground((WORD) arg1); + gotoxy(1, arg1); } - else if (*p == 'M') + else if (argc == 1 && *p == 'L') + { + insert_lines(arg1); + } + else if (argc == 1 && *p == 'M') { delete_lines(arg1); } @@ -6129,11 +6328,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; @@ -6143,7 +6338,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; @@ -7242,3 +7436,186 @@ 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(); + vtp_working = (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) + vtp_working = 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 +has_vtp_working(void) +{ + return vtp_working; +} + + int +use_vtp(void) +{ + return USE_VTP; +} + +#endif diff --git a/src/proto/os_win32.pro b/src/proto/os_win32.pro index a87d8b7673..d76e27020f 100644 --- a/src/proto/os_win32.pro +++ b/src/proto/os_win32.pro @@ -42,6 +42,7 @@ void mch_set_shellsize(void); void mch_new_shellsize(void); void mch_set_winsize_now(void); int mch_call_shell(char_u *cmd, int options); +void win32_build_env(dict_T *env, garray_T *gap, int is_terminal); void mch_job_start(char *cmd, job_T *job, jobopt_T *options); char *mch_job_status(job_T *job); job_T *mch_detect_ended_job(job_T *job_list); @@ -67,5 +68,7 @@ void used_file_arg(char *name, int literal, int full_path, int diff_mode); 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 has_vtp_working(void); +int use_vtp(void); /* vim: set ft=c : */ diff --git a/src/proto/term.pro b/src/proto/term.pro index b0ad418e80..92cb26d58b 100644 --- a/src/proto/term.pro +++ b/src/proto/term.pro @@ -73,6 +73,7 @@ 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/screen.c b/src/screen.c index 8b7a519c08..9592f55134 100644 --- a/src/screen.c +++ b/src/screen.c @@ -2177,6 +2177,25 @@ win_update(win_T *wp) * End of loop over all window lines. */ +#ifdef FEAT_VTP + /* Rewrite the character at the end of the screen line. */ + if (use_vtp()) + { + 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 fcffdbf8af..79b2796d2b 100644 --- a/src/syntax.c +++ b/src/syntax.c @@ -8927,6 +8927,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; @@ -9566,6 +9570,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 1f17d9f2fa..3e2b8ecc35 100644 --- a/src/term.c +++ b/src/term.c @@ -76,7 +76,6 @@ struct builtin_term static struct builtin_term *find_builtin_term(char_u *name); static void parse_builtin_tcap(char_u *s); -static void term_color(char_u *s, int n); static void gather_termleader(void); #ifdef FEAT_TERMRESPONSE static void req_codes_from_term(void); @@ -600,6 +599,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 +2010,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; } @@ -2818,31 +2826,12 @@ term_set_winsize(int height, int width) } #endif - void -term_fg_color(int n) -{ - /* Use "AF" termcap entry if present, "Sf" entry otherwise */ - if (*T_CAF) - term_color(T_CAF, n); - else if (*T_CSF) - term_color(T_CSF, n); -} - - void -term_bg_color(int n) -{ - /* Use "AB" termcap entry if present, "Sb" entry otherwise */ - if (*T_CAB) - term_color(T_CAB, n); - else if (*T_CSB) - term_color(T_CSB, n); -} - static void term_color(char_u *s, int n) { char buf[20]; - int i = 2; /* index in s[] just after <Esc>[ or CSI */ + int i = *s == CSI ? 1 : 2; + /* index in s[] just after <Esc>[ or CSI */ /* Special handling of 16 colors, because termcap can't handle it */ /* Also accept "\e[3%dm" for TERMINFO, it is sometimes used */ @@ -2869,6 +2858,26 @@ term_color(char_u *s, int n) OUT_STR(tgoto((char *)s, 0, n)); } + void +term_fg_color(int n) +{ + /* Use "AF" termcap entry if present, "Sf" entry otherwise */ + if (*T_CAF) + term_color(T_CAF, n); + else if (*T_CSF) + term_color(T_CSF, n); +} + + void +term_bg_color(int n) +{ + /* Use "AB" termcap entry if present, "Sb" entry otherwise */ + if (*T_CAB) + term_color(T_CAB, n); + else if (*T_CSB) + term_color(T_CSB, n); +} + #if defined(FEAT_TERMGUICOLORS) || defined(PROTO) #define RED(rgb) (((long_u)(rgb) >> 16) & 0xFF) @@ -6614,6 +6623,106 @@ update_tcap(int attr) ++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 */ + {( |