| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243 | /* *  Created by Phil on 25/2/2012. *  Copyright 2012 Two Blue Cubes Ltd. All rights reserved. * *  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) */#if defined(__clang__)#    pragma clang diagnostic push#    pragma clang diagnostic ignored "-Wexit-time-destructors"#endif#include "catch_console_colour.h"#include "catch_enforce.h"#include "catch_errno_guard.h"#include "catch_interfaces_config.h"#include "catch_stream.h"#include "catch_context.h"#include "catch_platform.h"#include "catch_debugger.h"#include "catch_windows_h_proxy.h"#include <sstream>namespace Catch {    namespace {        struct IColourImpl {            virtual ~IColourImpl() = default;            virtual void use( Colour::Code _colourCode ) = 0;        };        struct NoColourImpl : IColourImpl {            void use( Colour::Code ) override {}            static IColourImpl* instance() {                static NoColourImpl s_instance;                return &s_instance;            }        };    } // anon namespace} // namespace Catch#if !defined( CATCH_CONFIG_COLOUR_NONE ) && !defined( CATCH_CONFIG_COLOUR_WINDOWS ) && !defined( CATCH_CONFIG_COLOUR_ANSI )#   ifdef CATCH_PLATFORM_WINDOWS#       define CATCH_CONFIG_COLOUR_WINDOWS#   else#       define CATCH_CONFIG_COLOUR_ANSI#   endif#endif#if defined ( CATCH_CONFIG_COLOUR_WINDOWS ) /////////////////////////////////////////namespace Catch {namespace {    class Win32ColourImpl : public IColourImpl {    public:        Win32ColourImpl() : stdoutHandle( GetStdHandle(STD_OUTPUT_HANDLE) )        {            CONSOLE_SCREEN_BUFFER_INFO csbiInfo;            GetConsoleScreenBufferInfo( stdoutHandle, &csbiInfo );            originalForegroundAttributes = csbiInfo.wAttributes & ~( BACKGROUND_GREEN | BACKGROUND_RED | BACKGROUND_BLUE | BACKGROUND_INTENSITY );            originalBackgroundAttributes = csbiInfo.wAttributes & ~( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_INTENSITY );        }        void use( Colour::Code _colourCode ) override {            switch( _colourCode ) {                case Colour::None:      return setTextAttribute( originalForegroundAttributes );                case Colour::White:     return setTextAttribute( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE );                case Colour::Red:       return setTextAttribute( FOREGROUND_RED );                case Colour::Green:     return setTextAttribute( FOREGROUND_GREEN );                case Colour::Blue:      return setTextAttribute( FOREGROUND_BLUE );                case Colour::Cyan:      return setTextAttribute( FOREGROUND_BLUE | FOREGROUND_GREEN );                case Colour::Yellow:    return setTextAttribute( FOREGROUND_RED | FOREGROUND_GREEN );                case Colour::Grey:      return setTextAttribute( 0 );                case Colour::LightGrey:     return setTextAttribute( FOREGROUND_INTENSITY );                case Colour::BrightRed:     return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_RED );                case Colour::BrightGreen:   return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_GREEN );                case Colour::BrightWhite:   return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE );                case Colour::BrightYellow:  return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_GREEN );                case Colour::Bright: CATCH_INTERNAL_ERROR( "not a colour" );                default:                    CATCH_ERROR( "Unknown colour requested" );            }        }    private:        void setTextAttribute( WORD _textAttribute ) {            SetConsoleTextAttribute( stdoutHandle, _textAttribute | originalBackgroundAttributes );        }        HANDLE stdoutHandle;        WORD originalForegroundAttributes;        WORD originalBackgroundAttributes;    };    IColourImpl* platformColourInstance() {        static Win32ColourImpl s_instance;        IConfigPtr config = getCurrentContext().getConfig();        UseColour::YesOrNo colourMode = config            ? config->useColour()            : UseColour::Auto;        if( colourMode == UseColour::Auto )            colourMode = UseColour::Yes;        return colourMode == UseColour::Yes            ? &s_instance            : NoColourImpl::instance();    }} // end anon namespace} // end namespace Catch#elif defined( CATCH_CONFIG_COLOUR_ANSI ) //////////////////////////////////////#include <unistd.h>namespace Catch {namespace {    // use POSIX/ ANSI console terminal codes    // Thanks to Adam Strzelecki for original contribution    // (http://github.com/nanoant)    // https://github.com/philsquared/Catch/pull/131    class PosixColourImpl : public IColourImpl {    public:        void use( Colour::Code _colourCode ) override {            switch( _colourCode ) {                case Colour::None:                case Colour::White:     return setColour( "[0m" );                case Colour::Red:       return setColour( "[0;31m" );                case Colour::Green:     return setColour( "[0;32m" );                case Colour::Blue:      return setColour( "[0;34m" );                case Colour::Cyan:      return setColour( "[0;36m" );                case Colour::Yellow:    return setColour( "[0;33m" );                case Colour::Grey:      return setColour( "[1;30m" );                case Colour::LightGrey:     return setColour( "[0;37m" );                case Colour::BrightRed:     return setColour( "[1;31m" );                case Colour::BrightGreen:   return setColour( "[1;32m" );                case Colour::BrightWhite:   return setColour( "[1;37m" );                case Colour::BrightYellow:  return setColour( "[1;33m" );                case Colour::Bright: CATCH_INTERNAL_ERROR( "not a colour" );                default: CATCH_INTERNAL_ERROR( "Unknown colour requested" );            }        }        static IColourImpl* instance() {            static PosixColourImpl s_instance;            return &s_instance;        }    private:        void setColour( const char* _escapeCode ) {            getCurrentContext().getConfig()->stream()                << '\033' << _escapeCode;        }    };    bool useColourOnPlatform() {        return#if defined(CATCH_PLATFORM_MAC) || defined(CATCH_PLATFORM_IPHONE)            !isDebuggerActive() &&#endif#if !(defined(__DJGPP__) && defined(__STRICT_ANSI__))            isatty(STDOUT_FILENO)#else            false#endif            ;    }    IColourImpl* platformColourInstance() {        ErrnoGuard guard;        IConfigPtr config = getCurrentContext().getConfig();        UseColour::YesOrNo colourMode = config            ? config->useColour()            : UseColour::Auto;        if( colourMode == UseColour::Auto )            colourMode = useColourOnPlatform()                ? UseColour::Yes                : UseColour::No;        return colourMode == UseColour::Yes            ? PosixColourImpl::instance()            : NoColourImpl::instance();    }} // end anon namespace} // end namespace Catch#else  // not Windows or ANSI ///////////////////////////////////////////////namespace Catch {    static IColourImpl* platformColourInstance() { return NoColourImpl::instance(); }} // end namespace Catch#endif // Windows/ ANSI/ Nonenamespace Catch {    Colour::Colour( Code _colourCode ) { use( _colourCode ); }    Colour::Colour( Colour&& other ) noexcept {        m_moved = other.m_moved;        other.m_moved = true;    }    Colour& Colour::operator=( Colour&& other ) noexcept {        m_moved = other.m_moved;        other.m_moved  = true;        return *this;    }    Colour::~Colour(){ if( !m_moved ) use( None ); }    void Colour::use( Code _colourCode ) {        static IColourImpl* impl = platformColourInstance();        // Strictly speaking, this cannot possibly happen.        // However, under some conditions it does happen (see #1626),        // and this change is small enough that we can let practicality        // triumph over purity in this case.        if (impl != nullptr) {            impl->use( _colourCode );        }    }    std::ostream& operator << ( std::ostream& os, Colour const& ) {        return os;    }} // end namespace Catch#if defined(__clang__)#    pragma clang diagnostic pop#endif
 |