2008-01-20  Juan Manuel Guerrero <juan.guerrero@gmx.de>

	* src/dosbuf.c (restore_blink_bit, screen_puts)
	(msdos_screen_write, djgpp_grep_startup) [__DJGPP__]: Functions
	to support colorization without requiring ANSI.SYS driver (or its
	work-alike) to be loaded have been reenabled.  
	(msdos_screen_write): Added support to decode and execute erase part
	of the line to the right escape sequence (ESC-[K), that is used to
	initialize and finish SGR escape sequences.

	* src/grep.c [__DJGPP__]: New macro IS_TERM defined.  If compiled with
	DJGPP do not check for the term environment variable to decided which
	value should color_option have.
	(main): Use IS_TERM.


2007-08-11  Juan Manuel Guerrero <juan.guerrero@gmx.de>

	* lib/isdir.c [DJGPP]: Include <unistd.h> for
	access declaration.
	(isdir) [DJGPP]: Use access to determinate if
	given path is an existing directory.

	* src/dosbuf.c (restore_blink_bit, screen_puts)
	(msdos_screen_write, djgpp_grep_startup) [__DJGPP__]: New functions
	to support colorization without requiring ANSI.SYS driver (or its
	work-alike) to be loaded.  Code has been taken from DJGPP port of
	grep 2.5.1 (aka grep251[bds].zip).  ATTENTION:  This code has been
	added to the file to avoid that it gets lost but it has been disabled.
	The way colorization is handled by grep has changed so this code does
	not work any more but it may be usfull as a base for developing the
	new one.


2007-08-10  Juan Manuel Guerrero <juan.guerrero@gmx.de>

	* src/system.h [DJGPP]: Depend on __DJGPP__ and
	__DJGPP_MINOR__ to define HAVE_DIR_EACCES_BUG.




diff -aprNU5 grep-2.5.3.orig/lib/isdir.c grep-2.5.3/lib/isdir.c
--- grep-2.5.3.orig/lib/isdir.c	2007-06-28 18:57:18 +0000
+++ grep-2.5.3/lib/isdir.c	2007-08-11 15:22:50 +0000
@@ -17,10 +17,13 @@
 
 #if HAVE_CONFIG_H
 # include <config.h>
 #endif
 
+#ifdef __DJGPP__
+# include <unistd.h>
+#endif
 #include <sys/types.h>
 #include <sys/stat.h>
 
 #if STAT_MACROS_BROKEN
 # undef S_ISDIR
@@ -36,7 +39,17 @@
 int
 isdir (const char *path)
 {
   struct stat stats;
 
+#ifdef __DJGPP__
+  /*
+   *  Computation of stat is very expensive.
+   *  To determinate if PATH is an existing
+   *  directory, access on DOS platforms is
+   *  mostly a fast system call.
+   */
+  return (access (path, D_OK) == 0);
+#else
   return stat (path, &stats) == 0 && S_ISDIR (stats.st_mode);
+#endif
 }
diff -aprNU5 grep-2.5.3.orig/src/dosbuf.c grep-2.5.3/src/dosbuf.c
--- grep-2.5.3.orig/src/dosbuf.c	2007-06-28 18:57:18 +0000
+++ grep-2.5.3/src/dosbuf.c	2007-08-12 18:02:54 +0000
@@ -1,14 +1,17 @@
 /* Messy DOS-specific code for correctly treating binary, Unix text
-   and DOS text files.
+   and DOS text files, and for emulating a Posix terminal driver
+   wrt SGR (a.k.a. ANSI) color escape sequences.
 
    This has several aspects:
 
      * Guessing the file type (unless the user tells us);
      * Stripping CR characters from DOS text files (otherwise regex
        functions won't work correctly);
      * Reporting correct byte count with -b for any kind of file.
+     * Redirecting output with ANSI color commands to direct screen
+       writes.
 
 */
 
 typedef enum {
   UNKNOWN, DOS_BINARY, DOS_TEXT, UNIX_TEXT
@@ -177,5 +180,347 @@ dossified_pos (off_t byteno)
         out_map_idx--;
     }
 
   return byteno + dos_pos_map[out_map_idx].add;
 }
