diff options
-rw-r--r-- | win32/winansi.c | 61 |
1 files changed, 44 insertions, 17 deletions
diff --git a/win32/winansi.c b/win32/winansi.c index f280177e6..e6528926e 100644 --- a/win32/winansi.c +++ b/win32/winansi.c | |||
@@ -10,6 +10,9 @@ | |||
10 | static BOOL charToConBuffA(LPSTR s, DWORD len); | 10 | static BOOL charToConBuffA(LPSTR s, DWORD len); |
11 | static BOOL charToConA(LPSTR s); | 11 | static BOOL charToConA(LPSTR s); |
12 | 12 | ||
13 | static int conv_fwriteCon(FILE *stream, char *buf, size_t siz); | ||
14 | static int conv_writeCon(int fd, char *buf, size_t siz); | ||
15 | |||
13 | /* | 16 | /* |
14 | Functions to be wrapped: | 17 | Functions to be wrapped: |
15 | */ | 18 | */ |
@@ -814,9 +817,7 @@ static int ansi_emulate(const char *s, FILE *stream) | |||
814 | size_t len = pos - str; | 817 | size_t len = pos - str; |
815 | 818 | ||
816 | if (len) { | 819 | if (len) { |
817 | *pos = '\0'; /* NB, '\033' has been overwritten */ | 820 | if (conv_fwriteCon(stream, str, len) == EOF) |
818 | charToConA(str); | ||
819 | if (fputs(str, stream) == EOF) | ||
820 | return EOF; | 821 | return EOF; |
821 | rv += len; | 822 | rv += len; |
822 | } | 823 | } |
@@ -837,9 +838,9 @@ static int ansi_emulate(const char *s, FILE *stream) | |||
837 | return EOF; | 838 | return EOF; |
838 | 839 | ||
839 | } else { | 840 | } else { |
840 | rv += strlen(str); | 841 | size_t len = strlen(str); |
841 | charToConA(str); | 842 | rv += len; |
842 | return fputs(str, stream) == EOF ? EOF : rv; | 843 | return conv_fwriteCon(stream, str, len) == EOF ? EOF : rv; |
843 | } | 844 | } |
844 | } | 845 | } |
845 | return rv; | 846 | return rv; |
@@ -853,8 +854,7 @@ int winansi_putchar(int c) | |||
853 | if (!is_console(STDOUT_FILENO)) | 854 | if (!is_console(STDOUT_FILENO)) |
854 | return putchar(c); | 855 | return putchar(c); |
855 | 856 | ||
856 | charToConBuffA(s, 1); | 857 | return conv_fwriteCon(stdout, s, 1) == EOF ? EOF : (unsigned char)c; |
857 | return putchar(t) == EOF ? EOF : (unsigned char)c; | ||
858 | } | 858 | } |
859 | 859 | ||
860 | int winansi_puts(const char *s) | 860 | int winansi_puts(const char *s) |
@@ -952,8 +952,7 @@ int winansi_fputc(int c, FILE *stream) | |||
952 | return ret; | 952 | return ret; |
953 | } | 953 | } |
954 | 954 | ||
955 | charToConBuffA(s, 1); | 955 | return conv_fwriteCon(stream, s, 1) == EOF ? EOF : (unsigned char )c; |
956 | return fputc(t, stream) == EOF ? EOF : (unsigned char )c; | ||
957 | } | 956 | } |
958 | 957 | ||
959 | #if !defined(__USE_MINGW_ANSI_STDIO) || !__USE_MINGW_ANSI_STDIO | 958 | #if !defined(__USE_MINGW_ANSI_STDIO) || !__USE_MINGW_ANSI_STDIO |
@@ -1083,8 +1082,7 @@ static int ansi_emulate_write(int fd, const void *buf, size_t count) | |||
1083 | len = pos - str; | 1082 | len = pos - str; |
1084 | 1083 | ||
1085 | if (len) { | 1084 | if (len) { |
1086 | charToConBuffA(str, len); | 1085 | out_len = conv_writeCon(fd, str, len); |
1087 | out_len = write(fd, str, len); | ||
1088 | if (out_len == -1) | 1086 | if (out_len == -1) |
1089 | return -1; | 1087 | return -1; |
1090 | rv += out_len; | 1088 | rv += out_len; |
@@ -1100,8 +1098,7 @@ static int ansi_emulate_write(int fd, const void *buf, size_t count) | |||
1100 | pos = str; | 1098 | pos = str; |
1101 | } else { | 1099 | } else { |
1102 | len = strlen(str); | 1100 | len = strlen(str); |
1103 | charToConA(str); | 1101 | out_len = conv_writeCon(fd, str, len); |
1104 | out_len = write(fd, str, len); | ||
1105 | return (out_len == -1) ? -1 : rv+out_len; | 1102 | return (out_len == -1) ? -1 : rv+out_len; |
1106 | } | 1103 | } |
1107 | } | 1104 | } |
@@ -1446,9 +1443,39 @@ void console_write(const char *str, int len) | |||
1446 | { | 1443 | { |
1447 | char *buf = xmemdup(str, len); | 1444 | char *buf = xmemdup(str, len); |
1448 | int fd = _open("CONOUT$", _O_WRONLY); | 1445 | int fd = _open("CONOUT$", _O_WRONLY); |
1449 | HANDLE fh = (HANDLE)_get_osfhandle(fd); | 1446 | conv_writeCon(fd, buf, len); |
1450 | charToConBuffA(buf, len); | ||
1451 | WriteConsole(fh, buf, len, NULL, NULL); | ||
1452 | close(fd); | 1447 | close(fd); |
1453 | free(buf); | 1448 | free(buf); |
1454 | } | 1449 | } |
1450 | |||
1451 | // TODO: improvements: | ||
1452 | // | ||
1453 | // 1. currently conv_[f]writeCon modify buf inplace, which means the caller | ||
1454 | // typically has to make a writable copy first just for this. | ||
1455 | // Sometimes it allocates a big copy once, and calls us with substrings. | ||
1456 | // Instead, we could make a writable copy here - it's not used later anyway. | ||
1457 | // To avoid the performance hit of many small allocations, we could use | ||
1458 | // a local buffer for short strings, and allocate only if it doesn't fit | ||
1459 | // (or maybe just reuse the local buffer with substring iterations). | ||
1460 | // | ||
1461 | // 2. Instead of converting from ACP to the console out CP - which guarantees | ||
1462 | // potential data-loss if they differ, we could convert it to wchar_t and | ||
1463 | // write it using WriteConsoleW. This should prevent all output data-loss. | ||
1464 | // care should be taken with DBCS codepages (e.g. 936) or other multi-byte | ||
1465 | // because then converting on arbitrary substring boundaries can fail. | ||
1466 | |||
1467 | // convert buf inplace from ACP to console out CP and write it to stream | ||
1468 | // returns EOF on error, 0 on success | ||
1469 | static int conv_fwriteCon(FILE *stream, char *buf, size_t siz) | ||
1470 | { | ||
1471 | charToConBuffA(buf, siz); | ||
1472 | return fwrite(buf, 1, siz, stream) < siz ? EOF : 0; | ||
1473 | } | ||
1474 | |||
1475 | // similar to above, but using lower level write | ||
1476 | // returns -1 on error, actually-written bytes on suceess | ||
1477 | static int conv_writeCon(int fd, char *buf, size_t siz) | ||
1478 | { | ||
1479 | charToConBuffA(buf, siz); | ||
1480 | return write(fd, buf, siz); | ||
1481 | } | ||