2009-02-15  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/system.h [DJGPP]: Depend on __DJGPP__ and __DJGPP_MINOR__
	to define HAVE_DIR_EACCES_BUG.

	* 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.

	* 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.  
	(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.






diff -aprNU5 grep-2.5.4.orig/lib/isdir.c grep-2.5.4/lib/isdir.c
--- grep-2.5.4.orig/lib/isdir.c	2007-06-28 19:10:44 +0000
+++ grep-2.5.4/lib/isdir.c	2009-02-15 01:29:12 +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.4.orig/src/dosbuf.c grep-2.5.4/src/dosbuf.c
--- grep-2.5.4.orig/src/dosbuf.c	2009-01-31 05:39:54 +0000
+++ grep-2.5.4/src/dosbuf.c	2009-02-15 02:09:32 +0000
@@ -16,18 +16,21 @@
    along with this program; if not, write to the Free Software
    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
    02110-1301, USA.  */
 
 /* 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
@@ -196,5 +199,346 @@ dossified_pos (off_t byteno)
         out_map_idx--;
     }
 
   return byteno + dos_pos_map[out_map_idx].add;
 }
+
+#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'
+#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)
+{
+  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;
+
+      /* 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 (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 */
+        {
+          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;
+                 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 != ';'))
+                {
+                  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__ */
diff -aprNU5 grep-2.5.4.orig/src/grep.c grep-2.5.4/src/grep.c
--- grep-2.5.4.orig/src/grep.c	2009-02-03 18:49:52 +0000
+++ grep-2.5.4/src/grep.c	2009-02-15 01:37:42 +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;
 };
@@ -2101,15 +2107,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)
diff -aprNU5 grep-2.5.4.orig/src/system.h grep-2.5.4/src/system.h
--- grep-2.5.4.orig/src/system.h	2009-01-31 05:39:54 +0000
+++ grep-2.5.4/src/system.h	2009-02-15 01:33:42 +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)))
