diff options
author | Corinna Vinschen <corinna@vinschen.de> | 2008-02-05 17:37:10 +0000 |
---|---|---|
committer | Corinna Vinschen <corinna@vinschen.de> | 2008-02-05 17:37:10 +0000 |
commit | a7197550f31c8db32c671bc43401c1b90c78ed74 (patch) | |
tree | 4250d45f44ad6d7a7fa5d1e4da95842d04097530 /winsup/cygwin/fhandler_console.cc | |
parent | 58d470721bb00194763cc7cb32abac80ddc9253a (diff) | |
download | cygnal-a7197550f31c8db32c671bc43401c1b90c78ed74.tar.gz cygnal-a7197550f31c8db32c671bc43401c1b90c78ed74.tar.bz2 cygnal-a7197550f31c8db32c671bc43401c1b90c78ed74.zip |
* autoload.cc (CharToOemA): Remove.
(CharNextExA): Define.
* environ.cc (codepage_init): Un-static. Set active_codepage to
active codepage. Default to ansi regardless of buf pointer.
* fhandler.h (dev_console::get_console_cp): New method.
(dev_console::con_to_str): Change declaration according to new
implementation.
(dev_console::str_to_con): Ditto.
* fhandler_console.cc (cp_convert): Remove.
(dev_console::con_to_str): Redefine to take WCHAR as incoming console
char.
(dev_console::get_console_cp): Return correct codepage according to
alternate_charset_active setting.
(dev_console::str_to_con): Redefine to create WCHAR buffer for console
output.
(fhandler_console::read): Read console input as WCHARs.
(base_chars): Fix typo in comment.
(fhandler_console::char_command): Save and restore console output
buffer using UNICODE functions.
(fhandler_console::write_normal): Convert to write output in UNICODE.
Use CharNextExA to recognize multibyte characters in input. Workaround
problem with UTF-8 and MultiByteToWideChar. Simplify the loop for
printing "normal" characters.
* strfuncs.cc (active_codepage): New variable to store active codepage.
(get_cp): Call codepage_init() if active_codepage is uninitialized.
Just return active_codepage.
(is_cp_multibyte): New function.
* winsup.h (active_codepage): Declare.
(codepage_init): Declare.
(is_cp_multibyte): Declare.
Diffstat (limited to 'winsup/cygwin/fhandler_console.cc')
-rw-r--r-- | winsup/cygwin/fhandler_console.cc | 132 |
1 files changed, 61 insertions, 71 deletions
diff --git a/winsup/cygwin/fhandler_console.cc b/winsup/cygwin/fhandler_console.cc index 9bc6b0fd2..f23bacb3e 100644 --- a/winsup/cygwin/fhandler_console.cc +++ b/winsup/cygwin/fhandler_console.cc @@ -35,28 +35,6 @@ details. */ #define CONVERT_LIMIT 16384 -static bool -cp_convert (UINT destcp, char *dest, UINT srccp, const char *src, DWORD size) -{ - if (!size) - /* no action */; - else if (destcp == srccp) - { - if (dest != src) - memcpy (dest, src, size); - } - else - { - WCHAR wbuffer[CONVERT_LIMIT]; /* same size as the maximum input, s.b. */ - if (!MultiByteToWideChar (srccp, 0, src, size, wbuffer, sizeof (wbuffer))) - return false; - if (!WideCharToMultiByte (destcp, 0, wbuffer, size, dest, size, - NULL, NULL)) - return false; - } - return true; -} - /* * Scroll the screen context. * x1, y1 - ul corner @@ -175,21 +153,21 @@ set_console_state_for_spawn (bool iscyg) cached, because a program or the user can change these values at any time. */ inline bool -dev_console::con_to_str (char *d, const char *s, DWORD sz) +dev_console::con_to_str (char *d, int dlen, WCHAR w) { - return cp_convert (get_cp (), d, GetConsoleCP (), s, sz); + return !!sys_wcstombs (d, dlen, &w, 1); } -inline bool -dev_console::str_to_con (char *d, const char *s, DWORD sz) +inline UINT +dev_console::get_console_cp () { - if (alternate_charset_active) - { - /* no translation when alternate charset is active */ - memcpy(d, s, sz); - return true; - } - return cp_convert (GetConsoleOutputCP (), d, get_cp (), s, sz); + return alternate_charset_active ? GetConsoleOutputCP () : get_cp (); +} + +inline DWORD +dev_console::str_to_con (PWCHAR d, const char *s, DWORD sz) +{ + return MultiByteToWideChar (get_console_cp (), 0, s, sz, d, CONVERT_LIMIT); } bool @@ -292,7 +270,7 @@ fhandler_console::read (void *pv, size_t& buflen) INPUT_RECORD input_rec; const char *toadd = NULL; - if (!ReadConsoleInput (h, &input_rec, 1, &nread)) + if (!ReadConsoleInputW (h, &input_rec, 1, &nread)) { syscall_printf ("ReadConsoleInput failed, %E"); goto err; /* seems to be failure */ @@ -376,18 +354,14 @@ fhandler_console::read (void *pv, size_t& buflen) } else { - tmp[1] = ich; - /* Need this check since US code page seems to have a bug when - converting a CTRL-U. */ - if ((unsigned char) ich > 0x7f) - dev_state->con_to_str (tmp + 1, tmp + 1, 1); + dev_state->con_to_str (tmp + 1, 59, wch); /* Determine if the keystroke is modified by META. The tricky part is to distinguish whether the right Alt key should be recognized as Alt, or as AltGr. */ bool meta; meta = (control_key_state & ALT_PRESSED) != 0 && ((control_key_state & CTRL_PRESSED) == 0 - || ((signed char) ich >= 0 && ich <= 0x1f || ich == 0x7f)); + || (wch <= 0x1f || wch == 0x7f)); if (!meta) toadd = tmp + 1; else if (dev_state->metabit) @@ -1081,7 +1055,7 @@ static const char base_chars[256] = /*10 11 12 13 14 15 16 17 */ NOR, NOR, ERR, ERR, ERR, ERR, ERR, ERR, /*18 19 1A 1B 1C 1D 1E 1F */ NOR, NOR, ERR, ESC, ERR, ERR, ERR, ERR, /* ! " # $ % & ' */ NOR, NOR, NOR, NOR, NOR, NOR, NOR, NOR, -/*() * + , - . / */ NOR, NOR, NOR, NOR, NOR, NOR, NOR, NOR, +/*( ) * + , - . / */ NOR, NOR, NOR, NOR, NOR, NOR, NOR, NOR, /*0 1 2 3 4 5 6 7 */ NOR, NOR, NOR, NOR, NOR, NOR, NOR, NOR, /*8 9 : ; < = > ? */ NOR, NOR, NOR, NOR, NOR, NOR, NOR, NOR, /*@ A B C D E F G */ NOR, NOR, NOR, NOR, NOR, NOR, NOR, NOR, @@ -1243,7 +1217,7 @@ fhandler_console::char_command (char c) dev_state->savebuf = (PCHAR_INFO) cmalloc_abort (HEAP_1_BUF, sizeof (CHAR_INFO) * dev_state->savebufsiz.X * dev_state->savebufsiz.Y); - ReadConsoleOutputA (get_output_handle (), dev_state->savebuf, + ReadConsoleOutputW (get_output_handle (), dev_state->savebuf, dev_state->savebufsiz, cob, &now.srWindow); } else /* restore */ @@ -1257,7 +1231,7 @@ fhandler_console::char_command (char c) if (!dev_state->savebuf) break; - WriteConsoleOutputA (get_output_handle (), dev_state->savebuf, + WriteConsoleOutputW (get_output_handle (), dev_state->savebuf, dev_state->savebufsiz, cob, &now.srWindow); cfree (dev_state->savebuf); @@ -1457,50 +1431,66 @@ fhandler_console::write_normal (const unsigned char *src, { /* Scan forward to see what a char which needs special treatment */ DWORD done; - const unsigned char *found = src; + unsigned char *found = (unsigned char *) src; + UINT cp = dev_state->get_console_cp (); + bool mb = is_cp_multibyte (cp); - while (found < end) + while (found < end + && found - src < CONVERT_LIMIT + && base_chars[*found] == NOR) { - char ch = base_chars[*found]; - if (ch != NOR) - break; - found++; + if (mb && *found && *found >= 0x80) + { + unsigned char *nfound = (unsigned char *) + CharNextExA (cp, (const CHAR *) found, 0); + /* Sanity check for UTF-8 to workaround the problem in + MultiByteToWideChar, that it's not capable of using replacement + characters for invalid source chars in the given codepage. */ + if (nfound == found + 1 && cp == CP_UTF8) + *found++ = '?'; + else + found = nfound; + } + else + ++found; } /* Print all the base ones out */ if (found != src) { DWORD len = found - src; - do + DWORD buf_len; + PWCHAR buf = (PWCHAR) alloca (CONVERT_LIMIT * sizeof (WCHAR)); + + buf_len = dev_state->str_to_con (buf, (const char *) src, len); + if (!buf_len) { - DWORD buf_len; - char buf[CONVERT_LIMIT]; - done = buf_len = min (sizeof (buf), len); - if (!dev_state->str_to_con (buf, (const char *) src, buf_len)) - { - debug_printf ("conversion error, handle %p", - get_output_handle ()); - __seterrno (); - return 0; - } + debug_printf ("conversion error, handle %p", + get_output_handle ()); + __seterrno (); + return 0; + } - if (dev_state->insert_mode) - { - int x, y; - cursor_get (&x, &y); - scroll_screen (x, y, -1, y, x + buf_len, y); - } + if (dev_state->insert_mode) + { + int x, y; + cursor_get (&x, &y); + scroll_screen (x, y, -1, y, x + buf_len, y); + } - if (!WriteFile (get_output_handle (), buf, buf_len, &done, 0)) + do + { + if (!WriteConsoleW (get_output_handle (), buf, buf_len, &done, 0)) { debug_printf ("write failed, handle %p", get_output_handle ()); __seterrno (); return 0; } - len -= done; - src += done; + buf_len -= done; + buf += done; } - while (len > 0); + while (buf_len > 0); + src = found; } if (src < end) @@ -1519,7 +1509,7 @@ fhandler_console::write_normal (const unsigned char *src, if (y >= srBottom) { if (y >= dev_state->info.winBottom && !dev_state->scroll_region.Top) - WriteFile (get_output_handle (), "\n", 1, &done, 0); + WriteConsoleW (get_output_handle (), L"\n", 1, &done, 0); else { scroll_screen (0, srTop + 1, -1, srBottom, 0, srTop); |