2019-01-06  Juan Manuel Guerrero <juan.guerrero@gmx.de>

	* lib/open.c [__DJGPP__]: Include "dosname.h" for ISSLASH definition.
	(open): Use ISSLASH to check for slash and/or backslash as directory
	separator.

	* lib/progname.c [MSDOS]: Define new macro GET_LAST_SLASH to find
	the last directory separator character.  On DOS-like systems these
	are slash, backslash or colon.  For POSIX this is simple a slash.
	(set_program_name): Use GET_LAST_SLASH to check for slash and/or
	backslash in the path.

	* lib/tempname.c: New macro HAVE_DIFFERENT_TMPDIR.  Value depends
	on if the OS is posix or not.
	(direxists): Use ISSLASH to check for the OS dependent directory
	separator character.  Use HAVE_DIFFERENT_TMPDIR to check for TMP
	and TEMP too, if none of them are defined or do not point to an
	existing directory default to the current directory.

	* src/cmp.c (main): Use CANONICALIZE_PATH to canonicalize the
	passed file names.
	Use STRIP_EXTENSION to strip path and extension from argv[0].
	Use SET_BINARY instead of set_binary_mode to change file mode
	to O_BINARY.

	* src/diff.c (main): Use CANONICALIZE_PATH to canonicalize
	the passed file names.
	Use STRIP_EXTENSION to strip path and extension from argv[0].
	Use SET_BINARY instead of set_binary_mode to change file mode
	to O_BINARY.
	Use IS_TERMINAL to decide if color shall be used or not.

	* src/sdiff.c (main): Use CANONICALIZE_PATH to canonicalize
	the passed file names.
	Use STRIP_EXTENSION to strip path and extension from argv[0].
	(temporary_file) [HAVE_LFN_SUPPORT]: Use HAVE_LFN_SUPPORT to
	determinate at run time the temp file pattern to be used.

	* src/diff3.c (main): Use CANONICALIZE_PATH to canonicalize
	the passed file names.
	Use STRIP_EXTENSION to strip path and extension from argv[0].

	* src/util.c [__DJGPP__]: New functions: restore_blink_bit, screen_puts,
	msdos_screen_write and djgpp_diff_startup to provide colorization support
	without having an ANSI.SYS driver loaded.

	* src/system.h [DJGPP]: New macro CANONICALIZE_PATH defined.
	For all other systems this is a no-ops.
	New macros HAVE_LFN_SUPPORT and STRIP_FULL_PATH_AND_EXTENSION
	defined.  For all other systems these are no-ops.
	New macro IS_TERMINAL defined.  For all other systems this is
	a no-ops.






diff -aprNU5 diffutils-3.7.orig/lib/getprogname.c diffutils-3.7/lib/getprogname.c
--- diffutils-3.7.orig/lib/getprogname.c	2018-12-24 01:25:28 +0000
+++ diffutils-3.7/lib/getprogname.c	2019-01-06 04:39:14 +0000
@@ -49,10 +49,14 @@
 # include <stdio.h>
 # include <fcntl.h>
 # include <sys/procfs.h>
 #endif
 
+#ifdef __DJGPP__
+# include <crt0.h>
+#endif
+
 #include "dirname.h"
 
 #ifndef HAVE_GETPROGNAME             /* not Mac OS X, FreeBSD, NetBSD, OpenBSD >= 5.4, Cygwin */
 char const *
 getprogname (void)
@@ -238,10 +242,12 @@ getprogname (void)
               return memcpy (namecopy, name, namelen);
             }
         }
     }
   return NULL;
+# elif __DJGPP__
+  return last_component (__crt0_argv ? __crt0_argv[0] : __dos_argv0);
 # else
 #  error "getprogname module not ported to this OS"
 # endif
 }
 
diff -aprNU5 diffutils-3.7.orig/lib/open.c diffutils-3.7/lib/open.c
--- diffutils-3.7.orig/lib/open.c	2018-06-25 04:08:28 +0000
+++ diffutils-3.7/lib/open.c	2019-01-06 04:39:14 +0000
@@ -31,10 +31,14 @@ static int
 orig_open (const char *filename, int flags, mode_t mode)
 {
   return open (filename, flags, mode);
 }
 
+#ifndef ISSLASH
+# include "dosname.h"
+#endif
+
 /* Specification.  */
 /* Write "fcntl.h" here, not <fcntl.h>, otherwise OSF/1 5.1 DTK cc eliminates
    this include because of the preliminary #include <fcntl.h> above.  */
 #include "fcntl.h"
 
