printf-hook-builtin: Support Windows console colors using TTY escape codes

This commit is contained in:
Martin Willi
2014-06-04 15:52:57 +02:00
parent 71bf82d474
commit 1f2b8c8c80
2 changed files with 128 additions and 1 deletions
@@ -1104,6 +1104,128 @@ int builtin_vprintf(const char *format, va_list ap)
return builtin_vfprintf(stdout, format, ap);
}
#ifdef WIN32
/**
* Set TTY color on Windows consoles
*/
static void set_console_color(HANDLE handle, int color)
{
CONSOLE_SCREEN_BUFFER_INFO info;
struct {
/* escape code */
int color;
/* windows console color combination */
WORD attributes;
} maps[] = {
{ 30, 0 },
{ 31, FOREGROUND_RED },
{ 32, FOREGROUND_GREEN },
{ 33, FOREGROUND_GREEN | FOREGROUND_RED },
{ 34, FOREGROUND_BLUE | FOREGROUND_INTENSITY },
{ 35, FOREGROUND_RED | FOREGROUND_BLUE },
{ 36, FOREGROUND_GREEN | FOREGROUND_BLUE },
{ 37, FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_RED },
{ 39, FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_RED },
{ 40, 0 },
{ 41, BACKGROUND_RED },
{ 42, BACKGROUND_GREEN },
{ 43, BACKGROUND_GREEN | BACKGROUND_RED },
{ 44, BACKGROUND_BLUE },
{ 45, BACKGROUND_RED | BACKGROUND_BLUE },
{ 46, BACKGROUND_GREEN | BACKGROUND_BLUE },
{ 47, BACKGROUND_GREEN | BACKGROUND_BLUE | BACKGROUND_RED },
{ 49, 0 },
};
int i;
if (GetConsoleScreenBufferInfo(handle, &info))
{
if (color < 40)
{
info.wAttributes &= ~(FOREGROUND_BLUE | FOREGROUND_GREEN |
FOREGROUND_RED | FOREGROUND_INTENSITY);
}
else
{
info.wAttributes &= ~(BACKGROUND_BLUE | BACKGROUND_GREEN |
BACKGROUND_RED | BACKGROUND_INTENSITY);
}
for (i = 0; i < countof(maps); i++)
{
if (maps[i].color == color)
{
info.wAttributes |= maps[i].attributes;
SetConsoleTextAttribute(handle, info.wAttributes);
break;
}
}
}
}
int builtin_vfprintf(FILE *stream, const char *format, va_list ap)
{
char buf[PRINTF_BUF_LEN], *pos, *stop;
HANDLE handle;
int len, total;
DWORD clen, mode;
total = len = builtin_vsnprintf(buf, sizeof(buf), format, ap);
switch (fileno(stream))
{
case 1:
handle = GetStdHandle(STD_OUTPUT_HANDLE);
break;
case 2:
handle = GetStdHandle(STD_ERROR_HANDLE);
break;
default:
handle = INVALID_HANDLE_VALUE;
break;
}
/* GetConsoleMode fails if output redirected */
if (handle == INVALID_HANDLE_VALUE || !GetConsoleMode(handle, &mode))
{
return fwrite(buf, 1, len, stream);
}
while (len)
{
pos = &buf[total - len];
if (len > 4)
{
if (pos[0] == '\e' && pos[1] == '[' && pos[4] == 'm')
{
if (isdigit(pos[3]))
{
if (pos[2] == '3' || pos[2] == '4')
{
set_console_color(handle,
(pos[2] - '0') * 10 + pos[3] - '0');
len -= 5;
continue;
}
}
}
}
stop = memchr(pos + 1, '\e', len);
if (stop)
{
clen = stop - pos;
}
else
{
clen = len;
}
if (clen && !WriteConsole(handle, pos, clen, &clen, NULL))
{
break;
}
len -= clen;
}
return total - len;
}
#else /* !WIN32 */
int builtin_vfprintf(FILE *stream, const char *format, va_list ap)
{
char buf[PRINTF_BUF_LEN];
@@ -1113,6 +1235,8 @@ int builtin_vfprintf(FILE *stream, const char *format, va_list ap)
return fwrite(buf, 1, len, stream);
}
#endif /* !WIN32 */
int builtin_vsprintf(char *str, const char *format, va_list ap)
{
return builtin_vsnprintf(str, ~(size_t)0, format, ap);
+4 -1
View File
@@ -363,6 +363,9 @@ char* tty_escape_get(int fd, tty_escape_t escape)
case TTY_BOLD:
case TTY_UNDERLINE:
case TTY_BLINKING:
#ifdef WIN32
return "";
#endif
case TTY_FG_BLACK:
case TTY_FG_RED:
case TTY_FG_GREEN:
@@ -382,7 +385,7 @@ char* tty_escape_get(int fd, tty_escape_t escape)
case TTY_BG_WHITE:
case TTY_BG_DEF:
return enum_to_name(tty_color_names, escape);
/* warn if a excape code is missing */
/* warn if a escape code is missing */
}
return "";
}