diff --git a/src/common/logging.c b/src/common/logging.c index c78ae79..8c0377f 100644 --- a/src/common/logging.c +++ b/src/common/logging.c @@ -32,6 +32,60 @@ static const char *sgr_locus = NULL; #define ANSI_ESCAPE_FMT "\x1b[%sm" #define ANSI_ESCAPE_RESET "\x1b[0m" +#define str_starts_with(str, substr) (strncmp(str, substr, strlen(substr)) == 0) +#define str_ends_with(str, substr) (strcmp(str + strlen(str) - strlen(substr), substr) == 0) +#ifndef ENABLE_VIRTUAL_TERMINAL_PROCESSING +#define ENABLE_VIRTUAL_TERMINAL_PROCESSING 0x0004 +#endif + +static bool +terminal_supports_color(void) +{ +#ifndef WIN32 + const char *term_env = getenv("TERM"); + + if (!term_env) + return false; + else if (strcmp(term_env, "ansi") == 0) + return true; + else if (strcmp(term_env, "cygwin") == 0) + return true; + else if (strcmp(term_env, "linux") == 0) + return true; + else if (str_starts_with(term_env, "rxvt")) + return true; + else if (str_starts_with(term_env, "screen")) + return true; + else if (str_starts_with(term_env, "xterm")) + return true; + else if (str_starts_with(term_env, "vt100")) + return true; + else if (str_ends_with(term_env, "color")) + return true; + else + return false; +#else +/* + * Windows supports color on console's VT100 mode. + * It is disabled by default, so it must be enabled to use color outpout. + */ + /* Check stderr */ + HANDLE hOut = GetStdHandle(STD_ERROR_HANDLE); + DWORD dwMode = 0; + + if (hOut == INVALID_HANDLE_VALUE) + return false; + if (!GetConsoleMode(hOut, &dwMode)) + return false; + if (dwMode & ENABLE_VIRTUAL_TERMINAL_PROCESSING) + return true; + dwMode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING; + if (!SetConsoleMode(hOut, dwMode)) + return false; + return true; +#endif +} + /* * This should be called before any output happens. */ @@ -40,6 +94,8 @@ pg_logging_init(const char *argv0) { const char *pg_color_env = getenv("PG_COLOR"); bool log_color = false; + bool color_terminal = isatty(fileno(stderr)) && + terminal_supports_color(); /* usually the default, but not on Windows */ setvbuf(stderr, NULL, _IONBF, 0); @@ -50,7 +106,7 @@ pg_logging_init(const char *argv0) if (pg_color_env) { if (strcmp(pg_color_env, "always") == 0 || - (strcmp(pg_color_env, "auto") == 0 && isatty(fileno(stderr)))) + (strcmp(pg_color_env, "auto") == 0 && color_terminal)) log_color = true; }