From 1eec41db86de1e48e1ca1cb1ce0bf41da25ed1c6 Mon Sep 17 00:00:00 2001
From: Brad King <brad.king@kitware.com>
Date: Sat, 22 Apr 2006 20:20:12 -0400
Subject: [PATCH] ENH: Adding 'Terminal' component to hold support routines for
 dealing with interactive terminals.  Currently only a cfprintf function is
 provided to print color messages.

---
 CMakeLists.txt |  14 +-
 Terminal.c     | 398 +++++++++++++++++++++++++++++++++++++++++++++++++
 Terminal.h.in  | 157 +++++++++++++++++++
 testTerminal.c |  31 ++++
 4 files changed, 595 insertions(+), 5 deletions(-)
 create mode 100644 Terminal.c
 create mode 100644 Terminal.h.in
 create mode 100644 testTerminal.c

diff --git a/CMakeLists.txt b/CMakeLists.txt
index d3008a6f..79a13e66 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -94,6 +94,7 @@ IF(KWSYS_STANDALONE OR CMake_SOURCE_DIR)
   SET(KWSYS_USE_SystemTools 1)
   SET(KWSYS_USE_CommandLineArguments 1)
   SET(KWSYS_USE_FundamentalType 1)
+  #SET(KWSYS_USE_Terminal 1)
 ENDIF(KWSYS_STANDALONE OR CMake_SOURCE_DIR)
 
 #-----------------------------------------------------------------------------
@@ -436,7 +437,7 @@ FOREACH(cpp ${cppclasses})
 ENDFOREACH(cpp)
 
 # Add selected C components.
-FOREACH(c Process Base64 FundamentalType)
+FOREACH(c Process Base64 FundamentalType Terminal)
   IF(KWSYS_USE_${c})
     SET(KWSYS_H_FILES ${KWSYS_H_FILES} ${c})
   ENDIF(KWSYS_USE_${c})
@@ -463,10 +464,12 @@ IF(KWSYS_USE_Process)
   ENDIF(NOT UNIX)
 ENDIF(KWSYS_USE_Process)
 
-# Add sources for Base64 encoding.
-IF(KWSYS_USE_Base64)
-  SET(KWSYS_C_SRCS ${KWSYS_C_SRCS} Base64.c)
-ENDIF(KWSYS_USE_Base64)
+# Add selected C sources.
+FOREACH(c Base64 Terminal)
+  IF(KWSYS_USE_${c})
+    SET(KWSYS_C_SRCS ${KWSYS_C_SRCS} ${c}.c)
+  ENDIF(KWSYS_USE_${c})
+ENDFOREACH(c)
 
 # Configure headers of C++ classes and construct the list of sources.
 FOREACH(c ${KWSYS_CLASSES})
@@ -632,6 +635,7 @@ IF(KWSYS_STANDALONE OR CMake_SOURCE_DIR)
     FOREACH(test
         testProcess
         testFail
+        # testTerminal
         )
       ADD_EXECUTABLE(${test} ${test}.c)
       TARGET_LINK_LIBRARIES(${test} ${KWSYS_NAMESPACE}_c)
