#undef WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN #include "diff.h" #include #include static CONSOLE_SCREEN_BUFFER_INFO console_info; static HANDLE console_hnd = INVALID_HANDLE_VALUE; /* * These (currently hard-coded) colours specify the foreground colors to use * in the different context functions. E.g.: * 'set_color_context(HEADER_CONTEXT)' uses 'color_map[4]' which by default sets * the foreground to bright white). * * color_map[4] -> file-header color * color_map[5] -> added color * color_map[6] -> delete color * color_map[7] -> line-number color (e.g. '@@ -49,21 +49,31 @@') * * The background color is never set. * * Note: The 'color_map[]' is remapped if 'color_palette' is used. * See 'map_sgi_to_wincon()'. * E.g. set the env-var "DIFF_COLORS=hd=37;1:ad=32;1:de=31;1:ln=33;1" * to define the SGI. And invoke diff with '--color --palette=%DIFF_COLORS%' */ #define C_HEADER 4 static WORD color_map [] = { 0, 0, 0, 0, 7 | FOREGROUND_INTENSITY, /* colour for HEADER_CONTEXT -> bright white */ 2 | FOREGROUND_INTENSITY, /* colour for ADD_CONTEXT -> bright green */ 4 | FOREGROUND_INTENSITY, /* colour for DELETE_CONTEXT -> bright red */ 3 | FOREGROUND_INTENSITY /* colour for LINE_NUMBER_CONTEXT -> bright cyan */ }; static void map_sgi_to_wincon (const char *color_name, const char *sgi, WORD *color) { int num, a1 = 0, a2 = 0, fg = 0, bg = 0; WORD orig = *color; /* Ref. http://en.wikipedia.org/wiki/ANSI_escape_code#Colors */ static WORD sgi_color_map[] = { 0, /* ESC[30m -> Black */ FOREGROUND_RED, /* ESC[31m -> Red */ FOREGROUND_GREEN, /* ESC[32m -> Green */ FOREGROUND_RED | FOREGROUND_GREEN, /* ESC[33m -> Yellow */ FOREGROUND_BLUE, /* ESC[34m -> Blue */ FOREGROUND_RED | FOREGROUND_BLUE, /* ESC[35m -> Magenta */ FOREGROUND_BLUE | FOREGROUND_GREEN, /* ESC[36m -> Cyan */ FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_GREEN /* ESC[37m -> White */ }; num = sscanf (sgi, "%d;%d", &a1, &a2); if (num == 2) { if (a1 >= 30 && a1 <= 37) { fg = sgi_color_map [a1 - 30]; if (a2 == 1) fg |= FOREGROUND_INTENSITY; } else if (a1 >= 40 && a1 <= 47) { bg = sgi_color_map [a1 - 40]; if (a2 == 1) bg |= BACKGROUND_INTENSITY; } } else if (num == 1) { if (a1 >= 30 && a1 <= 37) fg = sgi_color_map [a1 - 30]; } else return; if (fg) *color = fg | (orig & ~0xF); if (bg) *color = (bg << 4) | (orig & 0xF); } void init_wincon (void) { BOOL okay; WORD background; char sgi [20], *env; int i; assert (ARRAY_SIZE(color_indicator) <= ARRAY_SIZE(color_map)); console_hnd = GetStdHandle (STD_OUTPUT_HANDLE); okay = (console_hnd != INVALID_HANDLE_VALUE && GetConsoleScreenBufferInfo(console_hnd, &console_info)); if (!okay || GetFileType(console_hnd) != FILE_TYPE_CHAR) colors_enabled = false; else { background = console_info.wAttributes & ~7; for (i = 4; i < ARRAY_SIZE(color_map); i++) color_map[i] |= background; } if (color_palette) { for (i = 0; i < ARRAY_SIZE(color_indicator); i++) { if (i < C_HEADER) continue; memset (sgi, '\0', sizeof(sgi)); memcpy (sgi, color_indicator[i].string, color_indicator[i].len); map_sgi_to_wincon (indicator_name[i], sgi, &color_map[i]); } } } /* * Set console foreground and optionally background color. * color_map[index]: FG is in the low 4 bits. * BG is in the upper 4 bits of the BYTE. * If 'index == -1', set default console colour. */ void set_color (int index) { BYTE fg, bg; WORD attr; if (index == -1) /* restore to default colour */ { attr = console_info.wAttributes; fg = LOBYTE (attr); bg = HIBYTE (attr); } else { attr = color_map[index]; fg = LOBYTE (attr); bg = HIBYTE (attr); /* if (bg == (BYTE)-1) attr = console_info.wAttributes & ~7; else */ attr = bg << 4; attr |= fg; } SetConsoleTextAttribute (console_hnd, attr); }