* 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.
This commit is contained in:
@ -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;
|
||||
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)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
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))
|
||||
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);
|
||||
|
Reference in New Issue
Block a user