diff --git a/Terminal.c b/Terminal.c
new file mode 100644
index 00000000..a9f8cc13
--- /dev/null
+++ b/Terminal.c
@@ -0,0 +1,398 @@
+/*=========================================================================
+
+  Program:   KWSys - Kitware System Library
+  Module:    Terminal.c
+
+  Copyright (c) Kitware, Inc., Insight Consortium.  All rights reserved.
+  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
+
+     This software is distributed WITHOUT ANY WARRANTY; without even
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+     PURPOSE.  See the above copyright notices for more information.
+
+=========================================================================*/
+#include "kwsysPrivate.h"
+#include KWSYS_HEADER(Terminal.h)
+
+/* Work-around CMake dependency scanning limitation.  This must
+   duplicate the above list of headers.  */
+#if 0
+# include "Terminal.h.in"
+#endif
+
+/*--------------------------------------------------------------------------*/
+/* Configure support for this platform.  */
+#if defined(_WIN32) || defined(__CYGWIN__)
+# define KWSYS_TERMINAL_SUPPORT_CONSOLE
+#endif
+#if !defined(_WIN32)
+# define KWSYS_TERMINAL_ISATTY_WORKS
+#endif
+
+/*--------------------------------------------------------------------------*/
+/* Include needed system APIs.  */
+
+#include <stdlib.h> /* getenv */
+#include <stdarg.h> /* va_list */
+
+#if defined(KWSYS_TERMINAL_SUPPORT_CONSOLE)
+# include <windows.h> /* SetConsoleTextAttribute */
+# include <io.h>      /* _get_osfhandle */
+#endif
+
+#if defined(KWSYS_TERMINAL_ISATTY_WORKS)
+# include <unistd.h> /* isatty */
+#else
+# include <sys/stat.h> /* fstat */
+#endif
+
+/*--------------------------------------------------------------------------*/
+static int kwsysTerminalStreamIsVT100(FILE* stream, int default_vt100,
+                                      int default_tty);
+static void kwsysTerminalSetVT100Color(FILE* stream, int color);
+#if defined(KWSYS_TERMINAL_SUPPORT_CONSOLE)
+static HANDLE kwsysTerminalGetStreamHandle(FILE* stream);
+static void kwsysTerminalSetConsoleColor(HANDLE hOut,
+                                         CONSOLE_SCREEN_BUFFER_INFO* hOutInfo,
+                                         FILE* stream,
+                                         int color);
+#endif
+
+/*--------------------------------------------------------------------------*/
+void kwsysTerminal_cfprintf(int color, FILE* stream, const char* format, ...)
+{
+  /* Setup the stream with the given color if possible.  */
+  int pipeIsConsole;
+  int pipeIsVT100;
+  int default_vt100 = color & kwsysTerminal_Color_AssumeTTY;
+  int default_tty = color & kwsysTerminal_Color_AssumeTTY;
+#if defined(KWSYS_TERMINAL_SUPPORT_CONSOLE)
+  CONSOLE_SCREEN_BUFFER_INFO hOutInfo;
+  HANDLE hOut = kwsysTerminalGetStreamHandle(stream);
+  pipeIsConsole = GetConsoleScreenBufferInfo(hOut, &hOutInfo);
+  if(pipeIsConsole)
+    {
+    kwsysTerminalSetConsoleColor(hOut, &hOutInfo, stream, color);
+    }
+#endif
+  pipeIsVT100 = (!pipeIsConsole &&
+                 kwsysTerminalStreamIsVT100(stream,
+                                            default_vt100, default_tty));
+  if(pipeIsVT100)
+    {
+    kwsysTerminalSetVT100Color(stream, color);
+    }
+
+  /* Format the text into the stream.  */
+  {
+  va_list var_args;
+  va_start(var_args, format);
+  vfprintf(stream, format, var_args);
+  va_end(var_args);
+  }
+
+  /* Restore the normal color state for the stream.  */
+#if defined(KWSYS_TERMINAL_SUPPORT_CONSOLE)
+  if(pipeIsConsole)
+    {
+    kwsysTerminalSetConsoleColor(hOut, &hOutInfo, stream,
+                                 kwsysTerminal_Color_Normal);
+    }
+#endif
+  if(pipeIsVT100)
+    {
+    kwsysTerminalSetVT100Color(stream, kwsysTerminal_Color_Normal);
+    }
+}
+
+/*--------------------------------------------------------------------------*/
+/* Detect cases when a stream is definately not interactive.  */
+#if !defined(KWSYS_TERMINAL_ISATTY_WORKS)
+static int kwsysTerminalStreamIsNotInteractive(FILE* stream)
+{
+  /* The given stream is definately not interactive if it is a regular
+     file.  */
+  struct stat stream_stat;
+  if(fstat(fileno(stream), &stream_stat) == 0)
+    {
+    if(stream_stat.st_mode & S_IFREG)
+      {
+      return 1;
+      }
+    }
+  return 0;
+}
+#endif
+
+/*--------------------------------------------------------------------------*/
+/* List of terminal names known to support VT100 color escape sequences.  */
+static const char* kwsysTerminalVT100Names[] =
+{
+  "Eterm",
+  "ansi",
+  "color-xterm",
+  "con132x25",
+  "con132x30",
+  "con132x43",
+  "con132x60",
+  "con80x25",
+  "con80x28",
+  "con80x30",
+  "con80x43",
+  "con80x50",
+  "con80x60",
+  "console",
+  "konsole",
+  "linux",
+  "msys",
+  "rxvt",
+  "vt100",
+  "xterm",
+  "xterm-color",
+  0
+};
+
+/*--------------------------------------------------------------------------*/
+/* Detect whether a stream is displayed in a VT100-compatible terminal.  */
+static int kwsysTerminalStreamIsVT100(FILE* stream, int default_vt100,
+                                      int default_tty)
+{
+  /* Check for a valid terminal.  */
+  if(!default_vt100)
+    {
+    const char** t = 0;
+    const char* term = getenv("TERM");
+    if(term)
+      {
+      for(t = kwsysTerminalVT100Names; *t && strcmp(term, *t) != 0; ++t) {}
+      }
+    if(!(t && *t))
+      {
+      return 0;
+      }
+    }
+
+#if defined(KWSYS_TERMINAL_ISATTY_WORKS)
+  /* Make sure the stream is a tty. */
+  (void)default_tty;
+  return isatty(fileno(stream))? 1:0;
+#else
+  /* Check for cases in which the stream is definately not a tty.  */
+  if(kwsysTerminalStreamIsNotInteractive(stream))
+    {
+    return 0;
+    }
+
+  /* Use the provided default for whether this is a tty.  */
+  return default_tty;
+#endif
+}
+
+/*--------------------------------------------------------------------------*/
+/* VT100 escape sequence strings.  */
+#define KWSYS_TERMINAL_VT100_NORMAL              "\33[0m"
+#define KWSYS_TERMINAL_VT100_BOLD                "\33[1m"
+#define KWSYS_TERMINAL_VT100_UNDERLINE           "\33[4m"
+#define KWSYS_TERMINAL_VT100_BLINK               "\33[5m"
+#define KWSYS_TERMINAL_VT100_INVERSE             "\33[7m"
+#define KWSYS_TERMINAL_VT100_FOREGROUND_BLACK    "\33[30m"
+#define KWSYS_TERMINAL_VT100_FOREGROUND_RED      "\33[31m"
+#define KWSYS_TERMINAL_VT100_FOREGROUND_GREEN    "\33[32m"
+#define KWSYS_TERMINAL_VT100_FOREGROUND_YELLOW   "\33[33m"
+#define KWSYS_TERMINAL_VT100_FOREGROUND_BLUE     "\33[34m"
+#define KWSYS_TERMINAL_VT100_FOREGROUND_MAGENTA  "\33[35m"
+#define KWSYS_TERMINAL_VT100_FOREGROUND_CYAN     "\33[36m"
+#define KWSYS_TERMINAL_VT100_FOREGROUND_WHITE    "\33[37m"
+#define KWSYS_TERMINAL_VT100_BACKGROUND_BLACK    "\33[40m"
+#define KWSYS_TERMINAL_VT100_BACKGROUND_RED      "\33[41m"
+#define KWSYS_TERMINAL_VT100_BACKGROUND_GREEN    "\33[42m"
+#define KWSYS_TERMINAL_VT100_BACKGROUND_YELLOW   "\33[43m"
+#define KWSYS_TERMINAL_VT100_BACKGROUND_BLUE     "\33[44m"
+#define KWSYS_TERMINAL_VT100_BACKGROUND_MAGENTA  "\33[45m"
+#define KWSYS_TERMINAL_VT100_BACKGROUND_CYAN     "\33[46m"
+#define KWSYS_TERMINAL_VT100_BACKGROUND_WHITE    "\33[47m"
+
+/*--------------------------------------------------------------------------*/
+/* Write VT100 escape sequences to the stream for the given color.  */
+static void kwsysTerminalSetVT100Color(FILE* stream, int color)
+{
+  if(color == kwsysTerminal_Color_Normal)
+    {
+    fprintf(stream, KWSYS_TERMINAL_VT100_NORMAL);
+    return;
+    }
+
+  switch(color & kwsysTerminal_Color_ForegroundMask)
+    {
+    case kwsysTerminal_Color_Normal:
+      fprintf(stream, KWSYS_TERMINAL_VT100_NORMAL);
+      break;
+    case kwsysTerminal_Color_ForegroundBlack:
+      fprintf(stream, KWSYS_TERMINAL_VT100_FOREGROUND_BLACK);
+      break;
+    case kwsysTerminal_Color_ForegroundRed:
+      fprintf(stream, KWSYS_TERMINAL_VT100_FOREGROUND_RED);
+      break;
+    case kwsysTerminal_Color_ForegroundGreen:
+      fprintf(stream, KWSYS_TERMINAL_VT100_FOREGROUND_GREEN);
+      break;
+    case kwsysTerminal_Color_ForegroundYellow:
+      fprintf(stream, KWSYS_TERMINAL_VT100_FOREGROUND_YELLOW);
+      break;
+    case kwsysTerminal_Color_ForegroundBlue:
+      fprintf(stream, KWSYS_TERMINAL_VT100_FOREGROUND_BLUE);
+      break;
+    case kwsysTerminal_Color_ForegroundMagenta:
+      fprintf(stream, KWSYS_TERMINAL_VT100_FOREGROUND_MAGENTA);
+      break;
+    case kwsysTerminal_Color_ForegroundCyan:
+      fprintf(stream, KWSYS_TERMINAL_VT100_FOREGROUND_CYAN);
+      break;
+    case kwsysTerminal_Color_ForegroundWhite:
+      fprintf(stream, KWSYS_TERMINAL_VT100_FOREGROUND_WHITE);
+      break;
+    }
+  switch(color & kwsysTerminal_Color_BackgroundMask)
+    {
+    case kwsysTerminal_Color_BackgroundBlack:
+      fprintf(stream, KWSYS_TERMINAL_VT100_BACKGROUND_BLACK);
+      break;
+    case kwsysTerminal_Color_BackgroundRed:
+      fprintf(stream, KWSYS_TERMINAL_VT100_BACKGROUND_RED);
+      break;
+    case kwsysTerminal_Color_BackgroundGreen:
+      fprintf(stream, KWSYS_TERMINAL_VT100_BACKGROUND_GREEN);
+      break;
+    case kwsysTerminal_Color_BackgroundYellow:
+      fprintf(stream, KWSYS_TERMINAL_VT100_BACKGROUND_YELLOW);
+      break;
+    case kwsysTerminal_Color_BackgroundBlue:
+      fprintf(stream, KWSYS_TERMINAL_VT100_BACKGROUND_BLUE);
+      break;
+    case kwsysTerminal_Color_BackgroundMagenta:
+      fprintf(stream, KWSYS_TERMINAL_VT100_BACKGROUND_MAGENTA);
+      break;
+    case kwsysTerminal_Color_BackgroundCyan:
+      fprintf(stream, KWSYS_TERMINAL_VT100_BACKGROUND_CYAN);
+      break;
+    case kwsysTerminal_Color_BackgroundWhite:
+      fprintf(stream, KWSYS_TERMINAL_VT100_BACKGROUND_WHITE);
+      break;
+    }
+  if(color & kwsysTerminal_Color_ForegroundBold)
+    {
+    fprintf(stream, KWSYS_TERMINAL_VT100_BOLD);
+    }
+}
+
+/*--------------------------------------------------------------------------*/
+#if defined(KWSYS_TERMINAL_SUPPORT_CONSOLE)
+
+# define KWSYS_TERMINAL_MASK_FOREGROUND \
+  (FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_INTENSITY)
+# define KWSYS_TERMINAL_MASK_BACKGROUND \
+  (BACKGROUND_BLUE | BACKGROUND_GREEN | BACKGROUND_RED | BACKGROUND_INTENSITY)
+
+/* Get the Windows handle for a FILE stream.  */
+static HANDLE kwsysTerminalGetStreamHandle(FILE* stream)
+{
+  /* Get the C-library file descriptor from the stream.  */
+  int fd = fileno(stream);
+
+# if defined(__CYGWIN__)
+  /* Cygwin seems to have an extra pipe level.  If the file descriptor
+     corresponds to stdout or stderr then obtain the matching windows
+     handle directly.  */
+  if(fd == fileno(stdout))
+    {
+    return GetStdHandle(STD_OUTPUT_HANDLE);
+    }
+  else if(fd == fileno(stderr))
+    {
+    return GetStdHandle(STD_ERROR_HANDLE);
+    }
+# endif
+
+  /* Get the underlying Windows handle for the descriptor.  */
+  return (HANDLE)_get_osfhandle(fd);
+}
+
+/* Set color attributes in a Windows console.  */
+static void kwsysTerminalSetConsoleColor(HANDLE hOut,
+                                         CONSOLE_SCREEN_BUFFER_INFO* hOutInfo,
+                                         FILE* stream,
+                                         int color)
+{
+  WORD attributes = 0;
+  switch(color & kwsysTerminal_Color_ForegroundMask)
+    {
+    case kwsysTerminal_Color_Normal:
+      attributes |= hOutInfo->wAttributes & KWSYS_TERMINAL_MASK_FOREGROUND;
+      break;
+    case kwsysTerminal_Color_ForegroundBlack:
+      attributes |= 0;
+      break;
+    case kwsysTerminal_Color_ForegroundRed:
+      attributes |= FOREGROUND_RED;
+      break;
+    case kwsysTerminal_Color_ForegroundGreen:
+      attributes |= FOREGROUND_GREEN;
+      break;
+    case kwsysTerminal_Color_ForegroundYellow:
+      attributes |= FOREGROUND_RED | FOREGROUND_GREEN;
+      break;
+    case kwsysTerminal_Color_ForegroundBlue:
+      attributes |= FOREGROUND_BLUE;
+      break;
+    case kwsysTerminal_Color_ForegroundMagenta:
+      attributes |= FOREGROUND_RED | FOREGROUND_BLUE;
+      break;
+    case kwsysTerminal_Color_ForegroundCyan:
+      attributes |= FOREGROUND_BLUE | FOREGROUND_GREEN;
+      break;
+    case kwsysTerminal_Color_ForegroundWhite:
+      attributes |= FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED;
+      break;
+    }
+  switch(color & kwsysTerminal_Color_BackgroundMask)
+    {
+    case kwsysTerminal_Color_Normal:
+      attributes |= hOutInfo->wAttributes & KWSYS_TERMINAL_MASK_BACKGROUND;
+      break;
+    case kwsysTerminal_Color_BackgroundBlack:
+      attributes |= 0;
+      break;
+    case kwsysTerminal_Color_BackgroundRed:
+      attributes |= BACKGROUND_RED;
+      break;
+    case kwsysTerminal_Color_BackgroundGreen:
+      attributes |= BACKGROUND_GREEN;
+      break;
+    case kwsysTerminal_Color_BackgroundYellow:
+      attributes |= BACKGROUND_RED | BACKGROUND_GREEN;
+      break;
+    case kwsysTerminal_Color_BackgroundBlue:
+      attributes |= BACKGROUND_BLUE;
+      break;
+    case kwsysTerminal_Color_BackgroundMagenta:
+      attributes |= BACKGROUND_RED | BACKGROUND_BLUE;
+      break;
+    case kwsysTerminal_Color_BackgroundCyan:
+      attributes |= BACKGROUND_BLUE | BACKGROUND_GREEN;
+      break;
+    case kwsysTerminal_Color_BackgroundWhite:
+      attributes |= BACKGROUND_BLUE | BACKGROUND_GREEN | BACKGROUND_RED;
+      break;
+    }
+  if(color & kwsysTerminal_Color_ForegroundBold)
+    {
+    attributes |= FOREGROUND_INTENSITY;
+    }
+  if(color & kwsysTerminal_Color_BackgroundBold)
+    {
+    attributes |= BACKGROUND_INTENSITY;
+    }
+  fflush(stream);
+  SetConsoleTextAttribute(hOut, attributes);
+}
+#endif
diff --git a/Terminal.h.in b/Terminal.h.in
new file mode 100644
index 00000000..7db17d94
--- /dev/null
+++ b/Terminal.h.in
@@ -0,0 +1,157 @@
+/*=========================================================================
+
+  Program:   KWSys - Kitware System Library
+  Module:    Terminal.h.in
+
+  Copyright (c) Kitware, Inc., Insight Consortium.  All rights reserved.
+  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
+
+     This software is distributed WITHOUT ANY WARRANTY; without even
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+     PURPOSE.  See the above copyright notices for more information.
+
+=========================================================================*/
+#ifndef @KWSYS_NAMESPACE@_Terminal_h
+#define @KWSYS_NAMESPACE@_Terminal_h
+
+#include <@KWSYS_NAMESPACE@/Configure.h>
+
+#include <stdio.h> /* For file stream type FILE. */
+
+/* Redefine all public interface symbol names to be in the proper
+   namespace.  These macros are used internally to kwsys only, and are
+   not visible to user code.  Use kwsysHeaderDump.pl to reproduce
+   these macros after making changes to the interface.  */
+#if !defined(KWSYS_NAMESPACE)
+# define kwsys_ns(x) @KWSYS_NAMESPACE@##x
+# define kwsysEXPORT @KWSYS_NAMESPACE@_EXPORT
+#endif
+#define kwsysTerminal_cfprintf                kwsys_ns(Terminal_cfprintf)
+#define kwsysTerminal_Color_e                 kwsys_ns(Terminal_Color_e)
+#define kwsysTerminal_Color_Normal            kwsys_ns(Terminal_Color_Normal)
+#define kwsysTerminal_Color_ForegroundBlack   kwsys_ns(Terminal_Color_ForegroundBlack)
+#define kwsysTerminal_Color_ForegroundRed     kwsys_ns(Terminal_Color_ForegroundRed)
+#define kwsysTerminal_Color_ForegroundGreen   kwsys_ns(Terminal_Color_ForegroundGreen)
+#define kwsysTerminal_Color_ForegroundYellow  kwsys_ns(Terminal_Color_ForegroundYellow)
+#define kwsysTerminal_Color_ForegroundBlue    kwsys_ns(Terminal_Color_ForegroundBlue)
+#define kwsysTerminal_Color_ForegroundMagenta kwsys_ns(Terminal_Color_ForegroundMagenta)
+#define kwsysTerminal_Color_ForegroundCyan    kwsys_ns(Terminal_Color_ForegroundCyan)
+#define kwsysTerminal_Color_ForegroundWhite   kwsys_ns(Terminal_Color_ForegroundWhite)
+#define kwsysTerminal_Color_ForegroundMask    kwsys_ns(Terminal_Color_ForegroundMask)
+#define kwsysTerminal_Color_BackgroundBlack   kwsys_ns(Terminal_Color_BackgroundBlack)
+#define kwsysTerminal_Color_BackgroundRed     kwsys_ns(Terminal_Color_BackgroundRed)
+#define kwsysTerminal_Color_BackgroundGreen   kwsys_ns(Terminal_Color_BackgroundGreen)
+#define kwsysTerminal_Color_BackgroundYellow  kwsys_ns(Terminal_Color_BackgroundYellow)
+#define kwsysTerminal_Color_BackgroundBlue    kwsys_ns(Terminal_Color_BackgroundBlue)
+#define kwsysTerminal_Color_BackgroundMagenta kwsys_ns(Terminal_Color_BackgroundMagenta)
+#define kwsysTerminal_Color_BackgroundCyan    kwsys_ns(Terminal_Color_BackgroundCyan)
+#define kwsysTerminal_Color_BackgroundWhite   kwsys_ns(Terminal_Color_BackgroundWhite)
+#define kwsysTerminal_Color_BackgroundMask    kwsys_ns(Terminal_Color_BackgroundMask)
+#define kwsysTerminal_Color_ForegroundBold    kwsys_ns(Terminal_Color_ForegroundBold)
+#define kwsysTerminal_Color_BackgroundBold    kwsys_ns(Terminal_Color_BackgroundBold)
+#define kwsysTerminal_Color_AssumeTTY         kwsys_ns(Terminal_Color_AssumeTTY)
+#define kwsysTerminal_Color_AssumeVT100       kwsys_ns(Terminal_Color_AssumeVT100)
+#define kwsysTerminal_Color_AttributeMask     kwsys_ns(Terminal_Color_AttributeMask)
+
+#if defined(__cplusplus)
+extern "C"
+{
+#endif
+
+/**
+ * Write colored and formatted text to a stream.  Color is used only
+ * for streams supporting it.  The color specification is constructed
+ * by bitwise-OR-ing enumeration values.  At most one foreground and
+ * one background value may be given.
+ *
+ * Whether the a stream supports color is usually automatically
+ * detected, but with two exceptions:
+ *
+ *   - When the stream is displayed in a terminal supporting VT100
+ *   color but using an intermediate pipe for communication the
+ *   detection of a tty fails.  (This typically occurs for a shell
+ *   running in an rxvt terminal in MSYS.)  If the caller knows this
+ *   to be the case, the attribute Color_AssumeTTY may be included in
+ *   the color specification.
+ *
+ *   - When the stream is displayed in a terminal whose TERM
+ *   environment variable is not set or is set to a value that is not
+ *   known to support VT100 colors.  If the caller knows this to be
+ *   the case, the attribute Color_AssumeVT100 may be included in the
+ *   color specification.
+ */
+kwsysEXPORT void kwsysTerminal_cfprintf(int color, FILE* stream,
+                                        const char* format, ...);
+enum kwsysTerminal_Color_e
+{
+  /* Normal Text */
+  kwsysTerminal_Color_Normal = 0,
+
+  /* Foreground Color */
+  kwsysTerminal_Color_ForegroundBlack   = 0x1,
+  kwsysTerminal_Color_ForegroundRed     = 0x2,
+  kwsysTerminal_Color_ForegroundGreen   = 0x3,
+  kwsysTerminal_Color_ForegroundYellow  = 0x4,
+  kwsysTerminal_Color_ForegroundBlue    = 0x5,
+  kwsysTerminal_Color_ForegroundMagenta = 0x6,
+  kwsysTerminal_Color_ForegroundCyan    = 0x7,
+  kwsysTerminal_Color_ForegroundWhite   = 0x8,
+  kwsysTerminal_Color_ForegroundMask    = 0xF,
+
+  /* Background Color */
+  kwsysTerminal_Color_BackgroundBlack   = 0x10,
+  kwsysTerminal_Color_BackgroundRed     = 0x20,
+  kwsysTerminal_Color_BackgroundGreen   = 0x30,
+  kwsysTerminal_Color_BackgroundYellow  = 0x40,
+  kwsysTerminal_Color_BackgroundBlue    = 0x50,
+  kwsysTerminal_Color_BackgroundMagenta = 0x60,
+  kwsysTerminal_Color_BackgroundCyan    = 0x70,
+  kwsysTerminal_Color_BackgroundWhite   = 0x80,
+  kwsysTerminal_Color_BackgroundMask    = 0xF0,
+
+  /* Attributes */
+  kwsysTerminal_Color_ForegroundBold = 0x100,
+  kwsysTerminal_Color_BackgroundBold = 0x200,
+  kwsysTerminal_Color_AssumeTTY      = 0x400,
+  kwsysTerminal_Color_AssumeVT100    = 0x800,
+  kwsysTerminal_Color_AttributeMask  = 0xF00,
+};
+
+#if defined(__cplusplus)
+} /* extern "C" */
+#endif
+
+/* If we are building a kwsys .c or .cxx file, let it use these macros.
+   Otherwise, undefine them to keep the namespace clean.  */
+#if !defined(KWSYS_NAMESPACE)
+# undef kwsys_ns
+# undef kwsysEXPORT
+# undef kwsysTerminal_cfprintf
+# undef kwsysTerminal_Color_e
+# undef kwsysTerminal_Color_Normal
+# undef kwsysTerminal_Color_ForegroundBlack
+# undef kwsysTerminal_Color_ForegroundRed
+# undef kwsysTerminal_Color_ForegroundGreen
+# undef kwsysTerminal_Color_ForegroundYellow
+# undef kwsysTerminal_Color_ForegroundBlue
+# undef kwsysTerminal_Color_ForegroundMagenta
+# undef kwsysTerminal_Color_ForegroundCyan
+# undef kwsysTerminal_Color_ForegroundWhite
+# undef kwsysTerminal_Color_ForegroundMask
+# undef kwsysTerminal_Color_BackgroundBlack
+# undef kwsysTerminal_Color_BackgroundRed
+# undef kwsysTerminal_Color_BackgroundGreen
+# undef kwsysTerminal_Color_BackgroundYellow
+# undef kwsysTerminal_Color_BackgroundBlue
+# undef kwsysTerminal_Color_BackgroundMagenta
+# undef kwsysTerminal_Color_BackgroundCyan
+# undef kwsysTerminal_Color_BackgroundWhite
+# undef kwsysTerminal_Color_BackgroundMask
+# undef kwsysTerminal_Color_ForegroundBold
+# undef kwsysTerminal_Color_BackgroundBold
+# undef kwsysTerminal_Color_AssumeTTY
+# undef kwsysTerminal_Color_AssumeVT100
+# undef kwsysTerminal_Color_AttributeMask
+#endif
+
+#endif
diff --git a/testTerminal.c b/testTerminal.c
new file mode 100644
index 00000000..ec113d1b
--- /dev/null
+++ b/testTerminal.c
@@ -0,0 +1,31 @@
+/*=========================================================================
+
+  Program:   KWSys - Kitware System Library
+  Module:    testTerminal.c
+
+  Copyright (c) Kitware, Inc., Insight Consortium.  All rights reserved.
+  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
+
+     This software is distributed WITHOUT ANY WARRANTY; without even
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+     PURPOSE.  See the above copyright notices for more information.
+
+=========================================================================*/
+#include "kwsysPrivate.h"
+#include KWSYS_HEADER(Terminal.h)
+
+/* Work-around CMake dependency scanning limitation.  This must
+   duplicate the above list of headers.  */
+#if 0
+# include "Terminal.h.in"
+#endif
+
+int main()
+{
+  kwsysTerminal_cfprintf(kwsysTerminal_Color_ForegroundYellow |
+                         kwsysTerminal_Color_BackgroundBlue |
+                         kwsysTerminal_Color_AssumeTTY,
+                         stdout, "Hello %s!", "World");
+  fprintf(stdout, "\n");
+  return 0;
+}
-- 
GitLab