]> granicus.if.org Git - vim/commitdiff
patch 8.0.1531: cannot use 24 bit colors in MS-Windows console v8.0.1531
authorBram Moolenaar <Bram@vim.org>
Thu, 22 Feb 2018 20:07:09 +0000 (21:07 +0100)
committerBram Moolenaar <Bram@vim.org>
Thu, 22 Feb 2018 20:07:09 +0000 (21:07 +0100)
Problem:    Cannot use 24 bit colors in MS-Windows console.
Solution:   Add support for vcon. (Nobuhiro Takasaki, Ken Takasaki,
            fixes #1270, fixes #2060)

13 files changed:
runtime/doc/options.txt
src/evalfunc.c
src/feature.h
src/misc1.c
src/option.c
src/os_win32.c
src/proto/os_win32.pro
src/proto/term.pro
src/screen.c
src/syntax.c
src/term.c
src/testdir/gen_opt_test.vim
src/version.c

index b260d7e11d8d19067be62b54c52ca2d6b3313d1c..b9f15176816b07e5203c30cf7f1b746d59584217 100644 (file)
@@ -1,4 +1,4 @@
-*options.txt*  For Vim version 8.0.  Last change: 2018 Feb 03
+*options.txt*  For Vim version 8.0.  Last change: 2018 Feb 22
 
 
                  VIM REFERENCE MANUAL    by Bram Moolenaar
@@ -5203,8 +5203,11 @@ A jump table for the options with a short description can be found at |Q_op|.
                        {not in Vi}
        Maximum amount of memory (in Kbyte) to use for one buffer.  When this
        limit is reached allocating extra memory for a buffer will cause
-       other memory to be freed.  The maximum usable value is about 2000000.
-       Use this to work without a limit.  Also see 'maxmemtot'.
+       other memory to be freed.
+       The maximum usable value is about 2000000.  Use this to work without a
+       limit.
+       The value is ignored when 'swapfile' is off.
+       Also see 'maxmemtot'.
 
                                                *'maxmempattern'* *'mmp'*
 'maxmempattern' 'mmp'  number  (default 1000)
@@ -5233,6 +5236,8 @@ A jump table for the options with a short description can be found at |Q_op|.
        need more than 2 Gbyte for text editing?  Keep in mind that text is
        stored in the swap file, one can edit files > 2 Gbyte anyway.  We do
        need the memory to store undo info.
+       Buffers with 'swapfile' off still count to the total amount of memory
+       used.
        Also see 'maxmem'.
 
                                                *'menuitems'* *'mis'*
@@ -5956,14 +5961,13 @@ A jump table for the options with a short description can be found at |Q_op|.
        |ins-completion-menu|.
 
                                                *'pumwidth'* *'pw'*
-'pumwidth' 'pw'                number  (default 0)
+'pumwidth' 'pw'                number  (default 15)
                        global
                        {not available when compiled without the
                        |+insert_expand| feature}
                        {not in Vi}
        Determines the minium width to use for the popup menu for Insert mode
-       completion.  When zero the default of 15 screen cells is used.
-       |ins-completion-menu|.
+       completion.  |ins-completion-menu|.
 
                                                *'pythondll'*
 'pythondll'            string  (default depends on the build)
@@ -7903,17 +7907,23 @@ 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'* *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.
+       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.
 
index 1fad78a189b751b797fe82237573ee5aa790514f..5b684bd9469928bfff072829dd8c08bfc58a0106 100644 (file)
@@ -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)
index a0b0f7e1d4bdcacee836620f58a942d94a2abfd6..d29e599a9bfae42322613066d5cd378ef1b6d974 100644 (file)
            || (defined(WIN3264) && defined(FEAT_GUI_W32))
 # define FEAT_FILTERPIPE
 #endif
+
+/*
+ * +vtp: Win32 virtual console.
+ */
+#if !defined(FEAT_GUI) && defined(WIN3264)
+# define FEAT_VTP
+#endif
index e639fbe41b5e9087df64bbccd65f1d01e8d0444e..32e3c17ae64c17a95008b9328ee258c2294043d8 100644 (file)
@@ -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
index 21ca0fa48bc90d399d51248a2bdcafbcf54218a5..96620395102682a96a2742bf04ed2fe2121578cf 100644 (file)
@@ -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
 
index 02f87102c1efaa40bdb8042e438d938d7d27d4cf..91f453f2e9a9b3db2d84cec77dda7770c19a4c09 100644 (file)
@@ -202,6 +202,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 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
index a87d8b767316732d032e2bcde3e4ba908c5ae793..d76e27020fd882955b7395019aeafc63ce7c23f5 100644 (file)
@@ -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 : */
index b0ad418e800d0c1fcfd701cc8ed37408fd8238e2..92cb26d58b4f366ea15cfb3e2f44772ae1ae30a2 100644 (file)
@@ -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 : */
index 8b7a519c08006eaacc7d8fe874928eb00fbc46fe..9592f551347b8ab8b5adc22303bbecb3690c04e8 100644 (file)
@@ -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;
index fcffdbf8af84f94fde6b21ba8e037a95eb0f06cb..79b2796d2b0d248c7ecb5dc2e8605cf3e557b1cf 100644 (file)
@@ -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
index 1f17d9f2fa91ec634f7af2109b0a43bf04e7f053..3e2b8ecc35ed0060fb9bc8cb47b5e9d4fead6d4d 100644 (file)
@@ -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 */
+    {(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)
index 4edf44aafd2d22c4af09bf5aed6789a3087d08ba..e781a0d2a851872c65fd3c2ebc9476a6307173a2 100644 (file)
@@ -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']],
index 422b820e6b42da13e3cbd13495d26dd56fff4cdd..2fb2c59001cefe54ba246c088b44a1b9b946bba1 100644 (file)
@@ -699,6 +699,13 @@ static char *(features[]) =
 #else
        "-vreplace",
 #endif
+#ifdef WIN3264
+# ifdef FEAT_VTP
+       "+vtp",
+# else
+       "-vtp",
+# endif
+#endif
 #ifdef FEAT_WILDIGN
        "+wildignore",
 #else
@@ -771,6 +778,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    1531,
 /**/
     1530,
 /**/