+
+#if 0
+/*
+ *  Original support colorization written for the DJGPP port of grep 2.5.1.
+ *  The way colorization is handled in grep 2.5.3 has changed.  They have
+ *  begun using SGR (Select Graphic Rendition )commands that the actual
+ *  DJGPP code is not capable to understand.  It will require some time
+ *  until I can fix this.
+ *
+ *  Juan Manuel Guerrero, 2007-08-12
+ */
+
+
+#ifdef __DJGPP__
+/*  Screen write redirection.  We need this to support colorization
+    without requiring ANSI.SYS driver (or its work-alike) to be loaded.
+
+    This function uses the DJGPP filesystem extensions mechanism.  It is
+    installed as a handler for handle-based functions (read/write/close)
+    for the standard output (but actually only handles writes, only if
+    the standard output is connected to the terminal, and only if user
+    asked for colorization).  When a buffer is written to the screen by
+    low-level functions of the DJGPP C library, our handler will be
+    called.  For any request that doesn't require colored screen writes
+    we return a zero to the caller, in which case the caller will handle
+    the output in the usual way (by eventually calling DOS).
+
+    When colorization *is* required, the buffer is written directly to
+    the screen while converting the ANSI escape sequences into calls to
+    DJGPP conio functions which change text attributes.  A non-zero value is
+    then returned to the caller to signal that the output has been handled.
+*/
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <errno.h>
+#include <unistd.h>
+#include <conio.h>
+#include <sys/fsext.h>
+#include <go32.h> /* for `_dos_ds' */
+#include <sys/farptr.h>
+
+static int norm_blink = -1, cur_blink = -1;
+static unsigned char norm_attr = 0, cur_attr = 0;
+static int isatty_stdout = -1;
+static size_t leftover = 0;
+
+/* Restore the BIOS blinking bit to its original value.  Called at exit.  */
+static void
+restore_blink_bit (void)
+{
+  if (cur_blink != norm_blink)
+    {
+      if (norm_blink > 0)
+        blinkvideo ();
+      else
+        intensevideo ();
+    }
+}
+
+/* Write a buffer to the screen video memory.  This expands the TAB
+   characters to the appropriate number of spaces, and also does TRT
+   with null characters and other non-printable characters, if
+   any.  */
+static void
+screen_puts (char *buf, char *buf_end)
+{
+  register char *p = buf, *q = p;
+  int row, col;
+  unsigned char c;
+
+  while (p < buf_end)
+    {
+      if (*p < ' ')
+        {
+          switch (*p)
+            {
+              case '\b':
+              case '\r':
+              case '\n':
+                /* nothing: cputs already does TRT with these */
+                break;
+              case '\t':
+                *p = '\0';
+                cputs (q);
+                ScreenGetCursor (&row, &col);
+                for (cputs (" "), col += 1; col % 8; col++)
+                  cputs (" ");
+                q = p + 1;
+                *p = '\t';
+                break;
+              default:
+                c = *p;
+                *p = '\0';
+                cputs (q);
+                cputs ("^");
+                putch (c | 0x40);
+                q = p + 1;
+                *p = c;
+                break;
+            }
+        }
+      p++;
+    }
+  /* Output whatever is left.  */
+  cputs (q);
+}
+
+#define ESC '\033'
+
+/* Screen writes redirector function.  */
+static int
+msdos_screen_write (__FSEXT_Fnumber func, int *retval, va_list rest_args)
+{
+  static char *cbuf = NULL;
+  static size_t cbuf_len = 0;
+  /* Only dark colors mentioned here, so that bold has visible effect.  */
+  static enum COLORS screen_color[] = {
+    BLACK,
+    RED,
+    GREEN,
+    BROWN,
+    BLUE,
+    MAGENTA,
+    CYAN,
+    LIGHTGRAY
+  };
+  char *anchor, *p_next;
+  unsigned char fg, bg;
+
+  int handle;
+  char *buf, *buf_end;
+  size_t buflen;
+
+  /* Avoid direct screen writes unless colorization was actually requested.
+     Otherwise, we will break programs that catch I/O from their children.  */
+  handle = va_arg (rest_args, int);
+  if (!color_option || func != __FSEXT_write ||
+       !(handle == STDOUT_FILENO ? isatty_stdout : isatty (handle)))
+    return 0;
+
+  buf = va_arg (rest_args, char *);
+  if (!buf)
+    {
+      errno = EINVAL;
+      *retval = -1;
+      return 1;
+    }
+
+  /* Allocate a sufficiently large buffer to hold the output.  */
+  buflen = va_arg (rest_args, size_t);
+  if (!cbuf)
+    {
+      struct text_info txtinfo;
+
+      cbuf_len = buflen + 1;
+      cbuf = (char *)xmalloc (cbuf_len);
+      gettextinfo (&txtinfo);
+      norm_attr = txtinfo.attribute; /* save the original text attribute */
+      cur_attr = norm_attr;
+      /* Does it normally blink when bg has its 3rd bit set?  */
+      norm_blink = (_farpeekb (_dos_ds, 0x465) & 0x20) ? 1 : 0;
+      cur_blink = norm_blink;
+    }
+  else if (buflen >= cbuf_len)
+    {
+      cbuf_len = buflen + 1 + leftover;
+      cbuf = (char *)xrealloc (cbuf, cbuf_len);
+    }
+  memcpy (cbuf + leftover, buf, buflen);
+  buf_end = cbuf + buflen + leftover;
+  *buf_end = '\0';
+
+  /* Current text attributes are used as baseline.  */
+  fg = cur_attr & 15;
+  bg = (cur_attr >> 4) & 15;
+
+  /* Walk the buffer, writing text directly to video RAM,
+     changing color attributes when an escape sequence is seen.  */
+  for (anchor = p_next = cbuf;
+       (p_next = memchr (p_next, ESC, buflen - (p_next - cbuf))) != 0; )
+    {
+      char *p = p_next;
+
+      /* Handle the null escape sequence (ESC-[m), which is used to
+         restore the original color. */
+      if ((p[1] == '[') && (p[2] == 'm'))
+        {
+          textattr (norm_attr);
+          p += 3;
+          anchor = p_next = p;
+          continue;
+        }
+
+      if (p[1] == '[') /* "Esc-[" sequence */
+        {
+          /* If some chars seen since the last escape sequence,
+             write it out to the screen using current text attributes.  */
+          if (p > anchor)
+            {
+              *p = '\0'; /* `cputs' needs ASCIIZ string */
+              screen_puts (anchor, p);
+              *p = ESC; /* restore the ESC character */
+              anchor = p;
+            }
+          p += 2; /* get past "Esc-[" sequence */
+          p_next = p;
+          while (*p != 'm') /* `m' ends the escape sequence */
+            {
+              char *q;
+              long code = strtol (p, &q, 10);
+
+              if (!*q)
+                {
+                  /* Incomplete escape sequence.  Remember the part
+                     we've seen for the next time.  */
+                  leftover = q - anchor;
+                  if (leftover >= cbuf_len)
+                    {
+                      cbuf_len += 1 + leftover;
+                      cbuf = (char *)xrealloc (cbuf, cbuf_len);
+                    }
+                  strcpy (cbuf, anchor);
+                  *retval = buflen; /* that's a lie, but we have to! */
+                  return 1;
+                }
+
+              /* 
+                 Sanity checks:
+
+                 q > p unless p doesn't point to a number;
+                 ANSI codes are between 0 and 49;
+                 Each ANSI code ends with a `;' or an `m'.
+
+                 If any of the above is violated, we just ignore the bogon.
+              */
+              if (q == p || code > 49 || code < 0 || (*q != 'm' && *q != ';'))
+                {
+                  p_next = q;
+                  break;
+                }
+              if (*q == ';') /* more codes to follow */
+                q++;
+
+              /* Convert ANSI codes to color fore- and background.  */
+              switch (code)
+                {
+                  case 0: /* all attributes off */
+                    fg = norm_attr & 15;
+                    bg = (norm_attr >> 4) & 15;
+                    break;
+                  case 1: /* intensity on */
+                    fg |= 8;
+                    break;
+                  case 4: /* underline on */
+                    fg |= 8; /* we can't, so make it bold instead */
+                    break;
+                  case 5: /* blink */
+                    if (cur_blink != 1)
+                      {
+                        blinkvideo (); /* ensure we are'nt in bright bg mode */
+                        cur_blink = 1;
+                      }
+                    bg |= 8;
+                    break;
+                  case 7: /* reverse video */
+                    {
+                      unsigned char t = fg;
+                      fg = bg;
+                      bg = t;
+
+                      /* If it was blinking before, let it blink after.  */
+                      if (fg & 8)
+                        bg |= 8;
+
+                      /* If the fg was bold, let the background be bold.  */
+                      if ((t & 8) && cur_blink != 0)
+                        {
+                          intensevideo ();
+                          cur_blink = 0;
+                        }
+                    }
+                    break;
+                  case 8: /* concealed on */
+                    fg = (bg & 7) | 8; /* make fg be like bg, only bright */
+                    break;
+                  case 30: case 31: case 32: case 33: /* foreground color */
+                  case 34: case 35: case 36: case 37:
+                    fg = (fg & 8) | (screen_color[code - 30] & 15);
+                    break;
+                  case 40: case 41: case 42: case 43: /* background color */
+                  case 44: case 45: case 46: case 47:
+                    bg = (bg & 8) | (screen_color[code - 40] & 15);
+                    break;
+                  case 39: /* default fg */
+                    fg = norm_attr & 15;
+                    break;
+                  case 49:
+                    bg = (norm_attr >> 4) & 15;
+                    break;
+                  default:
+                    p_next = q; /* ignore unknown codes */
+                    break;
+                }
+              p = q;
+            } /* while loop */
+
+          if (*p == 'm' && p > p_next)
+            {
+              /* They don't *really* want it invisible, do they?  */
+              if (fg == (bg & 7))
+                fg |= 8; /* make it concealed instead */
+
+              /* Construct the text attribute and set it.  */
+              cur_attr = (bg << 4) | fg;
+              textattr (cur_attr);
+              p_next = anchor = p + 1;
+            }
+          else
+            break;
+        }
+      else
+        p_next++;
+    }  /* for loop */
+
+  /* Output what's left in the buffer.  */
+  screen_puts (anchor, buf_end);
+  leftover = 0;
+  *retval = buflen;
+  return 1;
+}
+
+/* This is called before `main' to install our STDOUT redirector.  */
+static void __attribute__((constructor))
+djgpp_grep_startup (void)
+{
+  __FSEXT_set_function (STDOUT_FILENO, msdos_screen_write);
+  isatty_stdout = isatty (STDOUT_FILENO);
+  atexit (restore_blink_bit);
+}
+#endif  /* __DJGPP__ */
+#endif
diff -aprNU5 grep-2.5.3.orig/src/system.h grep-2.5.3/src/system.h
--- grep-2.5.3.orig/src/system.h	2007-06-28 18:57:18 +0000
+++ grep-2.5.3/src/system.h	2007-08-10 23:26:36 +0000
@@ -78,10 +78,14 @@ extern char *sys_errlist[];
 # define FILESYSTEM_PREFIX_LEN(f) 0
 #endif
 
 int isdir PARAMS ((char const *));
 
