Giuseppe Scrivano wrote: > thanks for your patches. Is it fine for you if we keep bug-diffutils in > the loop?
Sure. I forgot it was in the CC-list. Attached again; wincolor.c + diff-1.txt. Excused my diff format; I'm a "git n00b". Hope you figure it out. -- --gv
#undef WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN #include "diff.h" #include <assert.h> #include <windows.h> 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); }
--- a/src/diff.h 2016-01-30 20:29:29 +++ b/src/diff.h 2016-01-30 20:35:34 @@ -378,6 +378,18 @@ extern void print_sdiff_script (struct change *); /* util.c */ + +struct bin_str + { + size_t len; /* Number of bytes */ + const char *string; /* Pointer to the same */ + }; + +extern struct bin_str color_indicator [8]; +extern const char *const indicator_name[9]; +extern char const *color_palette; +extern bool colors_enabled; + extern char const change_letter[4]; extern char const pr_program[]; extern char *concat (char const *, char const *, char const *); @@ -419,3 +431,20 @@ extern void set_color_context (enum color_context color_context); extern void set_color_palette (char const *palette); + +/* wincolor.c */ + +#ifdef WIN32 + #include <signal.h> + + #ifndef SIGSTOP + #define SIGSTOP SIGTERM + #endif + + #ifndef ARRAY_SIZE + #define ARRAY_SIZE(a) (sizeof (a) / sizeof ((a)[0])) + #endif + + extern void init_wincon (void); + extern void set_color (int index); +#endif --- a/src/util.c 2016-01-30 20:29:29 +++ b/src/util.c 2016-01-30 20:38:12 @@ -208,7 +208,11 @@ int stops; sigset_t oldset; +#ifdef WIN32 + set_color (-1); +#else set_color_context (RESET_CONTEXT); +#endif fflush (stdout); sigprocmask (SIG_BLOCK, &caught_signals, &oldset); @@ -245,10 +249,20 @@ static int const sig[] = { /* This one is handled specially. */ +#ifdef SIGTSTP SIGTSTP, - +#endif +#ifdef SIGALRM + SIGALRM, +#endif +#ifdef SIGQUIT + SIGQUIT, +#endif /* The usual suspects. */ - SIGALRM, SIGHUP, SIGINT, SIGPIPE, SIGQUIT, SIGTERM, + SIGHUP, SIGINT, SIGPIPE, +#ifdef SIGTERM + SIGTERM, +#endif #ifdef SIGPOLL SIGPOLL, #endif @@ -298,7 +312,11 @@ caught_sig[j] = (signal (sig[j], SIG_IGN) != SIG_IGN); if (caught_sig[j]) { +#ifdef SIGTSTP signal (sig[j], sig[j] == SIGTSTP ? stophandler : sighandler); +#else + signal (sig[j], sighandler); +#endif siginterrupt (sig[j], 0); } } @@ -309,16 +327,10 @@ static char const *current_name0; static char const *current_name1; static bool currently_recursive; -static bool colors_enabled; +bool colors_enabled; static struct color_ext_type *color_ext_list = NULL; -struct bin_str - { - size_t len; /* Number of bytes */ - const char *string; /* Pointer to the same */ - }; - struct color_ext_type { struct bin_str ext; /* The extension we're looking for */ @@ -546,7 +558,7 @@ #define LEN_STR_PAIR(s) sizeof (s) - 1, s -static struct bin_str color_indicator[] = +struct bin_str color_indicator[8] = { { LEN_STR_PAIR ("\033[") }, /* lc: Left of color sequence */ { LEN_STR_PAIR ("m") }, /* rc: Right of color sequence */ @@ -558,13 +570,13 @@ { LEN_STR_PAIR ("36") }, /* ln: Line number */ }; -static const char *const indicator_name[] = +const char *const indicator_name[9] = { "lc", "rc", "ec", "rs", "hd", "ad", "de", "ln", NULL }; ARGMATCH_VERIFY (indicator_name, color_indicator); -static char const *color_palette; +char const *color_palette; void set_color_palette (char const *palette) @@ -714,9 +726,12 @@ colors_enabled = (colors_style == ALWAYS || (colors_style == AUTO && output_is_tty)); - - if (colors_enabled) + if (colors_enabled) { parse_diff_color (); +#ifdef WIN32 + init_wincon(); +#endif + } if (output_is_tty) install_signal_handlers (); @@ -1341,7 +1356,40 @@ static void put_indicator (const struct bin_str *ind) { +#ifdef WIN32 +#define IND_TO_ADDR(x) ((const char*)ind == (const char*)&color_indicator[x]) + + if (IND_TO_ADDR(C_LEFT) || IND_TO_ADDR(C_RIGHT)) + return; + + if (IND_TO_ADDR(C_RESET) || interrupt_signal) + { + fflush (outfile); + set_color (-1); + } + else if (IND_TO_ADDR(C_HEADER)) + { + fflush (outfile); + set_color (C_HEADER); + } + else if (IND_TO_ADDR(C_LINE)) + { + fflush (outfile); + set_color (C_LINE); + } + else if (IND_TO_ADDR(C_ADD)) + { + fflush (outfile); + set_color (C_ADD); + } + else if (IND_TO_ADDR(C_DELETE)) + { + fflush (outfile); + set_color (C_DELETE); + } +#else fwrite (ind->string, ind->len, 1, outfile); +#endif } static enum color_context last_context = RESET_CONTEXT;