1 #pragma once
2 #include <cstdint>
3 #include <cstdio>
4 
5 //#define CONSOLE_COLORS_FORCE_ASCII
6 
7 #if defined _WIN32 && !defined PRINT_COLORED_FORCE_ASCII
8 #define USE_WIN32_API
9 #endif
10 
11 #if defined(USE_WIN32_API)
12 
13 namespace win32_lite
14 {
15 typedef void* HANDLE;
16 typedef uint32_t DWORD;
17 
18 #define WIN32_LITE_STD_INPUT_HANDLE (static_cast<win32_lite::DWORD>(-10))
19 #define WIN32_LITE_STD_OUTPUT_HANDLE (static_cast<win32_lite::DWORD>(-11))
20 #define WIN32_LITE_STD_ERROR_HANDLE (static_cast<win32_lite::DWORD>(-12))
21 
22 #define WIN32_LITE_ENABLE_VIRTUAL_TERMINAL_PROCESSING (4)
23 
24 #define WIN32_LITE_DECLSPEC_IMPORT __declspec(dllimport)
25 
26 #define WIN32_LITE_WINAPI __stdcall
27 
28 typedef short SHORT;
29 typedef unsigned short WORD;
30 typedef int WINBOOL;
31 
32 extern "C"
33 {
34     WIN32_LITE_DECLSPEC_IMPORT WINBOOL WIN32_LITE_WINAPI GetConsoleMode(HANDLE hConsole, DWORD* dwMode);
35     WIN32_LITE_DECLSPEC_IMPORT WINBOOL WIN32_LITE_WINAPI SetConsoleMode(HANDLE hConsole, DWORD dwMode);
36     WIN32_LITE_DECLSPEC_IMPORT HANDLE WIN32_LITE_WINAPI GetStdHandle(DWORD nStdHandle);
37     WIN32_LITE_DECLSPEC_IMPORT WINBOOL WIN32_LITE_WINAPI SetConsoleTextAttribute(HANDLE hConsoleOutput,
38                                                                                  WORD wAttributes);
39 }
40 } // namespace win32_lite
41 
42 #endif
43 
44 namespace console_colors
45 {
46 
47 enum text_color : uint32_t
48 {
49     Black         = 0x00,
50     DarkBlue      = 0x01,
51     DarkGreen     = 0x02,
52     DarkCyan      = 0x03,
53     DarkRed       = 0x04,
54     DarkMagenta   = 0x05,
55     DarkYellow    = 0x06,
56     LightGrey     = 0x07,
57     Gray          = 0x08,
58     Blue          = 0x09,
59     Green         = 0x0A,
60     Cyan          = 0x0B,
61     Red           = 0x0C,
62     Magenta       = 0x0D,
63     Yellow        = 0x0E,
64     White         = 0x0F,
65     BgBlack       = 0x00,
66     BgDarkBlue    = 0x10,
67     BgDarkGreen   = 0x20,
68     BgDarkCyan    = 0x30,
69     BgDarkRed     = 0x40,
70     BgDarkMagenta = 0x50,
71     BgDarkYellow  = 0x60,
72     BgLightGrey   = 0x70,
73     BgGray        = 0x80,
74     BgBlue        = 0x90,
75     BgGreen       = 0xA0,
76     BgCyan        = 0xB0,
77     BgRed         = 0xC0,
78     BgMagenta     = 0xD0,
79     BgYellow      = 0xE0,
80     BgWhite       = 0xF0,
81 
82     Normal = BgBlack | LightGrey
83 };
84 
85 enum console_buffer
86 {
87     ConsoleStdOutput,
88     ConsoleStdError
89 };
90 
91 struct console_color
92 {
93 public:
console_colorconsole_colors::console_color94     console_color(text_color c, console_buffer console = ConsoleStdOutput)
95         : m_old(get(console)), m_console(console)
96     {
97         set(c, m_console);
98     }
99 
~console_colorconsole_colors::console_color100     ~console_color() { set(m_old, m_console); }
101 
102 private:
getconsole_colors::console_color103     text_color get(console_buffer = ConsoleStdOutput) { return saved_color(); }
104 
setconsole_colors::console_color105     void set(text_color new_color, console_buffer console = ConsoleStdOutput)
106     {
107 #ifdef USE_WIN32_API
108         win32_lite::SetConsoleTextAttribute(win32_lite::GetStdHandle(console == ConsoleStdOutput
109                                                                          ? WIN32_LITE_STD_OUTPUT_HANDLE
110                                                                          : WIN32_LITE_STD_ERROR_HANDLE),
111                                             static_cast<win32_lite::WORD>(new_color));
112 #else
113         if (new_color != Normal)
114         {
115             uint8_t t    = new_color & 0xF;
116             uint8_t b    = (new_color & 0xF0) >> 4;
117             uint8_t tnum = 30 + ((t & 1) << 2 | (t & 2) | (t & 4) >> 2);
118             uint8_t bnum = 40 + ((b & 1) << 2 | (b & 2) | (b & 4) >> 2);
119             if (t & 8)
120                 tnum += 60;
121             if (b & 8)
122                 bnum += 60;
123             std::fprintf(console == ConsoleStdOutput ? stdout : stderr, "\x1B[%d;%dm", tnum, bnum);
124         }
125         else
126         {
127             std::fprintf(console == ConsoleStdOutput ? stdout : stderr, "\x1B[0m");
128         }
129 #endif
130         saved_color() = new_color;
131     }
132 
133     text_color m_old;
134     console_buffer m_console;
saved_colorconsole_colors::console_color135     static text_color& saved_color()
136     {
137         static text_color color = Normal;
138         return color;
139     }
140 };
141 
142 template <text_color color, console_buffer console = ConsoleStdOutput>
143 struct console_color_tpl : public console_color
144 {
145 public:
console_color_tplconsole_colors::console_color_tpl146     console_color_tpl() : console_color(color, console) {}
147 
148 private:
149 };
150 
151 typedef console_color_tpl<DarkBlue> darkblue_text;
152 typedef console_color_tpl<DarkGreen> darkgreen_text;
153 typedef console_color_tpl<DarkCyan> darkcyan_text;
154 typedef console_color_tpl<DarkRed> darkred_text;
155 typedef console_color_tpl<DarkMagenta> darkmagenta_text;
156 typedef console_color_tpl<DarkYellow> darkyellow_text;
157 typedef console_color_tpl<LightGrey> lightgrey_text;
158 typedef console_color_tpl<Gray> gray_text;
159 typedef console_color_tpl<Blue> blue_text;
160 typedef console_color_tpl<Green> green_text;
161 typedef console_color_tpl<Cyan> cyan_text;
162 typedef console_color_tpl<Red> red_text;
163 typedef console_color_tpl<Magenta> magenta_text;
164 typedef console_color_tpl<Yellow> yellow_text;
165 typedef console_color_tpl<White> white_text;
166 } // namespace console_colors
167