+#if __DJGPP__ == 2 && __DJGPP_MINOR__ < 4
+# define HAVE_DIR_EACCES_BUG
+#endif
+
 #ifdef HAVE_DIR_EACCES_BUG
 # ifdef EISDIR
 #  define is_EISDIR(e, f) \
      ((e) == EISDIR \
       || ((e) == EACCES && isdir (f) && ((e) = EISDIR, 1)))
diff -aprNU5 grep-2.5.3.orig/src/dosbuf.c grep-2.5.3/src/dosbuf.c
--- grep-2.5.3.orig/src/dosbuf.c	2008-01-20 17:58:56 +0000
+++ grep-2.5.3/src/dosbuf.c	2008-01-20 18:13:00 +0000
@@ -181,22 +181,10 @@ dossified_pos (off_t byteno)
     }
 
   return byteno + dos_pos_map[out_map_idx].add;
 }
 
-#if 0
-/*
- *  Original support colorization written for the DJGPP port of grep 2.5.1.
- *  The way colorization is handled in grep 2.5.3 has changed.  They have
- *  begun using SGR (Select Graphic Rendition )commands that the actual
- *  DJGPP code is not capable to understand.  It will require some time
- *  until I can fix this.
- *
- *  Juan Manuel Guerrero, 2007-08-12
- */
-
-
 #ifdef __DJGPP__
 /*  Screen write redirection.  We need this to support colorization
     without requiring ANSI.SYS driver (or its work-alike) to be loaded.
 
     This function uses the DJGPP filesystem extensions mechanism.  It is
@@ -289,10 +277,12 @@ screen_puts (char *buf, char *buf_end)
   /* Output whatever is left.  */
   cputs (q);
 }
 
 #define ESC '\033'
