0031036: Foundation Classes, Message_PrinterOStream - add option printing colored...
[occt.git] / src / Message / Message_PrinterOStream.cxx
index b9ffc53..5028d67 100644 (file)
 // Alternatively, this file may be used under the terms of Open CASCADE
 // commercial license or contractual agreement.
 
-#include <Message_PrinterOStream.ixx>
+#ifdef _WIN32
+  #include <windows.h>
+#endif
+
+#include <Message_PrinterOStream.hxx>
 
-#include <Message_Gravity.hxx>
+#include <OSD_OpenFile.hxx>
 #include <TCollection_AsciiString.hxx>
 #include <TCollection_ExtendedString.hxx>
-#include <Standard_Mutex.hxx>
-#include <Standard_Stream.hxx>
+
+IMPLEMENT_STANDARD_RTTIEXT(Message_PrinterOStream,Message_Printer)
+
+#if !defined(_MSC_VER)
+  #include <strings.h>
+#endif
 
 //=======================================================================
 //function : Constructor
 //purpose  : Empty constructor, defaulting to cerr
 //=======================================================================
-
-Message_PrinterOStream::Message_PrinterOStream (const Message_Gravity theTraceLevel) 
-: myTraceLevel(theTraceLevel), myStream(&cout), 
-  myIsFile(Standard_False), myUseUtf8(Standard_False)
+Message_PrinterOStream::Message_PrinterOStream (const Message_Gravity theTraceLevel)
+: myStream  (&std::cout),
+  myIsFile  (Standard_False),
+  myUseUtf8 (Standard_False),
+  myToColorize (Standard_False)
 {
+  myTraceLevel = theTraceLevel;
 }
 
 //=======================================================================
 //function : Constructor
-//purpose  : Opening a file as an ostream
+//purpose  : Opening a file as an std::ostream
 //           for specific file names standard streams are created
 //=======================================================================
 Message_PrinterOStream::Message_PrinterOStream (const Standard_CString theFileName,
-                                               const Standard_Boolean doAppend,
-                                               const Message_Gravity theTraceLevel)
-: myTraceLevel(theTraceLevel), myStream(&cout), myIsFile(Standard_False)
+                                                const Standard_Boolean theToAppend,
+                                                const Message_Gravity  theTraceLevel)
+: myStream (&std::cout),
+  myIsFile (Standard_False),
+  myUseUtf8 (Standard_False),
+  myToColorize (Standard_False)
 {
-  if ( strcasecmp(theFileName, "cout") == 0 ) 
-    myStream = &cerr;
-  else if ( strcasecmp(theFileName, "cerr") == 0 ) 
-    myStream = &cout;
-  else 
+  myTraceLevel = theTraceLevel;
+  if (strcasecmp(theFileName, "cerr") == 0)
   {
-    TCollection_AsciiString aFileName (theFileName);
-#ifdef WNT
-    aFileName.ChangeAll ('/', '\\');
+    myStream = &std::cerr;
+    return;
+  }
+  else if (strcasecmp(theFileName, "cout") == 0)
+  {
+    myStream = &std::cout;
+    return;
+  }
+
+  TCollection_AsciiString aFileName (theFileName);
+#ifdef _WIN32
+  aFileName.ChangeAll ('/', '\\');
 #endif
 
-    ofstream *ofile = new ofstream (aFileName.ToCString(),
-#ifdef USE_STL_STREAMS
-                                (doAppend ? (std::ios_base::app | std::ios_base::out) : std::ios_base::out ) );
-#else
-                                (doAppend ? ios::app : ios::out ) );
+  std::ofstream* aFile = new std::ofstream();
+  OSD_OpenStream (*aFile, aFileName.ToCString(), (theToAppend ? (std::ios_base::app | std::ios_base::out) : std::ios_base::out));
+  if (aFile->is_open())
+  {
+    myStream = (Standard_OStream* )aFile;
+    myIsFile = Standard_True;
+  }
+  else
+  {
+    delete aFile;
+    myStream = &std::cout;
+#ifdef OCCT_DEBUG
+    std::cerr << "Error opening " << theFileName << std::endl << std::flush;
 #endif
-    if ( ofile ) {
-      myStream = (Standard_OStream*)ofile;
-      myIsFile = Standard_True;
-    }
-    else {
-      myStream = &cout;
-      cerr << "Error opening " << theFileName << endl << flush;
-    }
   }
 }
 
