setcolor.hpp 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324
  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. // See http://www.boost.org/libs/test for the library home page.
  6. //
  7. // File : $RCSfile$
  8. //
  9. // Version : $Revision$
  10. //
  11. // Description : contains definition for setcolor iostream manipulator
  12. // ***************************************************************************
  13. #ifndef BOOST_TEST_UTILS_SETCOLOR_HPP
  14. #define BOOST_TEST_UTILS_SETCOLOR_HPP
  15. // Boost.Test
  16. #include <boost/test/detail/config.hpp>
  17. #include <boost/core/ignore_unused.hpp>
  18. // STL
  19. #include <iostream>
  20. #include <cstdio>
  21. #include <boost/test/detail/suppress_warnings.hpp>
  22. #ifdef _WIN32
  23. #include <windows.h>
  24. #if defined(__MINGW32__) && !defined(COMMON_LVB_UNDERSCORE)
  25. // mingw badly mimicking windows.h
  26. #define COMMON_LVB_UNDERSCORE 0x8000
  27. #endif
  28. #endif
  29. //____________________________________________________________________________//
  30. namespace boost {
  31. namespace unit_test {
  32. namespace utils {
  33. // ************************************************************************** //
  34. // ************** term_attr ************** //
  35. // ************************************************************************** //
  36. struct term_attr { enum _ {
  37. NORMAL = 0,
  38. BRIGHT = 1,
  39. DIM = 2,
  40. UNDERLINE = 4,
  41. BLINK = 5,
  42. REVERSE = 7,
  43. CROSSOUT = 9
  44. }; };
  45. // ************************************************************************** //
  46. // ************** term_color ************** //
  47. // ************************************************************************** //
  48. struct term_color { enum _ {
  49. BLACK = 0,
  50. RED = 1,
  51. GREEN = 2,
  52. YELLOW = 3,
  53. BLUE = 4,
  54. MAGENTA = 5,
  55. CYAN = 6,
  56. WHITE = 7,
  57. ORIGINAL = 9
  58. }; };
  59. // ************************************************************************** //
  60. // ************** setcolor ************** //
  61. // ************************************************************************** //
  62. #ifndef _WIN32
  63. class setcolor {
  64. public:
  65. // Constructor
  66. explicit setcolor( bool is_color_output = false,
  67. term_attr::_ attr = term_attr::NORMAL,
  68. term_color::_ fg = term_color::ORIGINAL,
  69. term_color::_ bg = term_color::ORIGINAL )
  70. : m_is_color_output(is_color_output)
  71. {
  72. m_command_size = std::sprintf( m_control_command, "%c[%c;3%c;4%cm",
  73. 0x1B,
  74. static_cast<char>(attr + '0'),
  75. static_cast<char>(fg + '0'),
  76. static_cast<char>(bg + '0'));
  77. }
  78. friend std::ostream&
  79. operator<<( std::ostream& os, setcolor const& sc )
  80. {
  81. if (sc.m_is_color_output && (&os == &std::cout || &os == &std::cerr)) {
  82. return os.write( sc.m_control_command, sc.m_command_size );
  83. }
  84. return os;
  85. }
  86. private:
  87. // Data members
  88. bool m_is_color_output;
  89. char m_control_command[13];
  90. int m_command_size;
  91. };
  92. #else
  93. class setcolor {
  94. protected:
  95. void set_console_color(std::ostream& os, WORD *attributes = NULL) const {
  96. if (!m_is_color_output) {
  97. return;
  98. }
  99. DWORD console_type;
  100. if (&os == &std::cout) {
  101. console_type = STD_OUTPUT_HANDLE;
  102. }
  103. else if (&os == &std::cerr) {
  104. console_type = STD_ERROR_HANDLE;
  105. }
  106. else {
  107. return;
  108. }
  109. HANDLE hConsole = GetStdHandle(console_type);
  110. if(hConsole == INVALID_HANDLE_VALUE || hConsole == NULL )
  111. return;
  112. if(attributes != NULL) {
  113. SetConsoleTextAttribute(hConsole, *attributes);
  114. return;
  115. }
  116. CONSOLE_SCREEN_BUFFER_INFO consoleInfo;
  117. GetConsoleScreenBufferInfo(hConsole, &consoleInfo);
  118. saved_attributes = consoleInfo.wAttributes;
  119. WORD fg_attr = 0;
  120. switch(m_fg)
  121. {
  122. case term_color::WHITE:
  123. fg_attr = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE;
  124. break;
  125. case term_color::BLACK:
  126. fg_attr = 0;
  127. break;
  128. case term_color::RED:
  129. fg_attr = FOREGROUND_RED;
  130. break;
  131. case term_color::GREEN:
  132. fg_attr = FOREGROUND_GREEN;
  133. break;
  134. case term_color::CYAN:
  135. fg_attr = FOREGROUND_GREEN | FOREGROUND_BLUE;
  136. break;
  137. case term_color::MAGENTA:
  138. fg_attr = FOREGROUND_RED | FOREGROUND_BLUE;
  139. break;
  140. case term_color::BLUE:
  141. fg_attr = FOREGROUND_BLUE;
  142. break;
  143. case term_color::YELLOW:
  144. fg_attr = FOREGROUND_RED | FOREGROUND_GREEN;
  145. break;
  146. case term_color::ORIGINAL:
  147. default:
  148. fg_attr = saved_attributes & (FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
  149. break;
  150. }
  151. WORD bg_attr = 0;
  152. switch(m_bg)
  153. {
  154. case term_color::BLACK:
  155. bg_attr = 0;
  156. break;
  157. case term_color::WHITE:
  158. bg_attr = BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE;
  159. break;
  160. case term_color::RED:
  161. bg_attr = BACKGROUND_RED;
  162. break;
  163. case term_color::GREEN:
  164. bg_attr = BACKGROUND_GREEN;
  165. break;
  166. case term_color::BLUE:
  167. bg_attr = BACKGROUND_BLUE;
  168. break;
  169. case term_color::ORIGINAL:
  170. default:
  171. bg_attr = saved_attributes & (BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE);
  172. break;
  173. }
  174. WORD text_attr = 0;
  175. switch(m_attr)
  176. {
  177. case term_attr::BRIGHT:
  178. text_attr = FOREGROUND_INTENSITY;
  179. break;
  180. case term_attr::UNDERLINE:
  181. text_attr = COMMON_LVB_UNDERSCORE;
  182. break;
  183. default:
  184. break;
  185. }
  186. SetConsoleTextAttribute(hConsole, fg_attr | bg_attr | text_attr);
  187. return;
  188. }
  189. public:
  190. // Constructor
  191. explicit setcolor(
  192. bool is_color_output = false,
  193. term_attr::_ attr = term_attr::NORMAL,
  194. term_color::_ fg = term_color::ORIGINAL,
  195. term_color::_ bg = term_color::ORIGINAL )
  196. : m_is_color_output(is_color_output)
  197. , m_attr(attr)
  198. , m_fg(fg)
  199. , m_bg(bg)
  200. {}
  201. friend std::ostream&
  202. operator<<( std::ostream& os, setcolor const& sc )
  203. {
  204. sc.set_console_color(os);
  205. return os;
  206. }
  207. private:
  208. bool m_is_color_output;
  209. term_attr::_ m_attr;
  210. term_color::_ m_fg;
  211. term_color::_ m_bg;
  212. protected:
  213. // Data members
  214. mutable WORD saved_attributes;
  215. };
  216. #endif
  217. // ************************************************************************** //
  218. // ************** scope_setcolor ************** //
  219. // ************************************************************************** //
  220. #ifndef _WIN32
  221. struct scope_setcolor {
  222. scope_setcolor() : m_os( 0 ) {}
  223. explicit scope_setcolor( bool is_color_output,
  224. std::ostream& os,
  225. term_attr::_ attr = term_attr::NORMAL,
  226. term_color::_ fg = term_color::ORIGINAL,
  227. term_color::_ bg = term_color::ORIGINAL )
  228. : m_os( &os )
  229. , m_is_color_output( is_color_output )
  230. {
  231. os << setcolor( is_color_output, attr, fg, bg );
  232. }
  233. ~scope_setcolor()
  234. {
  235. if( m_os )
  236. *m_os << setcolor( m_is_color_output );
  237. }
  238. private:
  239. scope_setcolor(const scope_setcolor& r);
  240. scope_setcolor& operator=(const scope_setcolor& r);
  241. // Data members
  242. std::ostream* m_os;
  243. bool m_is_color_output;
  244. };
  245. #else
  246. struct scope_setcolor : setcolor {
  247. scope_setcolor() : m_os( 0 ) {}
  248. explicit scope_setcolor(
  249. bool is_color_output,
  250. std::ostream& os,
  251. term_attr::_ attr = term_attr::NORMAL,
  252. term_color::_ fg = term_color::ORIGINAL,
  253. term_color::_ bg = term_color::ORIGINAL )
  254. : setcolor(is_color_output, attr, fg, bg)
  255. , m_os( &os )
  256. {
  257. os << *this;
  258. }
  259. ~scope_setcolor()
  260. {
  261. if (m_os) {
  262. set_console_color(*m_os, &this->saved_attributes);
  263. }
  264. }
  265. private:
  266. scope_setcolor(const scope_setcolor& r);
  267. scope_setcolor& operator=(const scope_setcolor& r);
  268. // Data members
  269. std::ostream* m_os;
  270. };
  271. #endif
  272. #define BOOST_TEST_SCOPE_SETCOLOR( is_color_output, os, attr, color ) \
  273. utils::scope_setcolor const sc(is_color_output, os, utils::attr, utils::color); \
  274. boost::ignore_unused( sc ) \
  275. /**/
  276. } // namespace utils
  277. } // namespace unit_test
  278. } // namespace boost
  279. #include <boost/test/detail/enable_warnings.hpp>
  280. #endif // BOOST_TEST_UTILS_SETCOLOR_HPP