+#define IS_SGR(s) (((s)[1] == '[') && ((s)[2] == 'm'))
+#define IS_EL(s)  (((s)[1] == '[') && ((s)[2] == 'K'))
 
 /* Screen writes redirector function.  */
 static int
 msdos_screen_write (__FSEXT_Fnumber func, int *retval, va_list rest_args)
 {
@@ -364,31 +354,42 @@ msdos_screen_write (__FSEXT_Fnumber func
   for (anchor = p_next = cbuf;
        (p_next = memchr (p_next, ESC, buflen - (p_next - cbuf))) != 0; )
     {
       char *p = p_next;
 
+
+      /* If some chars seen since the last escape sequence,
+         write it out to the screen using current text attributes.  */
+      if (p > anchor)
+        {
+          *p = '\0'; /* `cputs' needs ASCIIZ string */
+          screen_puts (anchor, p);
+          *p = ESC; /* restore the ESC character */
+          anchor = p;
+        }
+
       /* Handle the null escape sequence (ESC-[m), which is used to
          restore the original color. */
-      if ((p[1] == '[') && (p[2] == 'm'))
+      if (IS_SGR(p))
         {
           textattr (norm_attr);
           p += 3;
           anchor = p_next = p;
           continue;
         }
 
+      /* Handle the erase in line to the right escape sequence (ESC-[K). */
+      if (IS_EL(p))
+        {
+          clreol();
+          p += 3;
+          anchor = p_next = p;
+          continue;
+        }
+
       if (p[1] == '[') /* "Esc-[" sequence */
         {
-          /* If some chars seen since the last escape sequence,
-             write it out to the screen using current text attributes.  */
-          if (p > anchor)
-            {
-              *p = '\0'; /* `cputs' needs ASCIIZ string */
-              screen_puts (anchor, p);
-              *p = ESC; /* restore the ESC character */
-              anchor = p;
-            }
           p += 2; /* get past "Esc-[" sequence */
           p_next = p;
           while (*p != 'm') /* `m' ends the escape sequence */
             {
               char *q;
@@ -411,12 +412,12 @@ msdos_screen_write (__FSEXT_Fnumber func
 
               /* 
                  Sanity checks:
 
                  q > p unless p doesn't point to a number;
-                 ANSI codes are between 0 and 49;
-                 Each ANSI code ends with a `;' or an `m'.
+                 SGR codes supported by ANSI.SYS are between 0 and 49;
+                 Each SGR code ends with a `;' or an `m'.
 
                  If any of the above is violated, we just ignore the bogon.
               */
               if (q == p || code > 49 || code < 0 || (*q != 'm' && *q != ';'))
                 {
@@ -521,6 +522,5 @@ djgpp_grep_startup (void)
   __FSEXT_set_function (STDOUT_FILENO, msdos_screen_write);
   isatty_stdout = isatty (STDOUT_FILENO);
   atexit (restore_blink_bit);
 }
 #endif  /* __DJGPP__ */
-#endif
diff -aprNU5 grep-2.5.3.orig/src/grep.c grep-2.5.3/src/grep.c
--- grep-2.5.3.orig/src/grep.c	2007-06-28 18:57:18 +0000
+++ grep-2.5.3/src/grep.c	2008-01-20 18:12:18 +0000
@@ -53,10 +53,16 @@
 
 #define SEP_CHAR_SELECTED ':'
 #define SEP_CHAR_REJECTED '-'
 #define SEP_STR_GROUP    "--"
 
+#ifdef __DJGPP__
+# define IS_TERMINAL (isatty(STDOUT_FILENO))
+#else
+# define IS_TERMINAL (isatty(STDOUT_FILENO) && getenv("TERM") && strcmp(getenv("TERM"), "dumb"))
+#endif
+
 struct stats
 {
   struct stats const *parent;
   struct stat stat;
 };
@@ -2092,15 +2098,11 @@ main (int argc, char **argv)
           else
             show_help = 1;
         } else
           color_option = 2;
         if(color_option == 2) {
-          if(isatty(STDOUT_FILENO) && getenv("TERM") &&
-	     strcmp(getenv("TERM"), "dumb"))
-                  color_option = 1;
-          else
-            color_option = 0;
+          color_option = (IS_TERMINAL) ? 1 : 0;
         }
 	break;
 
       case EXCLUDE_OPTION:
 	if (!excluded_patterns)
