aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/nvim/CMakeLists.txt8
-rw-r--r--src/nvim/channel.c20
-rw-r--r--src/nvim/main.c11
-rw-r--r--src/nvim/option.c3
-rw-r--r--src/nvim/os/os_win_console.c42
-rw-r--r--src/nvim/os/os_win_console.h8
-rw-r--r--src/nvim/os/pty_conpty_win.c199
-rw-r--r--src/nvim/os/pty_conpty_win.h22
-rw-r--r--src/nvim/os/pty_process_win.c136
-rw-r--r--src/nvim/os/pty_process_win.h15
-rw-r--r--src/nvim/tui/input.c11
11 files changed, 408 insertions, 67 deletions
diff --git a/src/nvim/CMakeLists.txt b/src/nvim/CMakeLists.txt
index bc8e64dd41..089dd537e9 100644
--- a/src/nvim/CMakeLists.txt
+++ b/src/nvim/CMakeLists.txt
@@ -134,6 +134,12 @@ foreach(sfile ${NVIM_SOURCES})
if(NOT WIN32 AND ${f} MATCHES "^(pty_process_win.c)$")
list(APPEND to_remove ${sfile})
endif()
+ if(NOT WIN32 AND ${f} MATCHES "^(pty_conpty_win.c)$")
+ list(APPEND to_remove ${sfile})
+ endif()
+ if(NOT WIN32 AND ${f} MATCHES "^(os_win_console.c)$")
+ list(APPEND to_remove ${sfile})
+ endif()
endforeach()
list(REMOVE_ITEM NVIM_SOURCES ${to_remove})
@@ -637,6 +643,8 @@ endfunction()
set(NO_SINGLE_CHECK_HEADERS
os/win_defs.h
os/pty_process_win.h
+ os/pty_conpty_win.h
+ os/os_win_console.h
)
foreach(hfile ${NVIM_HEADERS})
get_test_target(test-includes "${hfile}" relative_path texe)
diff --git a/src/nvim/channel.c b/src/nvim/channel.c
index 2bb568f025..c66a0682e3 100644
--- a/src/nvim/channel.c
+++ b/src/nvim/channel.c
@@ -11,6 +11,10 @@
#include "nvim/msgpack_rpc/channel.h"
#include "nvim/msgpack_rpc/server.h"
#include "nvim/os/shell.h"
+#ifdef WIN32
+# include "nvim/os/pty_conpty_win.h"
+# include "nvim/os/os_win_console.h"
+#endif
#include "nvim/path.h"
#include "nvim/ascii.h"
@@ -469,8 +473,20 @@ uint64_t channel_from_stdio(bool rpc, CallbackReader on_output,
Channel *channel = channel_alloc(kChannelStreamStdio);
- rstream_init_fd(&main_loop, &channel->stream.stdio.in, 0, 0);
- wstream_init_fd(&main_loop, &channel->stream.stdio.out, 1, 0);
+ int stdin_dup_fd = STDIN_FILENO;
+ int stdout_dup_fd = STDOUT_FILENO;
+#ifdef WIN32
+ // Strangely, ConPTY doesn't work if stdin and stdout are pipes. So replace
+ // stdin and stdout with CONIN$ and CONOUT$, respectively.
+ if (embedded_mode && os_has_conpty_working()) {
+ stdin_dup_fd = os_dup(STDIN_FILENO);
+ os_replace_stdin_to_conin();
+ stdout_dup_fd = os_dup(STDOUT_FILENO);
+ os_replace_stdout_and_stderr_to_conout();
+ }
+#endif
+ rstream_init_fd(&main_loop, &channel->stream.stdio.in, stdin_dup_fd, 0);
+ wstream_init_fd(&main_loop, &channel->stream.stdio.out, stdout_dup_fd, 0);
if (rpc) {
rpc_start(channel);
diff --git a/src/nvim/main.c b/src/nvim/main.c
index c7011f4f4e..be279b449a 100644
--- a/src/nvim/main.c
+++ b/src/nvim/main.c
@@ -64,6 +64,9 @@
#include "nvim/os/os.h"
#include "nvim/os/time.h"
#include "nvim/os/fileio.h"
+#ifdef WIN32
+# include "nvim/os/os_win_console.h"
+#endif
#include "nvim/event/loop.h"
#include "nvim/os/signal.h"
#include "nvim/event/process.h"
@@ -1120,13 +1123,7 @@ scripterror:
const int stdin_dup_fd = os_dup(STDIN_FILENO);
#ifdef WIN32
// Replace the original stdin with the console input handle.
- close(STDIN_FILENO);
- const HANDLE conin_handle =
- CreateFile("CONIN$", GENERIC_READ | GENERIC_WRITE,
- FILE_SHARE_READ, (LPSECURITY_ATTRIBUTES)NULL,
- OPEN_EXISTING, 0, (HANDLE)NULL);
- const int conin_fd = _open_osfhandle(conin_handle, _O_RDONLY);
- assert(conin_fd == STDIN_FILENO);
+ os_replace_stdin_to_conin();
#endif
FileDescriptor *const stdin_dup = file_open_fd_new(
&error, stdin_dup_fd, kFileReadOnly|kFileNonBlocking);
diff --git a/src/nvim/option.c b/src/nvim/option.c
index 9d3e02949e..0c87a422dc 100644
--- a/src/nvim/option.c
+++ b/src/nvim/option.c
@@ -76,6 +76,9 @@
#include "nvim/undo.h"
#include "nvim/window.h"
#include "nvim/os/os.h"
+#ifdef WIN32
+# include "nvim/os/pty_conpty_win.h"
+#endif
#include "nvim/api/private/helpers.h"
#include "nvim/os/input.h"
#include "nvim/os/lang.h"
diff --git a/src/nvim/os/os_win_console.c b/src/nvim/os/os_win_console.c
new file mode 100644
index 0000000000..8a0aa2f5ae
--- /dev/null
+++ b/src/nvim/os/os_win_console.c
@@ -0,0 +1,42 @@
+// This is an open source non-commercial project. Dear PVS-Studio, please check
+// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+
+#include "nvim/vim.h"
+#include "nvim/os/os_win_console.h"
+
+int os_get_conin_fd(void)
+{
+ const HANDLE conin_handle = CreateFile("CONIN$",
+ GENERIC_READ | GENERIC_WRITE,
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ (LPSECURITY_ATTRIBUTES)NULL,
+ OPEN_EXISTING, 0, (HANDLE)NULL);
+ assert(conin_handle != INVALID_HANDLE_VALUE);
+ int conin_fd = _open_osfhandle((intptr_t)conin_handle, _O_RDONLY);
+ assert(conin_fd != -1);
+ return conin_fd;
+}
+
+void os_replace_stdin_to_conin(void)
+{
+ close(STDIN_FILENO);
+ const int conin_fd = os_get_conin_fd();
+ assert(conin_fd == STDIN_FILENO);
+}
+
+void os_replace_stdout_and_stderr_to_conout(void)
+{
+ const HANDLE conout_handle =
+ CreateFile("CONOUT$",
+ GENERIC_READ | GENERIC_WRITE,
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ (LPSECURITY_ATTRIBUTES)NULL,
+ OPEN_EXISTING, 0, (HANDLE)NULL);
+ assert(conout_handle != INVALID_HANDLE_VALUE);
+ close(STDOUT_FILENO);
+ const int conout_fd = _open_osfhandle((intptr_t)conout_handle, 0);
+ assert(conout_fd == STDOUT_FILENO);
+ close(STDERR_FILENO);
+ const int conerr_fd = _open_osfhandle((intptr_t)conout_handle, 0);
+ assert(conerr_fd == STDERR_FILENO);
+}
diff --git a/src/nvim/os/os_win_console.h b/src/nvim/os/os_win_console.h
new file mode 100644
index 0000000000..154ec83d8a
--- /dev/null
+++ b/src/nvim/os/os_win_console.h
@@ -0,0 +1,8 @@
+#ifndef NVIM_OS_OS_WIN_CONSOLE_H
+#define NVIM_OS_OS_WIN_CONSOLE_H
+
+#ifdef INCLUDE_GENERATED_DECLARATIONS
+# include "os/os_win_console.h.generated.h"
+#endif
+
+#endif // NVIM_OS_OS_WIN_CONSOLE_H
diff --git a/src/nvim/os/pty_conpty_win.c b/src/nvim/os/pty_conpty_win.c
new file mode 100644
index 0000000000..5bcadd6490
--- /dev/null
+++ b/src/nvim/os/pty_conpty_win.c
@@ -0,0 +1,199 @@
+// This is an open source non-commercial project. Dear PVS-Studio, please check
+// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+
+#include <uv.h>
+
+#include "nvim/vim.h"
+#include "nvim/os/os.h"
+#include "nvim/os/pty_conpty_win.h"
+
+#ifndef EXTENDED_STARTUPINFO_PRESENT
+# define EXTENDED_STARTUPINFO_PRESENT 0x00080000
+#endif
+#ifndef PROC_THREAD_ATTRIBUTE_PSEUDOCONSOLE
+# define PROC_THREAD_ATTRIBUTE_PSEUDOCONSOLE 0x00020016
+#endif
+
+HRESULT (WINAPI *pCreatePseudoConsole)(COORD, HANDLE, HANDLE, DWORD, HPCON *);
+HRESULT (WINAPI *pResizePseudoConsole)(HPCON, COORD);
+void (WINAPI *pClosePseudoConsole)(HPCON);
+
+bool os_has_conpty_working(void)
+{
+ static TriState has_conpty = kNone;
+ if (has_conpty == kNone) {
+ has_conpty = os_dyn_conpty_init();
+ }
+
+ return has_conpty == kTrue;
+}
+
+TriState os_dyn_conpty_init(void)
+{
+ uv_lib_t kernel;
+ if (uv_dlopen("kernel32.dll", &kernel)) {
+ uv_dlclose(&kernel);
+ return kFalse;
+ }
+ static struct {
+ char *name;
+ FARPROC *ptr;
+ } conpty_entry[] = {
+ { "CreatePseudoConsole", (FARPROC *)&pCreatePseudoConsole },
+ { "ResizePseudoConsole", (FARPROC *)&pResizePseudoConsole },
+ { "ClosePseudoConsole", (FARPROC *)&pClosePseudoConsole },
+ { NULL, NULL }
+ };
+ for (int i = 0;
+ conpty_entry[i].name != NULL && conpty_entry[i].ptr != NULL; i++) {
+ if (uv_dlsym(&kernel, conpty_entry[i].name, (void **)conpty_entry[i].ptr)) {
+ uv_dlclose(&kernel);
+ return kFalse;
+ }
+ }
+ return kTrue;
+}
+
+conpty_t *os_conpty_init(char **in_name, char **out_name,
+ uint16_t width, uint16_t height)
+{
+ static int count = 0;
+ conpty_t *conpty_object = xcalloc(1, sizeof(*conpty_object));
+ const char *emsg = NULL;
+ HANDLE in_read = INVALID_HANDLE_VALUE;
+ HANDLE out_write = INVALID_HANDLE_VALUE;
+ char buf[MAXPATHL];
+ SECURITY_ATTRIBUTES sa = { 0 };
+ const DWORD mode = PIPE_ACCESS_INBOUND
+ | PIPE_ACCESS_OUTBOUND | FILE_FLAG_FIRST_PIPE_INSTANCE;
+
+ sa.nLength = sizeof(sa);
+ snprintf(buf, sizeof(buf), "\\\\.\\pipe\\nvim-term-in-%d-%d",
+ os_get_pid(), count);
+ *in_name = xstrdup(buf);
+ if ((in_read = CreateNamedPipeA(
+ *in_name,
+ mode,
+ PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT,
+ 1,
+ 0,
+ 0,
+ 30000,
+ &sa)) == INVALID_HANDLE_VALUE) {
+ emsg = "create input pipe failed";
+ goto failed;
+ }
+ snprintf(buf, sizeof(buf), "\\\\.\\pipe\\nvim-term-out-%d-%d",
+ os_get_pid(), count);
+ *out_name = xstrdup(buf);
+ if ((out_write = CreateNamedPipeA(
+ *out_name,
+ mode,
+ PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT,
+ 1,
+ 0,
+ 0,
+ 30000,
+ &sa)) == INVALID_HANDLE_VALUE) {
+ emsg = "create output pipe failed";
+ goto failed;
+ }
+ assert(width <= SHRT_MAX);
+ assert(height <= SHRT_MAX);
+ COORD size = { (int16_t)width, (int16_t)height };
+ HRESULT hr;
+ hr = pCreatePseudoConsole(size, in_read, out_write, 0, &conpty_object->pty);
+ if (FAILED(hr)) {
+ emsg = "create psudo console failed";
+ goto failed;
+ }
+
+ conpty_object->si_ex.StartupInfo.cb = sizeof(conpty_object->si_ex);
+ size_t bytes_required;
+ InitializeProcThreadAttributeList(NULL, 1, 0, & bytes_required);
+ conpty_object->si_ex.lpAttributeList =
+ (PPROC_THREAD_ATTRIBUTE_LIST)xmalloc(bytes_required);
+ if (!InitializeProcThreadAttributeList(
+ conpty_object->si_ex.lpAttributeList,
+ 1,
+ 0,
+ &bytes_required)) {
+ emsg = "InitializeProcThreadAttributeList failed";
+ goto failed;
+ }
+ if (!UpdateProcThreadAttribute(
+ conpty_object->si_ex.lpAttributeList,
+ 0,
+ PROC_THREAD_ATTRIBUTE_PSEUDOCONSOLE,
+ conpty_object->pty,
+ sizeof(conpty_object->pty),
+ NULL,
+ NULL)) {
+ emsg = "UpdateProcThreadAttribute failed";
+ goto failed;
+ }
+ count++;
+ goto finished;
+
+failed:
+ ELOG("os_conpty_init:%s : error code: %d",
+ emsg, os_translate_sys_error((int)GetLastError()));
+ os_conpty_free(conpty_object);
+ conpty_object = NULL;
+finished:
+ if (in_read != INVALID_HANDLE_VALUE) {
+ CloseHandle(in_read);
+ }
+ if (out_write != INVALID_HANDLE_VALUE) {
+ CloseHandle(out_write);
+ }
+ return conpty_object;
+}
+
+bool os_conpty_spawn(conpty_t *conpty_object, HANDLE *process_handle,
+ wchar_t *name, wchar_t *cmd_line, wchar_t *cwd,
+ wchar_t *env)
+{
+ PROCESS_INFORMATION pi = { 0 };
+ if (!CreateProcessW(
+ name,
+ cmd_line,
+ NULL,
+ NULL,
+ false,
+ EXTENDED_STARTUPINFO_PRESENT | CREATE_UNICODE_ENVIRONMENT,
+ env,
+ cwd,
+ &conpty_object->si_ex.StartupInfo,
+ &pi)) {
+ return false;
+ }
+ *process_handle = pi.hProcess;
+ return true;
+}
+
+void os_conpty_set_size(conpty_t *conpty_object,
+ uint16_t width, uint16_t height)
+{
+ assert(width <= SHRT_MAX);
+ assert(height <= SHRT_MAX);
+ COORD size = { (int16_t)width, (int16_t)height };
+ if (pResizePseudoConsole(conpty_object->pty, size) != S_OK) {
+ ELOG("ResizePseudoConsoel failed: error code: %d",
+ os_translate_sys_error((int)GetLastError()));
+ }
+}
+
+void os_conpty_free(conpty_t *conpty_object)
+{
+ if (conpty_object != NULL) {
+ if (conpty_object->si_ex.lpAttributeList != NULL) {
+ DeleteProcThreadAttributeList(conpty_object->si_ex.lpAttributeList);
+ xfree(conpty_object->si_ex.lpAttributeList);
+ }
+ if (conpty_object->pty != NULL) {
+ pClosePseudoConsole(conpty_object->pty);
+ }
+ }
+ xfree(conpty_object);
+}
diff --git a/src/nvim/os/pty_conpty_win.h b/src/nvim/os/pty_conpty_win.h
new file mode 100644
index 0000000000..c243db4fa5
--- /dev/null
+++ b/src/nvim/os/pty_conpty_win.h
@@ -0,0 +1,22 @@
+#ifndef NVIM_OS_PTY_CONPTY_WIN_H
+#define NVIM_OS_PTY_CONPTY_WIN_H
+
+#ifndef HPCON
+# define HPCON VOID *
+#endif
+
+extern HRESULT (WINAPI *pCreatePseudoConsole) // NOLINT(whitespace/parens)
+ (COORD, HANDLE, HANDLE, DWORD, HPCON *);
+extern HRESULT (WINAPI *pResizePseudoConsole)(HPCON, COORD);
+extern void (WINAPI *pClosePseudoConsole)(HPCON);
+
+typedef struct conpty {
+ HPCON pty;
+ STARTUPINFOEXW si_ex;
+} conpty_t;
+
+#ifdef INCLUDE_GENERATED_DECLARATIONS
+# include "os/pty_conpty_win.h.generated.h"
+#endif
+
+#endif // NVIM_OS_PTY_CONPTY_WIN_H
diff --git a/src/nvim/os/pty_process_win.c b/src/nvim/os/pty_process_win.c
index 183219bd3e..6f7100e846 100644
--- a/src/nvim/os/pty_process_win.c
+++ b/src/nvim/os/pty_process_win.c
@@ -12,6 +12,7 @@
#include "nvim/memory.h"
#include "nvim/mbyte.h" // for utf8_to_utf16, utf16_to_utf8
#include "nvim/os/pty_process_win.h"
+#include "nvim/os/pty_conpty_win.h"
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "os/pty_process_win.c.generated.h"
@@ -23,6 +24,11 @@ static void CALLBACK pty_process_finish1(void *context, BOOLEAN unused)
PtyProcess *ptyproc = (PtyProcess *)context;
Process *proc = (Process *)ptyproc;
+ if (ptyproc->type == kConpty
+ && ptyproc->object.conpty != NULL) {
+ os_conpty_free(ptyproc->object.conpty);
+ ptyproc->object.conpty = NULL;
+ }
uv_timer_init(&proc->loop->uv, &ptyproc->wait_eof_timer);
ptyproc->wait_eof_timer.data = (void *)ptyproc;
uv_timer_start(&ptyproc->wait_eof_timer, wait_eof_timer_cb, 200, 200);
@@ -38,6 +44,7 @@ int pty_process_spawn(PtyProcess *ptyproc)
winpty_config_t *cfg = NULL;
winpty_spawn_config_t *spawncfg = NULL;
winpty_t *winpty_object = NULL;
+ conpty_t *conpty_object = NULL;
char *in_name = NULL;
char *out_name = NULL;
HANDLE process_handle = NULL;
@@ -49,29 +56,39 @@ int pty_process_spawn(PtyProcess *ptyproc)
assert(proc->err.closed);
- cfg = winpty_config_new(WINPTY_FLAG_ALLOW_CURPROC_DESKTOP_CREATION, &err);
- if (cfg == NULL) {
- emsg = "winpty_config_new failed";
- goto cleanup;
+ if (os_has_conpty_working()) {
+ if ((conpty_object =
+ os_conpty_init(&in_name, &out_name,
+ ptyproc->width, ptyproc->height)) != NULL) {
+ ptyproc->type = kConpty;
+ }
}
- winpty_config_set_initial_size(cfg, ptyproc->width, ptyproc->height);
- winpty_object = winpty_open(cfg, &err);
- if (winpty_object == NULL) {
- emsg = "winpty_open failed";
- goto cleanup;
- }
+ if (ptyproc->type == kWinpty) {
+ cfg = winpty_config_new(WINPTY_FLAG_ALLOW_CURPROC_DESKTOP_CREATION, &err);
+ if (cfg == NULL) {
+ emsg = "winpty_config_new failed";
+ goto cleanup;
+ }
- status = utf16_to_utf8(winpty_conin_name(winpty_object), -1, &in_name);
- if (status != 0) {
- emsg = "utf16_to_utf8(winpty_conin_name) failed";
- goto cleanup;
- }
+ winpty_config_set_initial_size(cfg, ptyproc->width, ptyproc->height);
+ winpty_object = winpty_open(cfg, &err);
+ if (winpty_object == NULL) {
+ emsg = "winpty_open failed";
+ goto cleanup;
+ }
- status = utf16_to_utf8(winpty_conout_name(winpty_object), -1, &out_name);
- if (status != 0) {
- emsg = "utf16_to_utf8(winpty_conout_name) failed";
- goto cleanup;
+ status = utf16_to_utf8(winpty_conin_name(winpty_object), -1, &in_name);
+ if (status != 0) {
+ emsg = "utf16_to_utf8(winpty_conin_name) failed";
+ goto cleanup;
+ }
+
+ status = utf16_to_utf8(winpty_conout_name(winpty_object), -1, &out_name);
+ if (status != 0) {
+ emsg = "utf16_to_utf8(winpty_conout_name) failed";
+ goto cleanup;
+ }
}
if (!proc->in.closed) {
@@ -107,32 +124,45 @@ int pty_process_spawn(PtyProcess *ptyproc)
goto cleanup;
}
- spawncfg = winpty_spawn_config_new(
- WINPTY_SPAWN_FLAG_AUTO_SHUTDOWN,
- NULL, // Optional application name
- cmd_line,
- cwd,
- NULL, // Optional environment variables
- &err);
- if (spawncfg == NULL) {
- emsg = "winpty_spawn_config_new failed";
- goto cleanup;
- }
+ if (ptyproc->type == kConpty) {
+ if (!os_conpty_spawn(conpty_object,
+ &process_handle,
+ NULL,
+ cmd_line,
+ cwd,
+ NULL)) {
+ emsg = "os_conpty_spawn failed";
+ status = (int)GetLastError();
+ goto cleanup;
+ }
+ } else {
+ spawncfg = winpty_spawn_config_new(
+ WINPTY_SPAWN_FLAG_AUTO_SHUTDOWN,
+ NULL, // Optional application name
+ cmd_line,
+ cwd,
+ NULL, // Optional environment variables
+ &err);
+ if (spawncfg == NULL) {
+ emsg = "winpty_spawn_config_new failed";
+ goto cleanup;
+ }
- DWORD win_err = 0;
- if (!winpty_spawn(winpty_object,
- spawncfg,
- &process_handle,
- NULL, // Optional thread handle
- &win_err,
- &err)) {
- if (win_err) {
- status = (int)win_err;
- emsg = "failed to spawn process";
- } else {
- emsg = "winpty_spawn failed";
+ DWORD win_err = 0;
+ if (!winpty_spawn(winpty_object,
+ spawncfg,
+ &process_handle,
+ NULL, // Optional thread handle
+ &win_err,
+ &err)) {
+ if (win_err) {
+ status = (int)win_err;
+ emsg = "failed to spawn process";
+ } else {
+ emsg = "winpty_spawn failed";
+ }
+ goto cleanup;
}
- goto cleanup;
}
proc->pid = (int)GetProcessId(process_handle);
@@ -152,9 +182,12 @@ int pty_process_spawn(PtyProcess *ptyproc)
uv_run(&proc->loop->uv, UV_RUN_ONCE);
}
- ptyproc->winpty_object = winpty_object;
+ (ptyproc->type == kConpty) ?
+ (void *)(ptyproc->object.conpty = conpty_object) :
+ (void *)(ptyproc->object.winpty = winpty_object);
ptyproc->process_handle = process_handle;
winpty_object = NULL;
+ conpty_object = NULL;
process_handle = NULL;
cleanup:
@@ -171,6 +204,7 @@ cleanup:
winpty_config_free(cfg);
winpty_spawn_config_free(spawncfg);
winpty_free(winpty_object);
+ os_conpty_free(conpty_object);
xfree(in_name);
xfree(out_name);
if (process_handle != NULL) {
@@ -192,8 +226,11 @@ void pty_process_resize(PtyProcess *ptyproc, uint16_t width,
uint16_t height)
FUNC_ATTR_NONNULL_ALL
{
- if (ptyproc->winpty_object != NULL) {
- winpty_set_size(ptyproc->winpty_object, width, height, NULL);
+ if (ptyproc->type == kConpty
+ && ptyproc->object.conpty != NULL) {
+ os_conpty_set_size(ptyproc->object.conpty, width, height);
+ } else if (ptyproc->object.winpty != NULL) {
+ winpty_set_size(ptyproc->object.winpty, width, height, NULL);
}
}
@@ -212,9 +249,10 @@ void pty_process_close(PtyProcess *ptyproc)
void pty_process_close_master(PtyProcess *ptyproc)
FUNC_ATTR_NONNULL_ALL
{
- if (ptyproc->winpty_object != NULL) {
- winpty_free(ptyproc->winpty_object);
- ptyproc->winpty_object = NULL;
+ if (ptyproc->type == kWinpty
+ && ptyproc->object.winpty != NULL) {
+ winpty_free(ptyproc->object.winpty);
+ ptyproc->object.winpty = NULL;
}
}
diff --git a/src/nvim/os/pty_process_win.h b/src/nvim/os/pty_process_win.h
index 1a4019e654..8ad5ba7286 100644
--- a/src/nvim/os/pty_process_win.h
+++ b/src/nvim/os/pty_process_win.h
@@ -6,12 +6,22 @@
#include "nvim/event/process.h"
#include "nvim/lib/queue.h"
+#include "nvim/os/pty_conpty_win.h"
+
+typedef enum {
+ kWinpty,
+ kConpty
+} PtyType;
typedef struct pty_process {
Process process;
char *term_name;
uint16_t width, height;
- winpty_t *winpty_object;
+ union {
+ winpty_t *winpty;
+ conpty_t *conpty;
+ } object;
+ PtyType type;
HANDLE finish_wait;
HANDLE process_handle;
uv_timer_t wait_eof_timer;
@@ -30,7 +40,8 @@ static inline PtyProcess pty_process_init(Loop *loop, void *data)
rv.term_name = NULL;
rv.width = 80;
rv.height = 24;
- rv.winpty_object = NULL;
+ rv.object.winpty = NULL;
+ rv.type = kWinpty;
rv.finish_wait = NULL;
rv.process_handle = NULL;
return rv;
diff --git a/src/nvim/tui/input.c b/src/nvim/tui/input.c
index c71378463f..951cb50c3c 100644
--- a/src/nvim/tui/input.c
+++ b/src/nvim/tui/input.c
@@ -14,6 +14,9 @@
#include "nvim/option.h"
#include "nvim/os/os.h"
#include "nvim/os/input.h"
+#ifdef WIN32
+# include "nvim/os/os_win_console.h"
+#endif
#include "nvim/event/rstream.h"
#define KEY_BUFFER_SIZE 0xfff
@@ -37,13 +40,7 @@ void tinput_init(TermInput *input, Loop *loop)
// ls *.md | xargs nvim
#ifdef WIN32
if (!os_isatty(input->in_fd)) {
- const HANDLE conin_handle = CreateFile("CONIN$",
- GENERIC_READ | GENERIC_WRITE,
- FILE_SHARE_READ | FILE_SHARE_WRITE,
- (LPSECURITY_ATTRIBUTES)NULL,
- OPEN_EXISTING, 0, (HANDLE)NULL);
- input->in_fd = _open_osfhandle(conin_handle, _O_RDONLY);
- assert(input->in_fd != -1);
+ input->in_fd = os_get_conin_fd();
}
#else
if (!os_isatty(input->in_fd) && os_isatty(STDERR_FILENO)) {