+static HANDLE
+get_handle(int fd)
+{
+ intptr_t value = _get_osfhandle(fd);
+ return (HANDLE) value;
+}
+
+#if WINVER >= 0x0600
+/* This function tests, whether or not the ncurses application
+ is running as a descendant of MSYS2/cygwin mintty terminal
+ application. mintty doesn't use Windows Console for it's screen
+ I/O, so the native Windows _isatty doesn't recognize it as
+ character device. But we can discover we are at the end of an
+ Pipe and can query to server side of the pipe, looking whether
+ or not this is mintty.
+ */
+static int
+_ismintty(int fd, LPHANDLE pMinTTY)
+{
+ HANDLE handle = get_handle(fd);
+ DWORD dw;
+ int code = 0;
+
+ T((T_CALLED("win32con::_ismintty(%d, %p)"), fd, pMinTTY));
+
+ if (handle != INVALID_HANDLE_VALUE) {
+ dw = GetFileType(handle);
+ if (dw == FILE_TYPE_PIPE) {
+ if (GetNamedPipeInfo(handle, 0, 0, 0, 0)) {
+ ULONG pPid;
+ /* Requires NT6 */
+ if (GetNamedPipeServerProcessId(handle, &pPid)) {
+ TCHAR buf[MAX_PATH];
+ DWORD len = 0;
+ /* These security attributes may allow us to
+ create a remote thread in mintty to manipulate
+ the terminal state remotely */
+ HANDLE pHandle = OpenProcess(
+ PROCESS_CREATE_THREAD
+ | PROCESS_QUERY_INFORMATION
+ | PROCESS_VM_OPERATION
+ | PROCESS_VM_WRITE
+ | PROCESS_VM_READ,
+ FALSE,
+ pPid);
+ if (pMinTTY)
+ *pMinTTY = INVALID_HANDLE_VALUE;
+ if (pHandle != INVALID_HANDLE_VALUE) {
+ if ((len = GetProcessImageFileName(
+ pHandle,
+ buf,
+ (DWORD)
+ array_length(buf)))) {
+ TCHAR *pos = _tcsrchr(buf, _T('\\'));
+ if (pos) {
+ pos++;
+ if (_tcsnicmp(pos, _TEXT("mintty.exe"), 10)
+ == 0) {
+ if (pMinTTY)
+ *pMinTTY = pHandle;
+ code = 1;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ returnCode(code);
+}
+#endif
+
+/* Borrowed from ansicon project.
+ Check whether or not an I/O handle is associated with
+ a Windows console.
+*/
+static BOOL
+IsConsoleHandle(HANDLE hdl)
+{
+ DWORD dwFlag = 0;
+ BOOL result;
+
+ if (!GetConsoleMode(hdl, &dwFlag)) {
+ result = (int) WriteConsoleA(hdl, NULL, 0, &dwFlag, NULL);
+ } else {
+ result = (int) (dwFlag & ENABLE_PROCESSED_OUTPUT);
+ }
+ return result;
+}
+
+/* Our replacement for the systems _isatty to include also
+ a test for mintty. This is called from the NC_ISATTY macro
+ defined in curses.priv.h
+ */
+int
+_nc_mingw_isatty(int fd)
+{
+ int result = 0;
+
+#ifdef __MING32__
+#define SysISATTY(fd) _isatty(fd)
+#else
+#define SysISATTY(fd) isatty(fd)
+#endif
+ if (SysISATTY(fd)) {
+ result = 1;
+ } else {
+#if WINVER >= 0x0600
+ result = _ismintty(fd, NULL);
+#endif
+ }
+ return result;
+}
+
+/* This is used when running in terminfo mode to discover,
+ whether or not the "terminal" is actually a Windows
+ Console. It's the responsibility of the console to deal
+ with the terminal escape sequences that are sent by
+ terminfo.
+ */
+int
+_nc_mingw_isconsole(int fd)
+{
+ HANDLE hdl = get_handle(fd);
+ int code = 0;
+
+ T((T_CALLED("win32con::_nc_mingw_isconsole(%d)"), fd));
+
+ code = (int) IsConsoleHandle(hdl);
+
+ returnCode(code);
+}
+
+#define TC_PROLOGUE(fd) \
+ SCREEN *sp; \
+ TERMINAL *term = 0; \
+ int code = ERR; \
+ if (_nc_screen_chain == 0) \
+ return 0; \
+ for (each_screen(sp)) { \
+ if (sp->_term && (sp->_term->Filedes == fd)) { \
+ term = sp->_term; \
+ break; \
+ } \
+ } \
+ assert(term != 0)
+
+int
+_nc_mingw_tcsetattr(
+ int fd,
+ int optional_action GCC_UNUSED,
+ const struct termios *arg)
+{
+ TC_PROLOGUE(fd);
+
+ if (_nc_mingw_isconsole(fd)) {
+ DWORD dwFlag = 0;
+ HANDLE ofd = get_handle(fd);
+ if (ofd != INVALID_HANDLE_VALUE) {
+ if (arg) {
+ if (arg->c_lflag & ICANON)
+ dwFlag |= ENABLE_LINE_INPUT;
+ else
+ dwFlag = dwFlag & (DWORD) (~ENABLE_LINE_INPUT);
+
+ if (arg->c_lflag & ECHO)
+ dwFlag = dwFlag | ENABLE_ECHO_INPUT;
+ else
+ dwFlag = dwFlag & (DWORD) (~ENABLE_ECHO_INPUT);
+
+ if (arg->c_iflag & BRKINT)
+ dwFlag |= ENABLE_PROCESSED_INPUT;
+ else
+ dwFlag = dwFlag & (DWORD) (~ENABLE_PROCESSED_INPUT);
+ }
+ dwFlag |= ENABLE_MOUSE_INPUT;
+ SetConsoleMode(ofd, dwFlag);
+ code = OK;
+ }
+ }
+ if (arg)
+ term->Nttyb = *arg;
+
+ return code;
+}
+
+int
+_nc_mingw_tcgetattr(int fd, struct termios *arg)
+{
+ TC_PROLOGUE(fd);
+
+ if (_nc_mingw_isconsole(fd)) {
+ if (arg)
+ *arg = term->Nttyb;
+ }
+ return code;
+}
+
+int
+_nc_mingw_tcflush(int fd, int queue)
+{
+ TC_PROLOGUE(fd);
+ (void) term;
+
+ if (_nc_mingw_isconsole(fd)) {
+ if (queue == TCIFLUSH) {
+ BOOL b = FlushConsoleInputBuffer(GetStdHandle(STD_INPUT_HANDLE));
+ if (!b)
+ return (int) GetLastError();