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;

Reply via email to