DotNetDupe 4.0.6
C++17/20 Implementation of the .NET Base Class Library (BCL)
Loading...
Searching...
No Matches
Console.cpp
Go to the documentation of this file.
1#include "pch.h"
2#include "System/Console.h"
5#include <mutex>
6#include <iostream>
7#include <string>
8#include <vector>
9
10#if defined(_WIN32)
11#include <windows.h>
12#include "Win32Internal.h"
13using namespace DotNetDupe::System::Internal;
14#else
15#include <unistd.h>
16#endif
17
18using namespace DotNetDupe::System;
19
20namespace {
21 static std::vector<String> s_outputs;
22 static std::vector<String> s_inputs;
23 static String s_accumulator = String("");
24 static std::recursive_mutex s_mutex;
25 static ConsoleColor s_defaultFore = ConsoleColor::Gray;
26 static ConsoleColor s_defaultBack = ConsoleColor::Black;
27 static ConsoleColor s_currentFore = ConsoleColor::Gray;
28 static ConsoleColor s_currentBack = ConsoleColor::Black;
29 static String s_consoleTitle = String("");
30 static bool s_colorsInitialized = false;
31
32 void EnsureColorsInitialized() {
33 if (!s_colorsInitialized) {
34#if defined(_WIN32)
35 CONSOLE_SCREEN_BUFFER_INFO csbi;
36 if (GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi)) {
37 s_defaultFore = (ConsoleColor)(csbi.wAttributes & 0x0F);
38 s_defaultBack = (ConsoleColor)((csbi.wAttributes & 0xF0) >> 4);
39 s_currentFore = s_defaultFore;
40 s_currentBack = s_defaultBack;
41 }
42#endif
43 s_colorsInitialized = true;
44 }
45 }
46 static SmartPointer<IO::TextWriter> s_pOutWriter = nullptr;
47 static SmartPointer<IO::TextWriter> s_pErrorWriter = nullptr;
48 static SmartPointer<IO::TextReader> s_pInReader = nullptr;
49}
50
51void InternalWrite(const String& sValue) {
52 SmartPointer<IO::TextWriter> pWriter = nullptr;
53 {
55 std::lock_guard<std::recursive_mutex> lk(s_mutex);
56 s_accumulator = s_accumulator + sValue;
57 pWriter = s_pOutWriter;
58
60 if (!pWriter) {
61 std::cout << sValue.GetRawString() << std::flush;
62 return;
63 }
64 }
65
67 pWriter->Write(sValue);
68}
69
70void InternalWriteLine(const String& sValue) {
71 SmartPointer<IO::TextWriter> pWriter = nullptr;
72 {
73 std::lock_guard<std::recursive_mutex> lk(s_mutex);
74 s_accumulator = s_accumulator + sValue;
75 s_outputs.push_back(s_accumulator);
76 pWriter = s_pOutWriter;
77 if (!pWriter) {
78 std::cout << sValue.GetRawString() << std::endl;
79 s_accumulator = "";
80 return;
81 }
82 s_accumulator = "";
83 }
84 pWriter->WriteLine(sValue);
85}
86
87void Console::Write(bool value) { InternalWrite(value ? "True" : "False"); }
88void Console::Write(Char value) { char buf[2] = { static_cast<char>(value.GetChar()), 0 }; InternalWrite(buf); }
89void Console::Write(double value) { InternalWrite(String(std::to_string(value).c_str())); }
90void Console::Write(int value) { InternalWrite(String(std::to_string(value).c_str())); }
91void Console::Write(long value) { InternalWrite(String(std::to_string(value).c_str())); }
92void Console::Write(long long value) { InternalWrite(String(std::to_string(value).c_str())); }
93void Console::Write(float value) { InternalWrite(String(std::to_string(value).c_str())); }
94void Console::Write(const String& value) { InternalWrite(value); }
95void Console::Write(const char* value) { InternalWrite(value); }
96
98void Console::WriteLine(bool value) { InternalWriteLine(value ? "True" : "False"); }
99void Console::WriteLine(Char value) { char buf[2] = { static_cast<char>(value.GetChar()), 0 }; InternalWriteLine(String(buf)); }
100void Console::WriteLine(double value) { InternalWriteLine(String(std::to_string(value).c_str())); }
101void Console::WriteLine(int value) { InternalWriteLine(String(std::to_string(value).c_str())); }
102void Console::WriteLine(long value) { InternalWriteLine(String(std::to_string(value).c_str())); }
103void Console::WriteLine(long long value) { InternalWriteLine(String(std::to_string(value).c_str())); }
104void Console::WriteLine(float value) { InternalWriteLine(String(std::to_string(value).c_str())); }
105void Console::WriteLine(const String& value) { InternalWriteLine(value); }
106void Console::WriteLine(const char* value) { InternalWriteLine(String(value)); }
107
109 std::lock_guard<std::recursive_mutex> lk(s_mutex);
110 if (s_pInReader) {
111 return s_pInReader->Read();
112 }
113 return std::cin.get();
114}
115
117 std::lock_guard<std::recursive_mutex> lk(s_mutex);
118 if (s_pInReader) {
119 return s_pInReader->ReadLine();
120 }
121 if (!s_inputs.empty()) {
122 String v = s_inputs.front();
123 s_inputs.erase(s_inputs.begin());
124 return v;
125 }
126
127 std::string line;
128 std::getline(std::cin, line);
129 return String(line.c_str());
130}
131
133#if defined(_WIN32)
134 CONSOLE_SCREEN_BUFFER_INFO csbi;
135 if (GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi)) {
136 return csbi.dwCursorPosition.X;
137 }
138#endif
139 return 0;
140}
141
144}
145
147#if defined(_WIN32)
148 CONSOLE_SCREEN_BUFFER_INFO csbi;
149 if (GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi)) {
150 return csbi.dwCursorPosition.Y;
151 }
152#endif
153 return 0;
154}
155
158}
159
160void Console::SetCursorPosition(int left, int top) {
161#if defined(_WIN32)
162 COORD coord = { (SHORT)left, (SHORT)top };
163 SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord);
164#else
165 // ANSI escape: \033[{row};{col}H (1-indexed)
166 std::cout << "\033[" << (top + 1) << ";" << (left + 1) << "H" << std::flush;
167#endif
168}
169
171#if defined(_WIN32)
172 CONSOLE_CURSOR_INFO cci;
173 if (GetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &cci)) {
174 return cci.bVisible != FALSE;
175 }
176#endif
177 return true;
178}
179
180void Console::SetCursorVisible(bool visible) {
181#if defined(_WIN32)
182 CONSOLE_CURSOR_INFO cci;
183 HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
184 if (GetConsoleCursorInfo(hConsole, &cci)) {
185 cci.bVisible = visible;
186 SetConsoleCursorInfo(hConsole, &cci);
187 }
188#else
189 if (visible) std::cout << "\033[?25h" << std::flush;
190 else std::cout << "\033[?25l" << std::flush;
191#endif
192}
193
195#if defined(_WIN32)
196 CONSOLE_SCREEN_BUFFER_INFO csbi;
197 if (GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi)) {
198 return csbi.srWindow.Bottom - csbi.srWindow.Top + 1;
199 }
200#endif
201 return 25; // Standard fallback
202}
203
204void Console::SetWindowHeight(int height) {
205#if defined(_WIN32)
206 HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
207 CONSOLE_SCREEN_BUFFER_INFO csbi;
208 if (GetConsoleScreenBufferInfo(hConsole, &csbi)) {
209 SMALL_RECT rect = csbi.srWindow;
210 rect.Bottom = rect.Top + (SHORT)height - 1;
211 SetConsoleWindowInfo(hConsole, TRUE, &rect);
212 }
213#endif
214}
215
217#if defined(_WIN32)
218 CONSOLE_SCREEN_BUFFER_INFO csbi;
219 if (GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi)) {
220 return csbi.srWindow.Right - csbi.srWindow.Left + 1;
221 }
222#endif
223 return 80; // Standard fallback
224}
225
226void Console::SetWindowWidth(int width) {
227#if defined(_WIN32)
228 HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
229 CONSOLE_SCREEN_BUFFER_INFO csbi;
230 if (GetConsoleScreenBufferInfo(hConsole, &csbi)) {
231 SMALL_RECT rect = csbi.srWindow;
232 rect.Right = rect.Left + (SHORT)width - 1;
233 SetConsoleWindowInfo(hConsole, TRUE, &rect);
234 }
235#endif
236}
237
239#if defined(_WIN32)
240 return (GetKeyState(VK_CAPITAL) & 0x0001) != 0;
241#endif
242 return false;
243}
244
246#if defined(_WIN32)
247 return (GetKeyState(VK_NUMLOCK) & 0x0001) != 0;
248#endif
249 return false;
250}
251
253 EnsureColorsInitialized();
254#if defined(_WIN32)
255 CONSOLE_SCREEN_BUFFER_INFO csbi;
256 if (GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi)) {
257 return (ConsoleColor)((csbi.wAttributes & 0xF0) >> 4);
258 }
259#endif
260 return s_currentBack;
261}
262
264 EnsureColorsInitialized();
265 s_currentBack = color;
266#if defined(_WIN32)
267 HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
268 CONSOLE_SCREEN_BUFFER_INFO csbi;
269 if (GetConsoleScreenBufferInfo(hConsole, &csbi)) {
270 WORD attributes = (csbi.wAttributes & 0xFF0F) | (((WORD)color << 4) & 0x00F0);
271 SetConsoleTextAttribute(hConsole, attributes);
272 }
273#else
274 static const int ansiBack[] = { 40, 44, 42, 46, 41, 45, 43, 47, 100, 104, 102, 106, 101, 105, 103, 107 };
275 int idx = static_cast<int>(color);
276 if (idx >= 0 && idx < 16) {
277 std::cout << "\033[" << ansiBack[idx] << "m" << std::flush;
278 }
279#endif
280}
281
283 EnsureColorsInitialized();
284#if defined(_WIN32)
285 CONSOLE_SCREEN_BUFFER_INFO csbi;
286 if (GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi)) {
287 return (ConsoleColor)(csbi.wAttributes & 0x0F);
288 }
289#endif
290 return s_currentFore;
291}
292
294 EnsureColorsInitialized();
295 s_currentFore = color;
296#if defined(_WIN32)
297 HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
298 CONSOLE_SCREEN_BUFFER_INFO csbi;
299 if (GetConsoleScreenBufferInfo(hConsole, &csbi)) {
300 WORD attributes = (csbi.wAttributes & 0xFFF0) | ((WORD)color & 0x000F);
301 SetConsoleTextAttribute(hConsole, attributes);
302 }
303#else
304 static const int ansiFore[] = { 30, 34, 32, 36, 31, 35, 33, 37, 90, 94, 92, 96, 91, 95, 93, 97 };
305 int idx = static_cast<int>(color);
306 if (idx >= 0 && idx < 16) {
307 std::cout << "\033[" << ansiFore[idx] << "m" << std::flush;
308 }
309#endif
310}
311
313 EnsureColorsInitialized();
314 SetForegroundColor(s_defaultFore);
315 SetBackgroundColor(s_defaultBack);
316#if !defined(_WIN32)
317 std::cout << "\033[0m" << std::flush;
318#endif
319}
320
322#if defined(_WIN32)
323 wchar_t title[MAX_PATH];
324 if (GetConsoleTitleW(title, MAX_PATH)) {
325 return String(WCharToUtf8(title).c_str());
326 }
327#endif
328 return s_consoleTitle;
329}
330
331void Console::SetTitle(const String& title) {
332 s_consoleTitle = title;
333#if defined(_WIN32)
334 ::SetConsoleTitleW(Utf8ToWChar(title.GetRawString()).c_str());
335#else
336 std::cout << "\033]0;" << title.GetRawString() << "\007" << std::flush;
337#endif
338}
339
341#if defined(_WIN32)
342 ::Beep(800, 200);
343#else
344 std::cout << "\a" << std::flush;
345#endif
346}
347
349#if defined(_WIN32)
350 HANDLE h = GetStdHandle(STD_OUTPUT_HANDLE);
351 CONSOLE_SCREEN_BUFFER_INFO csbi;
352 DWORD count, cellCount;
353 COORD home = { 0, 0 };
354 if (GetConsoleScreenBufferInfo(h, &csbi)) {
355 cellCount = csbi.dwSize.X * csbi.dwSize.Y;
356 FillConsoleOutputCharacterW(h, (wchar_t)' ', cellCount, home, &count);
357 FillConsoleOutputAttribute(h, csbi.wAttributes, cellCount, home, &count);
358 SetConsoleCursorPosition(h, home);
359 }
360#else
361 std::cout << "\033[2J\033[1;1H" << std::flush;
362#endif
363}
364
366 std::lock_guard<std::recursive_mutex> lk(s_mutex);
367 s_outputs.clear();
368 s_inputs.clear();
369 s_accumulator = String("");
370 s_pOutWriter = nullptr;
371 s_pErrorWriter = nullptr;
372 s_pInReader = nullptr;
374}
375
377 std::lock_guard<std::recursive_mutex> lk(s_mutex);
378 s_pOutWriter = pOutWriter;
379}
380
382 std::lock_guard<std::recursive_mutex> lk(s_mutex);
383 s_pErrorWriter = pErrorWriter;
384}
385
387 if (!pInReader) {
388 throw ArgumentException("pInReader cannot be null.");
389 }
390 std::lock_guard<std::recursive_mutex> lk(s_mutex);
391 s_pInReader = pInReader;
392}
393
395 std::lock_guard<std::recursive_mutex> lk(s_mutex);
396 return s_pOutWriter;
397}
398
400 std::lock_guard<std::recursive_mutex> lk(s_mutex);
401 return s_pErrorWriter;
402}
403
405 std::lock_guard<std::recursive_mutex> lk(s_mutex);
406 return s_pInReader;
407}
408
409void Console::SetIn(const String& value) {
410 std::lock_guard<std::recursive_mutex> lk(s_mutex);
411 s_inputs.push_back(value);
412}
413
415 std::lock_guard<std::recursive_mutex> lk(s_mutex);
416 s_inputs.clear();
417}
418
420 std::lock_guard<std::recursive_mutex> lock(s_mutex);
421 Array<String> result((int)s_outputs.size());
422 for (int i = 0; i < (int)s_outputs.size(); i++) result[i] = s_outputs[i];
423 return result;
424}
void InternalWriteLine(const String &sValue)
Definition Console.cpp:70
static void ClearConsoleScreenNative()
Definition Console.cpp:348
void InternalWrite(const String &sValue)
Definition Console.cpp:51
Represents standard input, output, and error streams for console applications.
ArgumentException(const String &sMessage)
Initializes a new instance of the ArgumentException class with a specified error message.
Provides methods for creating, manipulating, searching, and sorting arrays, thereby serving as the ba...
Definition Array.h:29
Represents a Unicode character (as a UTF-32 char32_t code point).
Definition Char.h:20
char32_t GetChar() const
Definition Char.h:74
static void SetWindowHeight(int iHeight)
Definition Console.cpp:204
static void SetError(const SmartPointer< IO::TextWriter > &pErrorWriter)
Definition Console.cpp:381
static SmartPointer< IO::TextWriter > Error()
Definition Console.cpp:399
static bool GetNumberLock()
Definition Console.cpp:245
static void SetBackgroundColor(ConsoleColor enumColor)
Definition Console.cpp:263
static void SetOut(const SmartPointer< IO::TextWriter > &pOutWriter)
Definition Console.cpp:376
static void SetTitle(const String &sTitle)
Definition Console.cpp:331
static String ReadLine()
Definition Console.cpp:116
static void Write(bool bValue)
Definition Console.cpp:87
static String GetTitle()
Definition Console.cpp:321
static void SetWindowWidth(int iWidth)
Definition Console.cpp:226
static void SetCursorTop(int iTop)
Definition Console.cpp:156
static ConsoleColor GetForegroundColor()
Definition Console.cpp:282
static SmartPointer< IO::TextWriter > Out()
Definition Console.cpp:394
static ConsoleColor GetBackgroundColor()
Definition Console.cpp:252
static void SetIn(const SmartPointer< IO::TextReader > &pInReader)
Definition Console.cpp:386
static bool GetCursorVisible()
Definition Console.cpp:170
static void SetCursorVisible(bool bVisible)
Definition Console.cpp:180
static void SetCursorPosition(int iLeft, int iTop)
Definition Console.cpp:160
static void SetCursorLeft(int iLeft)
Definition Console.cpp:142
static Array< String > GetOutputs()
Definition Console.cpp:419
static SmartPointer< IO::TextReader > In()
Definition Console.cpp:404
static void SetForegroundColor(ConsoleColor enumColor)
Definition Console.cpp:293
A unified smart pointer that supports both unique and shared ownership semantics.
Represents text as a sequence of UTF-8 code units with culture-invariant operations.
Definition String.h:74
String()
Initializes a new instance of the String class to an empty string.
Definition String.cpp:64
const char * GetRawString() const
Definition String.cpp:230
std::string WCharToUtf8(const wchar_t *pWStr)
std::wstring Utf8ToWChar(const char *pUtf8Str)
ConsoleColor
Specifies constants that define foreground and background colors for the console.
Definition Console.h:23