From 93a63809f9146e39a1c36bdccdfb8ef3b7046c98 Mon Sep 17 00:00:00 2001 From: Ron Yorston Date: Sat, 2 Feb 2019 15:57:59 +0000 Subject: win32: add support for the euro currency symbol The euro currency symbol was added to some OEM code pages. See: https://www.aivosto.com/articles/charsets-codepages-dos.html Add a configuration option (enabled by default) to support this. When enabled: - The read_key() function requests wide character key events. This allows the euro symbol to be entered regardless of the console OEM code page, though it needs to be available in the ANSI code page. - Conversions between OEM and ANSI code pages in winansi.c are modified to work around a bug in the Microsoft routines. - If the OEM code page is 850 when BusyBox starts it's changed to 858. This is the only currently supported OEM code page. Also, the shell read builtin is modified to use read_key() whenever input is being taken from the console. --- Config.in | 9 +++++++ include/mingw.h | 1 + libbb/appletlib.c | 3 +++ shell/shell_common.c | 3 +-- win32/termios.c | 21 ++++++++++++++++ win32/winansi.c | 68 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 103 insertions(+), 2 deletions(-) diff --git a/Config.in b/Config.in index 5bd98aa23..0318a6aff 100644 --- a/Config.in +++ b/Config.in @@ -454,6 +454,15 @@ config FEATURE_ICON_ALL endchoice +config FEATURE_EURO + bool "Support the euro currency symbol (0.5 kb)" + default y + depends on PLATFORM_MINGW32 + help + Support the entry and display of the euro currency symbol. This + requires the OEM code page to be 858. If the OEM code page of + the console is 850 when BusyBox starts it's changed to 858. + comment 'Build Options' config STATIC diff --git a/include/mingw.h b/include/mingw.h index 4077c8d44..4655fe511 100644 --- a/include/mingw.h +++ b/include/mingw.h @@ -485,6 +485,7 @@ void qsort_string_vector_case(char **sv, unsigned count) FAST_FUNC; const char *get_busybox_exec_path(void); void init_winsock(void); +void init_codepage(void); int has_bat_suffix(const char *p); int has_exe_suffix(const char *p); diff --git a/libbb/appletlib.c b/libbb/appletlib.c index 8efb1754a..921883475 100644 --- a/libbb/appletlib.c +++ b/libbb/appletlib.c @@ -1221,6 +1221,9 @@ int main(int argc UNUSED_PARAM, char **argv) break; } } +# if ENABLE_FEATURE_EURO + init_codepage(); +# endif #endif #if defined(__MINGW64_VERSION_MAJOR) diff --git a/shell/shell_common.c b/shell/shell_common.c index 23e5f1c25..e7c07e6a9 100644 --- a/shell/shell_common.c +++ b/shell/shell_common.c @@ -235,8 +235,7 @@ shell_builtin_read(struct builtin_read_params *params) } #else errno = 0; - if (isatty(fd) && (params->opt_n || params->opt_d || params->opt_t || - (read_flags & BUILTIN_READ_SILENT))) { + if (isatty(fd)) { int64_t key; key = read_key(fd, NULL, timeout); diff --git a/win32/termios.c b/win32/termios.c index 7a107c5bd..fe6f0c546 100644 --- a/win32/termios.c +++ b/win32/termios.c @@ -6,7 +6,12 @@ int64_t FAST_FUNC read_key(int fd, char *buf UNUSED_PARAM, int timeout) INPUT_RECORD record; DWORD nevent_out, mode; int ret = -1; +#if ENABLE_FEATURE_EURO + wchar_t uchar; + char achar; +#else char *s; +#endif int alt_pressed = FALSE; DWORD state; @@ -22,7 +27,11 @@ int64_t FAST_FUNC read_key(int fd, char *buf UNUSED_PARAM, int timeout) if (WaitForSingleObject(cin, timeout) != WAIT_OBJECT_0) goto done; } +#if ENABLE_FEATURE_EURO + if (!ReadConsoleInputW(cin, &record, 1, &nevent_out)) +#else if (!ReadConsoleInput(cin, &record, 1, &nevent_out)) +#endif goto done; if (record.EventType != KEY_EVENT) @@ -40,7 +49,11 @@ int64_t FAST_FUNC read_key(int fd, char *buf UNUSED_PARAM, int timeout) alt_pressed = ((state & LEFT_ALT_PRESSED) != 0); } +#if ENABLE_FEATURE_EURO + if (!record.Event.KeyEvent.uChar.UnicodeChar) { +#else if (!record.Event.KeyEvent.uChar.AsciiChar) { +#endif if (alt_pressed) { switch (record.Event.KeyEvent.wVirtualKeyCode) { case VK_MENU: @@ -91,11 +104,19 @@ int64_t FAST_FUNC read_key(int fd, char *buf UNUSED_PARAM, int timeout) } continue; } +#if ENABLE_FEATURE_EURO + uchar = record.Event.KeyEvent.uChar.UnicodeChar; + achar = uchar & 0x7f; + if (achar != uchar) + WideCharToMultiByte(CP_ACP, 0, &uchar, 1, &achar, 1, NULL, NULL); + ret = achar; +#else if ( (record.Event.KeyEvent.uChar.AsciiChar & 0x80) == 0x80 ) { s = &record.Event.KeyEvent.uChar.AsciiChar; OemToCharBuff(s, s, 1); } ret = record.Event.KeyEvent.uChar.AsciiChar; +#endif break; } done: diff --git a/win32/winansi.c b/win32/winansi.c index 9e7d10a56..e0ae38a91 100644 --- a/win32/winansi.c +++ b/win32/winansi.c @@ -391,6 +391,74 @@ static const char *set_attr(const char *str) return func + 1; } +#if ENABLE_FEATURE_EURO +void init_codepage(void) +{ + if (GetConsoleCP() == 850 && GetConsoleOutputCP() == 850) { + SetConsoleCP(858); + SetConsoleOutputCP(858); + } +} + +static BOOL winansi_CharToOemBuff(LPCSTR s, LPSTR d, DWORD len) +{ + WCHAR *buf; + int i; + + if (!s || !d) + return FALSE; + + buf = xmalloc(len*sizeof(WCHAR)); + MultiByteToWideChar(CP_ACP, 0, s, len, buf, len); + WideCharToMultiByte(CP_OEMCP, 0, buf, len, d, len, NULL, NULL); + if (GetConsoleOutputCP() == 858) { + for (i=0; i