ALib C++ Library
Library Version: 2402 R1
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 (HPP_ALOX_WINDOWS_CONSOLE_LOGGER)
11#endif
12
13
14#if defined( _WIN32 )
15
16#if !defined(ALIB_DOX)
17# if !defined (HPP_ALIB_ALOXMODULE)
19# endif
20# if !defined (HPP_ALIB_STRINGS_UTIL_TOKENIZER)
22# endif
23# if !defined(HPP_ALIB_STRINGS_UTIL_SPACES)
25# endif
26
27# if !defined(HPP_ALIB_ENUMS_SERIALIZATION)
29# endif
30# if !defined(HPP_ALIB_CAMP_MESSAGE_REPORT)
32# endif
33# if !defined (_GLIBCXX_IOSTREAM) && !defined(_IOSTREAM_)
34# include <iostream>
35# endif
36# if !defined (_STRING_H) && !defined(_INC_STRING)
37# include <string.h>
38# endif
39#endif // !defined(ALIB_DOX)
40
41
42namespace alib::lox::loggers {
43
44using namespace detail;
45
46// #################################################################################################
47// Windows Console Colors
48// #################################################################################################
49 #define W32C_FOREGROUND_MASK 0xFFF0
50 #define W32C_BACKGROUND_MASK 0xFF0F
51
52 #define W32C_BLACK 0
53 #define W32C_RED FOREGROUND_RED
54 #define W32C_GREEN FOREGROUND_GREEN
55 #define W32C_BLUE FOREGROUND_BLUE
56 #define W32C_CYAN FOREGROUND_GREEN | FOREGROUND_BLUE
57 #define W32C_MAGENTA FOREGROUND_RED | FOREGROUND_BLUE
58 #define W32C_YELLOW FOREGROUND_RED | FOREGROUND_GREEN
59 #define W32C_WHITE FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY
60
61 #define W32C_GRAY_LIGHT FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE
62 #define W32C_GRAY_DARK FOREGROUND_INTENSITY
63
64 //! @cond NO_DOX
65 WORD win32Cols[]=
66 {
67 W32C_RED,
68 W32C_GREEN,
69 W32C_YELLOW,
70 W32C_BLUE,
71 W32C_MAGENTA,
72 W32C_CYAN,
73 };
74 //! @endcond
75
76// #################################################################################################
77// Constructor/Destructor
78// #################################################################################################
79
81: TextLogger( name, "WINDOWS_CONSOLE", true)
82{
83 // get actual console attributes
84 WORD actualAttributes;
85 {
86 HANDLE H= GetStdHandle(STD_OUTPUT_HANDLE);
87 CONSOLE_SCREEN_BUFFER_INFO info;
88 GetConsoleScreenBufferInfo( H, &info );
89 actualAttributes= info.wAttributes;
90 originalConsoleAttributes= actualAttributes;
91 }
92
93 // evaluate environment variable "ALOX_CONSOLE_LIGHT_COLORS"
96 if ( ALOX.GetConfig().Load( variable ) != Priorities::NONE && variable.Size() > 0)
97 {
98 Substring p= variable.GetString();
99 if(p.Trim().IsNotEmpty())
100 {
101 if( !enums::Parse<LightColorUsage>( p, UseLightColors ) )
102 {
103 ALIB_WARNING( "ALOX", "Unknown value specified in variable: {} = {!Q'}.",
104 variable.Fullname(), variable.GetString() )
105 }
106 }
107 }
108
110 {
111 // default: dark background, hence use light color on foreground
114 }
115
116 // move verbosity information to the end to colorize the whole line
118 MetaInfo->Format._(A_CHAR("%V"));
123
124 // evaluate config variable CODE_PAGE
125 if ( ALOX.GetConfig().Load( variable.Declare( Variables::CODEPAGE ) ) > 0 )
126 CodePage= (UINT) variable.GetInteger();
127}
131
132// #################################################################################################
133// logText
134// #################################################################################################
136 AString& msg,
137 ScopeInfo& , int )
138{
139 HANDLE H= GetStdHandle(STD_OUTPUT_HANDLE);
140 DWORD ignore;
141
142 // get actual console attributes
143 WORD actualAttributes;
144 {
145 CONSOLE_SCREEN_BUFFER_INFO info;
146 GetConsoleScreenBufferInfo( H, &info );
147 actualAttributes= info.wAttributes;
148 }
149 WORD previousAttributes= actualAttributes;
150
151 // set codepage;
152 if ( CodePage != 0 )
153 SetConsoleOutputCP( CodePage );
154
155
156 // loop over message, print the parts between the escape sequences
157 integer column= 0;
158 Tokenizer msgParts( msg, '\x1B' );
159 Substring& actual= msgParts.Actual;
160 Substring& rest= msgParts.Rest;
161 for(;;)
162 {
163 if ( msgParts.Next(lang::Whitespaces::Keep ).IsNotEmpty() )
164 {
165 #if !ALIB_CHARACTERS_WIDE
166 WriteConsoleA( H, actual.Buffer(), (DWORD) actual.Length(), &ignore, NULL );
167 #else
168 WriteConsoleW( H, actual.Buffer(), (DWORD) actual.Length(), &ignore, NULL );
169 #endif
170 column+= actual.WStringLength();
171 }
172
173 if ( !msgParts.HasNext() )
174 break;
175
176 // found a delimiter: process ESC sequence
177 character c= rest.ConsumeChar<false>();
178
179 // Colors
180 bool isForeGround= true;
181 if( c == 'C' || c == 'c' )
182 {
183 isForeGround= c== 'c';
184
185 c= rest.ConsumeChar();
186 int colNo= c - '0';
187 ALIB_ASSERT_WARNING( colNo >=0 && colNo <=9, "ALOX", "ConsoleLogger: Unknown ESC-c code" )
188
189 WORD attr= 0;
190 WORD light= UseLightColors != LightColorUsage::Never && ((UseLightColors== LightColorUsage::Foreground) == isForeGround ) ? FOREGROUND_INTENSITY : 0;
191
192 // 0..5 (red, green, yellow, blue, magenta, cyan)
193 if ( colNo >= 0 && colNo < 6) attr= (win32Cols[colNo] | light);
194
195 else if ( colNo == 6 ) attr= W32C_BLACK;
196 else if ( colNo == 7 ) attr= W32C_WHITE;
197 else if ( colNo == 8 ) attr= light ? W32C_GRAY_LIGHT : W32C_GRAY_DARK;
198 else if ( colNo == 9 ) attr= isForeGround ? originalConsoleAttributes & ~W32C_FOREGROUND_MASK
199 : ( originalConsoleAttributes & ~W32C_BACKGROUND_MASK ) >> 4;
200 else
201 {
202 ALIB_WARNING( "ALOX", "Unknown ESC- code \"C{}{}...\"", c, rest.Substring(0,10) );
203 }
204
205 actualAttributes= isForeGround ? ( actualAttributes & W32C_FOREGROUND_MASK ) | attr
206 : ( actualAttributes & W32C_BACKGROUND_MASK ) | (attr << 4);
207 }
208
209 // Styles
210 else if ( c == 's' )
211 {
212 // bold/italics style not supported in Windows console
213
214 // reset all
215 if ( rest.ConsumeChar() == 'a' )
216 actualAttributes= originalConsoleAttributes;
217 }
218
219 // auto tab / end of meta
220 else if ( c == 't' || c == 'A' )
221 {
222 c= rest.ConsumeChar();
223 int extraSpace= c >= '0' && c <= '9' ? (int) ( c - '0' )
224 : (int) ( c - 'A' ) + 10;
225
226 // tab stop (write spaces using a growing buffer)
227 integer tabStop= AutoSizes.Next( AutoSizes::Types::Tabstop, column, extraSpace );
228 integer qtySpaces= tabStop - column;
229 if( qtySpaces > 0 )
230 {
231 column+= qtySpaces;
233 while ( qtySpaces > 0 )
234 {
235 integer nextQty= qtySpaces < spaces.Length() ? qtySpaces
236 : spaces.Length();
237 #if !ALIB_CHARACTERS_WIDE
238 WriteConsoleA( H, spaces.Buffer(), (DWORD) nextQty, &ignore, NULL );
239 #else
240 WriteConsoleW( H, spaces.Buffer(), (DWORD) nextQty, &ignore, NULL );
241 #endif
242
243 qtySpaces-= nextQty;
244 }
245 }
246 }
247
248
249 // Link (we just colorize links here)
250 else if ( c == 'l' )
251 {
252 if ( rest.ConsumeChar() == 'S' )
253 actualAttributes= ( actualAttributes & W32C_FOREGROUND_MASK ) | W32C_BLUE | ( UseLightColors == LightColorUsage::Foreground ? FOREGROUND_INTENSITY : 0 );
254 else
255 actualAttributes= ( actualAttributes & W32C_FOREGROUND_MASK ) | ( originalConsoleAttributes & ~W32C_FOREGROUND_MASK );
256 }
257
258
259 else
260 {
261 ALIB_WARNING( "ALOX", "WindowsConsoleLogger: Unknown ESC code" );
262 }
263
264 // set the attributes
265 ALIB_ASSERT_RESULT_NOT_EQUALS( SetConsoleTextAttribute( H, actualAttributes ), 0 );
266
267
268 } // write loop
269
270 ALIB_ASSERT_RESULT_NOT_EQUALS( SetConsoleTextAttribute( H, previousAttributes ), 0 );
271
272 std::cout << std::endl;
273}
274
275} // namespace [alib::lox::loggers]
276
277#endif // Win32
ALIB_API Priorities Load(Variable &variable)
integer Size() const
Definition variable.hpp:708
ALIB_API const String & Fullname()
Definition variable.cpp:266
ALIB_API Variable & Declare(const VariableDecl &declaration, const Box &replacements)
Definition variable.cpp:77
const String & GetString(int idx=0)
Definition variable.hpp:780
ALIB_API integer GetInteger(int idx=0)
Definition variable.cpp:244
config::Configuration & GetConfig()
Definition camp.hpp:231
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.
virtual ALIB_API void logText(detail::Domain &domain, Verbosity verbosity, AString &msg, detail::ScopeInfo &scope, int lineNumber)
ALIB_API WindowsConsoleLogger(const NString &name=nullptr)
TAString & _(const TString< TChar > &src, integer regionStart, integer regionLength=MAX_LEN)
Definition astring.hpp:1056
ALIB_API integer SearchAndReplace(TChar needle, TChar replacement, integer startIdx=0)
Definition astring.cpp:330
constexpr bool IsNotEmpty() const
Definition string.hpp:420
constexpr integer Length() const
Definition string.hpp:357
TString< TChar > Substring(integer regionStart, integer regionLength=MAX_LEN) const
Definition string.hpp:314
constexpr const TChar * Buffer() const
Definition string.hpp:350
integer WStringLength() const
TSubstring & Trim(const TCString< TChar > &whiteSpaces=TT_StringConstants< TChar >::DefaultWhitespaces())
@ Tabstop
denotes a tab stop entry.
integer Next(Types type, integer requestedSize, integer growthPadding)
static String & Get(integer minLength=128)
Definition spaces.hpp:58
ALIB_API TSubstring< TChar > & Next(lang::Whitespaces trimming=lang::Whitespaces::Trim, TChar newDelim='\0')
Definition tokenizer.cpp:18
TSubstring< TChar > Actual
Definition tokenizer.hpp:84
#define ALIB_WARNING(...)
Definition alib.hpp:981
#define A_CHAR(STR)
#define ALIB_ASSERT_RESULT_NOT_EQUALS( func, value)
Definition alib.hpp:1000
#define ALIB_ASSERT_WARNING(cond,...)
Definition alib.hpp:985
@ Keep
Keep whitespaces in string.
lox::ALox ALOX
characters::character character
Type alias in namespace alib.
lang::integer integer
Type alias in namespace alib.
Definition integers.hpp:286