To: vim_dev@googlegroups.com Subject: Patch 8.0.1531 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 8.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) Files: runtime/doc/options.txt, src/misc1.c, src/option.c, src/evalfunc.c, src/os_win32.c, src/proto/os_win32.pro, src/feature.h, src/proto/term.pro, src/screen.c, src/syntax.c, src/term.c, src/testdir/gen_opt_test.vim, src/version.c *** ../vim-8.0.1530/runtime/doc/options.txt 2018-02-10 15:36:51.134901664 +0100 --- runtime/doc/options.txt 2018-02-22 20:28:41.818700640 +0100 *************** *** 7792,7808 **** :set encoding=utf-8 < You need to do this when your system has no locale support for UTF-8. ! *'termguicolors'* *'tgc'* 'termguicolors' 'tgc' boolean (default off) global {not in Vi} {not available when compiled without the |+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. ! If setting this option does not work (produces a colorless UI) ! reading |xterm-true-color| might help. *'terse'* *'noterse'* 'terse' boolean (default off) --- 7907,7961 ---- :set encoding=utf-8 < You need to do this when your system has no locale support for UTF-8. ! *'termguicolors'* *'tgc'* *E954* 'termguicolors' 'tgc' boolean (default off) global {not in Vi} {not available when compiled without the |+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. If setting this option ! does not work (produces a colorless UI) reading |xterm-true-color| ! might help. ! ! For Win32 console, Windows 10 version 1703 (Creators Update) or later ! is required. Use this check to find out: > ! if has('vcon') ! < ! Note that the "cterm" attributes are still used, not the "gui" ones. ! NOTE: This option is reset when 'compatible' is set. ! ! *'termkey'* *'tk'* ! 'termkey' 'tk' string (default "") ! local to window ! {not in Vi} ! The key that starts a CTRL-W command in a terminal window. Other keys ! are sent to the job running in the window. ! The <> notation can be used, e.g.: > ! :set termkey= ! < The string must be one key stroke but can be multiple bytes. ! When not set CTRL-W is used, so that CTRL-W : gets you to the command ! line. If 'termkey' is set to CTRL-L then CTRL-L : gets you to the ! command line. ! ! *'termsize'* *'tms'* ! 'termsize' 'tms' string (default "") ! local to window ! {not in Vi} ! Size of the |terminal| window. Format: {rows}x{columns}. ! - When empty the terminal gets the size from the window. ! - When set (e.g., "24x80") the terminal size is not adjusted to the ! window size. If the window is smaller only the top-left part is ! displayed. ! When rows is zero then use the height of the window. ! When columns is zero then use the width of the window. ! For example: "30x0" uses 30 rows with the current window width. ! Using "0x0" is the same as empty. ! Note that the command running in the terminal window may still change ! the size of the terminal. In that case the Vim window will be ! adjusted to that size, if possible. *'terse'* *'noterse'* 'terse' boolean (default off) *** ../vim-8.0.1530/src/misc1.c 2018-02-13 12:26:08.904247750 +0100 --- src/misc1.c 2018-02-22 20:54:43.450843489 +0100 *************** *** 3714,3720 **** --- 3714,3735 ---- && !(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 *** ../vim-8.0.1530/src/option.c 2018-02-10 18:45:21.076822101 +0100 --- src/option.c 2018-02-22 20:54:47.694769101 +0100 *************** *** 8690,8699 **** --- 8690,8714 ---- /* '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 *** ../vim-8.0.1530/src/evalfunc.c 2018-02-18 22:13:06.261057963 +0100 --- src/evalfunc.c 2018-02-22 20:54:38.094936858 +0100 *************** *** 851,857 **** #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_getaltscreen", 1, 1, f_term_getaltscreen}, {"term_getattr", 2, 2, f_term_getattr}, {"term_getcursor", 1, 1, f_term_getcursor}, --- 851,857 ---- #ifdef FEAT_TERMINAL {"term_dumpdiff", 2, 3, f_term_dumpdiff}, {"term_dumpload", 1, 2, f_term_dumpload}, ! {"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,6331 **** 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. */ #endif #ifdef FEAT_NETBEANS_INTG else if (STRICMP(name, "netbeans_enabled") == 0) --- 6323,6331 ---- else if (STRICMP(name, "syntax_items") == 0) n = syntax_present(curwin); #endif ! #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) *** ../vim-8.0.1530/src/os_win32.c 2018-02-11 16:40:13.439759211 +0100 --- src/os_win32.c 2018-02-22 20:54:52.022692873 +0100 *************** *** 203,208 **** --- 203,234 ---- 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,216 **** --- 237,290 ---- 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,2542 **** --- 2611,2617 ---- /* set termcap codes to current text attributes */ update_tcap(g_attrCurrent); + swap_tcap(); GetConsoleCursorInfo(g_hConOut, &g_cci); GetConsoleMode(g_hConIn, &g_cmodein); *************** *** 2577,2582 **** --- 2652,2659 ---- #ifdef FEAT_CLIPBOARD win_clip_init(); #endif + + vtp_init(); } /* *************** *** 2589,2594 **** --- 2666,2673 ---- { exiting = TRUE; + vtp_exit(); + stoptermcap(); if (g_fWindInitCalled) settmode(TMODE_COOK); *************** *** 3801,3807 **** if (g_fMouseActive) cmodein |= ENABLE_MOUSE_INPUT; #endif ! cmodeout &= ~(ENABLE_PROCESSED_OUTPUT | ENABLE_WRAP_AT_EOL_OUTPUT); bEnableHandler = TRUE; } else /* cooked */ --- 3880,3894 ---- if (g_fMouseActive) cmodein |= ENABLE_MOUSE_INPUT; #endif ! 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,5453 **** --- 5535,5541 ---- * 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,5465 **** --- 5548,5554 ---- * 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,5513 **** --- 5597,5603 ---- cb = &g_cbNonTermcap; #endif RestoreConsoleBuffer(cb, p_rs); + reset_console_color_rgb(); SetConsoleCursorInfo(g_hConOut, &g_cci); if (p_rs || exiting) *************** *** 5562,5568 **** DWORD dwDummy; FillConsoleOutputCharacter(g_hConOut, ' ', n, coord, &dwDummy); ! FillConsoleOutputAttribute(g_hConOut, g_attrCurrent, n, coord, &dwDummy); } --- 5652,5662 ---- DWORD dwDummy; FillConsoleOutputCharacter(g_hConOut, ' ', n, coord, &dwDummy); ! ! if (!USE_VTP) ! FillConsoleOutputAttribute(g_hConOut, g_attrCurrent, n, coord, &dwDummy); ! else ! FillConsoleOutputAttribute(g_hConOut, 0, n, coord, &dwDummy); } *************** *** 5573,5579 **** clear_screen(void) { g_coord.X = g_coord.Y = 0; ! clear_chars(g_coord, Rows * Columns); } --- 5667,5681 ---- clear_screen(void) { g_coord.X = g_coord.Y = 0; ! ! if (!USE_VTP) ! clear_chars(g_coord, Rows * Columns); ! else ! { ! set_console_color_rgb(); ! gotoxy(1, 1); ! vtp_printf("\033[2J"); ! } } *************** *** 5583,5590 **** static void clear_to_end_of_display(void) { ! clear_chars(g_coord, (Rows - g_coord.Y - 1) * Columns + (Columns - g_coord.X)); } --- 5685,5704 ---- static void clear_to_end_of_display(void) { ! 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,5600 **** static void clear_to_end_of_line(void) { ! clear_chars(g_coord, Columns - g_coord.X); } --- 5708,5726 ---- static void clear_to_end_of_line(void) { ! 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,5638 **** --- 5759,5767 ---- 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,5663 **** source.Right = g_srScrollRegion.Right; source.Bottom = g_srScrollRegion.Bottom - cLines; ! fill.Char.AsciiChar = ' '; ! fill.Attributes = g_attrCurrent; ! ScrollConsoleScreenBuffer(g_hConOut, &source, NULL, dest, &fill); /* 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 --- 5783,5802 ---- source.Right = g_srScrollRegion.Right; source.Bottom = g_srScrollRegion.Bottom - cLines; ! if (!USE_VTP) ! { ! fill.Char.AsciiChar = ' '; ! fill.Attributes = g_attrCurrent; ! ! 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,5705 **** source.Right = g_srScrollRegion.Right; source.Bottom = g_srScrollRegion.Bottom; ! fill.Char.AsciiChar = ' '; ! fill.Attributes = g_attrCurrent; ! ScrollConsoleScreenBuffer(g_hConOut, &source, NULL, dest, &fill); /* 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 --- 5835,5854 ---- source.Right = g_srScrollRegion.Right; source.Bottom = g_srScrollRegion.Bottom; ! if (!USE_VTP) ! { ! fill.Char.AsciiChar = ' '; ! fill.Attributes = g_attrCurrent; ! 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,5741 **** /* 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); } --- 5884,5894 ---- /* external cursor coords are 1-based; internal are 0-based */ g_coord.X = x - 1; g_coord.Y = y - 1; ! ! if (!USE_VTP) ! SetConsoleCursorPosition(g_hConOut, g_coord); ! else ! vtp_printf("\033[%d;%dH", y, x); } *************** *** 5757,5763 **** { g_attrCurrent = (g_attrCurrent & 0xf0) + (wAttr & 0x0f); ! SetConsoleTextAttribute(g_hConOut, g_attrCurrent); } --- 5910,5919 ---- { g_attrCurrent = (g_attrCurrent & 0xf0) + (wAttr & 0x0f); ! if (!USE_VTP) ! SetConsoleTextAttribute(g_hConOut, g_attrCurrent); ! else ! vtp_sgr_bulk(wAttr); } *************** *** 5766,5772 **** { g_attrCurrent = (g_attrCurrent & 0x0f) + ((wAttr & 0x0f) << 4); ! SetConsoleTextAttribute(g_hConOut, g_attrCurrent); } --- 5922,5931 ---- { g_attrCurrent = (g_attrCurrent & 0x0f) + ((wAttr & 0x0f) << 4); ! if (!USE_VTP) ! SetConsoleTextAttribute(g_hConOut, g_attrCurrent); ! else ! vtp_sgr_bulk(wAttr); } *************** *** 5776,5782 **** static void normvideo(void) { ! textattr(g_attrDefault); } --- 5935,5944 ---- static void normvideo(void) { ! if (!USE_VTP) ! textattr(g_attrDefault); ! else ! vtp_sgr_bulk(0); } *************** *** 5789,5794 **** --- 5951,5957 ---- standout(void) { g_attrPreStandout = g_attrCurrent; + textattr((WORD) (g_attrCurrent|FOREGROUND_INTENSITY|BACKGROUND_INTENSITY)); } *************** *** 5800,5809 **** standend(void) { if (g_attrPreStandout) - { textattr(g_attrPreStandout); ! g_attrPreStandout = 0; ! } } --- 5963,5971 ---- standend(void) { if (g_attrPreStandout) textattr(g_attrPreStandout); ! ! g_attrPreStandout = 0; } *************** *** 5818,5824 **** 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); --- 5980,5990 ---- 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); *************** *** 5828,5833 **** --- 5994,6003 ---- 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,5857 **** coordOrigin, &dwDummy); Sleep(15); /* wait for 15 msec */ ! WriteConsoleOutputAttribute(g_hConOut, oldattrs, Rows * Columns, coordOrigin, &dwDummy); vim_free(oldattrs); } --- 6021,6028 ---- coordOrigin, &dwDummy); Sleep(15); /* wait for 15 msec */ ! if (!USE_VTP) ! WriteConsoleOutputAttribute(g_hConOut, oldattrs, Rows * Columns, coordOrigin, &dwDummy); vim_free(oldattrs); } *************** *** 5901,5914 **** 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 (cchwritten == length) { --- 6072,6095 ---- unicodebuf, unibuflen); cells = mb_string2cells(pchBuf, cbToWrite); ! ! 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,5940 **** 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; g_coord.X += (SHORT) written; } --- 6108,6130 ---- else #endif { ! 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,6126 **** char_u *old_s = s; #endif char_u *p; ! int arg1 = 0, arg2 = 0; 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; ! arg2 = getdigits(&p); /* no check for length! */ 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); } ! else if (*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') { ! /* move cursor right arg1 columns in same line */ ! gotoxy(min(g_srScrollRegion.Right, g_coord.X + arg1) + 1, ! g_coord.Y + 1); } ! else if (*p == 'H') { ! gotoxy(1, arg1); } ! else if (*p == 'L') { ! insert_lines(arg1); } ! else if (*p == 'm') { ! if (arg1 == 0) ! normvideo(); ! else ! textattr((WORD) arg1); } ! else if (*p == 'f') { textcolor((WORD) arg1); } ! else if (*p == 'b') { ! textbackground((WORD) arg1); } ! else if (*p == 'M') { delete_lines(arg1); } --- 6250,6325 ---- char_u *old_s = s; #endif char_u *p; ! int arg1 = 0, arg2 = 0, argc = 0, args[16]; switch (s[2]) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': ! p = s + 1; ! do { ++p; ! args[argc] = getdigits(&p); ! argc += (argc < 15) ? 1 : 0; if (p > s + len) break; + } while (*p == ';'); ! if (p > s + len) ! break; ! ! 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 (argc == 2 && *p == 'H') { ! gotoxy(arg2, arg1); } ! else if (argc == 2 && *p == 'r') { ! set_scroll_region(0, arg1 - 1, Columns - 1, arg2 - 1); } ! else if (argc == 1 && *p == 'A') { ! gotoxy(g_coord.X + 1, ! max(g_srScrollRegion.Top, g_coord.Y - arg1) + 1); } ! else if (argc == 1 && *p == 'b') { ! textbackground((WORD) arg1); } ! else if (argc == 1 && *p == 'C') { ! gotoxy(min(g_srScrollRegion.Right, g_coord.X + arg1) + 1, ! g_coord.Y + 1); } ! else if (argc == 1 && *p == 'f') { textcolor((WORD) arg1); } ! else if (argc == 1 && *p == 'H') { ! gotoxy(1, arg1); } ! else if (argc == 1 && *p == 'L') ! { ! insert_lines(arg1); ! } ! else if (argc == 1 && *p == 'M') { delete_lines(arg1); } *************** *** 6129,6139 **** 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; --- 6328,6334 ---- *************** *** 6143,6149 **** 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; --- 6338,6343 ---- *************** *** 7242,7244 **** --- 7436,7621 ---- 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 *** ../vim-8.0.1530/src/proto/os_win32.pro 2017-11-21 18:11:23.657015881 +0100 --- src/proto/os_win32.pro 2018-02-22 20:54:57.114602718 +0100 *************** *** 42,47 **** --- 42,48 ---- 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,71 **** 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); /* vim: set ft=c : */ --- 68,74 ---- void set_alist_count(void); void fix_arg_enc(void); int mch_setenv(char *var, char *value, int x); ! void control_console_color_rgb(void); ! int has_vtp_working(void); ! int use_vtp(void); /* vim: set ft=c : */ *** ../vim-8.0.1530/src/feature.h 2017-11-27 22:48:57.909206815 +0100 --- src/feature.h 2018-02-22 20:33:07.789316271 +0100 *************** *** 1394,1396 **** --- 1394,1403 ---- || (defined(WIN3264) && defined(FEAT_GUI_W32)) # define FEAT_FILTERPIPE #endif + + /* + * +vtp: Win32 virtual console. + */ + #if !defined(FEAT_GUI) && defined(WIN3264) + # define FEAT_VTP + #endif *** ../vim-8.0.1530/src/proto/term.pro 2018-01-31 20:51:40.305835913 +0100 --- src/proto/term.pro 2018-02-22 20:14:31.580661029 +0100 *************** *** 73,78 **** --- 73,79 ---- 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 : */ *** ../vim-8.0.1530/src/screen.c 2018-02-20 21:44:39.386348846 +0100 --- src/screen.c 2018-02-22 20:45:02.571896399 +0100 *************** *** 2177,2182 **** --- 2177,2201 ---- * 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; *** ../vim-8.0.1530/src/syntax.c 2018-02-20 21:44:39.390348818 +0100 --- src/syntax.c 2018-02-22 20:14:31.588661060 +0100 *************** *** 8927,8932 **** --- 8927,8936 ---- 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,9571 **** --- 9570,9592 ---- 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 *** ../vim-8.0.1530/src/term.c 2018-02-10 18:45:21.096821957 +0100 --- src/term.c 2018-02-22 20:14:31.588661060 +0100 *************** *** 76,82 **** 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); --- 76,81 ---- *************** *** 600,605 **** --- 599,608 ---- # 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,2012 **** --- 2010,2020 ---- 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,2848 **** } #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 [ or CSI */ /* Special handling of 16 colors, because termcap can't handle it */ /* Also accept "\e[3%dm" for TERMINFO, it is sometimes used */ --- 2826,2837 ---- } #endif static void term_color(char_u *s, int n) { char buf[20]; ! int i = *s == CSI ? 1 : 2; ! /* index in s[] just after [ 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,2874 **** --- 2858,2883 ---- 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,6619 **** --- 6623,6728 ---- ++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) *** ../vim-8.0.1530/src/testdir/gen_opt_test.vim 2017-11-26 23:47:14.219034826 +0100 --- src/testdir/gen_opt_test.vim 2018-02-22 20:14:31.592661075 +0100 *************** *** 129,134 **** --- 129,135 ---- \ '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']], *** ../vim-8.0.1530/src/version.c 2018-02-22 11:42:45.331211013 +0100 --- src/version.c 2018-02-22 20:34:48.214523701 +0100 *************** *** 699,704 **** --- 699,711 ---- #else "-vreplace", #endif + #ifdef WIN3264 + # ifdef FEAT_VTP + "+vtp", + # else + "-vtp", + # endif + #endif #ifdef FEAT_WILDIGN "+wildignore", #else *** ../vim-8.0.1530/src/version.c 2018-02-22 11:42:45.331211013 +0100 --- src/version.c 2018-02-22 20:34:48.214523701 +0100 *************** *** 773,774 **** --- 780,783 ---- { /* Add new patch number below this line */ + /**/ + 1531, /**/ -- I bought a book on hair loss, but the pages kept falling out. /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\ /// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\ \\\ an exciting new programming language -- http://www.Zimbu.org /// \\\ help me help AIDS victims -- http://ICCF-Holland.org ///