eina log: expose cross platform way to set console colors.

changed the win32 color parse to be malloc-less and also support more
colors. It should be more correct, but I have no windows machine to
test.



SVN revision: 74742
This commit is contained in:
Gustavo Sverzut Barbieri 2012-08-01 15:34:13 +00:00
parent 3fc5ceadd7
commit 73ab74bd09
2 changed files with 135 additions and 54 deletions

View File

@ -19,6 +19,7 @@
#ifndef EINA_LOG_H_ #ifndef EINA_LOG_H_
#define EINA_LOG_H_ #define EINA_LOG_H_
#include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdarg.h> #include <stdarg.h>
#include <sys/types.h> #include <sys/types.h>
@ -890,6 +891,19 @@ EAPI void eina_log_print_cb_file(const Eina_Log_Domain *d,
void *data, void *data,
va_list args); va_list args);
/**
* Configure console color of given file.
*
* @param fp file to configure console color (usually stderr or stdout).
* @param color a VT color code such as #EINA_COLOR_RED or #EINA_COLOR_RESET.
*
* @note if color is disabled, nothing is done. See
* eina_log_color_disable_get()
* @note on windows, both @a fp and @a color is converted automatically.
*/
EAPI void eina_log_console_color_set(FILE *fp,
const char *color) EINA_ARG_NONNULL(1, 2);
#include "eina_inline_log.x" #include "eina_inline_log.x"
/** /**

View File

@ -252,75 +252,110 @@ static const char *_names[] = {
}; };
#ifdef _WIN32 #ifdef _WIN32
/* TODO: query win32_def_attr on eina_log_init() */
static int win32_def_attr = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE;
/* NOTE: can't use eina_log from inside this function */
static int static int
eina_log_win32_color_get(const char *domain_str) eina_log_win32_color_convert(const char *color, const char **endptr)
{ {
char *str; const char *p;
char *tmp; int attr = 0;
char *tmp2;
int code = -1;
int lighted = 0;
int ret = 0;
str = strdup(domain_str); if (endptr) *endptr = color;
if (!str)
return 0;
/* this should not append */ if (color[0] != '\033') return 0;
if (str[0] != '\033') if (color[1] != '[') return 0;
p = color + 2;
while (1)
{ {
free(str); char *end;
return 0; int code = strtol(p, &end, 10);
}
/* we skip the first char and the [ */ if (p == end)
tmp = tmp2 = str + 2;
while (*tmp != 'm')
{
if (*tmp == ';')
{ {
*tmp = '\0'; //fputs("empty color string\n", stderr);
code = atol(tmp2); if (endptr) *endptr = end;
tmp++; attr = 0; /* assume it was not color, must end with 'm' */
tmp2 = tmp; break;
} }
tmp++; if (code)
} {
*tmp = '\0'; if (code == 0) attr = win32_def_attr;
if (code < 0) else if (code == 1) attr |= FOREGROUND_INTENSITY;
code = atol(tmp2); else if (code == 4) attr |= COMMON_LVB_UNDERSCORE;
else else if (code == 7) attr |= COMMON_LVB_REVERSE_VIDEO;
lighted = atol(tmp2); else if ((code >= 30) && (code <= 37))
{
/* clear foreground */
attr &= ~(FOREGROUND_RED |
FOREGROUND_GREEN |
FOREGROUND_BLUE);
free(str); if (code == 31)
attr |= FOREGROUND_RED;
else if (code == 32)
attr |= FOREGROUND_GREEN;
else if (code == 33)
attr |= FOREGROUND_RED | FOREGROUND_GREEN;
else if (code == 34)
attr |= FOREGROUND_BLUE;
else if (code == 35)
attr |= FOREGROUND_RED | FOREGROUND_BLUE;
else if (code == 36)
attr |= FOREGROUND_GREEN | FOREGROUND_BLUE;
else if (code == 37)
attr |= FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE;
}
else if ((code >= 40) && (code <= 47))
{
/* clear background */
attr &= ~(BACKGROUND_RED |
BACKGROUND_GREEN |
BACKGROUND_BLUE);
if (code < lighted) if (code == 41)
{ attr |= BACKGROUND_RED;
int c; else if (code == 42)
attr |= BACKGROUND_GREEN;
else if (code == 44)
attr |= BACKGROUND_RED | BACKGROUND_GREEN;
else if (code == 44)
attr |= BACKGROUND_BLUE;
else if (code == 45)
attr |= BACKGROUND_RED | BACKGROUND_BLUE;
else if (code == 46)
attr |= BACKGROUND_GREEN | BACKGROUND_BLUE;
else if (code == 47)
attr |= BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE;
}
}
c = code; if (*end == 'm')
code = lighted; {
lighted = c; if (endptr) *endptr = end + 1;
break;
}
else if (*end == ';')
p = end + 1;
else
{
//fprintf(stderr, "unexpected char in color string: %s\n", end);
attr = 0; /* assume it was not color */
if (endptr) *endptr = end;
break;
}
} }
if (lighted) return attr;
ret = FOREGROUND_INTENSITY; }
if (code == 31) static int
ret |= FOREGROUND_RED; eina_log_win32_color_get(const char *color)
else if (code == 32) {
ret |= FOREGROUND_GREEN; return eina_log_win32_color_convert(color, NULL);
else if (code == 33)
ret |= FOREGROUND_RED | FOREGROUND_GREEN;
else if (code == 34)
ret |= FOREGROUND_BLUE;
else if (code == 36)
ret |= FOREGROUND_GREEN | FOREGROUND_BLUE;
else if (code == 37)
ret |= FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE;
return ret;
} }
#endif #endif
@ -2027,3 +2062,35 @@ eina_log_vprint(int domain, Eina_Log_Level level, const char *file,
#endif #endif
} }
EAPI void
eina_log_console_color_set(FILE *fp, const char *color)
{
#ifdef EINA_ENABLE_LOG
EINA_SAFETY_ON_NULL_RETURN(fp);
EINA_SAFETY_ON_NULL_RETURN(color);
if (_disable_color) return;
#ifdef _WIN32
int attr = eina_log_win32_color_convert(color);
HANDLE *handle;
if (fp == stderr)
handle = GetStdHandle(STD_ERROR_HANDLE);
else if (fp == stdout)
handle = GetStdHandle(STD_OUTPUT_HANDLE);
else
{
/* Do we have a way to convert FILE* to HANDLE?
* Should we use it?
*/
return;
}
SetConsoleTextAttribute(handle, attr);
#else
fputs(color, fp);
#endif
#else
(void)color;
#endif
}