printf-hook-builtin: Support Windows console colors using TTY escape codes
This commit is contained in:
@@ -1104,6 +1104,128 @@ int builtin_vprintf(const char *format, va_list ap)
|
|||||||
return builtin_vfprintf(stdout, format, 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)
|
int builtin_vfprintf(FILE *stream, const char *format, va_list ap)
|
||||||
{
|
{
|
||||||
char buf[PRINTF_BUF_LEN];
|
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);
|
return fwrite(buf, 1, len, stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif /* !WIN32 */
|
||||||
|
|
||||||
int builtin_vsprintf(char *str, const char *format, va_list ap)
|
int builtin_vsprintf(char *str, const char *format, va_list ap)
|
||||||
{
|
{
|
||||||
return builtin_vsnprintf(str, ~(size_t)0, format, ap);
|
return builtin_vsnprintf(str, ~(size_t)0, format, ap);
|
||||||
|
|||||||
@@ -363,6 +363,9 @@ char* tty_escape_get(int fd, tty_escape_t escape)
|
|||||||
case TTY_BOLD:
|
case TTY_BOLD:
|
||||||
case TTY_UNDERLINE:
|
case TTY_UNDERLINE:
|
||||||
case TTY_BLINKING:
|
case TTY_BLINKING:
|
||||||
|
#ifdef WIN32
|
||||||
|
return "";
|
||||||
|
#endif
|
||||||
case TTY_FG_BLACK:
|
case TTY_FG_BLACK:
|
||||||
case TTY_FG_RED:
|
case TTY_FG_RED:
|
||||||
case TTY_FG_GREEN:
|
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_WHITE:
|
||||||
case TTY_BG_DEF:
|
case TTY_BG_DEF:
|
||||||
return enum_to_name(tty_color_names, escape);
|
return enum_to_name(tty_color_names, escape);
|
||||||
/* warn if a excape code is missing */
|
/* warn if a escape code is missing */
|
||||||
}
|
}
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user