]> git.cworth.org Git - vogl/blob - src/voglcore/vogl_colorized_console.cpp
Initial vogl checkin
[vogl] / src / voglcore / vogl_colorized_console.cpp
1 /**************************************************************************
2  *
3  * Copyright 2013-2014 RAD Game Tools and Valve Software
4  * Copyright 2010-2014 Rich Geldreich and Tenacious Software LLC
5  * All Rights Reserved.
6  *
7  * Permission is hereby granted, free of charge, to any person obtaining a copy
8  * of this software and associated documentation files (the "Software"), to deal
9  * in the Software without restriction, including without limitation the rights
10  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11  * copies of the Software, and to permit persons to whom the Software is
12  * furnished to do so, subject to the following conditions:
13  *
14  * The above copyright notice and this permission notice shall be included in
15  * all copies or substantial portions of the Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23  * THE SOFTWARE.
24  *
25  **************************************************************************/
26
27 // File: vogl_colorized_console.cpp
28 #include "vogl_core.h"
29 #include "vogl_colorized_console.h"
30 #ifdef VOGL_USE_WIN32_API
31 #include "vogl_winhdr.h"
32 #endif
33
34 namespace vogl
35 {
36     static vogl_exception_callback_t g_pPrev_exception_callback;
37
38     void colorized_console::atexit_func()
39     {
40         set_default_color();
41     }
42
43     void colorized_console::exception_callback()
44     {
45         set_default_color();
46
47         if (g_pPrev_exception_callback)
48             (*g_pPrev_exception_callback)();
49     }
50
51     void colorized_console::init()
52     {
53         console::init();
54         console::add_console_output_func(console_output_func, NULL);
55
56         atexit(atexit_func);
57     }
58
59     void colorized_console::set_exception_callback()
60     {
61         g_pPrev_exception_callback = vogl_set_exception_callback(exception_callback);
62     }
63
64     void colorized_console::deinit()
65     {
66         console::remove_console_output_func(console_output_func);
67         console::deinit();
68     }
69
70     void colorized_console::tick()
71     {
72     }
73
74 #ifdef VOGL_USE_WIN32_API
75     void colorized_console::set_default_color()
76     {
77         DWORD attr = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE;
78         SetConsoleTextAttribute(cons, (WORD)attr);
79     }
80
81     bool colorized_console::console_output_func(eConsoleMessageType type, const char *pMsg, void *pData)
82     {
83         pData;
84
85         if (console::get_output_disabled())
86             return true;
87
88         HANDLE cons = GetStdHandle(STD_OUTPUT_HANDLE);
89
90         DWORD attr = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE;
91         switch (type)
92         {
93             case cDebugConsoleMessage:
94                 attr = FOREGROUND_BLUE | FOREGROUND_INTENSITY;
95                 break;
96             case cMessageConsoleMessage:
97                 attr = FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY;
98                 break;
99             case cWarningConsoleMessage:
100                 attr = FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_INTENSITY;
101                 break;
102             case cErrorConsoleMessage:
103                 attr = FOREGROUND_RED | FOREGROUND_INTENSITY;
104                 break;
105             default:
106                 break;
107         }
108
109         if (INVALID_HANDLE_VALUE != cons)
110             SetConsoleTextAttribute(cons, (WORD)attr);
111
112         puts(pMsg);
113
114         if (INVALID_HANDLE_VALUE != cons)
115             SetConsoleTextAttribute(cons, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
116
117         return true;
118     }
119 #elif VOGL_USE_LINUX_API
120 #define ANSI_RESET "\033[0m"
121 #define ANSI_BLACK "\033[30m"              /* Black */
122 #define ANSI_RED "\033[31m"                /* Red */
123 #define ANSI_GREEN "\033[32m"              /* Green */
124 #define ANSI_YELLOW "\033[33m"             /* Yellow */
125 #define ANSI_BLUE "\033[34m"               /* Blue */
126 #define ANSI_MAGENTA "\033[35m"            /* Magenta */
127 #define ANSI_CYAN "\033[36m"               /* Cyan */
128 #define ANSI_WHITE "\033[37m"              /* White */
129 #define ANSI_BOLDBLACK "\033[1m\033[30m"   /* Bold Black */
130 #define ANSI_BOLDRED "\033[1m\033[31m"     /* Bold Red */
131 #define ANSI_BOLDGREEN "\033[1m\033[32m"   /* Bold Green */
132 #define ANSI_BOLDYELLOW "\033[1m\033[33m"  /* Bold Yellow */
133 #define ANSI_BOLDBLUE "\033[1m\033[34m"    /* Bold Blue */
134 #define ANSI_BOLDMAGENTA "\033[1m\033[35m" /* Bold Magenta */
135 #define ANSI_BOLDCYAN "\033[1m\033[36m"    /* Bold Cyan */
136 #define ANSI_BOLDWHITE "\033[1m\033[37m"   /* Bold White */
137
138     void colorized_console::set_default_color()
139     {
140         if (isatty(fileno(stdout)))
141         {
142             fputs(ANSI_RESET, stdout);
143         }
144
145         if (isatty(fileno(stderr)))
146         {
147             fputs(ANSI_RESET, stderr);
148         }
149     }
150
151     bool colorized_console::console_output_func(eConsoleMessageType type, const char *pMsg, void *pData)
152     {
153         (void)pData;
154
155         static bool g_colors_inited = false;
156         static dynamic_string g_colors[cCMTTotal];
157
158         if (console::get_output_disabled())
159             return true;
160
161         if (!g_colors_inited)
162         {
163             g_colors_inited = true;
164
165             g_colors[cDebugConsoleMessage] = ANSI_BOLDBLUE;       // debugging messages
166             g_colors[cProgressConsoleMessage] = "";               // progress messages
167             g_colors[cInfoConsoleMessage] = "";                   // ordinary messages
168             g_colors[cConsoleConsoleMessage] = "";                // user console output
169             g_colors[cMessageConsoleMessage] = ANSI_BOLDCYAN;     // high importance messages
170             g_colors[cWarningConsoleMessage] = ANSI_BOLDYELLOW;   // warnings
171             g_colors[cErrorConsoleMessage] = ANSI_BOLDRED;        // errors
172             g_colors[cHeader1ConsoleMessage] = "\033[44m\033[1m"; // header (dark blue background)
173
174             // Use just like LS_COLORS. Example: VOGL_COLORS='warning=1;34:message=31'
175             // Tokens are debug, progress, info, default, message, warning, error.
176             const char *vogl_colors = getenv("VOGL_COLORS");
177             if (vogl_colors)
178             {
179                 dynamic_string_array tokens;
180                 dynamic_string colors = (vogl_colors[0] == '\'') ? (vogl_colors + 1) : vogl_colors;
181
182                 colors.tokenize(":", tokens, true);
183                 for (uint i = 0; i < tokens.size(); i++)
184                 {
185                     dynamic_string &str = tokens[i];
186                     dynamic_string_array color_tokens;
187
188                     str.tokenize("=;", color_tokens, true);
189                     if (color_tokens.size() >= 2)
190                     {
191                         eConsoleMessageType color_type = console::get_message_type_from_str(color_tokens[0].c_str());
192                         if (color_type >= 0)
193                         {
194                             for (uint j = 1; j < color_tokens.size(); j++)
195                             {
196                                 if (j == 1)
197                                     g_colors[color_type].format("\033[%sm", color_tokens[j].c_str());
198                                 else
199                                     g_colors[color_type].format_append("\033[%sm", color_tokens[j].c_str());
200                             }
201                         }
202                     }
203                 }
204             }
205         }
206
207         const char *pANSIColor = g_colors[type].c_str();
208         FILE *pFile = (type == cErrorConsoleMessage) ? stderr : stdout;
209         bool is_redirected = !isatty(fileno(pFile)) && pANSIColor[0];
210
211         if (!is_redirected)
212             fputs(pANSIColor, pFile);
213
214         fputs(pMsg, pFile);
215
216         if (!is_redirected)
217             fputs(ANSI_RESET, pFile);
218
219         return true;
220     }
221
222 #else
223     void colorized_console::set_default_color()
224     {
225     }
226
227     bool colorized_console::console_output_func(eConsoleMessageType type, const char *pMsg, void *pData)
228     {
229         pData;
230         if (console::get_output_disabled())
231             return true;
232
233         FILE *pFile = (type == cErrorConsoleMessage) ? stderr : stdout;
234
235         fputs(pMsg, pFile);
236
237         return true;
238     }
239 #endif
240
241 } // namespace vogl