forked from aniani/vim
patch 8.1.0870: Vim doesn't use the new ConPTY support in Windows 10
Problem: Vim doesn't use the new ConPTY support in Windows 10. Solution: Use ConPTY support, if available. (Nobuhiro Takasaki, closes #3794)
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
*eval.txt* For Vim version 8.1. Last change: 2019 Jan 29
|
*eval.txt* For Vim version 8.1. Last change: 2019 Feb 03
|
||||||
|
|
||||||
|
|
||||||
VIM REFERENCE MANUAL by Bram Moolenaar
|
VIM REFERENCE MANUAL by Bram Moolenaar
|
||||||
@@ -696,7 +696,7 @@ similar to -1. >
|
|||||||
:let otherblob = myblob[:] " make a copy of the Blob
|
:let otherblob = myblob[:] " make a copy of the Blob
|
||||||
|
|
||||||
If the first index is beyond the last byte of the Blob or the second index is
|
If the first index is beyond the last byte of the Blob or the second index is
|
||||||
before the first index, the result is an empty list. There is no error
|
before the first index, the result is an empty Blob. There is no error
|
||||||
message.
|
message.
|
||||||
|
|
||||||
If the second index is equal to or greater than the length of the list the
|
If the second index is equal to or greater than the length of the list the
|
||||||
@@ -9469,6 +9469,10 @@ term_start({cmd}, {options}) *term_start()*
|
|||||||
"ansi_colors" A list of 16 color names or hex codes
|
"ansi_colors" A list of 16 color names or hex codes
|
||||||
defining the ANSI palette used in GUI
|
defining the ANSI palette used in GUI
|
||||||
color modes. See |g:terminal_ansi_colors|.
|
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}
|
{only available when compiled with the |+terminal| feature}
|
||||||
|
|
||||||
@@ -10186,6 +10190,7 @@ cmdline_hist Compiled with |cmdline-history| support.
|
|||||||
cmdline_info Compiled with 'showcmd' and 'ruler' support.
|
cmdline_info Compiled with 'showcmd' and 'ruler' support.
|
||||||
comments Compiled with |'comments'| support.
|
comments Compiled with |'comments'| support.
|
||||||
compatible Compiled to be very Vi compatible.
|
compatible Compiled to be very Vi compatible.
|
||||||
|
conpty Platform where |ConPTY| can be used.
|
||||||
cryptv Compiled with encryption support |encryption|.
|
cryptv Compiled with encryption support |encryption|.
|
||||||
cscope Compiled with |cscope| support.
|
cscope Compiled with |cscope| support.
|
||||||
cursorbind Compiled with |cursorbind| (always true)
|
cursorbind Compiled with |cursorbind| (always true)
|
||||||
|
|||||||
@@ -8054,6 +8054,23 @@ A jump table for the options with a short description can be found at |Q_op|.
|
|||||||
Note that the "cterm" attributes are still used, not the "gui" ones.
|
Note that the "cterm" attributes are still used, not the "gui" ones.
|
||||||
NOTE: This option is reset when 'compatible' is set.
|
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'*
|
||||||
'termwinscroll' 'twsl' number (default 10000)
|
'termwinscroll' 'twsl' number (default 10000)
|
||||||
local to buffer
|
local to buffer
|
||||||
|
|||||||
@@ -228,7 +228,8 @@ Syntax ~
|
|||||||
for Python "++eof=exit()". Special
|
for Python "++eof=exit()". Special
|
||||||
codes can be used like with `:map`,
|
codes can be used like with `:map`,
|
||||||
e.g. "<C-Z>" for CTRL-Z.
|
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()|
|
If you want to use more options use the |term_start()|
|
||||||
function.
|
function.
|
||||||
If you want to split the window vertically, use: >
|
If you want to split the window vertically, use: >
|
||||||
@@ -410,6 +411,13 @@ Just put the files somewhere in your PATH. You can set the 'winptydll' option
|
|||||||
to point to the right file, if needed. If you have both the 32-bit and 64-bit
|
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
|
version, rename to winpty32.dll and winpty64.dll to match the way Vim was
|
||||||
build.
|
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:
|
Environment variables are used to pass information to the running job:
|
||||||
VIM_SERVERNAME v:servername
|
VIM_SERVERNAME v:servername
|
||||||
|
|||||||
@@ -1720,11 +1720,7 @@ channel_get_all(channel_T *channel, ch_part_T part, int *outlen)
|
|||||||
char_u *res;
|
char_u *res;
|
||||||
char_u *p;
|
char_u *p;
|
||||||
|
|
||||||
/* If there is only one buffer just get that one. */
|
// Concatenate everything into one buffer.
|
||||||
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)
|
for (node = head->rq_next; node != NULL; node = node->rq_next)
|
||||||
len += node->rq_buflen;
|
len += node->rq_buflen;
|
||||||
res = lalloc(len + 1, TRUE);
|
res = lalloc(len + 1, TRUE);
|
||||||
@@ -1738,7 +1734,7 @@ channel_get_all(channel_T *channel, ch_part_T part, int *outlen)
|
|||||||
}
|
}
|
||||||
*p = NUL;
|
*p = NUL;
|
||||||
|
|
||||||
/* Free all buffers */
|
// Free all buffers
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
p = channel_get(channel, part, NULL);
|
p = channel_get(channel, part, NULL);
|
||||||
@@ -1747,16 +1743,37 @@ channel_get_all(channel_T *channel, ch_part_T part, int *outlen)
|
|||||||
|
|
||||||
if (outlen != NULL)
|
if (outlen != NULL)
|
||||||
{
|
{
|
||||||
|
// Returning the length, keep NUL characters.
|
||||||
*outlen += len;
|
*outlen += len;
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* turn all NUL into NL */
|
// Turn all NUL into NL, so that the result can be used as a string.
|
||||||
while (len > 0)
|
p = res;
|
||||||
|
while (p < res + len)
|
||||||
{
|
{
|
||||||
--len;
|
if (*p == NUL)
|
||||||
if (res[len] == NUL)
|
*p = NL;
|
||||||
res[len] = 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;
|
return res;
|
||||||
@@ -4330,7 +4347,7 @@ channel_parse_messages(void)
|
|||||||
channel = first_channel;
|
channel = first_channel;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (channel->ch_to_be_freed)
|
if (channel->ch_to_be_freed || channel->ch_killing)
|
||||||
{
|
{
|
||||||
channel_free(channel);
|
channel_free(channel);
|
||||||
/* channel has been freed, start over */
|
/* channel has been freed, start over */
|
||||||
@@ -4930,6 +4947,28 @@ get_job_options(typval_T *tv, jobopt_T *opt, int supported, int supported2)
|
|||||||
opt->jo_set2 |= JO2_TERM_KILL;
|
opt->jo_set2 |= JO2_TERM_KILL;
|
||||||
opt->jo_term_kill = tv_get_string_chk(item);
|
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)
|
# if defined(FEAT_GUI) || defined(FEAT_TERMGUICOLORS)
|
||||||
else if (STRCMP(hi->hi_key, "ansi_colors") == 0)
|
else if (STRCMP(hi->hi_key, "ansi_colors") == 0)
|
||||||
{
|
{
|
||||||
@@ -5440,6 +5479,16 @@ job_cleanup(job_T *job)
|
|||||||
channel_need_redraw = TRUE;
|
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
|
// 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().
|
// isn't invoked yet and may get information by job_info().
|
||||||
if (job->jv_refcount == 0 && !job_channel_still_useful(job))
|
if (job->jv_refcount == 0 && !job_channel_still_useful(job))
|
||||||
|
|||||||
@@ -6737,6 +6737,10 @@ f_has(typval_T *argvars, typval_T *rettv)
|
|||||||
#if defined(FEAT_TERMINAL) && defined(WIN3264)
|
#if defined(FEAT_TERMINAL) && defined(WIN3264)
|
||||||
else if (STRICMP(name, "terminal") == 0)
|
else if (STRICMP(name, "terminal") == 0)
|
||||||
n = terminal_enabled();
|
n = terminal_enabled();
|
||||||
|
#endif
|
||||||
|
#if defined(FEAT_TERMINAL) && defined(WIN3264)
|
||||||
|
else if (STRICMP(name, "conpty") == 0)
|
||||||
|
n = use_conpty();
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1432,7 +1432,8 @@ EXTERN char e_fsync[] INIT(= N_("E667: Fsync failed"));
|
|||||||
|| defined(DYNAMIC_ICONV) \
|
|| defined(DYNAMIC_ICONV) \
|
||||||
|| defined(DYNAMIC_GETTEXT) \
|
|| defined(DYNAMIC_GETTEXT) \
|
||||||
|| defined(DYNAMIC_MZSCHEME) \
|
|| defined(DYNAMIC_MZSCHEME) \
|
||||||
|| defined(DYNAMIC_LUA)
|
|| defined(DYNAMIC_LUA) \
|
||||||
|
|| defined(FEAT_TERMINAL)
|
||||||
EXTERN char e_loadlib[] INIT(= N_("E370: Could not load library %s"));
|
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"));
|
EXTERN char e_loadfunc[] INIT(= N_("E448: Could not load library function %s"));
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
36
src/option.c
36
src/option.c
@@ -253,6 +253,7 @@
|
|||||||
# define PV_TWK OPT_WIN(WV_TWK)
|
# define PV_TWK OPT_WIN(WV_TWK)
|
||||||
# define PV_TWS OPT_WIN(WV_TWS)
|
# define PV_TWS OPT_WIN(WV_TWS)
|
||||||
# define PV_TWSL OPT_BUF(BV_TWSL)
|
# define PV_TWSL OPT_BUF(BV_TWSL)
|
||||||
|
# define PV_TMOD OPT_WIN(WV_TMOD)
|
||||||
#endif
|
#endif
|
||||||
#ifdef FEAT_SIGNS
|
#ifdef FEAT_SIGNS
|
||||||
# define PV_SCL OPT_WIN(WV_SCL)
|
# define PV_SCL OPT_WIN(WV_SCL)
|
||||||
@@ -2698,6 +2699,15 @@ static struct vimoption options[] =
|
|||||||
#else
|
#else
|
||||||
(char_u*)NULL, PV_NONE,
|
(char_u*)NULL, PV_NONE,
|
||||||
{(char_u *)FALSE, (char_u *)FALSE}
|
{(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
|
#endif
|
||||||
SCTX_INIT},
|
SCTX_INIT},
|
||||||
{"termwinkey", "twk", P_STRING|P_ALLOCED|P_RWIN|P_VI_DEF,
|
{"termwinkey", "twk", P_STRING|P_ALLOCED|P_RWIN|P_VI_DEF,
|
||||||
@@ -3208,6 +3218,9 @@ static char *(p_cot_values[]) = {"menu", "menuone", "longest", "preview", "noins
|
|||||||
#ifdef FEAT_SIGNS
|
#ifdef FEAT_SIGNS
|
||||||
static char *(p_scl_values[]) = {"yes", "no", "auto", NULL};
|
static char *(p_scl_values[]) = {"yes", "no", "auto", NULL};
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef FEAT_TERMINAL
|
||||||
|
static char *(p_tmod_values[]) = {"winpty", "conpty", "", NULL};
|
||||||
|
#endif
|
||||||
|
|
||||||
static void set_options_default(int opt_flags);
|
static void set_options_default(int opt_flags);
|
||||||
static void set_string_default_esc(char *name, char_u *val, int escape);
|
static void set_string_default_esc(char *name, char_u *val, int escape);
|
||||||
@@ -3661,7 +3674,12 @@ set_init_1(int clean_arg)
|
|||||||
{
|
{
|
||||||
char buf[50];
|
char buf[50];
|
||||||
|
|
||||||
sprintf(buf, "cp%ld", (long)GetConsoleCP());
|
/* 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);
|
p_tenc = vim_strsave((char_u *)buf);
|
||||||
if (p_tenc != NULL)
|
if (p_tenc != NULL)
|
||||||
{
|
{
|
||||||
@@ -7468,14 +7486,14 @@ did_set_string_option(
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef FEAT_TERMINAL
|
#ifdef FEAT_TERMINAL
|
||||||
/* 'termwinkey' */
|
// 'termwinkey'
|
||||||
else if (varp == &curwin->w_p_twk)
|
else if (varp == &curwin->w_p_twk)
|
||||||
{
|
{
|
||||||
if (*curwin->w_p_twk != NUL
|
if (*curwin->w_p_twk != NUL
|
||||||
&& string_to_key(curwin->w_p_twk, TRUE) == 0)
|
&& string_to_key(curwin->w_p_twk, TRUE) == 0)
|
||||||
errmsg = e_invarg;
|
errmsg = e_invarg;
|
||||||
}
|
}
|
||||||
/* 'termwinsize' */
|
// 'termwinsize'
|
||||||
else if (varp == &curwin->w_p_tws)
|
else if (varp == &curwin->w_p_tws)
|
||||||
{
|
{
|
||||||
if (*curwin->w_p_tws != NUL)
|
if (*curwin->w_p_tws != NUL)
|
||||||
@@ -7487,6 +7505,12 @@ did_set_string_option(
|
|||||||
errmsg = e_invarg;
|
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
|
#endif
|
||||||
|
|
||||||
#ifdef FEAT_VARTABS
|
#ifdef FEAT_VARTABS
|
||||||
@@ -8838,7 +8862,7 @@ set_bool_option(
|
|||||||
if (!has_vtp_working())
|
if (!has_vtp_working())
|
||||||
{
|
{
|
||||||
p_tgc = 0;
|
p_tgc = 0;
|
||||||
return (char_u*)N_("E954: 24-bit colors are not supported on this environment");
|
return N_("E954: 24-bit colors are not supported on this environment");
|
||||||
}
|
}
|
||||||
if (is_term_win32())
|
if (is_term_win32())
|
||||||
swap_tcap();
|
swap_tcap();
|
||||||
@@ -10928,6 +10952,7 @@ get_varp(struct vimoption *p)
|
|||||||
case PV_TWK: return (char_u *)&(curwin->w_p_twk);
|
case PV_TWK: return (char_u *)&(curwin->w_p_twk);
|
||||||
case PV_TWS: return (char_u *)&(curwin->w_p_tws);
|
case PV_TWS: return (char_u *)&(curwin->w_p_tws);
|
||||||
case PV_TWSL: return (char_u *)&(curbuf->b_p_twsl);
|
case PV_TWSL: return (char_u *)&(curbuf->b_p_twsl);
|
||||||
|
case PV_TMOD: return (char_u *)&(curwin->w_p_tmod);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
case PV_AI: return (char_u *)&(curbuf->b_p_ai);
|
case PV_AI: return (char_u *)&(curbuf->b_p_ai);
|
||||||
@@ -11128,6 +11153,7 @@ copy_winopt(winopt_T *from, winopt_T *to)
|
|||||||
#ifdef FEAT_TERMINAL
|
#ifdef FEAT_TERMINAL
|
||||||
to->wo_twk = vim_strsave(from->wo_twk);
|
to->wo_twk = vim_strsave(from->wo_twk);
|
||||||
to->wo_tws = vim_strsave(from->wo_tws);
|
to->wo_tws = vim_strsave(from->wo_tws);
|
||||||
|
to->wo_tmod = vim_strsave(from->wo_tmod);
|
||||||
#endif
|
#endif
|
||||||
#ifdef FEAT_FOLDING
|
#ifdef FEAT_FOLDING
|
||||||
to->wo_fdc = from->wo_fdc;
|
to->wo_fdc = from->wo_fdc;
|
||||||
@@ -11198,6 +11224,7 @@ check_winopt(winopt_T *wop UNUSED)
|
|||||||
#ifdef FEAT_TERMINAL
|
#ifdef FEAT_TERMINAL
|
||||||
check_string_option(&wop->wo_twk);
|
check_string_option(&wop->wo_twk);
|
||||||
check_string_option(&wop->wo_tws);
|
check_string_option(&wop->wo_tws);
|
||||||
|
check_string_option(&wop->wo_tmod);
|
||||||
#endif
|
#endif
|
||||||
#ifdef FEAT_LINEBREAK
|
#ifdef FEAT_LINEBREAK
|
||||||
check_string_option(&wop->wo_briopt);
|
check_string_option(&wop->wo_briopt);
|
||||||
@@ -11241,6 +11268,7 @@ clear_winopt(winopt_T *wop UNUSED)
|
|||||||
#ifdef FEAT_TERMINAL
|
#ifdef FEAT_TERMINAL
|
||||||
clear_string_option(&wop->wo_twk);
|
clear_string_option(&wop->wo_twk);
|
||||||
clear_string_option(&wop->wo_tws);
|
clear_string_option(&wop->wo_tws);
|
||||||
|
clear_string_option(&wop->wo_tmod);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1112,6 +1112,7 @@ enum
|
|||||||
#ifdef FEAT_TERMINAL
|
#ifdef FEAT_TERMINAL
|
||||||
, WV_TWK
|
, WV_TWK
|
||||||
, WV_TWS
|
, WV_TWS
|
||||||
|
, WV_TMOD
|
||||||
#endif
|
#endif
|
||||||
, WV_CRBIND
|
, WV_CRBIND
|
||||||
#ifdef FEAT_LINEBREAK
|
#ifdef FEAT_LINEBREAK
|
||||||
|
|||||||
@@ -186,8 +186,10 @@ static int win32_getattrs(char_u *name);
|
|||||||
static int win32_setattrs(char_u *name, int attrs);
|
static int win32_setattrs(char_u *name, int attrs);
|
||||||
static int win32_set_archive(char_u *name);
|
static int win32_set_archive(char_u *name);
|
||||||
|
|
||||||
#ifndef FEAT_GUI_W32
|
|
||||||
static int vtp_working = 0;
|
static int vtp_working = 0;
|
||||||
|
static void vtp_flag_init();
|
||||||
|
|
||||||
|
#ifndef FEAT_GUI_W32
|
||||||
static void vtp_init();
|
static void vtp_init();
|
||||||
static void vtp_exit();
|
static void vtp_exit();
|
||||||
static int vtp_printf(char *format, ...);
|
static int vtp_printf(char *format, ...);
|
||||||
@@ -247,6 +249,7 @@ static PfnGetConsoleScreenBufferInfoEx pGetConsoleScreenBufferInfoEx;
|
|||||||
typedef BOOL (WINAPI *PfnSetConsoleScreenBufferInfoEx)(HANDLE, PDYN_CONSOLE_SCREEN_BUFFER_INFOEX);
|
typedef BOOL (WINAPI *PfnSetConsoleScreenBufferInfoEx)(HANDLE, PDYN_CONSOLE_SCREEN_BUFFER_INFOEX);
|
||||||
static PfnSetConsoleScreenBufferInfoEx pSetConsoleScreenBufferInfoEx;
|
static PfnSetConsoleScreenBufferInfoEx pSetConsoleScreenBufferInfoEx;
|
||||||
static BOOL has_csbiex = FALSE;
|
static BOOL has_csbiex = FALSE;
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Get version number including build number
|
* Get version number including build number
|
||||||
@@ -276,7 +279,7 @@ get_build_number(void)
|
|||||||
return ver;
|
return ver;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef FEAT_GUI_W32
|
||||||
/*
|
/*
|
||||||
* Version of ReadConsoleInput() that works with IME.
|
* Version of ReadConsoleInput() that works with IME.
|
||||||
* Works around problems on Windows 8.
|
* Works around problems on Windows 8.
|
||||||
@@ -1508,9 +1511,8 @@ WaitForChar(long msec, int ignore_input)
|
|||||||
/* Wait forever. */
|
/* Wait forever. */
|
||||||
dwEndTime = INFINITE;
|
dwEndTime = INFINITE;
|
||||||
|
|
||||||
/* We need to loop until the end of the time period, because
|
// We need to loop until the end of the time period, because
|
||||||
* we might get multiple unusable mouse events in that time.
|
// we might get multiple unusable mouse events in that time.
|
||||||
*/
|
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
// Only process messages when waiting.
|
// Only process messages when waiting.
|
||||||
@@ -2175,6 +2177,8 @@ mch_init(void)
|
|||||||
#ifdef FEAT_CLIPBOARD
|
#ifdef FEAT_CLIPBOARD
|
||||||
win_clip_init();
|
win_clip_init();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
vtp_flag_init();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -2675,6 +2679,7 @@ mch_init(void)
|
|||||||
win_clip_init();
|
win_clip_init();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
vtp_flag_init();
|
||||||
vtp_init();
|
vtp_init();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -5683,7 +5688,11 @@ mch_signal_job(job_T *job, char_u *how)
|
|||||||
{
|
{
|
||||||
/* deadly signal */
|
/* deadly signal */
|
||||||
if (job->jv_job_object != NULL)
|
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 TerminateJobObject(job->jv_job_object, 0) ? OK : FAIL;
|
||||||
|
}
|
||||||
return terminate_all(job->jv_proc_info.hProcess, 0) ? OK : FAIL;
|
return terminate_all(job->jv_proc_info.hProcess, 0) ? OK : FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -7621,31 +7630,53 @@ mch_setenv(char *var, char *value, int x)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef FEAT_GUI_W32
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Support for 256 colors and 24-bit colors was added in Windows 10
|
* Support for 256 colors and 24-bit colors was added in Windows 10
|
||||||
* version 1703 (Creators update).
|
* version 1703 (Creators update).
|
||||||
*/
|
*/
|
||||||
# define VTP_FIRST_SUPPORT_BUILD MAKE_VER(10, 0, 15063)
|
#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
|
static void
|
||||||
vtp_init(void)
|
vtp_init(void)
|
||||||
{
|
{
|
||||||
DWORD ver, mode;
|
|
||||||
HMODULE hKerneldll;
|
HMODULE hKerneldll;
|
||||||
DYN_CONSOLE_SCREEN_BUFFER_INFOEX csbi;
|
DYN_CONSOLE_SCREEN_BUFFER_INFOEX csbi;
|
||||||
# ifdef FEAT_TERMGUICOLORS
|
# ifdef FEAT_TERMGUICOLORS
|
||||||
COLORREF fg, bg;
|
COLORREF fg, bg;
|
||||||
# endif
|
# 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 */
|
/* Use functions supported from Vista */
|
||||||
hKerneldll = GetModuleHandle("kernel32.dll");
|
hKerneldll = GetModuleHandle("kernel32.dll");
|
||||||
if (hKerneldll != NULL)
|
if (hKerneldll != NULL)
|
||||||
@@ -7828,12 +7859,6 @@ control_console_color_rgb(void)
|
|||||||
reset_console_color_rgb();
|
reset_console_color_rgb();
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
|
||||||
has_vtp_working(void)
|
|
||||||
{
|
|
||||||
return vtp_working;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
int
|
||||||
use_vtp(void)
|
use_vtp(void)
|
||||||
{
|
{
|
||||||
@@ -7847,3 +7872,9 @@ is_term_win32(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
int
|
||||||
|
has_vtp_working(void)
|
||||||
|
{
|
||||||
|
return vtp_working;
|
||||||
|
}
|
||||||
|
|||||||
@@ -57,4 +57,6 @@ void f_term_wait(typval_T *argvars, typval_T *rettv);
|
|||||||
void term_send_eof(channel_T *ch);
|
void term_send_eof(channel_T *ch);
|
||||||
job_T *term_getjob(term_T *term);
|
job_T *term_getjob(term_T *term);
|
||||||
int terminal_enabled(void);
|
int terminal_enabled(void);
|
||||||
|
void term_free_conpty(term_T *term);
|
||||||
|
int use_conpty(void);
|
||||||
/* vim: set ft=c : */
|
/* vim: set ft=c : */
|
||||||
|
|||||||
@@ -282,6 +282,8 @@ typedef struct
|
|||||||
# define w_p_twk w_onebuf_opt.wo_twk /* 'termwinkey' */
|
# define w_p_twk w_onebuf_opt.wo_twk /* 'termwinkey' */
|
||||||
char_u *wo_tws;
|
char_u *wo_tws;
|
||||||
# define w_p_tws w_onebuf_opt.wo_tws /* 'termwinsize' */
|
# 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
|
#endif
|
||||||
|
|
||||||
#ifdef FEAT_EVAL
|
#ifdef FEAT_EVAL
|
||||||
@@ -1728,13 +1730,15 @@ struct channel_S {
|
|||||||
int ch_keep_open; /* do not close on read error */
|
int ch_keep_open; /* do not close on read error */
|
||||||
int ch_nonblock;
|
int ch_nonblock;
|
||||||
|
|
||||||
job_T *ch_job; /* Job that uses this channel; this does not
|
job_T *ch_job; // Job that uses this channel; this does not
|
||||||
* count as a reference to avoid a circular
|
// count as a reference to avoid a circular
|
||||||
* reference, the job refers to the channel. */
|
// reference, the job refers to the channel.
|
||||||
int ch_job_killed; /* TRUE when there was a job and it was killed
|
int ch_job_killed; // TRUE when there was a job and it was killed
|
||||||
* or we know it died. */
|
// or we know it died.
|
||||||
|
int ch_anonymous_pipe; // ConPTY
|
||||||
|
int ch_killing; // TerminateJobObject() was called
|
||||||
|
|
||||||
int ch_refcount; /* reference count */
|
int ch_refcount; // reference count
|
||||||
int ch_copyID;
|
int ch_copyID;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1787,6 +1791,7 @@ struct channel_S {
|
|||||||
#define JO2_NORESTORE 0x2000 /* "norestore" */
|
#define JO2_NORESTORE 0x2000 /* "norestore" */
|
||||||
#define JO2_TERM_KILL 0x4000 /* "term_kill" */
|
#define JO2_TERM_KILL 0x4000 /* "term_kill" */
|
||||||
#define JO2_ANSI_COLORS 0x8000 /* "ansi_colors" */
|
#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_MODE_ALL (JO_MODE + JO_IN_MODE + JO_OUT_MODE + JO_ERR_MODE)
|
||||||
#define JO_CB_ALL \
|
#define JO_CB_ALL \
|
||||||
@@ -1859,6 +1864,7 @@ typedef struct
|
|||||||
# if defined(FEAT_GUI) || defined(FEAT_TERMGUICOLORS)
|
# if defined(FEAT_GUI) || defined(FEAT_TERMGUICOLORS)
|
||||||
long_u jo_ansi_colors[16];
|
long_u jo_ansi_colors[16];
|
||||||
# endif
|
# endif
|
||||||
|
int jo_term_mode; // first character of "term_mode"
|
||||||
#endif
|
#endif
|
||||||
} jobopt_T;
|
} jobopt_T;
|
||||||
|
|
||||||
|
|||||||
474
src/terminal.c
474
src/terminal.c
@@ -65,6 +65,23 @@ typedef struct sb_line_S {
|
|||||||
cellattr_T sb_fill_attr; /* for short line */
|
cellattr_T sb_fill_attr; /* for short line */
|
||||||
} sb_line_T;
|
} 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 */
|
/* typedef term_T in structs.h */
|
||||||
struct terminal_S {
|
struct terminal_S {
|
||||||
term_T *tl_next;
|
term_T *tl_next;
|
||||||
@@ -92,10 +109,15 @@ struct terminal_S {
|
|||||||
char_u *tl_opencmd;
|
char_u *tl_opencmd;
|
||||||
char_u *tl_eof_chars;
|
char_u *tl_eof_chars;
|
||||||
|
|
||||||
|
char_u *tl_arg0_cmd; // To format the status bar
|
||||||
|
|
||||||
#ifdef WIN3264
|
#ifdef WIN3264
|
||||||
void *tl_winpty_config;
|
void *tl_winpty_config;
|
||||||
void *tl_winpty;
|
void *tl_winpty;
|
||||||
|
|
||||||
|
HPCON tl_conpty;
|
||||||
|
DYN_STARTUPINFOEXW tl_siex; // Structure that always needs to be hold
|
||||||
|
|
||||||
FILE *tl_out_fd;
|
FILE *tl_out_fd;
|
||||||
#endif
|
#endif
|
||||||
#if defined(FEAT_SESSION)
|
#if defined(FEAT_SESSION)
|
||||||
@@ -147,6 +169,11 @@ static term_T *first_term = NULL;
|
|||||||
/* Terminal active in terminal_loop(). */
|
/* Terminal active in terminal_loop(). */
|
||||||
static term_T *in_terminal_loop = NULL;
|
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 MAX_ROW 999999 /* used for tl_dirty_row_end to update all rows */
|
||||||
#define KEY_BUF_LEN 200
|
#define KEY_BUF_LEN 200
|
||||||
|
|
||||||
@@ -715,6 +742,16 @@ ex_terminal(exarg_T *eap)
|
|||||||
vim_free(buf);
|
vim_free(buf);
|
||||||
*p = ' ';
|
*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
|
else
|
||||||
{
|
{
|
||||||
if (*p)
|
if (*p)
|
||||||
@@ -771,6 +808,11 @@ term_write_session(FILE *fd, win_T *wp)
|
|||||||
if (fprintf(fd, "terminal ++curwin ++cols=%d ++rows=%d ",
|
if (fprintf(fd, "terminal ++curwin ++cols=%d ++rows=%d ",
|
||||||
term->tl_cols, term->tl_rows) < 0)
|
term->tl_cols, term->tl_rows) < 0)
|
||||||
return FAIL;
|
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)
|
if (term->tl_command != NULL && fputs((char *)term->tl_command, fd) < 0)
|
||||||
return FAIL;
|
return FAIL;
|
||||||
|
|
||||||
@@ -871,6 +913,7 @@ free_unused_terminals()
|
|||||||
vim_free(term->tl_status_text);
|
vim_free(term->tl_status_text);
|
||||||
vim_free(term->tl_opencmd);
|
vim_free(term->tl_opencmd);
|
||||||
vim_free(term->tl_eof_chars);
|
vim_free(term->tl_eof_chars);
|
||||||
|
vim_free(term->tl_arg0_cmd);
|
||||||
#ifdef WIN3264
|
#ifdef WIN3264
|
||||||
if (term->tl_out_fd != NULL)
|
if (term->tl_out_fd != NULL)
|
||||||
fclose(term->tl_out_fd);
|
fclose(term->tl_out_fd);
|
||||||
@@ -2639,10 +2682,18 @@ handle_settermprop(
|
|||||||
{
|
{
|
||||||
case VTERM_PROP_TITLE:
|
case VTERM_PROP_TITLE:
|
||||||
vim_free(term->tl_title);
|
vim_free(term->tl_title);
|
||||||
/* a blank title isn't useful, make it empty, so that "running" is
|
// a blank title isn't useful, make it empty, so that "running" is
|
||||||
* displayed */
|
// displayed
|
||||||
if (*skipwhite((char_u *)value->string) == NUL)
|
if (*skipwhite((char_u *)value->string) == NUL)
|
||||||
term->tl_title = NULL;
|
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
|
#ifdef WIN3264
|
||||||
else if (!enc_utf8 && enc_codepage > 0)
|
else if (!enc_utf8 && enc_codepage > 0)
|
||||||
{
|
{
|
||||||
@@ -5318,7 +5369,7 @@ f_term_start(typval_T *argvars, typval_T *rettv)
|
|||||||
+ JO2_TERM_COLS + JO2_TERM_ROWS + JO2_VERTICAL + JO2_CURWIN
|
+ JO2_TERM_COLS + JO2_TERM_ROWS + JO2_VERTICAL + JO2_CURWIN
|
||||||
+ JO2_CWD + JO2_ENV + JO2_EOF_CHARS
|
+ JO2_CWD + JO2_ENV + JO2_EOF_CHARS
|
||||||
+ JO2_NORESTORE + JO2_TERM_KILL
|
+ JO2_NORESTORE + JO2_TERM_KILL
|
||||||
+ JO2_ANSI_COLORS) == FAIL)
|
+ JO2_ANSI_COLORS + JO2_TERM_MODE) == FAIL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
buf = term_start(&argvars[0], NULL, &opt, 0);
|
buf = term_start(&argvars[0], NULL, &opt, 0);
|
||||||
@@ -5426,6 +5477,327 @@ term_getjob(term_T *term)
|
|||||||
* 2. MS-Windows implementation.
|
* 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
|
# ifndef PROTO
|
||||||
|
|
||||||
#define WINPTY_SPAWN_FLAG_AUTO_SHUTDOWN 1ul
|
#define WINPTY_SPAWN_FLAG_AUTO_SHUTDOWN 1ul
|
||||||
@@ -5516,16 +5888,11 @@ dyn_winpty_init(int verbose)
|
|||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Create a new terminal of "rows" by "cols" cells.
|
|
||||||
* Store a reference in "term".
|
|
||||||
* Return OK or FAIL.
|
|
||||||
*/
|
|
||||||
static int
|
static int
|
||||||
term_and_job_init(
|
winpty_term_and_job_init(
|
||||||
term_T *term,
|
term_T *term,
|
||||||
typval_T *argvar,
|
typval_T *argvar,
|
||||||
char **argv UNUSED,
|
char **argv,
|
||||||
jobopt_T *opt,
|
jobopt_T *opt,
|
||||||
jobopt_T *orig_opt)
|
jobopt_T *orig_opt)
|
||||||
{
|
{
|
||||||
@@ -5543,8 +5910,6 @@ term_and_job_init(
|
|||||||
garray_T ga_cmd, ga_env;
|
garray_T ga_cmd, ga_env;
|
||||||
char_u *cmd = NULL;
|
char_u *cmd = NULL;
|
||||||
|
|
||||||
if (dyn_winpty_init(TRUE) == FAIL)
|
|
||||||
return FAIL;
|
|
||||||
ga_init2(&ga_cmd, (int)sizeof(char*), 20);
|
ga_init2(&ga_cmd, (int)sizeof(char*), 20);
|
||||||
ga_init2(&ga_env, (int)sizeof(char*), 20);
|
ga_init2(&ga_env, (int)sizeof(char*), 20);
|
||||||
|
|
||||||
@@ -5564,6 +5929,8 @@ term_and_job_init(
|
|||||||
goto failed;
|
goto failed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
term->tl_arg0_cmd = vim_strsave(cmd);
|
||||||
|
|
||||||
cmd_wchar = enc_to_utf16(cmd, NULL);
|
cmd_wchar = enc_to_utf16(cmd, NULL);
|
||||||
ga_clear(&ga_cmd);
|
ga_clear(&ga_cmd);
|
||||||
if (cmd_wchar == NULL)
|
if (cmd_wchar == NULL)
|
||||||
@@ -5676,9 +6043,9 @@ term_and_job_init(
|
|||||||
job->jv_job_object = jo;
|
job->jv_job_object = jo;
|
||||||
job->jv_status = JOB_STARTED;
|
job->jv_status = JOB_STARTED;
|
||||||
job->jv_tty_in = utf16_to_enc(
|
job->jv_tty_in = utf16_to_enc(
|
||||||
(short_u*)winpty_conin_name(term->tl_winpty), NULL);
|
(short_u *)winpty_conin_name(term->tl_winpty), NULL);
|
||||||
job->jv_tty_out = utf16_to_enc(
|
job->jv_tty_out = utf16_to_enc(
|
||||||
(short_u*)winpty_conout_name(term->tl_winpty), NULL);
|
(short_u *)winpty_conout_name(term->tl_winpty), NULL);
|
||||||
++job->jv_refcount;
|
++job->jv_refcount;
|
||||||
term->tl_job = job;
|
term->tl_job = job;
|
||||||
|
|
||||||
@@ -5722,7 +6089,7 @@ failed:
|
|||||||
term->tl_winpty_config = NULL;
|
term->tl_winpty_config = NULL;
|
||||||
if (winpty_err != NULL)
|
if (winpty_err != NULL)
|
||||||
{
|
{
|
||||||
char_u *msg = utf16_to_enc(
|
char *msg = (char *)utf16_to_enc(
|
||||||
(short_u *)winpty_error_msg(winpty_err), NULL);
|
(short_u *)winpty_error_msg(winpty_err), NULL);
|
||||||
|
|
||||||
emsg(msg);
|
emsg(msg);
|
||||||
@@ -5731,6 +6098,76 @@ failed:
|
|||||||
return FAIL;
|
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
|
static int
|
||||||
create_pty_only(term_T *term, jobopt_T *options)
|
create_pty_only(term_T *term, jobopt_T *options)
|
||||||
{
|
{
|
||||||
@@ -5804,6 +6241,7 @@ failed:
|
|||||||
static void
|
static void
|
||||||
term_free_vterm(term_T *term)
|
term_free_vterm(term_T *term)
|
||||||
{
|
{
|
||||||
|
term_free_conpty(term);
|
||||||
if (term->tl_winpty != NULL)
|
if (term->tl_winpty != NULL)
|
||||||
winpty_free(term->tl_winpty);
|
winpty_free(term->tl_winpty);
|
||||||
term->tl_winpty = NULL;
|
term->tl_winpty = NULL;
|
||||||
@@ -5821,6 +6259,8 @@ term_free_vterm(term_T *term)
|
|||||||
static void
|
static void
|
||||||
term_report_winsize(term_T *term, int rows, int cols)
|
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)
|
if (term->tl_winpty)
|
||||||
winpty_set_size(term->tl_winpty, cols, rows, NULL);
|
winpty_set_size(term->tl_winpty, cols, rows, NULL);
|
||||||
}
|
}
|
||||||
@@ -5828,7 +6268,7 @@ term_report_winsize(term_T *term, int rows, int cols)
|
|||||||
int
|
int
|
||||||
terminal_enabled(void)
|
terminal_enabled(void)
|
||||||
{
|
{
|
||||||
return dyn_winpty_init(FALSE) == OK;
|
return dyn_winpty_init(FALSE) == OK || dyn_conpty_init(FALSE) == OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
# else
|
# else
|
||||||
@@ -5852,6 +6292,8 @@ term_and_job_init(
|
|||||||
jobopt_T *opt,
|
jobopt_T *opt,
|
||||||
jobopt_T *orig_opt UNUSED)
|
jobopt_T *orig_opt UNUSED)
|
||||||
{
|
{
|
||||||
|
term->tl_arg0_cmd = NULL;
|
||||||
|
|
||||||
if (create_vterm(term, term->tl_rows, term->tl_cols) == FAIL)
|
if (create_vterm(term, term->tl_rows, term->tl_cols) == FAIL)
|
||||||
return FAIL;
|
return FAIL;
|
||||||
|
|
||||||
|
|||||||
@@ -131,6 +131,7 @@ let test_values = {
|
|||||||
\ 'term': [[], []],
|
\ 'term': [[], []],
|
||||||
\ 'termguicolors': [[], []],
|
\ 'termguicolors': [[], []],
|
||||||
\ 'termencoding': [has('gui_gtk') ? [] : ['', 'utf-8'], ['xxx']],
|
\ 'termencoding': [has('gui_gtk') ? [] : ['', 'utf-8'], ['xxx']],
|
||||||
|
\ 'termmode': [['', 'winpty', 'conpty'], ['xxx']],
|
||||||
\ 'termwinsize': [['', '24x80', '0x80', '32x0', '0x0'], ['xxx', '80', '8ax9', '24x80b']],
|
\ 'termwinsize': [['', '24x80', '0x80', '32x0', '0x0'], ['xxx', '80', '8ax9', '24x80b']],
|
||||||
\ 'toolbar': [['', 'icons', 'text'], ['xxx']],
|
\ 'toolbar': [['', 'icons', 'text'], ['xxx']],
|
||||||
\ 'toolbariconsize': [['', 'tiny', 'huge'], ['xxx']],
|
\ 'toolbariconsize': [['', 'tiny', 'huge'], ['xxx']],
|
||||||
|
|||||||
@@ -1397,7 +1397,13 @@ func Test_Changed_FirstTime()
|
|||||||
let buf = term_start([GetVimProg(), '--clean', '-c', 'set noswapfile'], {'term_rows': 3})
|
let buf = term_start([GetVimProg(), '--clean', '-c', 'set noswapfile'], {'term_rows': 3})
|
||||||
call assert_equal('running', term_getstatus(buf))
|
call assert_equal('running', term_getstatus(buf))
|
||||||
" Wait for the ruler (in the status line) to be shown.
|
" Wait for the ruler (in the status line) to be shown.
|
||||||
call WaitForAssert({-> assert_match('\<All$', term_getline(buf, 3))})
|
" 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.
|
" 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, ":au! TextChanged <buffer> call writefile(['No'], 'Xchanged.txt')\<cr>")
|
||||||
call term_sendkeys(buf, "\<C-\\>\<C-N>:qa!\<cr>")
|
call term_sendkeys(buf, "\<C-\\>\<C-N>:qa!\<cr>")
|
||||||
|
|||||||
@@ -295,7 +295,7 @@ func Test_mksession_terminal_shell()
|
|||||||
call assert_report('unexpected shell line: ' . line)
|
call assert_report('unexpected shell line: ' . line)
|
||||||
endif
|
endif
|
||||||
endfor
|
endfor
|
||||||
call assert_match('terminal ++curwin ++cols=\d\+ ++rows=\d\+\s*$', term_cmd)
|
call assert_match('terminal ++curwin ++cols=\d\+ ++rows=\d\+\s*.*$', term_cmd)
|
||||||
|
|
||||||
call Stop_shell_in_terminal(bufnr('%'))
|
call Stop_shell_in_terminal(bufnr('%'))
|
||||||
call delete('Xtest_mks.out')
|
call delete('Xtest_mks.out')
|
||||||
@@ -375,7 +375,7 @@ func Test_mksession_terminal_restore_other()
|
|||||||
let term_cmd = line
|
let term_cmd = line
|
||||||
endif
|
endif
|
||||||
endfor
|
endfor
|
||||||
call assert_match('terminal ++curwin ++cols=\d\+ ++rows=\d\+ other', term_cmd)
|
call assert_match('terminal ++curwin ++cols=\d\+ ++rows=\d\+.*other', term_cmd)
|
||||||
|
|
||||||
call Stop_shell_in_terminal(bufnr('%'))
|
call Stop_shell_in_terminal(bufnr('%'))
|
||||||
call delete('Xtest_mks.out')
|
call delete('Xtest_mks.out')
|
||||||
|
|||||||
@@ -39,8 +39,11 @@ func Test_terminal_basic()
|
|||||||
call assert_match('^/dev/', job_info(g:job).tty_out)
|
call assert_match('^/dev/', job_info(g:job).tty_out)
|
||||||
call assert_match('^/dev/', term_gettty(''))
|
call assert_match('^/dev/', term_gettty(''))
|
||||||
else
|
else
|
||||||
call assert_match('^\\\\.\\pipe\\', job_info(g:job).tty_out)
|
" ConPTY works on anonymous pipe.
|
||||||
call assert_match('^\\\\.\\pipe\\', term_gettty(''))
|
if !has('conpty')
|
||||||
|
call assert_match('^\\\\.\\pipe\\', job_info(g:job).tty_out)
|
||||||
|
call assert_match('^\\\\.\\pipe\\', term_gettty(''))
|
||||||
|
endif
|
||||||
endif
|
endif
|
||||||
call assert_equal('t', mode())
|
call assert_equal('t', mode())
|
||||||
call assert_equal('yes', b:done)
|
call assert_equal('yes', b:done)
|
||||||
@@ -129,7 +132,12 @@ endfunc
|
|||||||
|
|
||||||
func Get_cat_123_cmd()
|
func Get_cat_123_cmd()
|
||||||
if has('win32')
|
if has('win32')
|
||||||
return 'cmd /c "cls && color 2 && echo 123"'
|
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
|
else
|
||||||
call writefile(["\<Esc>[32m123"], 'Xtext')
|
call writefile(["\<Esc>[32m123"], 'Xtext')
|
||||||
return "cat Xtext"
|
return "cat Xtext"
|
||||||
@@ -143,8 +151,8 @@ func Test_terminal_nasty_cb()
|
|||||||
|
|
||||||
call WaitForAssert({-> assert_equal("dead", job_status(g:job))})
|
call WaitForAssert({-> assert_equal("dead", job_status(g:job))})
|
||||||
call WaitForAssert({-> assert_equal(0, g:buf)})
|
call WaitForAssert({-> assert_equal(0, g:buf)})
|
||||||
unlet g:buf
|
|
||||||
unlet g:job
|
unlet g:job
|
||||||
|
unlet g:buf
|
||||||
call delete('Xtext')
|
call delete('Xtext')
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
@@ -563,6 +571,9 @@ func Test_terminal_noblock()
|
|||||||
" The shell or something else has a problem dealing with more than 1000
|
" The shell or something else has a problem dealing with more than 1000
|
||||||
" characters at the same time.
|
" characters at the same time.
|
||||||
let len = 1000
|
let len = 1000
|
||||||
|
" NPFS is used in Windows, nonblocking mode does not work properly.
|
||||||
|
elseif has('win32')
|
||||||
|
let len = 1
|
||||||
else
|
else
|
||||||
let len = 5000
|
let len = 5000
|
||||||
endif
|
endif
|
||||||
@@ -693,8 +704,11 @@ func Test_terminal_redir_file()
|
|||||||
let cmd = Get_cat_123_cmd()
|
let cmd = Get_cat_123_cmd()
|
||||||
let buf = term_start(cmd, {'out_io': 'file', 'out_name': 'Xfile'})
|
let buf = term_start(cmd, {'out_io': 'file', 'out_name': 'Xfile'})
|
||||||
call term_wait(buf)
|
call term_wait(buf)
|
||||||
call WaitForAssert({-> assert_notequal(0, len(readfile("Xfile")))})
|
" ConPTY may precede escape sequence. There are things that are not so.
|
||||||
call assert_match('123', readfile('Xfile')[0])
|
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)
|
let g:job = term_getjob(buf)
|
||||||
call WaitForAssert({-> assert_equal("dead", job_status(g:job))})
|
call WaitForAssert({-> assert_equal("dead", job_status(g:job))})
|
||||||
call delete('Xfile')
|
call delete('Xfile')
|
||||||
@@ -1661,6 +1675,10 @@ func Test_terminal_hidden_and_close()
|
|||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
func Test_terminal_does_not_truncate_last_newlines()
|
func Test_terminal_does_not_truncate_last_newlines()
|
||||||
|
" This test does not pass through ConPTY.
|
||||||
|
if has('conpty')
|
||||||
|
return
|
||||||
|
endif
|
||||||
let contents = [
|
let contents = [
|
||||||
\ [ 'One', '', 'X' ],
|
\ [ 'One', '', 'X' ],
|
||||||
\ [ 'Two', '', '' ],
|
\ [ 'Two', '', '' ],
|
||||||
|
|||||||
@@ -783,6 +783,8 @@ static char *(features[]) =
|
|||||||
|
|
||||||
static int included_patches[] =
|
static int included_patches[] =
|
||||||
{ /* Add new patch number below this line */
|
{ /* Add new patch number below this line */
|
||||||
|
/**/
|
||||||
|
870,
|
||||||
/**/
|
/**/
|
||||||
869,
|
869,
|
||||||
/**/
|
/**/
|
||||||
|
|||||||
Reference in New Issue
Block a user