summaryrefslogtreecommitdiff
path: root/Parser/myreadline.c
diff options
context:
space:
mode:
authorSteve Dower <steve.dower@microsoft.com>2016-08-30 21:22:36 -0700
committerSteve Dower <steve.dower@microsoft.com>2016-08-30 21:22:36 -0700
commit3929499914d47365ae744df312e16da8955c90ac (patch)
tree05b723ba49e1767624ffbe932708bccb681dd702 /Parser/myreadline.c
parentb957b0c2bc467fbf16fbe5ceaf5a289bc62a5442 (diff)
downloadcpython-git-3929499914d47365ae744df312e16da8955c90ac.tar.gz
Issue #1602: Windows console doesn't input or print Unicode (PEP 528)
Closes #17602: Adds a readline implementation for the Windows console
Diffstat (limited to 'Parser/myreadline.c')
-rw-r--r--Parser/myreadline.c113
1 files changed, 113 insertions, 0 deletions
diff --git a/Parser/myreadline.c b/Parser/myreadline.c
index 9522c794e8..c8b92da18a 100644
--- a/Parser/myreadline.c
+++ b/Parser/myreadline.c
@@ -98,6 +98,100 @@ my_fgets(char *buf, int len, FILE *fp)
/* NOTREACHED */
}
+#ifdef MS_WINDOWS
+/* Readline implementation using ReadConsoleW */
+
+extern char _get_console_type(HANDLE handle);
+
+char *
+_PyOS_WindowsConsoleReadline(HANDLE hStdIn)
+{
+ static wchar_t wbuf_local[1024 * 16];
+ const DWORD chunk_size = 1024;
+
+ DWORD n_read, total_read, wbuflen, u8len;
+ wchar_t *wbuf;
+ char *buf = NULL;
+ int err = 0;
+
+ n_read = 0;
+ total_read = 0;
+ wbuf = wbuf_local;
+ wbuflen = sizeof(wbuf_local) / sizeof(wbuf_local[0]) - 1;
+ while (1) {
+ if (!ReadConsoleW(hStdIn, &wbuf[total_read], wbuflen - total_read, &n_read, NULL)) {
+ err = GetLastError();
+ goto exit;
+ }
+ if (n_read == 0) {
+ int s;
+ err = GetLastError();
+ if (err != ERROR_OPERATION_ABORTED)
+ goto exit;
+ err = 0;
+ HANDLE hInterruptEvent = _PyOS_SigintEvent();
+ if (WaitForSingleObjectEx(hInterruptEvent, 100, FALSE)
+ == WAIT_OBJECT_0) {
+ ResetEvent(hInterruptEvent);
+#ifdef WITH_THREAD
+ PyEval_RestoreThread(_PyOS_ReadlineTState);
+#endif
+ s = PyErr_CheckSignals();
+#ifdef WITH_THREAD
+ PyEval_SaveThread();
+#endif
+ if (s < 0)
+ goto exit;
+ }
+ break;
+ }
+
+ total_read += n_read;
+ if (total_read == 0 || wbuf[total_read - 1] == L'\n') {
+ break;
+ }
+ wbuflen += chunk_size;
+ if (wbuf == wbuf_local) {
+ wbuf[total_read] = '\0';
+ wbuf = (wchar_t*)PyMem_RawMalloc(wbuflen * sizeof(wchar_t));
+ if (wbuf)
+ wcscpy_s(wbuf, wbuflen, wbuf_local);
+ }
+ else
+ wbuf = (wchar_t*)PyMem_RawRealloc(wbuf, wbuflen * sizeof(wchar_t));
+ }
+
+ if (wbuf[0] == '\x1a') {
+ buf = PyMem_RawMalloc(1);
+ if (buf)
+ buf[0] = '\0';
+ goto exit;
+ }
+
+ u8len = WideCharToMultiByte(CP_UTF8, 0, wbuf, total_read, NULL, 0, NULL, NULL);
+ buf = PyMem_RawMalloc(u8len + 1);
+ u8len = WideCharToMultiByte(CP_UTF8, 0, wbuf, total_read, buf, u8len, NULL, NULL);
+ buf[u8len] = '\0';
+
+exit:
+ if (wbuf != wbuf_local)
+ PyMem_RawFree(wbuf);
+
+ if (err) {
+#ifdef WITH_THREAD
+ PyEval_RestoreThread(_PyOS_ReadlineTState);
+#endif
+ PyErr_SetFromWindowsErr(err);
+#ifdef WITH_THREAD
+ PyEval_SaveThread();
+#endif
+ }
+
+ return buf;
+}
+
+#endif
+
/* Readline implementation using fgets() */
@@ -107,6 +201,25 @@ PyOS_StdioReadline(FILE *sys_stdin, FILE *sys_stdout, const char *prompt)
size_t n;
char *p, *pr;
+#ifdef MS_WINDOWS
+ if (!Py_LegacyWindowsStdioFlag && sys_stdin == stdin) {
+ HANDLE hStdIn;
+
+ _Py_BEGIN_SUPPRESS_IPH
+ hStdIn = (HANDLE)_get_osfhandle(fileno(sys_stdin));
+ _Py_END_SUPPRESS_IPH
+
+ if (_get_console_type(hStdIn) == 'r') {
+ fflush(sys_stdout);
+ if (prompt)
+ fprintf(stderr, "%s", prompt);
+ fflush(stderr);
+ clearerr(sys_stdin);
+ return _PyOS_WindowsConsoleReadline(hStdIn);
+ }
+ }
+#endif
+
n = 100;
p = (char *)PyMem_RawMalloc(n);
if (p == NULL)