boost/test/utils/setcolor.hpp
// (C) Copyright Gennadiy Rozental 2001.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org/libs/test for the library home page.
//
// File : $RCSfile$
//
// Version : $Revision$
//
// Description : contains definition for setcolor iostream manipulator
// ***************************************************************************
#ifndef BOOST_TEST_UTILS_SETCOLOR_HPP
#define BOOST_TEST_UTILS_SETCOLOR_HPP
// Boost.Test
#include <boost/test/detail/config.hpp>
// STL
#include <iostream>
#include <cstdio>
#include <boost/test/detail/suppress_warnings.hpp>
#ifdef _WIN32
#include <windows.h>
#if defined(__MINGW32__) && !defined(COMMON_LVB_UNDERSCORE)
// mingw badly mimicking windows.h
#define COMMON_LVB_UNDERSCORE 0x8000
#endif
#endif
//____________________________________________________________________________//
namespace boost {
namespace unit_test {
namespace utils {
// ************************************************************************** //
// ************** term_attr ************** //
// ************************************************************************** //
struct term_attr { enum _ {
NORMAL = 0,
BRIGHT = 1,
DIM = 2,
UNDERLINE = 4,
BLINK = 5,
REVERSE = 7,
CROSSOUT = 9
}; };
// ************************************************************************** //
// ************** term_color ************** //
// ************************************************************************** //
struct term_color { enum _ {
BLACK = 0,
RED = 1,
GREEN = 2,
YELLOW = 3,
BLUE = 4,
MAGENTA = 5,
CYAN = 6,
WHITE = 7,
ORIGINAL = 9
}; };
// ************************************************************************** //
// ************** setcolor ************** //
// ************************************************************************** //
#ifndef _WIN32
class setcolor {
public:
// Constructor
explicit setcolor( term_attr::_ attr = term_attr::NORMAL,
term_color::_ fg = term_color::ORIGINAL,
term_color::_ bg = term_color::ORIGINAL )
{
m_command_size = std::sprintf( m_control_command, "%c[%d;%d;%dm", 0x1B, attr, fg + 30, bg + 40 );
}
friend std::ostream&
operator<<( std::ostream& os, setcolor const& sc )
{
if (&os == &std::cout || &os == &std::cerr) {
return os.write( sc.m_control_command, sc.m_command_size );
}
return os;
}
private:
// Data members
char m_control_command[13];
int m_command_size;
};
#else
class setcolor {
protected:
void set_console_color(std::ostream& os, WORD *attributes = NULL) const {
DWORD console_type;
if (&os == &std::cout) {
console_type = STD_OUTPUT_HANDLE;
}
else if (&os == &std::cerr) {
console_type = STD_ERROR_HANDLE;
}
else {
return;
}
HANDLE hConsole = GetStdHandle(console_type);
if(hConsole == INVALID_HANDLE_VALUE || hConsole == NULL )
return;
if(attributes != NULL) {
SetConsoleTextAttribute(hConsole, *attributes);
return;
}
CONSOLE_SCREEN_BUFFER_INFO consoleInfo;
GetConsoleScreenBufferInfo(hConsole, &consoleInfo);
//if(!has_written_console_ext) {
saved_attributes = consoleInfo.wAttributes;
//}
WORD fg_attr = 0;
switch(m_fg)
{
case term_color::WHITE:
fg_attr = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE;
break;
case term_color::BLACK:
fg_attr = 0;
break;
case term_color::RED:
fg_attr = FOREGROUND_RED;
break;
case term_color::GREEN:
fg_attr = FOREGROUND_GREEN;
break;
case term_color::CYAN:
fg_attr = FOREGROUND_GREEN | FOREGROUND_BLUE;
break;
case term_color::MAGENTA:
fg_attr = FOREGROUND_RED | FOREGROUND_BLUE;
break;
case term_color::BLUE:
fg_attr = FOREGROUND_BLUE;
break;
case term_color::YELLOW:
fg_attr = FOREGROUND_RED | FOREGROUND_GREEN;
break;
case term_color::ORIGINAL:
default:
fg_attr = saved_attributes & (FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
break;
}
WORD bg_attr = 0;
switch(m_bg)
{
case term_color::BLACK:
bg_attr = 0;
break;
case term_color::WHITE:
bg_attr = BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE;
break;
case term_color::RED:
bg_attr = BACKGROUND_RED;
break;
case term_color::GREEN:
bg_attr = BACKGROUND_GREEN;
break;
case term_color::BLUE:
bg_attr = BACKGROUND_BLUE;
break;
case term_color::ORIGINAL:
default:
bg_attr = saved_attributes & (BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE);
break;
}
WORD text_attr = 0;
switch(m_attr)
{
case term_attr::BRIGHT:
text_attr = FOREGROUND_INTENSITY;
break;
case term_attr::UNDERLINE:
text_attr = COMMON_LVB_UNDERSCORE;
break;
default:
break;
}
SetConsoleTextAttribute(hConsole, fg_attr | bg_attr | text_attr);
//has_written_console_ext = true;
return;
}
public:
// Constructor
explicit setcolor(
term_attr::_ attr = term_attr::NORMAL,
term_color::_ fg = term_color::ORIGINAL,
term_color::_ bg = term_color::ORIGINAL )
: /*has_written_console_ext(false)
, */m_attr(attr)
, m_fg(fg)
, m_bg(bg)
{}
friend std::ostream&
operator<<( std::ostream& os, setcolor const& sc )
{
sc.set_console_color(os);
return os;
}
private:
term_attr::_ m_attr;
term_color::_ m_fg;
term_color::_ m_bg;
protected:
// Data members
mutable WORD saved_attributes;
//mutable bool has_written_console_ext;
};
#endif
// ************************************************************************** //
// ************** scope_setcolor ************** //
// ************************************************************************** //
#ifndef _WIN32
struct scope_setcolor {
scope_setcolor() : m_os( 0 ) {}
explicit scope_setcolor( std::ostream& os,
term_attr::_ attr = term_attr::NORMAL,
term_color::_ fg = term_color::ORIGINAL,
term_color::_ bg = term_color::ORIGINAL )
: m_os( &os )
{
os << setcolor( attr, fg, bg );
}
~scope_setcolor()
{
if( m_os )
*m_os << setcolor();
}
private:
scope_setcolor(const scope_setcolor& r);
scope_setcolor& operator=(const scope_setcolor& r);
// Data members
std::ostream* m_os;
};
#else
struct scope_setcolor : setcolor {
scope_setcolor() : m_os( 0 ) {}
explicit scope_setcolor(
std::ostream& os,
term_attr::_ attr = term_attr::NORMAL,
term_color::_ fg = term_color::ORIGINAL,
term_color::_ bg = term_color::ORIGINAL )
:
setcolor(attr, fg, bg),
m_os( &os )
{
os << *this;
}
~scope_setcolor()
{
if (m_os) {
set_console_color(*m_os, &this->saved_attributes);
}
}
private:
scope_setcolor(const scope_setcolor& r);
scope_setcolor& operator=(const scope_setcolor& r);
// Data members
std::ostream* m_os;
};
#endif
#define BOOST_TEST_SCOPE_SETCOLOR( is_color_output, os, attr, color ) \
utils::scope_setcolor const sc( \
os, \
is_color_output ? utils::attr : utils::term_attr::NORMAL, \
is_color_output ? utils::color : utils::term_color::ORIGINAL);\
ut_detail::ignore_unused_variable_warning( sc ) \
/**/
} // namespace utils
} // namespace unit_test
} // namespace boost
#include <boost/test/detail/enable_warnings.hpp>
#endif // BOOST_TEST_UTILS_SETCOLOR_HPP