patch 8.0.1074: ":term NONE" does not work on MS-Windows

Problem:    ":term NONE" does not work on MS-Windows.
Solution:   Make it work.  Split "pty" into "pty_in" and "pty_out". (Yasuhiro
            Matsumoto, closes #2058, closes #2045)
diff --git a/src/terminal.c b/src/terminal.c
index 3ceb360..9c4e759 100644
--- a/src/terminal.c
+++ b/src/terminal.c
@@ -38,8 +38,7 @@
  * in tl_scrollback are no longer used.
  *
  * TODO:
- * - ":term NONE" does not work on MS-Windows.
- *   https://github.com/vim/vim/pull/2056
+ * - patch to use GUI or cterm colors for vterm. Yasuhiro, #2067
  * - Redirecting output does not work on MS-Windows.
  * - implement term_setsize()
  * - add test for giving error for invalid 'termsize' value.
@@ -97,7 +96,8 @@
 
     /* used when tl_job is NULL and only a pty was created */
     int		tl_tty_fd;
-    char_u	*tl_tty_name;
+    char_u	*tl_tty_in;
+    char_u	*tl_tty_out;
 
     int		tl_normal_mode; /* TRUE: Terminal-Normal mode */
     int		tl_channel_closed;
@@ -2666,14 +2666,32 @@
 {
     buf_T	*buf = term_get_buf(argvars);
     char_u	*p;
+    int		num = 0;
 
     rettv->v_type = VAR_STRING;
     if (buf == NULL)
 	return;
-    if (buf->b_term->tl_job != NULL)
-	p = buf->b_term->tl_job->jv_tty_name;
-    else
-	p = buf->b_term->tl_tty_name;
+    if (argvars[1].v_type != VAR_UNKNOWN)
+	num = get_tv_number(&argvars[1]);
+
+    switch (num)
+    {
+	case 0:
+	    if (buf->b_term->tl_job != NULL)
+		p = buf->b_term->tl_job->jv_tty_out;
+	    else
+		p = buf->b_term->tl_tty_out;
+	    break;
+	case 1:
+	    if (buf->b_term->tl_job != NULL)
+		p = buf->b_term->tl_job->jv_tty_in;
+	    else
+		p = buf->b_term->tl_tty_in;
+	    break;
+	default:
+	    EMSG2(_(e_invarg2), get_tv_string(&argvars[1]));
+	    return;
+    }
     if (p != NULL)
 	rettv->vval.v_string = vim_strsave(p);
 }
@@ -3055,7 +3073,6 @@
     HANDLE	    child_thread_handle;
     void	    *winpty_err;
     void	    *spawn_config = NULL;
-    char	    buf[MAX_PATH];
     garray_T	    ga;
     char_u	    *cmd;
 
@@ -3094,7 +3111,6 @@
     if (term->tl_winpty == NULL)
 	goto failed;
 
-    /* TODO: if the command is "NONE" only create a pty. */
     spawn_config = winpty_spawn_config_new(
 	    WINPTY_SPAWN_FLAG_AUTO_SHUTDOWN |
 		WINPTY_SPAWN_FLAG_EXIT_AFTER_SHUTDOWN,
@@ -3162,9 +3178,10 @@
     job->jv_proc_info.dwProcessId = GetProcessId(child_process_handle);
     job->jv_job_object = jo;
     job->jv_status = JOB_STARTED;
-    sprintf(buf, "winpty://%lu",
-	    GetProcessId(winpty_agent_process(term->tl_winpty)));
-    job->jv_tty_name = vim_strsave((char_u*)buf);
+    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;
 
@@ -3205,9 +3222,68 @@
 }
 
     static int
-create_pty_only(term_T *term, jobopt_T *opt)
+create_pty_only(term_T *term, jobopt_T *options)
 {
-    /* TODO: implement this */
+    HANDLE	    hPipeIn = INVALID_HANDLE_VALUE;
+    HANDLE	    hPipeOut = INVALID_HANDLE_VALUE;
+    char	    in_name[80], out_name[80];
+    channel_T	    *channel = NULL;
+
+    create_vterm(term, term->tl_rows, term->tl_cols);
+
+    vim_snprintf(in_name, sizeof(in_name), "\\\\.\\pipe\\vim-%d-in-%d",
+	    GetCurrentProcessId(),
+	    curbuf->b_fnum);
+    hPipeIn = CreateNamedPipe(in_name, PIPE_ACCESS_OUTBOUND,
+	    PIPE_TYPE_MESSAGE | PIPE_NOWAIT,
+	    PIPE_UNLIMITED_INSTANCES,
+	    0, 0, NMPWAIT_NOWAIT, NULL);
+    if (hPipeIn == INVALID_HANDLE_VALUE)
+	goto failed;
+
+    vim_snprintf(out_name, sizeof(out_name), "\\\\.\\pipe\\vim-%d-out-%d",
+	    GetCurrentProcessId(),
+	    curbuf->b_fnum);
+    hPipeOut = CreateNamedPipe(out_name, PIPE_ACCESS_INBOUND,
+	    PIPE_TYPE_MESSAGE | PIPE_NOWAIT,
+	    PIPE_UNLIMITED_INSTANCES,
+	    0, 0, 0, NULL);
+    if (hPipeOut == INVALID_HANDLE_VALUE)
+	goto failed;
+
+    ConnectNamedPipe(hPipeIn, NULL);
+    ConnectNamedPipe(hPipeOut, NULL);
+
+    term->tl_job = job_alloc();
+    if (term->tl_job == NULL)
+	goto failed;
+    ++term->tl_job->jv_refcount;
+
+    /* behave like the job is already finished */
+    term->tl_job->jv_status = JOB_FINISHED;
+
+    channel = add_channel();
+    if (channel == NULL)
+	goto failed;
+    term->tl_job->jv_channel = channel;
+    channel->ch_keep_open = TRUE;
+    channel->ch_named_pipe = TRUE;
+
+    channel_set_pipes(channel,
+	(sock_T)hPipeIn,
+	(sock_T)hPipeOut,
+	(sock_T)hPipeOut);
+    channel_set_job(channel, term->tl_job, options);
+    term->tl_job->jv_tty_in = vim_strsave((char_u*)in_name);
+    term->tl_job->jv_tty_out = vim_strsave((char_u*)out_name);
+
+    return OK;
+
+failed:
+    if (hPipeIn != NULL)
+	CloseHandle(hPipeIn);
+    if (hPipeOut != NULL)
+	CloseHandle(hPipeOut);
     return FAIL;
 }
 
@@ -3234,7 +3310,8 @@
     static void
 term_report_winsize(term_T *term, int rows, int cols)
 {
-    winpty_set_size(term->tl_winpty, cols, rows, NULL);
+    if (term->tl_winpty)
+	winpty_set_size(term->tl_winpty, cols, rows, NULL);
 }
 
     int