From 114ddd900acf9de27cc9e651d0af26df3948d34f Mon Sep 17 00:00:00 2001 From: Ron Yorston Date: Wed, 19 Mar 2014 11:44:05 +0000 Subject: 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. --- include/mingw.h | 4 +++ win32/termios.c | 3 +++ 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); * ANSI emulation wrappers */ +int winansi_putchar(int c); +size_t winansi_fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream); int winansi_fputs(const char *str, FILE *stream); int winansi_printf(const char *format, ...) __attribute__((format (printf, 1, 2))); int winansi_fprintf(FILE *stream, const char *format, ...) __attribute__((format (printf, 2, 3))); +#define putchar winansi_putchar +#define fwrite winansi_fwrite #define fputs winansi_fputs #define printf(...) winansi_printf(__VA_ARGS__) #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) INPUT_RECORD record; DWORD nevent_out, mode; int ret = -1; + char *s; if (fd != 0) 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) } continue; } + s = &record.Event.KeyEvent.uChar.AsciiChar; + OemToCharBuff(s, s, 1); ret = record.Event.KeyEvent.uChar.AsciiChar; break; } 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 @@ #undef printf #undef fprintf #undef fputs +#undef putchar +#undef fwrite /* TODO: write */ /* @@ -309,10 +311,36 @@ static const char *set_attr(const char *str) return func + 1; } -static int ansi_emulate(const char *str, FILE *stream) +static int ansi_emulate(const char *s, FILE *stream) { int rv = 0; - const char *pos = str; + char *pos, *str; + size_t out_len, cur_len; + static size_t max_len = 0; + static char *mem = NULL; + + /* if no special treatment is required output the string as-is */ + for ( pos=s; *pos; ++pos ) { + if ( *pos == '\033' || *pos > 0x7f ) { + break; + } + } + + if ( *pos == '\0' ) { + return fputs(s, stream) == EOF ? EOF : strlen(s); + } + + /* make a writable copy of the string and retain it for reuse */ + cur_len = strlen(s); + if ( cur_len == 0 || cur_len > max_len ) { + free(mem); + mem = strdup(s); + max_len = cur_len; + } + else { + strcpy(mem, s); + } + pos = str = mem; while (*pos) { pos = strstr(str, "\033["); @@ -320,7 +348,8 @@ static int ansi_emulate(const char *str, FILE *stream) size_t len = pos - str; if (len) { - size_t out_len = fwrite(str, 1, len, stream); + CharToOemBuff(str, str, len); + out_len = fwrite(str, 1, len, stream); rv += out_len; if (out_len < len) return rv; @@ -331,11 +360,12 @@ static int ansi_emulate(const char *str, FILE *stream) fflush(stream); - pos = set_attr(str); + pos = (char *)set_attr(str); rv += pos - str; str = pos; } else { rv += strlen(str); + CharToOem(str, str); fputs(str, stream); return rv; } @@ -343,6 +373,52 @@ static int ansi_emulate(const char *str, FILE *stream) return rv; } +int winansi_putchar(int c) +{ + char t = c; + char *s = &t; + + if (!isatty(0)) + return putchar(c); + + init(); + + if (!console) + return putchar(c); + + CharToOemBuff(s, s, 1); + return putchar(t) == EOF ? EOF : c; +} + +size_t winansi_fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream) +{ + size_t lsize, lmemb; + char *str; + int rv; + + lsize = MIN(size, nmemb); + lmemb = MAX(size, nmemb); + if (lsize != 1) + return fwrite(ptr, size, nmemb, stream); + + if (!isatty(fileno(stream))) + return fwrite(ptr, size, nmemb, stream); + + init(); + + if (!console) + return fwrite(ptr, size, nmemb, stream); + + str = xmalloc(lmemb+1); + memcpy(str, ptr, lmemb); + str[lmemb] = '\0'; + + rv = ansi_emulate(str, stream); + free(str); + + return rv; +} + int winansi_fputs(const char *str, FILE *stream) { int rv; -- cgit v1.2.3-55-g6feb