aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--common/ttyio.c104
1 files changed, 73 insertions, 31 deletions
diff --git a/common/ttyio.c b/common/ttyio.c
index b19c3988c..eb6583436 100644
--- a/common/ttyio.c
+++ b/common/ttyio.c
@@ -221,6 +221,30 @@ tty_no_terminal(int onoff)
return old;
}
+
+#ifdef HAVE_W32_SYSTEM
+/* Write the UTF-8 encoded STRING to the console. */
+static void
+w32_write_console (const char *string)
+{
+ wchar_t *wstring;
+ DWORD n, nwritten;
+
+ wstring = utf8_to_wchar (string);
+ if (!wstring)
+ log_fatal ("w32_write_console failed: %s", strerror (errno));
+ n = wcslen (wstring);
+
+ if (!WriteConsoleW (con.out, wstring, n, &nwritten, NULL))
+ log_fatal ("WriteConsole failed: %s", w32_strerror (-1));
+ if (n != nwritten)
+ log_fatal ("WriteConsole failed: %lu != %lu\n",
+ (unsigned long)n, (unsigned long)nwritten);
+ last_prompt_len += n;
+}
+#endif /*HAVE_W32_SYSTEM*/
+
+
void
tty_printf (const char *fmt, ... )
{
@@ -237,18 +261,11 @@ tty_printf (const char *fmt, ... )
#ifdef HAVE_W32_SYSTEM
{
char *buf = NULL;
- int n;
- DWORD nwritten;
- n = vasprintf(&buf, fmt, arg_ptr);
+ vasprintf(&buf, fmt, arg_ptr);
if (!buf)
log_bug ("vasprintf() failed\n");
-
- if (!WriteConsoleA (con.out, buf, n, &nwritten, NULL))
- log_fatal ("WriteConsole failed: rc=%d", (int)GetLastError());
- if (n != nwritten)
- log_fatal ("WriteConsole failed: %d != %d\n", n, (int)nwritten);
- last_prompt_len += n;
+ w32_write_console (buf);
xfree (buf);
}
#else /* Unix */
@@ -285,18 +302,11 @@ tty_fprintf (estream_t fp, const char *fmt, ... )
#ifdef HAVE_W32_SYSTEM
{
char *buf = NULL;
- int n;
- DWORD nwritten;
- n = vasprintf (&buf, fmt, arg_ptr);
+ vasprintf (&buf, fmt, arg_ptr);
if (!buf)
log_bug ("vasprintf() failed\n");
-
- if (!WriteConsoleA (con.out, buf, n, &nwritten, NULL))
- log_fatal ("WriteConsole failed: rc=%d", (int)GetLastError());
- if (n != nwritten)
- log_fatal ("WriteConsole failed: %d != %d\n", n, (int)nwritten);
- last_prompt_len += n;
+ w32_write_console (buf);
xfree (buf);
}
#else /* Unix */
@@ -410,7 +420,12 @@ do_get (const char *prompt, int hidden)
int n; /* Allocated size of BUF. */
int i; /* Number of bytes in BUF. */
int c;
+#ifdef HAVE_W32_SYSTEM
+ char *utf8buf;
+ int errcount = 0;
+#else
byte cbuf[1];
+#endif
if (batchmode)
{
@@ -436,31 +451,58 @@ do_get (const char *prompt, int hidden)
if (hidden)
SetConsoleMode(con.in, HID_INPMODE );
+ utf8buf = NULL;
for (;;)
{
DWORD nread;
+ wchar_t wbuf[2];
+ const unsigned char *s;
- if (!ReadConsoleA( con.in, cbuf, 1, &nread, NULL))
- log_fatal ("ReadConsole failed: rc=%d", (int)GetLastError ());
+ if (!ReadConsoleW (con.in, wbuf, 1, &nread, NULL))
+ log_fatal ("ReadConsole failed: %s", w32_strerror (-1));
if (!nread)
continue;
- if (*cbuf == '\n')
- break;
+ wbuf[1] = 0;
+ xfree (utf8buf);
+ utf8buf = wchar_to_utf8 (wbuf);
+ if (!utf8buf)
+ {
+ log_info ("wchar_to_utf8 failed: %s\n", strerror (errno));
+ if (++errcount > 10)
+ log_fatal (_("too many errors; giving up\n"));
+ continue;
+ }
+ if (*utf8buf == '\n')
+ {
+ if (utf8buf[1])
+ {
+ log_info ("ReadConsole returned more than requested"
+ " (0x0a,0x%02x)\n", utf8buf[1]);
+ if (++errcount > 10)
+ log_fatal (_("too many errors; giving up\n"));
+ }
+ break;
+ }
if (!hidden)
last_prompt_len++;
- c = *cbuf;
- if (c == '\t')
- c = ' ';
- else if ( (c >= 0 && c <= 0x1f) || c == 0x7f)
- continue;
- if (!(i < n-1))
+
+ for (s=utf8buf; *s; s++)
{
- n += 50;
- buf = xrealloc (buf, n);
+ c = *s;
+ if (c == '\t')
+ c = ' '; /* Map tab to a space. */
+ else if ((c >= 0 && c <= 0x1f) || c == 0x7f)
+ continue; /* Remove control characters. */
+ if (!(i < n-1))
+ {
+ n += 50;
+ buf = xrealloc (buf, n);
+ }
+ buf[i++] = c;
}
- buf[i++] = c;
}
+ xfree (utf8buf);
if (hidden)
SetConsoleMode(con.in, DEF_INPMODE );