diff options
author | Ron Yorston <rmy@pobox.com> | 2019-02-02 15:57:59 +0000 |
---|---|---|
committer | Ron Yorston <rmy@pobox.com> | 2019-02-02 16:21:12 +0000 |
commit | 93a63809f9146e39a1c36bdccdfb8ef3b7046c98 (patch) | |
tree | 41adedb1f386dce9c163ff1bc634a725e8e1c8b8 | |
parent | 0e26e2ff3b87f8db635d3c7dca23f441a3961fd2 (diff) | |
download | busybox-w32-93a63809f9146e39a1c36bdccdfb8ef3b7046c98.tar.gz busybox-w32-93a63809f9146e39a1c36bdccdfb8ef3b7046c98.tar.bz2 busybox-w32-93a63809f9146e39a1c36bdccdfb8ef3b7046c98.zip |
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.
-rw-r--r-- | Config.in | 9 | ||||
-rw-r--r-- | include/mingw.h | 1 | ||||
-rw-r--r-- | libbb/appletlib.c | 3 | ||||
-rw-r--r-- | shell/shell_common.c | 3 | ||||
-rw-r--r-- | win32/termios.c | 21 | ||||
-rw-r--r-- | win32/winansi.c | 68 |
6 files changed, 103 insertions, 2 deletions
@@ -454,6 +454,15 @@ config FEATURE_ICON_ALL | |||
454 | 454 | ||
455 | endchoice | 455 | endchoice |
456 | 456 | ||
457 | config FEATURE_EURO | ||
458 | bool "Support the euro currency symbol (0.5 kb)" | ||
459 | default y | ||
460 | depends on PLATFORM_MINGW32 | ||
461 | help | ||
462 | Support the entry and display of the euro currency symbol. This | ||
463 | requires the OEM code page to be 858. If the OEM code page of | ||
464 | the console is 850 when BusyBox starts it's changed to 858. | ||
465 | |||
457 | comment 'Build Options' | 466 | comment 'Build Options' |
458 | 467 | ||
459 | config STATIC | 468 | 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; | |||
485 | 485 | ||
486 | const char *get_busybox_exec_path(void); | 486 | const char *get_busybox_exec_path(void); |
487 | void init_winsock(void); | 487 | void init_winsock(void); |
488 | void init_codepage(void); | ||
488 | 489 | ||
489 | int has_bat_suffix(const char *p); | 490 | int has_bat_suffix(const char *p); |
490 | int has_exe_suffix(const char *p); | 491 | 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) | |||
1221 | break; | 1221 | break; |
1222 | } | 1222 | } |
1223 | } | 1223 | } |
1224 | # if ENABLE_FEATURE_EURO | ||
1225 | init_codepage(); | ||
1226 | # endif | ||
1224 | #endif | 1227 | #endif |
1225 | 1228 | ||
1226 | #if defined(__MINGW64_VERSION_MAJOR) | 1229 | #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) | |||
235 | } | 235 | } |
236 | #else | 236 | #else |
237 | errno = 0; | 237 | errno = 0; |
238 | if (isatty(fd) && (params->opt_n || params->opt_d || params->opt_t || | 238 | if (isatty(fd)) { |
239 | (read_flags & BUILTIN_READ_SILENT))) { | ||
240 | int64_t key; | 239 | int64_t key; |
241 | 240 | ||
242 | key = read_key(fd, NULL, timeout); | 241 | 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) | |||
6 | INPUT_RECORD record; | 6 | INPUT_RECORD record; |
7 | DWORD nevent_out, mode; | 7 | DWORD nevent_out, mode; |
8 | int ret = -1; | 8 | int ret = -1; |
9 | #if ENABLE_FEATURE_EURO | ||
10 | wchar_t uchar; | ||
11 | char achar; | ||
12 | #else | ||
9 | char *s; | 13 | char *s; |
14 | #endif | ||
10 | int alt_pressed = FALSE; | 15 | int alt_pressed = FALSE; |
11 | DWORD state; | 16 | DWORD state; |
12 | 17 | ||
@@ -22,7 +27,11 @@ int64_t FAST_FUNC read_key(int fd, char *buf UNUSED_PARAM, int timeout) | |||
22 | if (WaitForSingleObject(cin, timeout) != WAIT_OBJECT_0) | 27 | if (WaitForSingleObject(cin, timeout) != WAIT_OBJECT_0) |
23 | goto done; | 28 | goto done; |
24 | } | 29 | } |
30 | #if ENABLE_FEATURE_EURO | ||
31 | if (!ReadConsoleInputW(cin, &record, 1, &nevent_out)) | ||
32 | #else | ||
25 | if (!ReadConsoleInput(cin, &record, 1, &nevent_out)) | 33 | if (!ReadConsoleInput(cin, &record, 1, &nevent_out)) |
34 | #endif | ||
26 | goto done; | 35 | goto done; |
27 | 36 | ||
28 | if (record.EventType != KEY_EVENT) | 37 | if (record.EventType != KEY_EVENT) |
@@ -40,7 +49,11 @@ int64_t FAST_FUNC read_key(int fd, char *buf UNUSED_PARAM, int timeout) | |||
40 | alt_pressed = ((state & LEFT_ALT_PRESSED) != 0); | 49 | alt_pressed = ((state & LEFT_ALT_PRESSED) != 0); |
41 | } | 50 | } |
42 | 51 | ||
52 | #if ENABLE_FEATURE_EURO | ||
53 | if (!record.Event.KeyEvent.uChar.UnicodeChar) { | ||
54 | #else | ||
43 | if (!record.Event.KeyEvent.uChar.AsciiChar) { | 55 | if (!record.Event.KeyEvent.uChar.AsciiChar) { |
56 | #endif | ||
44 | if (alt_pressed) { | 57 | if (alt_pressed) { |
45 | switch (record.Event.KeyEvent.wVirtualKeyCode) { | 58 | switch (record.Event.KeyEvent.wVirtualKeyCode) { |
46 | case VK_MENU: | 59 | case VK_MENU: |
@@ -91,11 +104,19 @@ int64_t FAST_FUNC read_key(int fd, char *buf UNUSED_PARAM, int timeout) | |||
91 | } | 104 | } |
92 | continue; | 105 | continue; |
93 | } | 106 | } |
107 | #if ENABLE_FEATURE_EURO | ||
108 | uchar = record.Event.KeyEvent.uChar.UnicodeChar; | ||
109 | achar = uchar & 0x7f; | ||
110 | if (achar != uchar) | ||
111 | WideCharToMultiByte(CP_ACP, 0, &uchar, 1, &achar, 1, NULL, NULL); | ||
112 | ret = achar; | ||
113 | #else | ||
94 | if ( (record.Event.KeyEvent.uChar.AsciiChar & 0x80) == 0x80 ) { | 114 | if ( (record.Event.KeyEvent.uChar.AsciiChar & 0x80) == 0x80 ) { |
95 | s = &record.Event.KeyEvent.uChar.AsciiChar; | 115 | s = &record.Event.KeyEvent.uChar.AsciiChar; |
96 | OemToCharBuff(s, s, 1); | 116 | OemToCharBuff(s, s, 1); |
97 | } | 117 | } |
98 | ret = record.Event.KeyEvent.uChar.AsciiChar; | 118 | ret = record.Event.KeyEvent.uChar.AsciiChar; |
119 | #endif | ||
99 | break; | 120 | break; |
100 | } | 121 | } |
101 | done: | 122 | 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) | |||
391 | return func + 1; | 391 | return func + 1; |
392 | } | 392 | } |
393 | 393 | ||
394 | #if ENABLE_FEATURE_EURO | ||
395 | void init_codepage(void) | ||
396 | { | ||
397 | if (GetConsoleCP() == 850 && GetConsoleOutputCP() == 850) { | ||
398 | SetConsoleCP(858); | ||
399 | SetConsoleOutputCP(858); | ||
400 | } | ||
401 | } | ||
402 | |||
403 | static BOOL winansi_CharToOemBuff(LPCSTR s, LPSTR d, DWORD len) | ||
404 | { | ||
405 | WCHAR *buf; | ||
406 | int i; | ||
407 | |||
408 | if (!s || !d) | ||
409 | return FALSE; | ||
410 | |||
411 | buf = xmalloc(len*sizeof(WCHAR)); | ||
412 | MultiByteToWideChar(CP_ACP, 0, s, len, buf, len); | ||
413 | WideCharToMultiByte(CP_OEMCP, 0, buf, len, d, len, NULL, NULL); | ||
414 | if (GetConsoleOutputCP() == 858) { | ||
415 | for (i=0; i<len; ++i) { | ||
416 | if (buf[i] == 0x20ac) { | ||
417 | d[i] = 0xd5; | ||
418 | } | ||
419 | } | ||
420 | } | ||
421 | free(buf); | ||
422 | return TRUE; | ||
423 | } | ||
424 | |||
425 | static BOOL winansi_CharToOem(LPCSTR s, LPSTR d) | ||
426 | { | ||
427 | if (!s || !d) | ||
428 | return FALSE; | ||
429 | return winansi_CharToOemBuff(s, d, strlen(s)+1); | ||
430 | } | ||
431 | |||
432 | static BOOL winansi_OemToCharBuff(LPCSTR s, LPSTR d, DWORD len) | ||
433 | { | ||
434 | WCHAR *buf; | ||
435 | int i; | ||
436 | |||
437 | if (!s || !d) | ||
438 | return FALSE; | ||
439 | |||
440 | buf = xmalloc(len*sizeof(WCHAR)); | ||
441 | MultiByteToWideChar(CP_OEMCP, 0, s, len, buf, len); | ||
442 | WideCharToMultiByte(CP_ACP, 0, buf, len, d, len, NULL, NULL); | ||
443 | if (GetConsoleOutputCP() == 858) { | ||
444 | for (i=0; i<len; ++i) { | ||
445 | if (buf[i] == 0x0131) { | ||
446 | d[i] = 0x80; | ||
447 | } | ||
448 | } | ||
449 | } | ||
450 | free(buf); | ||
451 | return TRUE; | ||
452 | } | ||
453 | |||
454 | # undef CharToOemBuff | ||
455 | # undef CharToOem | ||
456 | # undef OemToCharBuff | ||
457 | # define CharToOemBuff winansi_CharToOemBuff | ||
458 | # define CharToOem winansi_CharToOem | ||
459 | # define OemToCharBuff winansi_OemToCharBuff | ||
460 | #endif | ||
461 | |||
394 | static int ansi_emulate(const char *s, FILE *stream) | 462 | static int ansi_emulate(const char *s, FILE *stream) |
395 | { | 463 | { |
396 | int rv = 0; | 464 | int rv = 0; |