ALib C++ Library
Library Version: 2412 R0
Documentation generated by doxygen
Loading...
Searching...
No Matches
windowsconsolelogger.cpp
1// #################################################################################################
2// alib::lox::loggers - ALox Logging Library
3//
4// Copyright 2013-2024 A-Worx GmbH, Germany
5// Published under 'Boost Software License' (a free software license, see LICENSE.txt)
6// #################################################################################################
8
9#if defined( _WIN32 )
11
12#if !DOXYGEN
13# include "alib/alox/aloxcamp.hpp"
17#endif // !DOXYGEN
18
19#include <iostream>
20#include <string.h>
21
22using namespace alib::lox::textlogger;
23
24namespace alib::lox::loggers {
25
26using namespace detail;
27
28// #################################################################################################
29// Windows Console Colors
30// #################################################################################################
31 #define W32C_FOREGROUND_MASK 0xFFF0
32 #define W32C_BACKGROUND_MASK 0xFF0F
33
34 #define W32C_BLACK 0
35 #define W32C_RED FOREGROUND_RED
36 #define W32C_GREEN FOREGROUND_GREEN
37 #define W32C_BLUE FOREGROUND_BLUE
38 #define W32C_CYAN FOREGROUND_GREEN | FOREGROUND_BLUE
39 #define W32C_MAGENTA FOREGROUND_RED | FOREGROUND_BLUE
40 #define W32C_YELLOW FOREGROUND_RED | FOREGROUND_GREEN
41 #define W32C_WHITE FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY
42
43 #define W32C_GRAY_LIGHT FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE
44 #define W32C_GRAY_DARK FOREGROUND_INTENSITY
45
46 //! @cond NO_DOX
47 WORD win32Cols[]=
48 {
49 W32C_RED,
50 W32C_GREEN,
51 W32C_YELLOW,
52 W32C_BLUE,
53 W32C_MAGENTA,
54 W32C_CYAN,
55 };
56 //! @endcond
57
58// #################################################################################################
59// Constructor/Destructor
60// #################################################################################################
61
63: TextLogger( name, "WINDOWS_CONSOLE", true)
64{
65 // get actual console attributes
66 WORD actualAttributes;
67 {
68 HANDLE H= GetStdHandle(STD_OUTPUT_HANDLE);
69 CONSOLE_SCREEN_BUFFER_INFO info;
70 GetConsoleScreenBufferInfo( H, &info );
71 actualAttributes= info.wAttributes;
72 originalConsoleAttributes= actualAttributes;
73 }
74}
75
77{
80 return;
81
82
83 // evaluate environment variable "ALOX_CONSOLE_LIGHT_COLORS"
84 // If default, we assume dark background, hence use light color on foreground
87 (void) useLightColors.Define();
88 CFP= useLightColors.Get<ColorfulLoggerParameters>();
89
90 if( CFP.LCU == ColorfulLoggerParameters::LightColorUsage::Auto )
91 {
92 // default: dark background, hence use light color on foreground
93 CFP.LCU= ( originalConsoleAttributes & ~W32C_FOREGROUND_MASK ) < 7
94 ? ColorfulLoggerParameters::LightColorUsage::Background
95 : ColorfulLoggerParameters::LightColorUsage::Foreground;
96 }
97
98 // move verbosity information to the end to colorize the whole line
101 fmt.VerbosityWarning.Reset(ESC::BLUE);
102 fmt.VerbosityInfo .Reset(A_CHAR(""));
103 fmt.VerbosityVerbose.Reset(ESC::GRAY);
104
105 // evaluate config variable CODEPAGE
107 if( codePage.IsDefined() )
108 CodePage= UINT(codePage.GetInt());
109}
110
111
112// #################################################################################################
113// logText
114// #################################################################################################
116 AString& msg,
117 ScopeInfo& , int )
118{
119 HANDLE H= GetStdHandle(STD_OUTPUT_HANDLE);
120 DWORD ignore;
121
122 // get actual console attributes
123 WORD actualAttributes;
124 {
125 CONSOLE_SCREEN_BUFFER_INFO info;
126 GetConsoleScreenBufferInfo( H, &info );
127 actualAttributes= info.wAttributes;
128 }
129 WORD previousAttributes= actualAttributes;
130
131 // set codepage;
132 if ( CodePage != 0 )
133 SetConsoleOutputCP( CodePage );
134
135
136 // loop over message, print the parts between the escape sequences
137 integer column= 0;
138 Tokenizer msgParts( msg, '\x1B' );
139 Substring& actual= msgParts.Actual;
140 Substring& rest= msgParts.Rest;
141 for(;;)
142 {
143 if ( msgParts.Next(lang::Whitespaces::Keep ).IsNotEmpty() )
144 {
145 #if !ALIB_CHARACTERS_WIDE
146 WriteConsoleA( H, actual.Buffer(), (DWORD) actual.Length(), &ignore, NULL );
147 #else
148 WriteConsoleW( H, actual.Buffer(), (DWORD) actual.Length(), &ignore, NULL );
149 #endif
150 column+= actual.WStringLength();
151 }
152
153 if ( !msgParts.HasNext() )
154 break;
155
156 // found a delimiter: process ESC sequence
157 character c= rest.ConsumeChar<NC>();
158
159 // Colors
160 bool isForeGround= true;
161 if( c == 'C' || c == 'c' )
162 {
163 isForeGround= c== 'c';
164
165 c= rest.ConsumeChar();
166 int colNo= c - '0';
167 ALIB_ASSERT_WARNING( colNo >=0 && colNo <=9, "ALOX", "ConsoleLogger: Unknown ESC-c code" )
168
169 WORD attr= 0;
170 WORD light= CFP.LCU!= ColorfulLoggerParameters::LightColorUsage::Never
171 && ((CFP.LCU== ColorfulLoggerParameters::LightColorUsage::Foreground)
172 == isForeGround )
173 ? FOREGROUND_INTENSITY
174 : 0;
175
176 // 0..5 (red, green, yellow, blue, magenta, cyan)
177 if ( colNo >= 0 && colNo < 6) attr= (win32Cols[colNo] | light);
178
179 else if ( colNo == 6 ) attr= W32C_BLACK;
180 else if ( colNo == 7 ) attr= W32C_WHITE;
181 else if ( colNo == 8 ) attr= light ? W32C_GRAY_LIGHT : W32C_GRAY_DARK;
182 else if ( colNo == 9 ) attr= isForeGround ? originalConsoleAttributes & ~W32C_FOREGROUND_MASK
183 : ( originalConsoleAttributes & ~W32C_BACKGROUND_MASK ) >> 4;
184 else
185 {
186 ALIB_WARNING( "ALOX", "Unknown ESC- code \"C{}{}...\"", c, rest.Substring(0,10) );
187 }
188
189 actualAttributes= isForeGround ? ( actualAttributes & W32C_FOREGROUND_MASK ) | attr
190 : ( actualAttributes & W32C_BACKGROUND_MASK ) | (attr << 4);
191 }
192
193 // Styles
194 else if ( c == 's' )
195 {
196 // bold/italics style not supported in Windows console
197
198 // reset all
199 if ( rest.ConsumeChar() == 'a' )
200 actualAttributes= originalConsoleAttributes;
201 }
202
203 // auto tab / end of meta
204 else if ( c == 't' || c == 'A' )
205 {
206 c= rest.ConsumeChar();
207 int extraSpace= c >= '0' && c <= '9' ? (int) ( c - '0' )
208 : (int) ( c - 'A' ) + 10;
209
210 // tab stop (write spaces using a growing buffer)
211 integer tabStop= varFormatAutoSizes.Get<FormatAutoSizes>().Main.Next(
212 AutoSizes::Types::Tabstop, column, extraSpace );
213 integer qtySpaces= tabStop - column;
214 if( qtySpaces > 0 )
215 {
216 column+= qtySpaces;
217 characters::AlignedCharArray<nchar, 8*sizeof(void*)> spaces( ' ' );
218 while (qtySpaces >= spaces.Length() ) {
219 WriteConsoleA( H, spaces.Buffer(), (DWORD) spaces.Length(), &ignore, NULL );
220 qtySpaces-= spaces.Length();
221 }
222 if (qtySpaces > 0)
223 WriteConsoleA( H, spaces.Buffer(), (DWORD) qtySpaces, &ignore, NULL );
224 }
225 }
226
227
228 // Link (we just colorize links here)
229 else if ( c == 'l' )
230 {
231 if ( rest.ConsumeChar() == 'S' )
232 actualAttributes= ( actualAttributes & W32C_FOREGROUND_MASK )
233 | W32C_BLUE
234 | ( CFP.LCU == ColorfulLoggerParameters::LightColorUsage::Foreground
235 ? FOREGROUND_INTENSITY
236 : 0 );
237 else
238 actualAttributes= ( actualAttributes & W32C_FOREGROUND_MASK ) | ( originalConsoleAttributes & ~W32C_FOREGROUND_MASK );
239 }
240
241
242 else
243 {
244 ALIB_WARNING( "ALOX", "WindowsConsoleLogger: Unknown ESC code" );
245 }
246
247 // set the attributes
248 ALIB_ASSERT_RESULT_NOT_EQUALS( SetConsoleTextAttribute( H, actualAttributes ), 0 );
249
250
251 } // write loop
252
253 ALIB_ASSERT_RESULT_NOT_EQUALS( SetConsoleTextAttribute( H, previousAttributes ), 0 );
254
255 std::cout << std::endl;
256}
257
258} // namespace [alib::lox::loggers]
259
260#endif // Win32
261
ALIB_API bool Define(Priority requestedPriority=Priority::Standard)
Definition variable.cpp:272
threads::SharedLock & GetConfigLock()
Definition camp.hpp:219
static constexpr character RED[4]
Select red color for foreground.
static constexpr character GRAY[4]
Select gray color for foreground.
static constexpr character BLUE[4]
Select blue color for foreground.
WORD originalConsoleAttributes
The attributes that were set on the windows console at the time this object was created.
virtual ALIB_API void logText(detail::Domain &domain, Verbosity verbosity, AString &msg, detail::ScopeInfo &scope, int lineNumber)
ALIB_API WindowsConsoleLogger(const NString &name=nullptr)
virtual ALIB_API void AcknowledgeLox(detail::LoxImpl *lox, lang::ContainerOp op) override
textlogger::ColorfulLoggerParameters CFP
virtual ALIB_API void AcknowledgeLox(detail::LoxImpl *lox, lang::ContainerOp op) override
constexpr integer Length() const
Definition string.hpp:326
TString< TChar > Substring(integer regionStart, integer regionLength=MAX_LEN) const
Definition string.hpp:406
constexpr const TChar * Buffer() const
Definition string.hpp:319
integer WStringLength() const
@ Tabstop
denotes a tab stop entry.
ALIB_API TSubstring< TChar > & Next(lang::Whitespaces trimming=lang::Whitespaces::Trim, TChar newDelim='\0')
Definition tokenizer.cpp:16
TSubstring< TChar > Actual
Definition tokenizer.hpp:73
#define ALIB_WARNING(...)
Definition alib.hpp:1268
#define A_CHAR(STR)
#define ALIB_ASSERT_RESULT_NOT_EQUALS( func, value)
Definition alib.hpp:1287
#define ALIB_ASSERT_WARNING(cond,...)
Definition alib.hpp:1272
#define ALIB_LOCK_WITH(lock)
Definition owner.hpp:456
@ Keep
Keep whitespaces in string.
ContainerOp
Denotes standard container operations.
@ Insert
Denotes insertions.
This namespaces defines class TextLogger and its helpers.
Definition loxpimpl.inl:41
@ CONSOLE_LIGHT_COLORS
Denotes configuration variable ALOX/CONSOLE_LIGHT_COLORS used by colorful specializations of class Te...
@ CODEPAGE
Denotes configuration variable ALOX/CODEPAGE used by class WindowsConsoleLogger.
lox::ALoxCamp ALOX
The singleton instance of ALib Camp class ALoxCamp.
Definition aloxcamp.cpp:33
characters::character character
Type alias in namespace alib.
characters::nchar nchar
Type alias in namespace alib.
lang::integer integer
Type alias in namespace alib.
Definition integers.hpp:273
Parameters specific to colorful loggers. As of today, this simply has one attribute.