From bb3656f8bfa3f1bdedc1368582b53e0c3bfefc50 Mon Sep 17 00:00:00 2001 From: Karsten Blees Date: Sat, 31 Jul 2010 00:04:01 +0000 Subject: [PATCH] Support Unicode console output on Windows WriteConsoleW seems to be the only way to reliably print unicode to the console (without weird code page conversions). Also redirects vfprintf to the winansi.c version. Signed-off-by: Karsten Blees Signed-off-by: Johannes Schindelin --- compat/mingw.h | 2 ++ compat/winansi.c | 26 ++++++++++++++++++++------ 2 files changed, 22 insertions(+), 6 deletions(-) diff --git a/compat/mingw.h b/compat/mingw.h index dbb179c450..849f37c02b 100644 --- a/compat/mingw.h +++ b/compat/mingw.h @@ -260,9 +260,11 @@ sig_handler_t mingw_signal(int sig, sig_handler_t handler); 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))); +int winansi_vfprintf(FILE *stream, const char *format, va_list list); #define fputs winansi_fputs #define printf(...) winansi_printf(__VA_ARGS__) #define fprintf(...) winansi_fprintf(__VA_ARGS__) +#define vfprintf winansi_vfprintf /* * git specific compatibility diff --git a/compat/winansi.c b/compat/winansi.c index dedce2104e..abe0feaa2c 100644 --- a/compat/winansi.c +++ b/compat/winansi.c @@ -3,6 +3,7 @@ */ #include "../git-compat-util.h" +#include /* Functions to be wrapped: @@ -10,6 +11,7 @@ #undef printf #undef fprintf #undef fputs +#undef vfprintf /* TODO: write */ /* @@ -46,6 +48,18 @@ static void init(void) initialized = 1; } +static int write_console(const char *str, size_t len) +{ + /* convert utf-8 to utf-16, write directly to console */ + int wlen = MultiByteToWideChar(CP_UTF8, 0, str, len, NULL, 0); + wchar_t *wbuf = (wchar_t *) alloca(wlen * sizeof(wchar_t)); + MultiByteToWideChar(CP_UTF8, 0, str, len, wbuf, wlen); + + WriteConsoleW(console, wbuf, wlen, NULL, NULL); + + /* return original (utf-8 encoded) length */ + return len; +} #define FOREGROUND_ALL (FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE) #define BACKGROUND_ALL (BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE) @@ -245,13 +259,15 @@ static int ansi_emulate(const char *str, FILE *stream) int rv = 0; const char *pos = str; + fflush(stream); + while (*pos) { pos = strstr(str, "\033["); if (pos) { size_t len = pos - str; if (len) { - size_t out_len = fwrite(str, 1, len, stream); + size_t out_len = write_console(str, len); rv += out_len; if (out_len < len) return rv; @@ -260,14 +276,12 @@ static int ansi_emulate(const char *str, FILE *stream) str = pos + 2; rv += 2; - fflush(stream); - pos = set_attr(str); rv += pos - str; str = pos; } else { - rv += strlen(str); - fputs(str, stream); + size_t len = strlen(str); + rv += write_console(str, len); return rv; } } @@ -294,7 +308,7 @@ int winansi_fputs(const char *str, FILE *stream) return EOF; } -static int winansi_vfprintf(FILE *stream, const char *format, va_list list) +int winansi_vfprintf(FILE *stream, const char *format, va_list list) { int len, rv; char small_buf[256]; -- 2.11.4.GIT