@@ -84,7 +103,7 @@ void Message_PrinterOStream::Close ()
   ostr->flush();
   if ( myIsFile )
   {
-    ofstream* ofile = (ofstream*)ostr;
+    std::ofstream* ofile = (std::ofstream* )ostr;
     ofile->close();
     delete ofile;
     myIsFile = Standard_False;
@@ -100,10 +119,55 @@ void Message_PrinterOStream::Send (const Standard_CString theString,
                                   const Message_Gravity theGravity,
                                   const Standard_Boolean putEndl) const
 {
-  if ( theGravity < myTraceLevel || ! myStream ) return;
-  Standard_OStream* ostr = (Standard_OStream*)myStream;
-  (*ostr) << theString;
-  if ( putEndl ) (*ostr) << endl;
+  if (theGravity < myTraceLevel
+   || myStream == NULL)
+  {
+    return;
+  }
+
+  Message_ConsoleColor aColor = Message_ConsoleColor_Default;
+  bool toIntense = false;
+  if (myToColorize && !myIsFile)
+  {
+    switch(theGravity)
+    {
+      case Message_Trace:
+        aColor = Message_ConsoleColor_Yellow;
+        break;
+      case Message_Info:
+        aColor = Message_ConsoleColor_Green;
+        toIntense = true;
+        break;
+      case Message_Warning:
+        aColor = Message_ConsoleColor_Yellow;
+        toIntense = true;
+        break;
+      case Message_Alarm:
+        aColor = Message_ConsoleColor_Red;
+        toIntense = true;
+        break;
+      case Message_Fail:
+        aColor = Message_ConsoleColor_Red;
+        toIntense = true;
+        break;
+    }
+  }
+
+  Standard_OStream* aStream = (Standard_OStream*)myStream;
+  if (toIntense || aColor != Message_ConsoleColor_Default)
+  {
+    SetConsoleTextColor (aStream, aColor, toIntense);
+    *aStream << theString;
+    SetConsoleTextColor (aStream, Message_ConsoleColor_Default, false);
+  }
+  else
+  {
+    *aStream << theString;
+  }
+  if (putEndl)
+  {
+    (*aStream) << std::endl;
+  }
 }
 
 //=======================================================================
@@ -127,16 +191,94 @@ void Message_PrinterOStream::Send (const TCollection_ExtendedString &theString,
                                   const Message_Gravity theGravity,
                                   const Standard_Boolean putEndl) const
 {
-  // Note: the string might need to be converted to Ascii
-  if ( myUseUtf8 ) {
-    char* astr = new char[theString.LengthOfCString()+1];
-    theString.ToUTF8CString (astr);
-    Send ( astr, theGravity, putEndl );
-    delete [] astr;
-    astr = 0;
+  TCollection_AsciiString aStr (theString, myUseUtf8 ? Standard_Character(0) : '?');
+  Send (aStr.ToCString(), theGravity, putEndl);
+}
+
+//=======================================================================
+//function : SetConsoleTextColor
+//purpose  :
+//=======================================================================
+void Message_PrinterOStream::SetConsoleTextColor (Standard_OStream* theOStream,
+                                                  Message_ConsoleColor theTextColor,
+                                                  bool theIsIntenseText)
+{
+#ifdef _WIN32
+  // there is no difference between STD_OUTPUT_HANDLE/STD_ERROR_HANDLE for std::cout/std::cerr
+  (void )theOStream;
+  if (HANDLE anStdOut = GetStdHandle (STD_OUTPUT_HANDLE))
+  {
+    WORD aFlags = 0;
+    if (theIsIntenseText)
+    {
+      aFlags |= FOREGROUND_INTENSITY;
+    }
+    switch (theTextColor)
+    {
+      case Message_ConsoleColor_Default:
+      case Message_ConsoleColor_White:
+        aFlags |= FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE;
+        break;
+      case Message_ConsoleColor_Black:
+        break;
+      case Message_ConsoleColor_Red:
+        aFlags |= FOREGROUND_RED;
+        break;
+      case Message_ConsoleColor_Green:
+        aFlags |= FOREGROUND_GREEN;
+        break;
+      case Message_ConsoleColor_Blue:
+        aFlags |= FOREGROUND_BLUE;
+        break;
+      case Message_ConsoleColor_Yellow:
+        aFlags |= FOREGROUND_RED | FOREGROUND_GREEN;
+        break;
+      case Message_ConsoleColor_Cyan:
+        aFlags |= FOREGROUND_GREEN | FOREGROUND_BLUE;
+        break;
+      case Message_ConsoleColor_Magenta:
+        aFlags |= FOREGROUND_RED | FOREGROUND_BLUE;
+        break;
+    }
+    SetConsoleTextAttribute (anStdOut, aFlags);
   }
-  else {
-    TCollection_AsciiString aStr ( theString, '?' );
-    Send ( aStr.ToCString(), theGravity, putEndl );
+#else
+  if (theOStream == NULL)
+  {
+    return;
   }
+
+  const char* aCode = "\e[0m";
+  switch (theTextColor)
+  {
+    case Message_ConsoleColor_Default:
+      aCode = theIsIntenseText ? "\e[0;1m" : "\e[0m";
+      break;
+    case Message_ConsoleColor_Black:
+      aCode = theIsIntenseText ? "\e[30;1m" : "\e[30m";
+      break;
+    case Message_ConsoleColor_Red:
+      aCode = theIsIntenseText ? "\e[31;1m" : "\e[31m";
+      break;
+    case Message_ConsoleColor_Green:
+      aCode = theIsIntenseText ? "\e[32;1m" : "\e[32m";
+      break;
+    case Message_ConsoleColor_Yellow:
+      aCode = theIsIntenseText ? "\e[33;1m" : "\e[33m";
+      break;
+    case Message_ConsoleColor_Blue:
+      aCode = theIsIntenseText ? "\e[34;1m" : "\e[34m";
+      break;
+    case Message_ConsoleColor_Magenta:
+      aCode = theIsIntenseText ? "\e[35;1m" : "\e[35m";
+      break;
+    case Message_ConsoleColor_Cyan:
+      aCode = theIsIntenseText ? "\e[36;1m" : "\e[36m";
+      break;
+    case Message_ConsoleColor_White:
+      aCode = theIsIntenseText ? "\e[37;1m" : "\e[37m";
+      break;
+  }
+  *theOStream << aCode;
+#endif
 }