summaryrefslogtreecommitdiff
path: root/data/vim/patches/8.1.0870
diff options
context:
space:
mode:
Diffstat (limited to 'data/vim/patches/8.1.0870')
-rw-r--r--data/vim/patches/8.1.08701685
1 files changed, 1685 insertions, 0 deletions
diff --git a/data/vim/patches/8.1.0870 b/data/vim/patches/8.1.0870
new file mode 100644
index 000000000..7112c7080
--- /dev/null
+++ b/data/vim/patches/8.1.0870
@@ -0,0 +1,1685 @@
+To: vim_dev@googlegroups.com
+Subject: Patch 8.1.0870
+Fcc: outbox
+From: Bram Moolenaar <Bram@moolenaar.net>
+Mime-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+------------
+
+Patch 8.1.0870
+Problem: Vim doesn't use the new ConPTY support in Windows 10.
+Solution: Use ConPTY support, if available. (Nobuhiro Takasaki, closes #3794)
+Files: runtime/doc/eval.txt, runtime/doc/options.txt,
+ runtime/doc/terminal.txt, src/channel.c, src/evalfunc.c,
+ src/globals.h, src/option.c, src/option.h, src/os_win32.c,
+ src/proto/terminal.pro, src/structs.h, src/terminal.c,
+ src/testdir/gen_opt_test.vim, src/testdir/test_autocmd.vim,
+ src/testdir/test_mksession.vim, src/testdir/test_terminal.vim
+
+
+*** ../vim-8.1.0869/runtime/doc/eval.txt 2019-01-31 15:52:05.265907656 +0100
+--- runtime/doc/eval.txt 2019-02-03 13:52:16.589856140 +0100
+***************
+*** 9410,9415 ****
+--- 9469,9478 ----
+ "ansi_colors" A list of 16 color names or hex codes
+ defining the ANSI palette used in GUI
+ color modes. See |g:terminal_ansi_colors|.
++ "term_mode" (MS-Windows only): Specify which pty to
++ use:
++ "winpty": Use winpty
++ "conpty": Use ConPTY (if available)
+
+ {only available when compiled with the |+terminal| feature}
+
+***************
+*** 10126,10133 ****
+--- 10190,10199 ----
+ cmdline_info Compiled with 'showcmd' and 'ruler' support.
+ comments Compiled with |'comments'| support.
+ compatible Compiled to be very Vi compatible.
++ conpty Platform where |ConPTY| can be used.
+ cryptv Compiled with encryption support |encryption|.
+ cscope Compiled with |cscope| support.
++ cursorbind Compiled with |cursorbind| (always true)
+ debug Compiled with "DEBUG" defined.
+ dialog_con Compiled with console dialog support.
+ dialog_gui Compiled with GUI dialog support.
+*** ../vim-8.1.0869/runtime/doc/options.txt 2019-01-31 18:26:05.730803572 +0100
+--- runtime/doc/options.txt 2019-02-03 14:35:38.054496226 +0100
+***************
+*** 8009,8014 ****
+--- 8054,8076 ----
+ Note that the "cterm" attributes are still used, not the "gui" ones.
+ NOTE: This option is reset when 'compatible' is set.
+
++ *'termmode'* *'tmod'*
++ 'termmode' 'tmod' string (default "")
++ local to window
++ {not in Vi, MS-Windows only}
++ Whether the window uses winpty or |ConPTY| as the virtual console.
++ When set before opening the terminal, it influences what pty is used.
++ When opening the terminal it will be set to the actually used pty.
++
++ Possible values are:
++ "" use ConPTY if possible, winpty otherwise
++ "winpty" use winpty, fail if not supported
++ "conpty" use |ConPTY|, fail if not supported
++
++ |ConPTY| support depends on the platform (Windows 10 October 2018
++ edition). winpty support needs to be installed. If neither is
++ supported then you cannot open a terminal window.
++
+ *'termwinscroll'* *'twsl'*
+ 'termwinscroll' 'twsl' number (default 10000)
+ local to buffer
+*** ../vim-8.1.0869/runtime/doc/terminal.txt 2018-10-19 22:35:04.885189994 +0200
+--- runtime/doc/terminal.txt 2019-02-03 13:53:49.233271142 +0100
+***************
+*** 228,234 ****
+ for Python "++eof=exit()". Special
+ codes can be used like with `:map`,
+ e.g. "<C-Z>" for CTRL-Z.
+!
+ If you want to use more options use the |term_start()|
+ function.
+ If you want to split the window vertically, use: >
+--- 228,235 ----
+ for Python "++eof=exit()". Special
+ codes can be used like with `:map`,
+ e.g. "<C-Z>" for CTRL-Z.
+! ++winpty Use winpty as the virtual console.
+! ++conpty Use |ConPTY| as the virtual console.
+ If you want to use more options use the |term_start()|
+ function.
+ If you want to split the window vertically, use: >
+***************
+*** 410,415 ****
+--- 411,423 ----
+ to point to the right file, if needed. If you have both the 32-bit and 64-bit
+ version, rename to winpty32.dll and winpty64.dll to match the way Vim was
+ build.
++ *ConPTY*
++ On more recent versions of MS-Windows 10 (beginning with the "October 2018
++ Update"), winpty is no longer required. On those versions, |:terminal| will use
++ Windows' built-in support for hosting terminal applications, "ConPTY". When
++ ConPTY is in use, there may be rendering artifacts regarding ambiguous-width
++ characters. If you encounter any such issues, set 'termmode' to winpty (which
++ you then must have instlled).
+
+ Environment variables are used to pass information to the running job:
+ VIM_SERVERNAME v:servername
+*** ../vim-8.1.0869/src/channel.c 2019-01-31 15:52:05.265907656 +0100
+--- src/channel.c 2019-02-03 14:13:11.701910368 +0100
+***************
+*** 1720,1730 ****
+ char_u *res;
+ char_u *p;
+
+! /* If there is only one buffer just get that one. */
+! if (head->rq_next == NULL || head->rq_next->rq_next == NULL)
+! return channel_get(channel, part, outlen);
+!
+! /* Concatenate everything into one buffer. */
+ for (node = head->rq_next; node != NULL; node = node->rq_next)
+ len += node->rq_buflen;
+ res = lalloc(len + 1, TRUE);
+--- 1720,1726 ----
+ char_u *res;
+ char_u *p;
+
+! // Concatenate everything into one buffer.
+ for (node = head->rq_next; node != NULL; node = node->rq_next)
+ len += node->rq_buflen;
+ res = lalloc(len + 1, TRUE);
+***************
+*** 1738,1744 ****
+ }
+ *p = NUL;
+
+! /* Free all buffers */
+ do
+ {
+ p = channel_get(channel, part, NULL);
+--- 1734,1740 ----
+ }
+ *p = NUL;
+
+! // Free all buffers
+ do
+ {
+ p = channel_get(channel, part, NULL);
+***************
+*** 1747,1762 ****
+
+ if (outlen != NULL)
+ {
+ *outlen += len;
+ return res;
+ }
+
+! /* turn all NUL into NL */
+! while (len > 0)
+ {
+! --len;
+! if (res[len] == NUL)
+! res[len] = NL;
+ }
+
+ return res;
+--- 1743,1779 ----
+
+ if (outlen != NULL)
+ {
++ // Returning the length, keep NUL characters.
+ *outlen += len;
+ return res;
+ }
+
+! // Turn all NUL into NL, so that the result can be used as a string.
+! p = res;
+! while (p < res + len)
+ {
+! if (*p == NUL)
+! *p = NL;
+! #ifdef WIN32
+! else if (*p == 0x1b)
+! {
+! // crush the escape sequence OSC 0/1/2: ESC ]0;
+! if (p + 3 < res + len
+! && p[1] == ']'
+! && (p[2] == '0' || p[2] == '1' || p[2] == '2')
+! && p[3] == ';')
+! {
+! // '\a' becomes a NL
+! while (p < res + (len - 1) && *p != '\a')
+! ++p;
+! // BEL is zero width characters, suppress display mistake
+! // ConPTY (after 10.0.18317) requires advance checking
+! if (p[-1] == NUL)
+! p[-1] = 0x07;
+! }
+! }
+! #endif
+! ++p;
+ }
+
+ return res;
+***************
+*** 4330,4336 ****
+ channel = first_channel;
+ continue;
+ }
+! if (channel->ch_to_be_freed)
+ {
+ channel_free(channel);
+ /* channel has been freed, start over */
+--- 4347,4353 ----
+ channel = first_channel;
+ continue;
+ }
+! if (channel->ch_to_be_freed || channel->ch_killing)
+ {
+ channel_free(channel);
+ /* channel has been freed, start over */
+***************
+*** 4930,4935 ****
+--- 4947,4974 ----
+ opt->jo_set2 |= JO2_TERM_KILL;
+ opt->jo_term_kill = tv_get_string_chk(item);
+ }
++ else if (STRCMP(hi->hi_key, "term_mode") == 0)
++ {
++ char_u *p;
++
++ if (!(supported2 & JO2_TERM_MODE))
++ break;
++ opt->jo_set2 |= JO2_TERM_MODE;
++ p = tv_get_string_chk(item);
++ if (p == NULL)
++ {
++ semsg(_(e_invargval), "term_mode");
++ return FAIL;
++ }
++ // Allow empty string, "winpty", "conpty".
++ if (!(*p == NUL || STRCMP(p, "winpty") == 0
++ || STRCMP(p, "conpty") == 0))
++ {
++ semsg(_(e_invargval), "term_mode");
++ return FAIL;
++ }
++ opt->jo_term_mode = p[0];
++ }
+ # if defined(FEAT_GUI) || defined(FEAT_TERMGUICOLORS)
+ else if (STRCMP(hi->hi_key, "ansi_colors") == 0)
+ {
+***************
+*** 5440,5445 ****
+--- 5479,5494 ----
+ channel_need_redraw = TRUE;
+ }
+
++ if (job->jv_channel != NULL
++ && job->jv_channel->ch_anonymous_pipe && !job->jv_channel->ch_killing)
++ {
++ ++safe_to_invoke_callback;
++ channel_free_contents(job->jv_channel);
++ job->jv_channel->ch_job = NULL;
++ job->jv_channel = NULL;
++ --safe_to_invoke_callback;
++ }
++
+ // Do not free the job in case the close callback of the associated channel
+ // isn't invoked yet and may get information by job_info().
+ if (job->jv_refcount == 0 && !job_channel_still_useful(job))
+*** ../vim-8.1.0869/src/evalfunc.c 2019-01-30 22:01:36.982854408 +0100
+--- src/evalfunc.c 2019-02-03 13:46:59.595853343 +0100
+***************
+*** 6738,6743 ****
+--- 6738,6747 ----
+ else if (STRICMP(name, "terminal") == 0)
+ n = terminal_enabled();
+ #endif
++ #if defined(FEAT_TERMINAL) && defined(WIN3264)
++ else if (STRICMP(name, "conpty") == 0)
++ n = use_conpty();
++ #endif
+ }
+
+ rettv->vval.v_number = n;
+*** ../vim-8.1.0869/src/globals.h 2019-01-26 17:28:22.224599141 +0100
+--- src/globals.h 2019-02-03 13:46:59.595853343 +0100
+***************
+*** 1432,1438 ****
+ || defined(DYNAMIC_ICONV) \
+ || defined(DYNAMIC_GETTEXT) \
+ || defined(DYNAMIC_MZSCHEME) \
+! || defined(DYNAMIC_LUA)
+ EXTERN char e_loadlib[] INIT(= N_("E370: Could not load library %s"));
+ EXTERN char e_loadfunc[] INIT(= N_("E448: Could not load library function %s"));
+ #endif
+--- 1432,1439 ----
+ || defined(DYNAMIC_ICONV) \
+ || defined(DYNAMIC_GETTEXT) \
+ || defined(DYNAMIC_MZSCHEME) \
+! || defined(DYNAMIC_LUA) \
+! || defined(FEAT_TERMINAL)
+ EXTERN char e_loadlib[] INIT(= N_("E370: Could not load library %s"));
+ EXTERN char e_loadfunc[] INIT(= N_("E448: Could not load library function %s"));
+ #endif
+*** ../vim-8.1.0869/src/option.c 2019-01-31 18:26:05.738803509 +0100
+--- src/option.c 2019-02-03 14:16:43.164569746 +0100
+***************
+*** 253,258 ****
+--- 253,259 ----
+ # define PV_TWK OPT_WIN(WV_TWK)
+ # define PV_TWS OPT_WIN(WV_TWS)
+ # define PV_TWSL OPT_BUF(BV_TWSL)
++ # define PV_TMOD OPT_WIN(WV_TMOD)
+ #endif
+ #ifdef FEAT_SIGNS
+ # define PV_SCL OPT_WIN(WV_SCL)
+***************
+*** 2700,2705 ****
+--- 2701,2715 ----
+ {(char_u *)FALSE, (char_u *)FALSE}
+ #endif
+ SCTX_INIT},
++ {"termmode", "tmod", P_STRING|P_ALLOCED|P_VI_DEF,
++ #ifdef FEAT_TERMINAL
++ (char_u *)VAR_WIN, PV_TMOD,
++ {(char_u *)"", (char_u *)NULL}
++ #else
++ (char_u *)NULL, PV_NONE,
++ {(char_u *)NULL, (char_u *)0L}
++ #endif
++ SCTX_INIT},
+ {"termwinkey", "twk", P_STRING|P_ALLOCED|P_RWIN|P_VI_DEF,
+ #ifdef FEAT_TERMINAL
+ (char_u *)VAR_WIN, PV_TWK,
+***************
+*** 3208,3213 ****
+--- 3218,3226 ----
+ #ifdef FEAT_SIGNS
+ static char *(p_scl_values[]) = {"yes", "no", "auto", NULL};
+ #endif
++ #ifdef FEAT_TERMINAL
++ static char *(p_tmod_values[]) = {"winpty", "conpty", "", NULL};
++ #endif
+
+ static void set_options_default(int opt_flags);
+ static void set_string_default_esc(char *name, char_u *val, int escape);
+***************
+*** 3661,3667 ****
+ {
+ char buf[50];
+
+! sprintf(buf, "cp%ld", (long)GetConsoleCP());
+ p_tenc = vim_strsave((char_u *)buf);
+ if (p_tenc != NULL)
+ {
+--- 3674,3685 ----
+ {
+ char buf[50];
+
+! /* Win32 console: In ConPTY, GetConsoleCP() returns zero.
+! * Use an alternative value. */
+! if (GetConsoleCP() == 0)
+! sprintf(buf, "cp%ld", (long)GetACP());
+! else
+! sprintf(buf, "cp%ld", (long)GetConsoleCP());
+ p_tenc = vim_strsave((char_u *)buf);
+ if (p_tenc != NULL)
+ {
+***************
+*** 7468,7481 ****
+ #endif
+
+ #ifdef FEAT_TERMINAL
+! /* 'termwinkey' */
+ else if (varp == &curwin->w_p_twk)
+ {
+ if (*curwin->w_p_twk != NUL
+ && string_to_key(curwin->w_p_twk, TRUE) == 0)
+ errmsg = e_invarg;
+ }
+! /* 'termwinsize' */
+ else if (varp == &curwin->w_p_tws)
+ {
+ if (*curwin->w_p_tws != NUL)
+--- 7486,7499 ----
+ #endif
+
+ #ifdef FEAT_TERMINAL
+! // 'termwinkey'
+ else if (varp == &curwin->w_p_twk)
+ {
+ if (*curwin->w_p_twk != NUL
+ && string_to_key(curwin->w_p_twk, TRUE) == 0)
+ errmsg = e_invarg;
+ }
+! // 'termwinsize'
+ else if (varp == &curwin->w_p_tws)
+ {
+ if (*curwin->w_p_tws != NUL)
+***************
+*** 7487,7492 ****
+--- 7505,7516 ----
+ errmsg = e_invarg;
+ }
+ }
++ // 'termmode'
++ else if (varp == &curwin->w_p_tmod)
++ {
++ if (check_opt_strings(*varp, p_tmod_values, FALSE) != OK)
++ errmsg = e_invarg;
++ }
+ #endif
+
+ #ifdef FEAT_VARTABS
+***************
+*** 8838,8844 ****
+ if (!has_vtp_working())
+ {
+ p_tgc = 0;
+! return (char_u*)N_("E954: 24-bit colors are not supported on this environment");
+ }
+ if (is_term_win32())
+ swap_tcap();
+--- 8862,8868 ----
+ if (!has_vtp_working())
+ {
+ p_tgc = 0;
+! return N_("E954: 24-bit colors are not supported on this environment");
+ }
+ if (is_term_win32())
+ swap_tcap();
+***************
+*** 10928,10933 ****
+--- 10952,10958 ----
+ case PV_TWK: return (char_u *)&(curwin->w_p_twk);
+ case PV_TWS: return (char_u *)&(curwin->w_p_tws);
+ case PV_TWSL: return (char_u *)&(curbuf->b_p_twsl);
++ case PV_TMOD: return (char_u *)&(curwin->w_p_tmod);
+ #endif
+
+ case PV_AI: return (char_u *)&(curbuf->b_p_ai);
+***************
+*** 11128,11133 ****
+--- 11153,11159 ----
+ #ifdef FEAT_TERMINAL
+ to->wo_twk = vim_strsave(from->wo_twk);
+ to->wo_tws = vim_strsave(from->wo_tws);
++ to->wo_tmod = vim_strsave(from->wo_tmod);
+ #endif
+ #ifdef FEAT_FOLDING
+ to->wo_fdc = from->wo_fdc;
+***************
+*** 11198,11203 ****
+--- 11224,11230 ----
+ #ifdef FEAT_TERMINAL
+ check_string_option(&wop->wo_twk);
+ check_string_option(&wop->wo_tws);
++ check_string_option(&wop->wo_tmod);
+ #endif
+ #ifdef FEAT_LINEBREAK
+ check_string_option(&wop->wo_briopt);
+***************
+*** 11241,11246 ****
+--- 11268,11274 ----
+ #ifdef FEAT_TERMINAL
+ clear_string_option(&wop->wo_twk);
+ clear_string_option(&wop->wo_tws);
++ clear_string_option(&wop->wo_tmod);
+ #endif
+ }
+
+*** ../vim-8.1.0869/src/option.h 2019-01-31 18:26:05.738803509 +0100
+--- src/option.h 2019-02-03 13:46:59.599853319 +0100
+***************
+*** 1112,1117 ****
+--- 1112,1118 ----
+ #ifdef FEAT_TERMINAL
+ , WV_TWK
+ , WV_TWS
++ , WV_TMOD
+ #endif
+ , WV_CRBIND
+ #ifdef FEAT_LINEBREAK
+*** ../vim-8.1.0869/src/os_win32.c 2019-01-24 23:11:44.631650199 +0100
+--- src/os_win32.c 2019-02-03 13:46:59.599853319 +0100
+***************
+*** 186,193 ****
+ 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, ...);
+--- 186,195 ----
+ static int win32_setattrs(char_u *name, int attrs);
+ static int win32_set_archive(char_u *name);
+
+ static int vtp_working = 0;
++ static void vtp_flag_init();
++
++ #ifndef FEAT_GUI_W32
+ static void vtp_init();
+ static void vtp_exit();
+ static int vtp_printf(char *format, ...);
+***************
+*** 247,252 ****
+--- 249,255 ----
+ typedef BOOL (WINAPI *PfnSetConsoleScreenBufferInfoEx)(HANDLE, PDYN_CONSOLE_SCREEN_BUFFER_INFOEX);
+ static PfnSetConsoleScreenBufferInfoEx pSetConsoleScreenBufferInfoEx;
+ static BOOL has_csbiex = FALSE;
++ #endif
+
+ /*
+ * Get version number including build number
+***************
+*** 276,282 ****
+ return ver;
+ }
+
+!
+ /*
+ * Version of ReadConsoleInput() that works with IME.
+ * Works around problems on Windows 8.
+--- 279,285 ----
+ return ver;
+ }
+
+! #ifndef FEAT_GUI_W32
+ /*
+ * Version of ReadConsoleInput() that works with IME.
+ * Works around problems on Windows 8.
+***************
+*** 1508,1516 ****
+ /* Wait forever. */
+ dwEndTime = INFINITE;
+
+! /* We need to loop until the end of the time period, because
+! * we might get multiple unusable mouse events in that time.
+! */
+ for (;;)
+ {
+ // Only process messages when waiting.
+--- 1511,1518 ----
+ /* Wait forever. */
+ dwEndTime = INFINITE;
+
+! // We need to loop until the end of the time period, because
+! // we might get multiple unusable mouse events in that time.
+ for (;;)
+ {
+ // Only process messages when waiting.
+***************
+*** 2175,2180 ****
+--- 2177,2184 ----
+ #ifdef FEAT_CLIPBOARD
+ win_clip_init();
+ #endif
++
++ vtp_flag_init();
+ }
+
+
+***************
+*** 2675,2680 ****
+--- 2679,2685 ----
+ win_clip_init();
+ #endif
+
++ vtp_flag_init();
+ vtp_init();
+ }
+
+***************
+*** 5683,5689 ****
+--- 5688,5698 ----
+ {
+ /* deadly signal */
+ if (job->jv_job_object != NULL)
++ {
++ if (job->jv_channel != NULL && job->jv_channel->ch_anonymous_pipe)
++ job->jv_channel->ch_killing = TRUE;
+ return TerminateJobObject(job->jv_job_object, 0) ? OK : FAIL;
++ }
+ return terminate_all(job->jv_proc_info.hProcess, 0) ? OK : FAIL;
+ }
+
+***************
+*** 7621,7651 ****
+ 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;
+ # ifdef FEAT_TERMGUICOLORS
+ COLORREF fg, bg;
+ # endif
+
+- 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)
+--- 7630,7682 ----
+ return 0;
+ }
+
+ /*
+ * 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)
+!
+! /*
+! * Support for pseudo-console (ConPTY) was added in windows 10
+! * version 1809 (October 2018 update).
+! */
+! #define CONPTY_FIRST_SUPPORT_BUILD MAKE_VER(10, 0, 17763)
+!
+! static void
+! vtp_flag_init(void)
+! {
+! DWORD ver = get_build_number();
+! #ifndef FEAT_GUI_W32
+! DWORD mode;
+! HANDLE out;
+!
+! out = GetStdHandle(STD_OUTPUT_HANDLE);
+!
+! vtp_working = (ver >= VTP_FIRST_SUPPORT_BUILD) ? 1 : 0;
+! GetConsoleMode(out, &mode);
+! mode |= (ENABLE_PROCESSED_OUTPUT | ENABLE_VIRTUAL_TERMINAL_PROCESSING);
+! if (SetConsoleMode(out, mode) == 0)
+! vtp_working = 0;
+! #endif
+!
+! #ifdef FEAT_GUI_W32
+! if (ver >= CONPTY_FIRST_SUPPORT_BUILD)
+! vtp_working = 1;
+! #endif
+!
+! }
+!
+! #ifndef FEAT_GUI_W32
+
+ static void
+ vtp_init(void)
+ {
+ HMODULE hKerneldll;
+ DYN_CONSOLE_SCREEN_BUFFER_INFOEX csbi;
+ # ifdef FEAT_TERMGUICOLORS
+ COLORREF fg, bg;
+ # endif
+
+ /* Use functions supported from Vista */
+ hKerneldll = GetModuleHandle("kernel32.dll");
+ if (hKerneldll != NULL)
+***************
+*** 7829,7840 ****
+ }
+
+ int
+- has_vtp_working(void)
+- {
+- return vtp_working;
+- }
+-
+- int
+ use_vtp(void)
+ {
+ return USE_VTP;
+--- 7860,7865 ----
+***************
+*** 7847,7849 ****
+--- 7872,7880 ----
+ }
+
+ #endif
++
++ int
++ has_vtp_working(void)
++ {
++ return vtp_working;
++ }
+*** ../vim-8.1.0869/src/proto/terminal.pro 2019-01-29 22:29:03.550799929 +0100
+--- src/proto/terminal.pro 2019-02-03 13:46:59.599853319 +0100
+***************
+*** 57,60 ****
+--- 57,62 ----
+ void term_send_eof(channel_T *ch);
+ job_T *term_getjob(term_T *term);
+ int terminal_enabled(void);
++ void term_free_conpty(term_T *term);
++ int use_conpty(void);
+ /* vim: set ft=c : */
+*** ../vim-8.1.0869/src/structs.h 2019-01-31 18:26:05.738803509 +0100
+--- src/structs.h 2019-02-03 14:13:33.145774428 +0100
+***************
+*** 282,287 ****
+--- 282,289 ----
+ # define w_p_twk w_onebuf_opt.wo_twk /* 'termwinkey' */
+ char_u *wo_tws;
+ # define w_p_tws w_onebuf_opt.wo_tws /* 'termwinsize' */
++ char_u *wo_tmod;
++ # define w_p_tmod w_onebuf_opt.wo_tmod /* 'termmode' */
+ #endif
+
+ #ifdef FEAT_EVAL
+***************
+*** 1728,1740 ****
+ int ch_keep_open; /* do not close on read error */
+ int ch_nonblock;
+
+! job_T *ch_job; /* Job that uses this channel; this does not
+! * count as a reference to avoid a circular
+! * reference, the job refers to the channel. */
+! int ch_job_killed; /* TRUE when there was a job and it was killed
+! * or we know it died. */
+
+! int ch_refcount; /* reference count */
+ int ch_copyID;
+ };
+
+--- 1730,1744 ----
+ int ch_keep_open; /* do not close on read error */
+ int ch_nonblock;
+
+! job_T *ch_job; // Job that uses this channel; this does not
+! // count as a reference to avoid a circular
+! // reference, the job refers to the channel.
+! int ch_job_killed; // TRUE when there was a job and it was killed
+! // or we know it died.
+! int ch_anonymous_pipe; // ConPTY
+! int ch_killing; // TerminateJobObject() was called
+
+! int ch_refcount; // reference count
+ int ch_copyID;
+ };
+
+***************
+*** 1787,1792 ****
+--- 1791,1797 ----
+ #define JO2_NORESTORE 0x2000 /* "norestore" */
+ #define JO2_TERM_KILL 0x4000 /* "term_kill" */
+ #define JO2_ANSI_COLORS 0x8000 /* "ansi_colors" */
++ #define JO2_TERM_MODE 0x10000 /* "term_mode" */
+
+ #define JO_MODE_ALL (JO_MODE + JO_IN_MODE + JO_OUT_MODE + JO_ERR_MODE)
+ #define JO_CB_ALL \
+***************
+*** 1859,1864 ****
+--- 1864,1870 ----
+ # if defined(FEAT_GUI) || defined(FEAT_TERMGUICOLORS)
+ long_u jo_ansi_colors[16];
+ # endif
++ int jo_term_mode; // first character of "term_mode"
+ #endif
+ } jobopt_T;
+
+*** ../vim-8.1.0869/src/terminal.c 2019-01-29 23:06:50.097182305 +0100
+--- src/terminal.c 2019-02-03 14:48:39.219131609 +0100
+***************
+*** 65,70 ****
+--- 65,87 ----
+ cellattr_T sb_fill_attr; /* for short line */
+ } sb_line_T;
+
++ #ifdef WIN3264
++ # ifndef HPCON
++ # define HPCON VOID*
++ # endif
++ # ifndef EXTENDED_STARTUPINFO_PRESENT
++ # define EXTENDED_STARTUPINFO_PRESENT 0x00080000
++ # endif
++ # ifndef PROC_THREAD_ATTRIBUTE_PSEUDOCONSOLE
++ # define PROC_THREAD_ATTRIBUTE_PSEUDOCONSOLE 0x00020016
++ # endif
++ typedef struct _DYN_STARTUPINFOEXW
++ {
++ STARTUPINFOW StartupInfo;
++ LPPROC_THREAD_ATTRIBUTE_LIST lpAttributeList;
++ } DYN_STARTUPINFOEXW, *PDYN_STARTUPINFOEXW;
++ #endif
++
+ /* typedef term_T in structs.h */
+ struct terminal_S {
+ term_T *tl_next;
+***************
+*** 92,101 ****
+--- 109,123 ----
+ char_u *tl_opencmd;
+ char_u *tl_eof_chars;
+
++ char_u *tl_arg0_cmd; // To format the status bar
++
+ #ifdef WIN3264
+ void *tl_winpty_config;
+ void *tl_winpty;
+
++ HPCON tl_conpty;
++ DYN_STARTUPINFOEXW tl_siex; // Structure that always needs to be hold
++
+ FILE *tl_out_fd;
+ #endif
+ #if defined(FEAT_SESSION)
+***************
+*** 147,152 ****
+--- 169,179 ----
+ /* Terminal active in terminal_loop(). */
+ static term_T *in_terminal_loop = NULL;
+
++ #ifdef WIN3264
++ static BOOL has_winpty = FALSE;
++ static BOOL has_conpty = FALSE;
++ #endif
++
+ #define MAX_ROW 999999 /* used for tl_dirty_row_end to update all rows */
+ #define KEY_BUF_LEN 200
+
+***************
+*** 715,720 ****
+--- 742,757 ----
+ vim_free(buf);
+ *p = ' ';
+ }
++ else if ((int)(p - cmd) == 6 && STRNICMP(cmd, "winpty", 6) == 0)
++ {
++ opt.jo_set2 |= JO2_TERM_MODE;
++ opt.jo_term_mode = 'w';
++ }
++ else if ((int)(p - cmd) == 6 && STRNICMP(cmd, "conpty", 6) == 0)
++ {
++ opt.jo_set2 |= JO2_TERM_MODE;
++ opt.jo_term_mode = 'c';
++ }
+ else
+ {
+ if (*p)
+***************
+*** 771,776 ****
+--- 808,818 ----
+ if (fprintf(fd, "terminal ++curwin ++cols=%d ++rows=%d ",
+ term->tl_cols, term->tl_rows) < 0)
+ return FAIL;
++ #ifdef WIN3264
++ if (*wp->w_p_tmod != NUL)
++ if (fprintf(fd, "++%s ", wp->w_p_tmod) < 0)
++ return FAIL;
++ #endif
+ if (term->tl_command != NULL && fputs((char *)term->tl_command, fd) < 0)
+ return FAIL;
+
+***************
+*** 871,876 ****
+--- 913,919 ----
+ vim_free(term->tl_status_text);
+ vim_free(term->tl_opencmd);
+ vim_free(term->tl_eof_chars);
++ vim_free(term->tl_arg0_cmd);
+ #ifdef WIN3264
+ if (term->tl_out_fd != NULL)
+ fclose(term->tl_out_fd);
+***************
+*** 2639,2648 ****
+ {
+ case VTERM_PROP_TITLE:
+ vim_free(term->tl_title);
+! /* a blank title isn't useful, make it empty, so that "running" is
+! * displayed */
+ if (*skipwhite((char_u *)value->string) == NUL)
+ term->tl_title = NULL;
+ #ifdef WIN3264
+ else if (!enc_utf8 && enc_codepage > 0)
+ {
+--- 2682,2699 ----
+ {
+ case VTERM_PROP_TITLE:
+ vim_free(term->tl_title);
+! // a blank title isn't useful, make it empty, so that "running" is
+! // displayed
+ if (*skipwhite((char_u *)value->string) == NUL)
+ term->tl_title = NULL;
++ // Same as blank
++ else if (term->tl_arg0_cmd != NULL
++ && STRNCMP(term->tl_arg0_cmd, (char_u *)value->string,
++ (int)STRLEN(term->tl_arg0_cmd)) == 0)
++ term->tl_title = NULL;
++ // Empty corrupted data of winpty
++ else if (STRNCMP(" - ", (char_u *)value->string, 4) == 0)
++ term->tl_title = NULL;
+ #ifdef WIN3264
+ else if (!enc_utf8 && enc_codepage > 0)
+ {
+***************
+*** 5318,5324 ****
+ + JO2_TERM_COLS + JO2_TERM_ROWS + JO2_VERTICAL + JO2_CURWIN
+ + JO2_CWD + JO2_ENV + JO2_EOF_CHARS
+ + JO2_NORESTORE + JO2_TERM_KILL
+! + JO2_ANSI_COLORS) == FAIL)
+ return;
+
+ buf = term_start(&argvars[0], NULL, &opt, 0);
+--- 5369,5375 ----
+ + JO2_TERM_COLS + JO2_TERM_ROWS + JO2_VERTICAL + JO2_CURWIN
+ + JO2_CWD + JO2_ENV + JO2_EOF_CHARS
+ + JO2_NORESTORE + JO2_TERM_KILL
+! + JO2_ANSI_COLORS + JO2_TERM_MODE) == FAIL)
+ return;
+
+ buf = term_start(&argvars[0], NULL, &opt, 0);
+***************
+*** 5426,5431 ****
+--- 5477,5803 ----
+ * 2. MS-Windows implementation.
+ */
+
++ HRESULT (WINAPI *pCreatePseudoConsole)(COORD, HANDLE, HANDLE, DWORD, HPCON*);
++ HRESULT (WINAPI *pResizePseudoConsole)(HPCON, COORD);
++ HRESULT (WINAPI *pClosePseudoConsole)(HPCON);
++ BOOL (*pInitializeProcThreadAttributeList)(LPPROC_THREAD_ATTRIBUTE_LIST, DWORD, DWORD, PSIZE_T);
++ BOOL (*pUpdateProcThreadAttribute)(LPPROC_THREAD_ATTRIBUTE_LIST, DWORD, DWORD_PTR, PVOID, SIZE_T, PVOID, PSIZE_T);
++ void (*pDeleteProcThreadAttributeList)(LPPROC_THREAD_ATTRIBUTE_LIST);
++
++ static int
++ dyn_conpty_init(int verbose)
++ {
++ static BOOL handled = FALSE;
++ static int result;
++ HMODULE hKerneldll;
++ int i;
++ static struct
++ {
++ char *name;
++ FARPROC *ptr;
++ } conpty_entry[] =
++ {
++ {"CreatePseudoConsole", (FARPROC*)&pCreatePseudoConsole},
++ {"ResizePseudoConsole", (FARPROC*)&pResizePseudoConsole},
++ {"ClosePseudoConsole", (FARPROC*)&pClosePseudoConsole},
++ {"InitializeProcThreadAttributeList",
++ (FARPROC*)&pInitializeProcThreadAttributeList},
++ {"UpdateProcThreadAttribute",
++ (FARPROC*)&pUpdateProcThreadAttribute},
++ {"DeleteProcThreadAttributeList",
++ (FARPROC*)&pDeleteProcThreadAttributeList},
++ {NULL, NULL}
++ };
++
++ if (handled)
++ return result;
++
++ if (!has_vtp_working())
++ {
++ handled = TRUE;
++ result = FAIL;
++ return FAIL;
++ }
++
++ hKerneldll = vimLoadLib("kernel32.dll");
++ for (i = 0; conpty_entry[i].name != NULL
++ && conpty_entry[i].ptr != NULL; ++i)
++ {
++ if ((*conpty_entry[i].ptr = (FARPROC)GetProcAddress(hKerneldll,
++ conpty_entry[i].name)) == NULL)
++ {
++ if (verbose)
++ semsg(_(e_loadfunc), conpty_entry[i].name);
++ return FAIL;
++ }
++ }
++
++ handled = TRUE;
++ result = OK;
++ return OK;
++ }
++
++ static int
++ conpty_term_and_job_init(
++ term_T *term,
++ typval_T *argvar,
++ char **argv,
++ jobopt_T *opt,
++ jobopt_T *orig_opt)
++ {
++ WCHAR *cmd_wchar = NULL;
++ WCHAR *cmd_wchar_copy = NULL;
++ WCHAR *cwd_wchar = NULL;
++ WCHAR *env_wchar = NULL;
++ channel_T *channel = NULL;
++ job_T *job = NULL;
++ HANDLE jo = NULL;
++ garray_T ga_cmd, ga_env;
++ char_u *cmd = NULL;
++ HRESULT hr;
++ COORD consize;
++ SIZE_T breq;
++ PROCESS_INFORMATION proc_info;
++ HANDLE i_theirs = NULL;
++ HANDLE o_theirs = NULL;
++ HANDLE i_ours = NULL;
++ HANDLE o_ours = NULL;
++
++ ga_init2(&ga_cmd, (int)sizeof(char*), 20);
++ ga_init2(&ga_env, (int)sizeof(char*), 20);
++
++ if (argvar->v_type == VAR_STRING)
++ {
++ cmd = argvar->vval.v_string;
++ }
++ else if (argvar->v_type == VAR_LIST)
++ {
++ if (win32_build_cmd(argvar->vval.v_list, &ga_cmd) == FAIL)
++ goto failed;
++ cmd = ga_cmd.ga_data;
++ }
++ if (cmd == NULL || *cmd == NUL)
++ {
++ emsg(_(e_invarg));
++ goto failed;
++ }
++
++ term->tl_arg0_cmd = vim_strsave(cmd);
++
++ cmd_wchar = enc_to_utf16(cmd, NULL);
++
++ if (cmd_wchar != NULL)
++ {
++ /* Request by CreateProcessW */
++ breq = wcslen(cmd_wchar) + 1 + 1; /* Addition of NUL by API */
++ cmd_wchar_copy = (PWSTR)alloc((int)(breq * sizeof(WCHAR)));
++ wcsncpy(cmd_wchar_copy, cmd_wchar, breq - 1);
++ }
++
++ ga_clear(&ga_cmd);
++ if (cmd_wchar == NULL)
++ goto failed;
++ if (opt->jo_cwd != NULL)
++ cwd_wchar = enc_to_utf16(opt->jo_cwd, NULL);
++
++ win32_build_env(opt->jo_env, &ga_env, TRUE);
++ env_wchar = ga_env.ga_data;
++
++ if (!CreatePipe(&i_theirs, &i_ours, NULL, 0))
++ goto failed;
++ if (!CreatePipe(&o_ours, &o_theirs, NULL, 0))
++ goto failed;
++
++ consize.X = term->tl_cols;
++ consize.Y = term->tl_rows;
++ hr = pCreatePseudoConsole(consize, i_theirs, o_theirs, 0,
++ &term->tl_conpty);
++ if (FAILED(hr))
++ goto failed;
++
++ term->tl_siex.StartupInfo.cb = sizeof(term->tl_siex);
++
++ /* Set up pipe inheritance safely: Vista or later. */
++ pInitializeProcThreadAttributeList(NULL, 1, 0, &breq);
++ term->tl_siex.lpAttributeList =
++ (PPROC_THREAD_ATTRIBUTE_LIST)alloc((int)breq);
++ if (!term->tl_siex.lpAttributeList)
++ goto failed;
++ if (!pInitializeProcThreadAttributeList(term->tl_siex.lpAttributeList, 1,
++ 0, &breq))
++ goto failed;
++ if (!pUpdateProcThreadAttribute(
++ term->tl_siex.lpAttributeList, 0,
++ PROC_THREAD_ATTRIBUTE_PSEUDOCONSOLE, term->tl_conpty,
++ sizeof(HPCON), NULL, NULL))
++ goto failed;
++
++ channel = add_channel();
++ if (channel == NULL)
++ goto failed;
++
++ job = job_alloc();
++ if (job == NULL)
++ goto failed;
++ if (argvar->v_type == VAR_STRING)
++ {
++ int argc;
++
++ build_argv_from_string(cmd, &job->jv_argv, &argc);
++ }
++ else
++ {
++ int argc;
++
++ build_argv_from_list(argvar->vval.v_list, &job->jv_argv, &argc);
++ }
++
++ if (opt->jo_set & JO_IN_BUF)
++ job->jv_in_buf = buflist_findnr(opt->jo_io_buf[PART_IN]);
++
++ if (!CreateProcessW(NULL, cmd_wchar_copy, NULL, NULL, FALSE,
++ EXTENDED_STARTUPINFO_PRESENT | CREATE_UNICODE_ENVIRONMENT
++ | CREATE_SUSPENDED | CREATE_NEW_PROCESS_GROUP
++ | CREATE_DEFAULT_ERROR_MODE,
++ env_wchar, cwd_wchar,
++ &term->tl_siex.StartupInfo, &proc_info))
++ goto failed;
++
++ CloseHandle(i_theirs);
++ CloseHandle(o_theirs);
++
++ channel_set_pipes(channel,
++ (sock_T)i_ours,
++ (sock_T)o_ours,
++ (sock_T)o_ours);
++
++ /* Write lines with CR instead of NL. */
++ channel->ch_write_text_mode = TRUE;
++
++ /* Use to explicitly delete anonymous pipe handle. */
++ channel->ch_anonymous_pipe = TRUE;
++
++ jo = CreateJobObject(NULL, NULL);
++ if (jo == NULL)
++ goto failed;
++
++ if (!AssignProcessToJobObject(jo, proc_info.hProcess))
++ {
++ /* Failed, switch the way to terminate process with TerminateProcess. */
++ CloseHandle(jo);
++ jo = NULL;
++ }
++
++ ResumeThread(proc_info.hThread);
++ CloseHandle(proc_info.hThread);
++
++ vim_free(cmd_wchar);
++ vim_free(cmd_wchar_copy);
++ vim_free(cwd_wchar);
++ vim_free(env_wchar);
++
++ if (create_vterm(term, term->tl_rows, term->tl_cols) == FAIL)
++ goto failed;
++
++ #if defined(FEAT_GUI) || defined(FEAT_TERMGUICOLORS)
++ if (opt->jo_set2 & JO2_ANSI_COLORS)
++ set_vterm_palette(term->tl_vterm, opt->jo_ansi_colors);
++ else
++ init_vterm_ansi_colors(term->tl_vterm);
++ #endif
++
++ channel_set_job(channel, job, opt);
++ job_set_options(job, opt);
++
++ job->jv_channel = channel;
++ job->jv_proc_info = proc_info;
++ job->jv_job_object = jo;
++ job->jv_status = JOB_STARTED;
++ ++job->jv_refcount;
++ term->tl_job = job;
++
++ /* Redirecting stdout and stderr doesn't work at the job level. Instead
++ * open the file here and handle it in. opt->jo_io was changed in
++ * setup_job_options(), use the original flags here. */
++ if (orig_opt->jo_io[PART_OUT] == JIO_FILE)
++ {
++ char_u *fname = opt->jo_io_name[PART_OUT];
++
++ ch_log(channel, "Opening output file %s", fname);
++ term->tl_out_fd = mch_fopen((char *)fname, WRITEBIN);
++ if (term->tl_out_fd == NULL)
++ semsg(_(e_notopen), fname);
++ }
++
++ return OK;
++
++ failed:
++ ga_clear(&ga_cmd);
++ ga_clear(&ga_env);
++ vim_free(cmd_wchar);
++ vim_free(cmd_wchar_copy);
++ vim_free(cwd_wchar);
++ if (channel != NULL)
++ channel_clear(channel);
++ if (job != NULL)
++ {
++ job->jv_channel = NULL;
++ job_cleanup(job);
++ }
++ term->tl_job = NULL;
++ if (jo != NULL)
++ CloseHandle(jo);
++
++ if (term->tl_siex.lpAttributeList != NULL)
++ {
++ pDeleteProcThreadAttributeList(term->tl_siex.lpAttributeList);
++ vim_free(term->tl_siex.lpAttributeList);
++ }
++ term->tl_siex.lpAttributeList = NULL;
++ if (o_theirs != NULL)
++ CloseHandle(o_theirs);
++ if (o_ours != NULL)
++ CloseHandle(o_ours);
++ if (i_ours != NULL)
++ CloseHandle(i_ours);
++ if (i_theirs != NULL)
++ CloseHandle(i_theirs);
++ if (term->tl_conpty != NULL)
++ pClosePseudoConsole(term->tl_conpty);
++ term->tl_conpty = NULL;
++ return FAIL;
++ }
++
++ static void
++ conpty_term_report_winsize(term_T *term, int rows, int cols)
++ {
++ COORD consize;
++
++ consize.X = cols;
++ consize.Y = rows;
++ pResizePseudoConsole(term->tl_conpty, consize);
++ }
++
++ void
++ term_free_conpty(term_T *term)
++ {
++ if (term->tl_siex.lpAttributeList != NULL)
++ {
++ pDeleteProcThreadAttributeList(term->tl_siex.lpAttributeList);
++ vim_free(term->tl_siex.lpAttributeList);
++ }
++ term->tl_siex.lpAttributeList = NULL;
++ if (term->tl_conpty != NULL)
++ pClosePseudoConsole(term->tl_conpty);
++ term->tl_conpty = NULL;
++ }
++
++ int
++ use_conpty(void)
++ {
++ return has_conpty;
++ }
++
+ # ifndef PROTO
+
+ #define WINPTY_SPAWN_FLAG_AUTO_SHUTDOWN 1ul
+***************
+*** 5516,5531 ****
+ return OK;
+ }
+
+- /*
+- * Create a new terminal of "rows" by "cols" cells.
+- * Store a reference in "term".
+- * Return OK or FAIL.
+- */
+ static int
+! term_and_job_init(
+ term_T *term,
+ typval_T *argvar,
+! char **argv UNUSED,
+ jobopt_T *opt,
+ jobopt_T *orig_opt)
+ {
+--- 5888,5898 ----
+ return OK;
+ }
+
+ static int
+! winpty_term_and_job_init(
+ term_T *term,
+ typval_T *argvar,
+! char **argv,
+ jobopt_T *opt,
+ jobopt_T *orig_opt)
+ {
+***************
+*** 5543,5550 ****
+ garray_T ga_cmd, ga_env;
+ char_u *cmd = NULL;
+
+- if (dyn_winpty_init(TRUE) == FAIL)
+- return FAIL;
+ ga_init2(&ga_cmd, (int)sizeof(char*), 20);
+ ga_init2(&ga_env, (int)sizeof(char*), 20);
+
+--- 5910,5915 ----
+***************
+*** 5564,5569 ****
+--- 5929,5936 ----
+ goto failed;
+ }
+
++ term->tl_arg0_cmd = vim_strsave(cmd);
++
+ cmd_wchar = enc_to_utf16(cmd, NULL);
+ ga_clear(&ga_cmd);
+ if (cmd_wchar == NULL)
+***************
+*** 5676,5684 ****
+ job->jv_job_object = jo;
+ job->jv_status = JOB_STARTED;
+ job->jv_tty_in = utf16_to_enc(
+! (short_u*)winpty_conin_name(term->tl_winpty), NULL);
+ job->jv_tty_out = utf16_to_enc(
+! (short_u*)winpty_conout_name(term->tl_winpty), NULL);
+ ++job->jv_refcount;
+ term->tl_job = job;
+
+--- 6043,6051 ----
+ job->jv_job_object = jo;
+ job->jv_status = JOB_STARTED;
+ job->jv_tty_in = utf16_to_enc(
+! (short_u *)winpty_conin_name(term->tl_winpty), NULL);
+ job->jv_tty_out = utf16_to_enc(
+! (short_u *)winpty_conout_name(term->tl_winpty), NULL);
+ ++job->jv_refcount;
+ term->tl_job = job;
+
+***************
+*** 5722,5728 ****
+ term->tl_winpty_config = NULL;
+ if (winpty_err != NULL)
+ {
+! char_u *msg = utf16_to_enc(
+ (short_u *)winpty_error_msg(winpty_err), NULL);
+
+ emsg(msg);
+--- 6089,6095 ----
+ term->tl_winpty_config = NULL;
+ if (winpty_err != NULL)
+ {
+! char *msg = (char *)utf16_to_enc(
+ (short_u *)winpty_error_msg(winpty_err), NULL);
+
+ emsg(msg);
+***************
+*** 5731,5736 ****
+--- 6098,6173 ----
+ return FAIL;
+ }
+
++ /*
++ * Create a new terminal of "rows" by "cols" cells.
++ * Store a reference in "term".
++ * Return OK or FAIL.
++ */
++ static int
++ term_and_job_init(
++ term_T *term,
++ typval_T *argvar,
++ char **argv UNUSED,
++ jobopt_T *opt,
++ jobopt_T *orig_opt)
++ {
++ int use_winpty = FALSE;
++ int use_conpty = FALSE;
++
++ has_winpty = dyn_winpty_init(FALSE) != FAIL ? TRUE : FALSE;
++ has_conpty = dyn_conpty_init(FALSE) != FAIL ? TRUE : FALSE;
++
++ if (!has_winpty && !has_conpty)
++ // If neither is available give the errors for winpty, since when
++ // conpty is not available it can't be installed either.
++ return dyn_winpty_init(TRUE);
++
++ if (opt->jo_term_mode == 'w')
++ set_string_option_direct((char_u *)"tmod", -1, (char_u *)"winpty",
++ OPT_FREE|OPT_LOCAL, 0);
++ if (opt->jo_term_mode == 'c')
++ set_string_option_direct((char_u *)"tmod", -1, (char_u *)"conpty",
++ OPT_FREE|OPT_LOCAL, 0);
++
++ if (curwin->w_p_tmod == NULL || *curwin->w_p_tmod == NUL)
++ {
++ if (has_conpty)
++ use_conpty = TRUE;
++ else if (has_winpty)
++ use_winpty = TRUE;
++ // else: error
++ }
++ else if (STRICMP(curwin->w_p_tmod, "winpty") == 0)
++ {
++ if (has_winpty)
++ use_winpty = TRUE;
++ }
++ else if (STRICMP(curwin->w_p_tmod, "conpty") == 0)
++ {
++ if (has_conpty)
++ use_conpty = TRUE;
++ else
++ return dyn_conpty_init(TRUE);
++ }
++
++ if (use_conpty)
++ {
++ set_string_option_direct((char_u *)"tmod", -1, (char_u *)"conpty",
++ OPT_FREE|OPT_LOCAL, 0);
++ return conpty_term_and_job_init(term, argvar, argv, opt, orig_opt);
++ }
++
++ if (use_winpty)
++ {
++ set_string_option_direct((char_u *)"tmod", -1, (char_u *)"winpty",
++ OPT_FREE|OPT_LOCAL, 0);
++ return winpty_term_and_job_init(term, argvar, argv, opt, orig_opt);
++ }
++
++ // error
++ return dyn_winpty_init(TRUE);
++ }
++
+ static int
+ create_pty_only(term_T *term, jobopt_T *options)
+ {
+***************
+*** 5804,5809 ****
+--- 6241,6247 ----
+ static void
+ term_free_vterm(term_T *term)
+ {
++ term_free_conpty(term);
+ if (term->tl_winpty != NULL)
+ winpty_free(term->tl_winpty);
+ term->tl_winpty = NULL;
+***************
+*** 5821,5826 ****
+--- 6259,6266 ----
+ static void
+ term_report_winsize(term_T *term, int rows, int cols)
+ {
++ if (term->tl_conpty)
++ conpty_term_report_winsize(term, rows, cols);
+ if (term->tl_winpty)
+ winpty_set_size(term->tl_winpty, cols, rows, NULL);
+ }
+***************
+*** 5828,5834 ****
+ int
+ terminal_enabled(void)
+ {
+! return dyn_winpty_init(FALSE) == OK;
+ }
+
+ # else
+--- 6268,6274 ----
+ int
+ terminal_enabled(void)
+ {
+! return dyn_winpty_init(FALSE) == OK || dyn_conpty_init(FALSE) == OK;
+ }
+
+ # else
+***************
+*** 5852,5857 ****
+--- 6292,6299 ----
+ jobopt_T *opt,
+ jobopt_T *orig_opt UNUSED)
+ {
++ term->tl_arg0_cmd = NULL;
++
+ if (create_vterm(term, term->tl_rows, term->tl_cols) == FAIL)
+ return FAIL;
+
+*** ../vim-8.1.0869/src/testdir/gen_opt_test.vim 2018-11-05 21:21:29.800286334 +0100
+--- src/testdir/gen_opt_test.vim 2019-02-03 13:46:59.603853294 +0100
+***************
+*** 131,136 ****
+--- 131,137 ----
+ \ 'term': [[], []],
+ \ 'termguicolors': [[], []],
+ \ 'termencoding': [has('gui_gtk') ? [] : ['', 'utf-8'], ['xxx']],
++ \ 'termmode': [['', 'winpty', 'conpty'], ['xxx']],
+ \ 'termwinsize': [['', '24x80', '0x80', '32x0', '0x0'], ['xxx', '80', '8ax9', '24x80b']],
+ \ 'toolbar': [['', 'icons', 'text'], ['xxx']],
+ \ 'toolbariconsize': [['', 'tiny', 'huge'], ['xxx']],
+*** ../vim-8.1.0869/src/testdir/test_autocmd.vim 2019-01-30 22:01:36.982854408 +0100
+--- src/testdir/test_autocmd.vim 2019-02-03 13:46:59.603853294 +0100
+***************
+*** 1397,1403 ****
+ let buf = term_start([GetVimProg(), '--clean', '-c', 'set noswapfile'], {'term_rows': 3})
+ call assert_equal('running', term_getstatus(buf))
+ " Wait for the ruler (in the status line) to be shown.
+! call WaitForAssert({-> assert_match('\<All$', term_getline(buf, 3))})
+ " It's only adding autocmd, so that no event occurs.
+ call term_sendkeys(buf, ":au! TextChanged <buffer> call writefile(['No'], 'Xchanged.txt')\<cr>")
+ call term_sendkeys(buf, "\<C-\\>\<C-N>:qa!\<cr>")
+--- 1397,1409 ----
+ let buf = term_start([GetVimProg(), '--clean', '-c', 'set noswapfile'], {'term_rows': 3})
+ call assert_equal('running', term_getstatus(buf))
+ " Wait for the ruler (in the status line) to be shown.
+! " In ConPTY, there is additional character which is drawn up to the width of
+! " the screen.
+! if has('conpty')
+! call WaitForAssert({-> assert_match('\<All.*$', term_getline(buf, 3))})
+! else
+! call WaitForAssert({-> assert_match('\<All$', term_getline(buf, 3))})
+! endif
+ " It's only adding autocmd, so that no event occurs.
+ call term_sendkeys(buf, ":au! TextChanged <buffer> call writefile(['No'], 'Xchanged.txt')\<cr>")
+ call term_sendkeys(buf, "\<C-\\>\<C-N>:qa!\<cr>")
+*** ../vim-8.1.0869/src/testdir/test_mksession.vim 2019-01-26 20:07:34.592237223 +0100
+--- src/testdir/test_mksession.vim 2019-02-03 13:46:59.603853294 +0100
+***************
+*** 295,301 ****
+ call assert_report('unexpected shell line: ' . line)
+ endif
+ endfor
+! call assert_match('terminal ++curwin ++cols=\d\+ ++rows=\d\+\s*$', term_cmd)
+
+ call Stop_shell_in_terminal(bufnr('%'))
+ call delete('Xtest_mks.out')
+--- 295,301 ----
+ call assert_report('unexpected shell line: ' . line)
+ endif
+ endfor
+! call assert_match('terminal ++curwin ++cols=\d\+ ++rows=\d\+\s*.*$', term_cmd)
+
+ call Stop_shell_in_terminal(bufnr('%'))
+ call delete('Xtest_mks.out')
+***************
+*** 375,381 ****
+ let term_cmd = line
+ endif
+ endfor
+! call assert_match('terminal ++curwin ++cols=\d\+ ++rows=\d\+ other', term_cmd)
+
+ call Stop_shell_in_terminal(bufnr('%'))
+ call delete('Xtest_mks.out')
+--- 375,381 ----
+ let term_cmd = line
+ endif
+ endfor
+! call assert_match('terminal ++curwin ++cols=\d\+ ++rows=\d\+.*other', term_cmd)
+
+ call Stop_shell_in_terminal(bufnr('%'))
+ call delete('Xtest_mks.out')
+*** ../vim-8.1.0869/src/testdir/test_terminal.vim 2019-01-29 22:58:02.401136295 +0100
+--- src/testdir/test_terminal.vim 2019-02-03 13:46:59.603853294 +0100
+***************
+*** 39,46 ****
+ call assert_match('^/dev/', job_info(g:job).tty_out)
+ call assert_match('^/dev/', term_gettty(''))
+ else
+! call assert_match('^\\\\.\\pipe\\', job_info(g:job).tty_out)
+! call assert_match('^\\\\.\\pipe\\', term_gettty(''))
+ endif
+ call assert_equal('t', mode())
+ call assert_equal('yes', b:done)
+--- 39,49 ----
+ call assert_match('^/dev/', job_info(g:job).tty_out)
+ call assert_match('^/dev/', term_gettty(''))
+ else
+! " ConPTY works on anonymous pipe.
+! if !has('conpty')
+! call assert_match('^\\\\.\\pipe\\', job_info(g:job).tty_out)
+! call assert_match('^\\\\.\\pipe\\', term_gettty(''))
+! endif
+ endif
+ call assert_equal('t', mode())
+ call assert_equal('yes', b:done)
+***************
+*** 129,135 ****
+
+ func Get_cat_123_cmd()
+ if has('win32')
+! return 'cmd /c "cls && color 2 && echo 123"'
+ else
+ call writefile(["\<Esc>[32m123"], 'Xtext')
+ return "cat Xtext"
+--- 132,143 ----
+
+ func Get_cat_123_cmd()
+ if has('win32')
+! if !has('conpty')
+! return 'cmd /c "cls && color 2 && echo 123"'
+! else
+! " When clearing twice, extra sequence is not output.
+! return 'cmd /c "cls && cls && color 2 && echo 123"'
+! endif
+ else
+ call writefile(["\<Esc>[32m123"], 'Xtext')
+ return "cat Xtext"
+***************
+*** 143,150 ****
+
+ call WaitForAssert({-> assert_equal("dead", job_status(g:job))})
+ call WaitForAssert({-> assert_equal(0, g:buf)})
+- unlet g:buf
+ unlet g:job
+ call delete('Xtext')
+ endfunc
+
+--- 151,158 ----
+
+ call WaitForAssert({-> assert_equal("dead", job_status(g:job))})
+ call WaitForAssert({-> assert_equal(0, g:buf)})
+ unlet g:job
++ unlet g:buf
+ call delete('Xtext')
+ endfunc
+
+***************
+*** 563,568 ****
+--- 571,579 ----
+ " The shell or something else has a problem dealing with more than 1000
+ " characters at the same time.
+ let len = 1000
++ " NPFS is used in Windows, nonblocking mode does not work properly.
++ elseif has('win32')
++ let len = 1
+ else
+ let len = 5000
+ endif
+***************
+*** 693,700 ****
+ let cmd = Get_cat_123_cmd()
+ let buf = term_start(cmd, {'out_io': 'file', 'out_name': 'Xfile'})
+ call term_wait(buf)
+! call WaitForAssert({-> assert_notequal(0, len(readfile("Xfile")))})
+! call assert_match('123', readfile('Xfile')[0])
+ let g:job = term_getjob(buf)
+ call WaitForAssert({-> assert_equal("dead", job_status(g:job))})
+ call delete('Xfile')
+--- 704,714 ----
+ let cmd = Get_cat_123_cmd()
+ let buf = term_start(cmd, {'out_io': 'file', 'out_name': 'Xfile'})
+ call term_wait(buf)
+! " ConPTY may precede escape sequence. There are things that are not so.
+! if !has('conpty')
+! call WaitForAssert({-> assert_notequal(0, len(readfile("Xfile")))})
+! call assert_match('123', readfile('Xfile')[0])
+! endif
+ let g:job = term_getjob(buf)
+ call WaitForAssert({-> assert_equal("dead", job_status(g:job))})
+ call delete('Xfile')
+***************
+*** 1661,1666 ****
+--- 1675,1684 ----
+ endfunc
+
+ func Test_terminal_does_not_truncate_last_newlines()
++ " This test does not pass through ConPTY.
++ if has('conpty')
++ return
++ endif
+ let contents = [
+ \ [ 'One', '', 'X' ],
+ \ [ 'Two', '', '' ],
+*** ../vim-8.1.0869/src/version.c 2019-02-03 13:12:20.344668681 +0100
+--- src/version.c 2019-02-03 13:50:03.310696825 +0100
+***************
+*** 785,786 ****
+--- 785,788 ----
+ { /* Add new patch number below this line */
++ /**/
++ 870,
+ /**/
+
+--
+A hamburger walks into a bar, and the bartender says: "I'm sorry,
+but we don't serve food here."
+
+ /// 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 ///