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