0031188: Draw Harness - enable colorized messages output to console by default
[occt.git] / src / Message / Message_PrinterOStream.cxx
1 // Created on: 2001-01-06
2 // Created by: OCC Team
3 // Copyright (c) 2001-2014 OPEN CASCADE SAS
4 //
5 // This file is part of Open CASCADE Technology software library.
6 //
7 // This library is free software; you can redistribute it and/or modify it under
8 // the terms of the GNU Lesser General Public License version 2.1 as published
9 // by the Free Software Foundation, with special exception defined in the file
10 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
11 // distribution for complete text of the license and disclaimer of any warranty.
12 //
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
15
16 #ifdef _WIN32
17   #include <windows.h>
18 #endif
19
20 #include <Message_PrinterOStream.hxx>
21
22 #include <OSD_OpenFile.hxx>
23 #include <TCollection_AsciiString.hxx>
24 #include <TCollection_ExtendedString.hxx>
25
26 IMPLEMENT_STANDARD_RTTIEXT(Message_PrinterOStream,Message_Printer)
27
28 #if !defined(_MSC_VER)
29   #include <strings.h>
30 #endif
31
32 //=======================================================================
33 //function : Constructor
34 //purpose  : Empty constructor, defaulting to cerr
35 //=======================================================================
36 Message_PrinterOStream::Message_PrinterOStream (const Message_Gravity theTraceLevel)
37 : myStream  (&std::cout),
38   myIsFile  (Standard_False),
39   myUseUtf8 (Standard_False),
40   myToColorize (Standard_True)
41 {
42   myTraceLevel = theTraceLevel;
43 }
44
45 //=======================================================================
46 //function : Constructor
47 //purpose  : Opening a file as an std::ostream
48 //           for specific file names standard streams are created
49 //=======================================================================
50 Message_PrinterOStream::Message_PrinterOStream (const Standard_CString theFileName,
51                                                 const Standard_Boolean theToAppend,
52                                                 const Message_Gravity  theTraceLevel)
53 : myStream (&std::cout),
54   myIsFile (Standard_False),
55   myUseUtf8 (Standard_False),
56   myToColorize (Standard_True)
57 {
58   myTraceLevel = theTraceLevel;
59   if (strcasecmp(theFileName, "cerr") == 0)
60   {
61     myStream = &std::cerr;
62     return;
63   }
64   else if (strcasecmp(theFileName, "cout") == 0)
65   {
66     myStream = &std::cout;
67     return;
68   }
69
70   TCollection_AsciiString aFileName (theFileName);
71 #ifdef _WIN32
72   aFileName.ChangeAll ('/', '\\');
73 #endif
74
75   std::ofstream* aFile = new std::ofstream();
76   OSD_OpenStream (*aFile, aFileName.ToCString(), (theToAppend ? (std::ios_base::app | std::ios_base::out) : std::ios_base::out));
77   if (aFile->is_open())
78   {
79     myStream = (Standard_OStream* )aFile;
80     myIsFile = Standard_True;
81     myToColorize = Standard_False;
82   }
83   else
84   {
85     delete aFile;
86     myStream = &std::cout;
87 #ifdef OCCT_DEBUG
88     std::cerr << "Error opening " << theFileName << std::endl << std::flush;
89 #endif
90   }
91 }
92
93 //=======================================================================
94 //function : Close
95 //purpose  : 
96 //=======================================================================
97
98 void Message_PrinterOStream::Close ()
99 {
100   if ( ! myStream ) return;
101   Standard_OStream* ostr = (Standard_OStream*)myStream;
102   myStream = 0;
103
104   ostr->flush();
105   if ( myIsFile )
106   {
107     std::ofstream* ofile = (std::ofstream* )ostr;
108     ofile->close();
109     delete ofile;
110     myIsFile = Standard_False;
111   }
112 }
113
114 //=======================================================================
115 //function : Send
116 //purpose  : 
117 //=======================================================================
118
119 void Message_PrinterOStream::Send (const Standard_CString theString,
120                                    const Message_Gravity theGravity,
121                                    const Standard_Boolean putEndl) const
122 {
123   if (theGravity < myTraceLevel
124    || myStream == NULL)
125   {
126     return;
127   }
128
129   Message_ConsoleColor aColor = Message_ConsoleColor_Default;
130   bool toIntense = false;
131   if (myToColorize && !myIsFile)
132   {
133     switch(theGravity)
134     {
135       case Message_Trace:
136         aColor = Message_ConsoleColor_Yellow;
137         break;
138       case Message_Info:
139         aColor = Message_ConsoleColor_Green;
140         toIntense = true;
141         break;
142       case Message_Warning:
143         aColor = Message_ConsoleColor_Yellow;
144         toIntense = true;
145         break;
146       case Message_Alarm:
147         aColor = Message_ConsoleColor_Red;
148         toIntense = true;
149         break;
150       case Message_Fail:
151         aColor = Message_ConsoleColor_Red;
152         toIntense = true;
153         break;
154     }
155   }
156
157   Standard_OStream* aStream = (Standard_OStream*)myStream;
158   if (toIntense || aColor != Message_ConsoleColor_Default)
159   {
160     SetConsoleTextColor (aStream, aColor, toIntense);
161     *aStream << theString;
162     SetConsoleTextColor (aStream, Message_ConsoleColor_Default, false);
163   }
164   else
165   {
166     *aStream << theString;
167   }
168   if (putEndl)
169   {
170     (*aStream) << std::endl;
171   }
172 }
173
174 //=======================================================================
175 //function : Send
176 //purpose  : 
177 //=======================================================================
178
179 void Message_PrinterOStream::Send (const TCollection_AsciiString &theString,
180                                    const Message_Gravity theGravity,
181                                    const Standard_Boolean putEndl) const
182 {
183   Send ( theString.ToCString(), theGravity, putEndl );
184 }
185
186 //=======================================================================
187 //function : Send
188 //purpose  : 
189 //=======================================================================
190
191 void Message_PrinterOStream::Send (const TCollection_ExtendedString &theString,
192                                    const Message_Gravity theGravity,
193                                    const Standard_Boolean putEndl) const
194 {
195   TCollection_AsciiString aStr (theString, myUseUtf8 ? Standard_Character(0) : '?');
196   Send (aStr.ToCString(), theGravity, putEndl);
197 }
198
199 //=======================================================================
200 //function : SetConsoleTextColor
201 //purpose  :
202 //=======================================================================
203 void Message_PrinterOStream::SetConsoleTextColor (Standard_OStream* theOStream,
204                                                   Message_ConsoleColor theTextColor,
205                                                   bool theIsIntenseText)
206 {
207 #ifdef _WIN32
208   // there is no difference between STD_OUTPUT_HANDLE/STD_ERROR_HANDLE for std::cout/std::cerr
209   (void )theOStream;
210   if (HANDLE anStdOut = GetStdHandle (STD_OUTPUT_HANDLE))
211   {
212     WORD aFlags = 0;
213     if (theIsIntenseText)
214     {
215       aFlags |= FOREGROUND_INTENSITY;
216     }
217     switch (theTextColor)
218     {
219       case Message_ConsoleColor_Default:
220       case Message_ConsoleColor_White:
221         aFlags |= FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE;
222         break;
223       case Message_ConsoleColor_Black:
224         break;
225       case Message_ConsoleColor_Red:
226         aFlags |= FOREGROUND_RED;
227         break;
228       case Message_ConsoleColor_Green:
229         aFlags |= FOREGROUND_GREEN;
230         break;
231       case Message_ConsoleColor_Blue:
232         aFlags |= FOREGROUND_BLUE;
233         break;
234       case Message_ConsoleColor_Yellow:
235         aFlags |= FOREGROUND_RED | FOREGROUND_GREEN;
236         break;
237       case Message_ConsoleColor_Cyan:
238         aFlags |= FOREGROUND_GREEN | FOREGROUND_BLUE;
239         break;
240       case Message_ConsoleColor_Magenta:
241         aFlags |= FOREGROUND_RED | FOREGROUND_BLUE;
242         break;
243     }
244     SetConsoleTextAttribute (anStdOut, aFlags);
245   }
246 #else
247   if (theOStream == NULL)
248   {
249     return;
250   }
251
252   const char* aCode = "\e[0m";
253   switch (theTextColor)
254   {
255     case Message_ConsoleColor_Default:
256       aCode = theIsIntenseText ? "\e[0;1m" : "\e[0m";
257       break;
258     case Message_ConsoleColor_Black:
259       aCode = theIsIntenseText ? "\e[30;1m" : "\e[30m";
260       break;
261     case Message_ConsoleColor_Red:
262       aCode = theIsIntenseText ? "\e[31;1m" : "\e[31m";
263       break;
264     case Message_ConsoleColor_Green:
265       aCode = theIsIntenseText ? "\e[32;1m" : "\e[32m";
266       break;
267     case Message_ConsoleColor_Yellow:
268       aCode = theIsIntenseText ? "\e[33;1m" : "\e[33m";
269       break;
270     case Message_ConsoleColor_Blue:
271       aCode = theIsIntenseText ? "\e[34;1m" : "\e[34m";
272       break;
273     case Message_ConsoleColor_Magenta:
274       aCode = theIsIntenseText ? "\e[35;1m" : "\e[35m";
275       break;
276     case Message_ConsoleColor_Cyan:
277       aCode = theIsIntenseText ? "\e[36;1m" : "\e[36m";
278       break;
279     case Message_ConsoleColor_White:
280       aCode = theIsIntenseText ? "\e[37;1m" : "\e[37m";
281       break;
282   }
283   *theOStream << aCode;
284 #endif
285 }