diff options
author | Ron Yorston <rmy@pobox.com> | 2014-03-19 11:44:05 +0000 |
---|---|---|
committer | Ron Yorston <rmy@pobox.com> | 2014-03-19 11:44:05 +0000 |
commit | 114ddd900acf9de27cc9e651d0af26df3948d34f (patch) | |
tree | 2dacb8e311a33e319a8bd6385efff890487a7ba9 | |
parent | cfb45378f7ecbfa87ad0b61e9463dd83bc5ce615 (diff) | |
download | busybox-w32-114ddd900acf9de27cc9e651d0af26df3948d34f.tar.gz busybox-w32-114ddd900acf9de27cc9e651d0af26df3948d34f.tar.bz2 busybox-w32-114ddd900acf9de27cc9e651d0af26df3948d34f.zip |
Use OEM codepage for console I/O
Windows console applications use different codepages for console I/O
and the rest of the API:
http://msdn.microsoft.com/en-us/goglobal/bb688114.aspx#E2F
Attempt to workaround this by converting characters when they're read from
and written to the console. Not all possible paths are handled.
-rw-r--r-- | include/mingw.h | 4 | ||||
-rw-r--r-- | win32/termios.c | 3 | ||||
-rw-r--r-- | win32/winansi.c | 84 |
3 files changed, 87 insertions, 4 deletions
diff --git a/include/mingw.h b/include/mingw.h index 31795bc40..a1a9f5f30 100644 --- a/include/mingw.h +++ b/include/mingw.h | |||
@@ -140,9 +140,13 @@ int mingw_pclose(FILE *fd); | |||
140 | * ANSI emulation wrappers | 140 | * ANSI emulation wrappers |
141 | */ | 141 | */ |
142 | 142 | ||
143 | int winansi_putchar(int c); | ||
144 | size_t winansi_fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream); | ||
143 | int winansi_fputs(const char *str, FILE *stream); | 145 | int winansi_fputs(const char *str, FILE *stream); |
144 | int winansi_printf(const char *format, ...) __attribute__((format (printf, 1, 2))); | 146 | int winansi_printf(const char *format, ...) __attribute__((format (printf, 1, 2))); |
145 | int winansi_fprintf(FILE *stream, const char *format, ...) __attribute__((format (printf, 2, 3))); | 147 | int winansi_fprintf(FILE *stream, const char *format, ...) __attribute__((format (printf, 2, 3))); |
148 | #define putchar winansi_putchar | ||
149 | #define fwrite winansi_fwrite | ||
146 | #define fputs winansi_fputs | 150 | #define fputs winansi_fputs |
147 | #define printf(...) winansi_printf(__VA_ARGS__) | 151 | #define printf(...) winansi_printf(__VA_ARGS__) |
148 | #define fprintf(...) winansi_fprintf(__VA_ARGS__) | 152 | #define fprintf(...) winansi_fprintf(__VA_ARGS__) |
diff --git a/win32/termios.c b/win32/termios.c index ad6ab117f..40e70309e 100644 --- a/win32/termios.c +++ b/win32/termios.c | |||
@@ -16,6 +16,7 @@ int64_t FAST_FUNC read_key(int fd, char *buf UNUSED_PARAM, int timeout) | |||
16 | INPUT_RECORD record; | 16 | INPUT_RECORD record; |
17 | DWORD nevent_out, mode; | 17 | DWORD nevent_out, mode; |
18 | int ret = -1; | 18 | int ret = -1; |
19 | char *s; | ||
19 | 20 | ||
20 | if (fd != 0) | 21 | if (fd != 0) |
21 | bb_error_msg_and_die("read_key only works on stdin"); | 22 | bb_error_msg_and_die("read_key only works on stdin"); |
@@ -74,6 +75,8 @@ int64_t FAST_FUNC read_key(int fd, char *buf UNUSED_PARAM, int timeout) | |||
74 | } | 75 | } |
75 | continue; | 76 | continue; |
76 | } | 77 | } |
78 | s = &record.Event.KeyEvent.uChar.AsciiChar; | ||
79 | OemToCharBuff(s, s, 1); | ||
77 | ret = record.Event.KeyEvent.uChar.AsciiChar; | 80 | ret = record.Event.KeyEvent.uChar.AsciiChar; |
78 | break; | 81 | break; |
79 | } | 82 | } |
diff --git a/win32/winansi.c b/win32/winansi.c index ea97a70c3..cafad031d 100644 --- a/win32/winansi.c +++ b/win32/winansi.c | |||
@@ -12,6 +12,8 @@ | |||
12 | #undef printf | 12 | #undef printf |
13 | #undef fprintf | 13 | #undef fprintf |
14 | #undef fputs | 14 | #undef fputs |
15 | #undef putchar | ||
16 | #undef fwrite | ||
15 | /* TODO: write */ | 17 | /* TODO: write */ |
16 | 18 | ||
17 | /* | 19 | /* |
@@ -309,10 +311,36 @@ static const char *set_attr(const char *str) | |||
309 | return func + 1; | 311 | return func + 1; |
310 | } | 312 | } |
311 | 313 | ||
312 | static int ansi_emulate(const char *str, FILE *stream) | 314 | static int ansi_emulate(const char *s, FILE *stream) |
313 | { | 315 | { |
314 | int rv = 0; | 316 | int rv = 0; |
315 | const char *pos = str; | 317 | char *pos, *str; |
318 | size_t out_len, cur_len; | ||
319 | static size_t max_len = 0; | ||
320 | static char *mem = NULL; | ||
321 | |||
322 | /* if no special treatment is required output the string as-is */ | ||
323 | for ( pos=s; *pos; ++pos ) { | ||
324 | if ( *pos == '\033' || *pos > 0x7f ) { | ||
325 | break; | ||
326 | } | ||
327 | } | ||
328 | |||
329 | if ( *pos == '\0' ) { | ||
330 | return fputs(s, stream) == EOF ? EOF : strlen(s); | ||
331 | } | ||
332 | |||
333 | /* make a writable copy of the string and retain it for reuse */ | ||
334 | cur_len = strlen(s); | ||
335 | if ( cur_len == 0 || cur_len > max_len ) { | ||
336 | free(mem); | ||
337 | mem = strdup(s); | ||
338 | max_len = cur_len; | ||
339 | } | ||
340 | else { | ||
341 | strcpy(mem, s); | ||
342 | } | ||
343 | pos = str = mem; | ||
316 | 344 | ||
317 | while (*pos) { | 345 | while (*pos) { |
318 | pos = strstr(str, "\033["); | 346 | pos = strstr(str, "\033["); |
@@ -320,7 +348,8 @@ static int ansi_emulate(const char *str, FILE *stream) | |||
320 | size_t len = pos - str; | 348 | size_t len = pos - str; |
321 | 349 | ||
322 | if (len) { | 350 | if (len) { |
323 | size_t out_len = fwrite(str, 1, len, stream); | 351 | CharToOemBuff(str, str, len); |
352 | out_len = fwrite(str, 1, len, stream); | ||
324 | rv += out_len; | 353 | rv += out_len; |
325 | if (out_len < len) | 354 | if (out_len < len) |
326 | return rv; | 355 | return rv; |
@@ -331,11 +360,12 @@ static int ansi_emulate(const char *str, FILE *stream) | |||
331 | 360 | ||
332 | fflush(stream); | 361 | fflush(stream); |
333 | 362 | ||
334 | pos = set_attr(str); | 363 | pos = (char *)set_attr(str); |
335 | rv += pos - str; | 364 | rv += pos - str; |
336 | str = pos; | 365 | str = pos; |
337 | } else { | 366 | } else { |
338 | rv += strlen(str); | 367 | rv += strlen(str); |
368 | CharToOem(str, str); | ||
339 | fputs(str, stream); | 369 | fputs(str, stream); |
340 | return rv; | 370 | return rv; |
341 | } | 371 | } |
@@ -343,6 +373,52 @@ static int ansi_emulate(const char *str, FILE *stream) | |||
343 | return rv; | 373 | return rv; |
344 | } | 374 | } |
345 | 375 | ||
376 | int winansi_putchar(int c) | ||
377 | { | ||
378 | char t = c; | ||
379 | char *s = &t; | ||
380 | |||
381 | if (!isatty(0)) | ||
382 | return putchar(c); | ||
383 | |||
384 | init(); | ||
385 | |||
386 | if (!console) | ||
387 | return putchar(c); | ||
388 | |||
389 | CharToOemBuff(s, s, 1); | ||
390 | return putchar(t) == EOF ? EOF : c; | ||
391 | } | ||
392 | |||
393 | size_t winansi_fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream) | ||
394 | { | ||
395 | size_t lsize, lmemb; | ||
396 | char *str; | ||
397 | int rv; | ||
398 | |||
399 | lsize = MIN(size, nmemb); | ||
400 | lmemb = MAX(size, nmemb); | ||
401 | if (lsize != 1) | ||
402 | return fwrite(ptr, size, nmemb, stream); | ||
403 | |||
404 | if (!isatty(fileno(stream))) | ||
405 | return fwrite(ptr, size, nmemb, stream); | ||
406 | |||
407 | init(); | ||
408 | |||
409 | if (!console) | ||
410 | return fwrite(ptr, size, nmemb, stream); | ||
411 | |||
412 | str = xmalloc(lmemb+1); | ||
413 | memcpy(str, ptr, lmemb); | ||
414 | str[lmemb] = '\0'; | ||
415 | |||
416 | rv = ansi_emulate(str, stream); | ||
417 | free(str); | ||
418 | |||
419 | return rv; | ||
420 | } | ||
421 | |||
346 | int winansi_fputs(const char *str, FILE *stream) | 422 | int winansi_fputs(const char *str, FILE *stream) |
347 | { | 423 | { |
348 | int rv; | 424 | int rv; |