1// (C) Copyright Gennadiy Rozental 2001.
2// Distributed under the Boost Software License, Version 1.0.
3// (See accompanying file LICENSE_1_0.txt or copy at
4// http://www.boost.org/LICENSE_1_0.txt)
5
6// See http://www.boost.org/libs/test for the library home page.
7//
8// File : $RCSfile$
9//
10// Version : $Revision$
11//
12// Description : contains definition for setcolor iostream manipulator
13// ***************************************************************************
14
15#ifndef BOOST_TEST_UTILS_SETCOLOR_HPP
16#define BOOST_TEST_UTILS_SETCOLOR_HPP
17
18// Boost.Test
19#include <boost/test/detail/config.hpp>
20
21#include <boost/core/ignore_unused.hpp>
22
23// STL
24#include <iostream>
25#include <cstdio>
26#include <cassert>
27
28#include <boost/test/detail/suppress_warnings.hpp>
29
30#ifdef _WIN32
31 #include <windows.h>
32
33 #if defined(__MINGW32__) && !defined(COMMON_LVB_UNDERSCORE)
34 // mingw badly mimicking windows.h
35 #define COMMON_LVB_UNDERSCORE 0x8000
36 #endif
37#endif
38
39//____________________________________________________________________________//
40
41namespace boost {
42namespace unit_test {
43namespace utils {
44
45// ************************************************************************** //
46// ************** term_attr ************** //
47// ************************************************************************** //
48
49struct term_attr { enum _ {
50 NORMAL = 0,
51 BRIGHT = 1,
52 DIM = 2,
53 UNDERLINE = 4,
54 BLINK = 5,
55 REVERSE = 7,
56 CROSSOUT = 9
57}; };
58
59// ************************************************************************** //
60// ************** term_color ************** //
61// ************************************************************************** //
62
63struct term_color { enum _ {
64 BLACK = 0,
65 RED = 1,
66 GREEN = 2,
67 YELLOW = 3,
68 BLUE = 4,
69 MAGENTA = 5,
70 CYAN = 6,
71 WHITE = 7,
72 ORIGINAL = 9
73}; };
74
75// ************************************************************************** //
76// ************** setcolor ************** //
77// ************************************************************************** //
78
79#ifndef _WIN32
80class setcolor {
81public:
82 typedef int state;
83
84 // Constructor
85 explicit setcolor( bool is_color_output = false,
86 term_attr::_ attr = term_attr::NORMAL,
87 term_color::_ fg = term_color::ORIGINAL,
88 term_color::_ bg = term_color::ORIGINAL,
89 state* /* unused */= NULL)
90 : m_is_color_output(is_color_output)
91 {
92 m_command_size = std::sprintf( s: m_control_command, format: "%c[%c;3%c;4%cm",
93 0x1B,
94 static_cast<char>(attr + '0'),
95 static_cast<char>(fg + '0'),
96 static_cast<char>(bg + '0'));
97 }
98
99 explicit setcolor(bool is_color_output,
100 state* /* unused */)
101 : m_is_color_output(is_color_output)
102 {
103 m_command_size = std::sprintf(s: m_control_command, format: "%c[%c;3%c;4%cm",
104 0x1B,
105 static_cast<char>(term_attr::NORMAL + '0'),
106 static_cast<char>(term_color::ORIGINAL + '0'),
107 static_cast<char>(term_color::ORIGINAL + '0'));
108 }
109
110 friend std::ostream&
111 operator<<( std::ostream& os, setcolor const& sc )
112 {
113 if (sc.m_is_color_output && (&os == &std::cout || &os == &std::cerr)) {
114 return os.write( s: sc.m_control_command, n: sc.m_command_size );
115 }
116 return os;
117 }
118
119private:
120 // Data members
121 bool m_is_color_output;
122 char m_control_command[13];
123 int m_command_size;
124};
125
126#else
127
128class setcolor {
129
130protected:
131 void set_console_color(std::ostream& os, WORD *attributes = NULL) const {
132 if (!m_is_color_output || m_state_saved) {
133 return;
134 }
135 DWORD console_type;
136 if (&os == &std::cout) {
137 console_type = STD_OUTPUT_HANDLE;
138 }
139 else if (&os == &std::cerr) {
140 console_type = STD_ERROR_HANDLE;
141 }
142 else {
143 return;
144 }
145 HANDLE hConsole = GetStdHandle(console_type);
146
147 if(hConsole == INVALID_HANDLE_VALUE || hConsole == NULL )
148 return;
149
150 state console_attributes;
151 if(attributes != NULL || (m_restore_state && m_s)) {
152 if (attributes != NULL) {
153 console_attributes = *attributes;
154 }
155 else {
156 console_attributes = *m_s;
157 *m_s = state();
158 }
159 SetConsoleTextAttribute(hConsole, console_attributes);
160 return;
161 }
162
163 CONSOLE_SCREEN_BUFFER_INFO consoleInfo;
164 GetConsoleScreenBufferInfo(hConsole, &consoleInfo);
165 console_attributes = consoleInfo.wAttributes;
166
167 if (!m_state_saved && m_s) {
168 assert(!m_restore_state);
169 // we can save the state only the first time this object is used
170 // for modifying the console.
171 *m_s = console_attributes;
172 m_state_saved = true;
173 }
174
175 WORD fg_attr = 0;
176 switch(m_fg)
177 {
178 case term_color::WHITE:
179 fg_attr = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE;
180 break;
181 case term_color::BLACK:
182 fg_attr = 0;
183 break;
184 case term_color::RED:
185 fg_attr = FOREGROUND_RED;
186 break;
187 case term_color::GREEN:
188 fg_attr = FOREGROUND_GREEN;
189 break;
190 case term_color::CYAN:
191 fg_attr = FOREGROUND_GREEN | FOREGROUND_BLUE;
192 break;
193 case term_color::MAGENTA:
194 fg_attr = FOREGROUND_RED | FOREGROUND_BLUE;
195 break;
196 case term_color::BLUE:
197 fg_attr = FOREGROUND_BLUE;
198 break;
199 case term_color::YELLOW:
200 fg_attr = FOREGROUND_RED | FOREGROUND_GREEN;
201 break;
202 case term_color::ORIGINAL:
203 default:
204 fg_attr = console_attributes & (FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
205 break;
206 }
207
208 WORD bg_attr = 0;
209 switch(m_bg)
210 {
211 case term_color::BLACK:
212 bg_attr = 0;
213 break;
214 case term_color::WHITE:
215 bg_attr = BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE;
216 break;
217 case term_color::RED:
218 bg_attr = BACKGROUND_RED;
219 break;
220 case term_color::GREEN:
221 bg_attr = BACKGROUND_GREEN;
222 break;
223 case term_color::BLUE:
224 bg_attr = BACKGROUND_BLUE;
225 break;
226 case term_color::ORIGINAL:
227 default:
228 bg_attr = console_attributes & (BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE);
229 break;
230 }
231
232 WORD text_attr = 0;
233 switch(m_attr)
234 {
235 case term_attr::BRIGHT:
236 text_attr = FOREGROUND_INTENSITY;
237 break;
238 case term_attr::UNDERLINE:
239 text_attr = COMMON_LVB_UNDERSCORE;
240 break;
241 default:
242 break;
243 }
244
245 SetConsoleTextAttribute(hConsole, fg_attr | bg_attr | text_attr);
246 return;
247 }
248
249public:
250 typedef WORD state;
251
252 // Constructor
253 explicit setcolor(
254 bool is_color_output = false,
255 term_attr::_ attr = term_attr::NORMAL,
256 term_color::_ fg = term_color::ORIGINAL,
257 term_color::_ bg = term_color::ORIGINAL,
258 state* s = NULL)
259 : m_is_color_output(is_color_output)
260 , m_attr(attr)
261 , m_fg(fg)
262 , m_bg(bg)
263 , m_s(s)
264 , m_restore_state(false)
265 , m_state_saved(false)
266 {}
267
268 explicit setcolor(
269 bool is_color_output,
270 state* s)
271 : m_is_color_output(is_color_output)
272 , m_attr(term_attr::NORMAL)
273 , m_fg(term_color::ORIGINAL)
274 , m_bg(term_color::ORIGINAL)
275 , m_s(s)
276 , m_restore_state(true)
277 , m_state_saved(false)
278 {}
279
280 friend std::ostream&
281 operator<<( std::ostream& os, setcolor const& sc )
282 {
283 sc.set_console_color(os);
284 return os;
285 }
286
287private:
288 bool m_is_color_output;
289 term_attr::_ m_attr;
290 term_color::_ m_fg;
291 term_color::_ m_bg;
292 state* m_s;
293 // indicates that the instance has been initialized to restore a previously
294 // stored state
295 bool m_restore_state;
296 // indicates the first time we pull and set the console information.
297 mutable bool m_state_saved;
298};
299
300#endif
301// ************************************************************************** //
302// ************** scope_setcolor ************** //
303// ************************************************************************** //
304
305struct scope_setcolor {
306 scope_setcolor()
307 : m_os( 0 )
308 , m_state()
309 , m_is_color_output(false)
310 {}
311
312 explicit scope_setcolor(
313 bool is_color_output,
314 std::ostream& os,
315 term_attr::_ attr = term_attr::NORMAL,
316 term_color::_ fg = term_color::ORIGINAL,
317 term_color::_ bg = term_color::ORIGINAL )
318 : m_os( &os )
319 , m_is_color_output(is_color_output)
320 {
321 os << setcolor(is_color_output, attr, fg, bg, &m_state);
322 }
323
324 ~scope_setcolor()
325 {
326 if (m_os) {
327 *m_os << setcolor(m_is_color_output, &m_state);
328 }
329 }
330private:
331 scope_setcolor(const scope_setcolor& r);
332 scope_setcolor& operator=(const scope_setcolor& r);
333 // Data members
334 std::ostream* m_os;
335 setcolor::state m_state;
336 bool m_is_color_output;
337};
338
339
340#define BOOST_TEST_SCOPE_SETCOLOR( is_color_output, os, attr, color ) \
341 utils::scope_setcolor const sc(is_color_output, os, utils::attr, utils::color); \
342 boost::ignore_unused( sc ) \
343/**/
344
345} // namespace utils
346} // namespace unit_test
347} // namespace boost
348
349#include <boost/test/detail/enable_warnings.hpp>
350
351#endif // BOOST_TEST_UTILS_SETCOLOR_HPP
352

source code of include/boost/test/utils/setcolor.hpp