@@ -114,11 +118,11 @@ open (const char *filename, int flags, .
        - if O_WRONLY or O_RDWR is specified, open() must fail because the
          file does not contain a '.' directory.  */
   if (flags & (O_CREAT | O_WRONLY | O_RDWR))
     {
       size_t len = strlen (filename);
-      if (len > 0 && filename[len - 1] == '/')
+      if (len > 0 && ISSLASH (filename[len - 1]))
         {
           errno = EISDIR;
           return -1;
         }
     }
@@ -183,11 +187,11 @@ open (const char *filename, int flags, .
      with ENOTDIR.  */
   if (fd >= 0)
     {
       /* We know len is positive, since open did not fail with ENOENT.  */
       size_t len = strlen (filename);
-      if (filename[len - 1] == '/')
+      if (ISSLASH (filename[len - 1]))
         {
           struct stat statbuf;
 
           if (fstat (fd, &statbuf) >= 0 && !S_ISDIR (statbuf.st_mode))
             {
diff -aprNU5 diffutils-3.7.orig/lib/tempname.c diffutils-3.7/lib/tempname.c
--- diffutils-3.7.orig/lib/tempname.c	2018-01-07 00:45:52 +0000
+++ diffutils-3.7/lib/tempname.c	2019-01-06 04:39:14 +0000
@@ -28,10 +28,16 @@
 #include <errno.h>
 #ifndef __set_errno
 # define __set_errno(Val) errno = (Val)
 #endif
 
+#ifdef MSDOS
+# define HAVE_DIFFERENT_TMPDIR  1
+#else
+# define HAVE_DIFFERENT_TMPDIR  0
+#endif
+
 #include <stdio.h>
 #ifndef P_tmpdir
 # define P_tmpdir "/tmp"
 #endif
 #ifndef TMP_MAX
@@ -136,30 +142,41 @@ __path_search (char *tmpl, size_t tmpl_l
   if (try_tmpdir)
     {
       d = __secure_getenv ("TMPDIR");
       if (d != NULL && direxists (d))
         dir = d;
+#if HAVE_DIFFERENT_TMPDIR
+      else if ((d = __secure_getenv ("TMP")) && direxists (d))
+	dir = d;
+      else if ((d = __secure_getenv ("TEMP")) && direxists (d))
+	dir = d;
+#endif
       else if (dir != NULL && direxists (dir))
         /* nothing */ ;
       else
         dir = NULL;
     }
   if (dir == NULL)
     {
       if (direxists (P_tmpdir))
         dir = P_tmpdir;
+#if !HAVE_DIFFERENT_TMPDIR
       else if (strcmp (P_tmpdir, "/tmp") != 0 && direxists ("/tmp"))
         dir = "/tmp";
+#else
+      else if (strcmp (P_tmpdir, ".") != 0 && direxists ("."))
+	dir = "./";
+#endif
       else
         {
           __set_errno (ENOENT);
           return -1;
         }
     }
 
   dlen = strlen (dir);
-  while (dlen > 1 && dir[dlen - 1] == '/')
+  while (dlen > 1 && ISSLASH (dir[dlen - 1]))
     dlen--;                     /* remove trailing slashes */
 
   /* check we have room for "${dir}/${pfx}XXXXXX\0" */
   if (tmpl_len < dlen + 1 + plen + 6 + 1)
     {
diff -aprNU5 diffutils-3.7.orig/src/cmp.c diffutils-3.7/src/cmp.c
--- diffutils-3.7.orig/src/cmp.c	2018-07-26 02:02:36 +0000
+++ diffutils-3.7/src/cmp.c	2019-01-06 04:39:14 +0000
@@ -265,10 +265,12 @@ main (int argc, char **argv)
   if (optind == argc)
     try_help ("missing operand after '%s'", argv[argc - 1]);
 
   file[0] = argv[optind++];
   file[1] = optind < argc ? argv[optind++] : "-";
+  CANONICALIZE_PATH(file[0]);
+  CANONICALIZE_PATH(file[1]);
 
   for (f = 0; f < 2 && optind < argc; f++)
     {
       char *arg = argv[optind++];
       specify_ignore_initial (f, &arg, 0);
diff -aprNU5 diffutils-3.7.orig/src/diff.c diffutils-3.7/src/diff.c
--- diffutils-3.7.orig/src/diff.c	2018-12-30 23:38:16 +0000
+++ diffutils-3.7/src/diff.c	2019-01-06 04:39:14 +0000
@@ -659,11 +659,15 @@ main (int argc, char **argv)
     }
 
   if (colors_style == AUTO)
     {
       char const *t = getenv ("TERM");
-      if (t && STREQ (t, "dumb"))
+      if (t && STREQ (t, "dumb")
+#ifdef IS_TERMINAL
+          || !IS_TERMINAL
+#endif
+         )
         colors_style = NEVER;
     }
 
   if (output_style == OUTPUT_UNSPECIFIED)
     {
@@ -771,21 +775,21 @@ main (int argc, char **argv)
       if (to_file)
 	fatal ("--from-file and --to-file both specified");
       else
 	for (; optind < argc; optind++)
 	  {
-	    int status = compare_files (NULL, from_file, argv[optind]);
+	    int status = compare_files (NULL, from_file, CANONICALIZE_PATH(argv[optind]));
 	    if (exit_status < status)
 	      exit_status = status;
 	  }
     }
   else
     {
       if (to_file)
 	for (; optind < argc; optind++)
 	  {
-	    int status = compare_files (NULL, argv[optind], to_file);
+	    int status = compare_files (NULL, CANONICALIZE_PATH(argv[optind]), to_file);
 	    if (exit_status < status)
 	      exit_status = status;
 	  }
       else
 	{
@@ -795,10 +799,12 @@ main (int argc, char **argv)
 		try_help ("missing operand after '%s'", argv[argc - 1]);
 	      else
 		try_help ("extra operand '%s'", argv[optind + 2]);
 	    }
 
+	  CANONICALIZE_PATH(argv[optind]);
+	  CANONICALIZE_PATH(argv[optind + 1]);
 	  exit_status = compare_files (NULL, argv[optind], argv[optind + 1]);
 	}
     }
 
   /* Print any messages that were saved up for last.  */
diff -aprNU5 diffutils-3.7.orig/src/sdiff.c diffutils-3.7/src/sdiff.c
--- diffutils-3.7.orig/src/sdiff.c	2018-06-07 00:00:42 +0000
+++ diffutils-3.7/src/sdiff.c	2019-01-06 04:39:14 +0000
@@ -453,10 +453,11 @@ main (int argc, char *argv[])
   set_program_name (argv[0]);
   setlocale (LC_ALL, "");
   bindtextdomain (PACKAGE, LOCALEDIR);
   textdomain (PACKAGE);
   c_stack_action (cleanup);
+  STRIP_EXTENSION(argv[0]);
 
   prog = getenv ("EDITOR");
   if (prog)
     editor_program = prog;
 
@@ -586,12 +587,12 @@ main (int argc, char *argv[])
       FILE *left, *right, *out, *diffout;
       bool interact_ok;
       struct line_filter lfilt;
       struct line_filter rfilt;
       struct line_filter diff_filt;
-      bool leftdir = diraccess (argv[optind]);
-      bool rightdir = diraccess (argv[optind + 1]);
+      bool leftdir = diraccess (CANONICALIZE_PATH(argv[optind]));
+      bool rightdir = diraccess (CANONICALIZE_PATH(argv[optind + 1]));
 
       if (leftdir & rightdir)
 	fatal ("both files to be compared are directories");
 
       lname = expand_name (argv[optind], leftdir, argv[optind + 1]);
diff -aprNU5 diffutils-3.7.orig/src/system.h diffutils-3.7/src/system.h
--- diffutils-3.7.orig/src/system.h	2018-12-30 23:38:16 +0000
+++ diffutils-3.7/src/system.h	2019-01-06 06:45:40 +0000
@@ -165,11 +165,31 @@ verify (LIN_MAX <= TYPE_MAXIMUM (printin
 #ifndef file_name_cmp
 # define file_name_cmp strcmp
 #endif
 
 #ifndef initialize_main
-# define initialize_main(argcp, argvp)
+# if defined __DJGPP__ && 0
+#  define initialize_main(argcp, argvp)                   \
+   (__gnuc_extension__                                    \
+     ({                                                   \
+        extern char __djgpp_program_invocation_name[];    \
+        char *_name = CANONICALIZE_PATH((*(argvp))[0]);   \
+                                                          \
+        int i;                                            \
+        for (i = 0; _name[i] && i < FILENAME_MAX; i++)    \
+          __djgpp_program_invocation_name[i] = _name[i];  \
+        for (; i; i--)                                    \
+          if (__djgpp_program_invocation_name[i] == '.')  \
+          {                                               \
+            __djgpp_program_invocation_name[i] = '\0';    \
+            break;                                        \
+          }                                               \
+     })                                                   \
+   )
+# else /* NOT __DJGPP__ */
+#  define initialize_main(argcp, argvp)
+# endif
 #endif
 
 #ifndef NULL_DEVICE
 # define NULL_DEVICE "/dev/null"
 #endif
@@ -236,5 +256,88 @@ verify (LIN_MAX <= TYPE_MAXIMUM (printin
 #  define FALLTHROUGH ((void) 0)
 # else
 #  define FALLTHROUGH __attribute__ ((__fallthrough__))
 # endif
 #endif
+
+
+#if O_BINARY
+# ifdef __DJGPP__
+/* MS-DOS and similar non-Posix systems have some peculiarities:
+    - they use both `/' and `\\' as directory separator in file names;
+    - they can have a drive letter X: prepended to a file name;
+   These are all parameterized here.  */
+
+#  if defined (__GNUC__) && (__GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 8))
+#   define __gnuc_extension__  __extension__
+#  else
+#   define __gnuc_extension__
+#  endif
+#  include <libc/unconst.h>
+#  define IS_DIR_SEPARATOR(c)  ((c) == '/' || (c) == '\\' || (c) == ':')
+
+#  define STRIP_FULL_PATH_AND_EXTENSION(file_name)          \
+   (__gnuc_extension__                                      \
+     ({                                                     \
+        char *_dst, *_src;                                  \
+        _dst = _src = unconst((file_name), char *);         \
+        while (*_src++)                                     \
+          ;                                                 \
+        while ((_src - _dst) && (*--_src != '.'))           \
+          ;                                                 \
+        for (*_src = '\0'; (_src - _dst); _src--)           \
+          if (IS_DIR_SEPARATOR(*_src))                      \
+            break;                                          \
+        if (_src - _dst)                                    \
+          while ((*_dst++ = *++_src))                       \
+            ;                                               \
+        (file_name);                                        \
+     })                                                     \
+   )
+
+#  define STRIP_EXTENSION(file_name)                        \
+   (__gnuc_extension__                                      \
+     ({                                                     \
+        char *_begin, *_end;                                \
+        _begin = _end = unconst((file_name), char *);       \
+        while (*_end++)                                     \
+          ;                                                 \
+        while ((_end - _begin) && (*--_end != '.'))         \
+          ;                                                 \
+        if (*_end == '.')                                   \
+          *_end = '\0';                                     \
+        (file_name);                                        \
+     })                                                     \
+   )
+
+#  define CANONICALIZE_PATH(path)                           \
+   (__gnuc_extension__                                      \
+     ({                                                     \
+        if ((path))                                         \
+        {                                                   \
+          char *_p = unconst((path), char *);               \
+          for (; *_p; _p++)                                 \
+            if (*_p == '\\')                                \
+              *_p = '/';                                    \
+        }                                                   \
+        (path);                                             \
+     })                                                     \
+   )
+
+#  define HAVE_LFN_SUPPORT(name)                    (pathconf ((name), _PC_NAME_MAX) > 12)
+# else  /* !__DJGPP__  */
+#  define STRIP_FULL_PATH_AND_EXTENSION(file_name)  (file_name)
+#  define STRIP_EXTENSION(file_name)                (file_name)
+#  define CANONICALIZE_PATH(path)                   (path)
+#  define HAVE_LFN_SUPPORT(name)                    (false)
+# endif  /* !__DJGPP__  */
+
+/*  If compiled with DJGPP do not check for the term environment
+    variable to decided which value should color_option have.
+*/
+# define IS_TERMINAL                                (isatty(STDOUT_FILENO))
+#else  /* !O_BINARY  */
+# define STRIP_FULL_PATH_AND_EXTENSION(file_name)   (file_name)
+# define STRIP_EXTENSION(file_name)                 (file_name)
+# define CANONICALIZE_PATH(path)                    (path)
+# define HAVE_LFN_SUPPORT(name)                     (true)
+#endif  /* !O_BINARY  */
diff -aprNU5 diffutils-3.7.orig/src/util.c diffutils-3.7/src/util.c
--- diffutils-3.7.orig/src/util.c	2018-12-29 04:36:24 +0000
+++ diffutils-3.7/src/util.c	2019-01-06 04:39:14 +0000
@@ -1572,5 +1572,355 @@ debug_script (struct change *sp)
 	       line0, line1, deleted, inserted);
     }
 
   fflush (stderr);
 }
+
+
+#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>
+#include <pc.h> /* for `ScreenGetCursor' */
+
+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 (colors_style == NEVER || 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_diff_startup (void)
+{
+  __FSEXT_set_function (STDOUT_FILENO, msdos_screen_write);
+  isatty_stdout = isatty (STDOUT_FILENO);
+  atexit (restore_blink_bit);
+}
+
+#endif  /* __DJGPP__ */
