aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--win32/winansi.c61
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 @@
10static BOOL charToConBuffA(LPSTR s, DWORD len); 10static BOOL charToConBuffA(LPSTR s, DWORD len);
11static BOOL charToConA(LPSTR s); 11static BOOL charToConA(LPSTR s);
12 12
13static int conv_fwriteCon(FILE *stream, char *buf, size_t siz);
14static 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
860int winansi_puts(const char *s) 860int 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
1469static 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
1477static int conv_writeCon(int fd, char *buf, size_t siz)
1478{
1479 charToConBuffA(buf, siz);
1480 return write(fd, buf, siz);
1481}