aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRon Yorston <rmy@pobox.com>2019-02-02 15:57:59 +0000
committerRon Yorston <rmy@pobox.com>2019-02-02 16:21:12 +0000
commit93a63809f9146e39a1c36bdccdfb8ef3b7046c98 (patch)
tree41adedb1f386dce9c163ff1bc634a725e8e1c8b8
parent0e26e2ff3b87f8db635d3c7dca23f441a3961fd2 (diff)
downloadbusybox-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.in9
-rw-r--r--include/mingw.h1
-rw-r--r--libbb/appletlib.c3
-rw-r--r--shell/shell_common.c3
-rw-r--r--win32/termios.c21
-rw-r--r--win32/winansi.c68
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
454 454
455endchoice 455endchoice
456 456
457config 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
457comment 'Build Options' 466comment 'Build Options'
458 467
459config STATIC 468config 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
486const char *get_busybox_exec_path(void); 486const char *get_busybox_exec_path(void);
487void init_winsock(void); 487void init_winsock(void);
488void init_codepage(void);
488 489
489int has_bat_suffix(const char *p); 490int has_bat_suffix(const char *p);
490int has_exe_suffix(const char *p); 491int 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
395void init_codepage(void)
396{
397 if (GetConsoleCP() == 850 && GetConsoleOutputCP() == 850) {
398 SetConsoleCP(858);
399 SetConsoleOutputCP(858);
400 }
401}
402
403static 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
425static 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
432static 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
394static int ansi_emulate(const char *s, FILE *stream) 462static int ansi_emulate(const char *s, FILE *stream)
395{ 463{
396 int rv = 0; 464 int rv = 0;