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;