summaryrefslogtreecommitdiff
path: root/ext/Log4Qt/src/colorconsoleappender.cpp
blob: e83fafd1b0cd3719971438e3ad43d347b3b690eb (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
/******************************************************************************
 *
 * package:			log4qt
 * file:        colorconsoleappender.cpp
 * created:     March 2010
 * author:      Filonenko Michael
 *
 *
 * Copyright 2010 Filonenko Michael
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 ******************************************************************************/

/******************************************************************************
 * Dependencies
 ******************************************************************************/

#include "colorconsoleappender.h"

#include <QtCore/QTextStream>

#include "loggingevent.h"
#include "layout.h"

#define NIX_BACK_BLACK		40
#define NIX_BACK_RED			41
#define NIX_BACK_GREEN		42
#define NIX_BACK_YELLOW		43
#define NIX_BACK_BLUE			44
#define NIX_BACK_MAGNETTA	45
#define NIX_BACK_CYAN			46
#define NIX_BACK_GRAY			47

#define NIX_FORE_BLACK		30
#define NIX_FORE_RED			31
#define NIX_FORE_GREEN		32
#define NIX_FORE_YELLOW		33
#define NIX_FORE_BLUE			34
#define NIX_FORE_MAGNETTA	35
#define NIX_FORE_CYAN			36
#define NIX_FORE_GRAY			37

#define NIX_FORE_BOLD			1

#define NIX_DEFAULT				0

#if defined(__WIN32__) || defined(WIN) || defined(WIN32) || defined(Q_OS_WIN32)
//#include <windows.h>
#define WIN_BACK_BLACK						0
#define WIN_BACK_RED							BACKGROUND_RED
#define WIN_BACK_LIGHT_RED				BACKGROUND_RED | BACKGROUND_INTENSITY
#define WIN_BACK_GREEN						BACKGROUND_GREEN
#define WIN_BACK_LIGHT_GREEN			BACKGROUND_GREEN | BACKGROUND_INTENSITY
#define WIN_BACK_YELLOW						BACKGROUND_GREEN | BACKGROUND_RED
#define WIN_BACK_LIGHT_YELLOW			BACKGROUND_GREEN | BACKGROUND_RED | BACKGROUND_INTENSITY
#define WIN_BACK_BLUE							BACKGROUND_BLUE
#define WIN_BACK_LIGHT_BLUE				BACKGROUND_BLUE | BACKGROUND_INTENSITY
#define WIN_BACK_MAGNETTA					BACKGROUND_RED | BACKGROUND_BLUE
#define WIN_BACK_LIGHT_MAGNETTA		BACKGROUND_RED | BACKGROUND_BLUE | BACKGROUND_INTENSITY
#define WIN_BACK_CYAN							BACKGROUND_BLUE | BACKGROUND_GREEN
#define WIN_BACK_LIGHT_CYAN				BACKGROUND_BLUE | BACKGROUND_GREEN
#define WIN_BACK_GRAY							BACKGROUND_BLUE | BACKGROUND_GREEN | BACKGROUND_RED
#define WIN_BACK_WHITE						BACKGROUND_BLUE | BACKGROUND_GREEN | BACKGROUND_RED | BACKGROUND_INTENSITY

#define WIN_FORE_BLACK						0
#define WIN_FORE_RED							FOREGROUND_RED
#define WIN_FORE_LIGHT_RED				FOREGROUND_RED | FOREGROUND_INTENSITY
#define WIN_FORE_GREEN						FOREGROUND_GREEN
#define WIN_FORE_LIGHT_GREEN			FOREGROUND_GREEN | FOREGROUND_INTENSITY
#define WIN_FORE_YELLOW						FOREGROUND_GREEN | FOREGROUND_RED
#define WIN_FORE_LIGHT_YELLOW			FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_INTENSITY
#define WIN_FORE_BLUE							FOREGROUND_BLUE
#define WIN_FORE_LIGHT_BLUE				FOREGROUND_BLUE | FOREGROUND_INTENSITY
#define WIN_FORE_MAGNETTA					FOREGROUND_RED | FOREGROUND_BLUE
#define WIN_FORE_LIGHT_MAGNETTA		FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_INTENSITY
#define WIN_FORE_CYAN							FOREGROUND_BLUE | FOREGROUND_GREEN
#define WIN_FORE_LIGHT_CYAN				FOREGROUND_BLUE | FOREGROUND_GREEN
#define WIN_FORE_GRAY							FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED
#define WIN_FORE_WHITE						FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_INTENSITY

#define WIN_FORE_BOLD							FOREGROUND_INTENSITY

#define WIN_DEFAULT								FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED

static void colorOutputString(HANDLE hConsole, const QString& output)
{
  QString message = output;

  // save colors
	CONSOLE_SCREEN_BUFFER_INFO cbi;
  GetConsoleScreenBufferInfo(hConsole,&cbi);

  wchar_t *wideMessage;

  QStringList colorizedMessage = message.split('\033');

  int actualSize;
  DWORD out;

  WORD color = 0;
  WORD newColor = 0;
  QString parsedWordString;
  QStringList escParams;
  int indexOfM;
  // display first part of message
  if (!colorizedMessage.at(0).isEmpty()) {
    wideMessage = new wchar_t [colorizedMessage.at(0).size()];
    actualSize = colorizedMessage.at(0).toWCharArray(wideMessage);
    WriteConsoleW(hConsole, wideMessage, actualSize, &out, 0);
    delete [] wideMessage;
    colorizedMessage.removeAt(0);
  }
  foreach (QString it, colorizedMessage) {
    // color setted
    if (it.startsWith("[")) {
      indexOfM = it.indexOf('m');
      // not esc-sequence
      if (indexOfM != -1) {
        parsedWordString = it.mid(1, indexOfM - 1);

        escParams = parsedWordString.split(';');
        foreach(QString param, escParams) {
          color = param.toUInt();
          switch(color) {
            case NIX_DEFAULT:
            newColor = WIN_DEFAULT;
            break;
            case NIX_FORE_BOLD:
            newColor |= WIN_FORE_BOLD;
            break;
            case NIX_BACK_BLACK :
            newColor = (newColor & 0x0f) | WIN_BACK_BLACK;
            break;
            case NIX_BACK_RED :
            newColor = (newColor & 0x0f) | WIN_BACK_RED;
            break;
            case NIX_BACK_GREEN :
            newColor = (newColor & 0x0f) | WIN_BACK_GREEN;
            break;
            case NIX_BACK_YELLOW :
            newColor = (newColor & 0x0f) | WIN_BACK_YELLOW;
            break;
            case NIX_BACK_BLUE :
            newColor = (newColor & 0x0f) | WIN_BACK_BLUE;
            break;
            case NIX_BACK_MAGNETTA :
            newColor = (newColor & 0x0f) | WIN_BACK_MAGNETTA;
            break;
            case NIX_BACK_CYAN :
            newColor = (newColor & 0x0f) | WIN_BACK_CYAN;
            break;
            case NIX_BACK_GRAY :
            newColor = (newColor & 0x0f) | WIN_BACK_GRAY;
            break;
            case NIX_FORE_BLACK :
            newColor = (newColor & 0xF8)| WIN_FORE_BLACK;
            break;
            case NIX_FORE_RED :
            newColor = (newColor & 0xF8) | WIN_FORE_RED;
            break;
            case NIX_FORE_GREEN :
            newColor = (newColor & 0xF8) | WIN_FORE_GREEN;
            break;
            case NIX_FORE_YELLOW :
            newColor = (newColor & 0xF8) | WIN_FORE_YELLOW;
            break;
            case NIX_FORE_BLUE :
            newColor = (newColor & 0xF8) | WIN_FORE_BLUE;
            break;
            case NIX_FORE_MAGNETTA :
            newColor = (newColor & 0xF8) | WIN_FORE_MAGNETTA;
            break;
            case NIX_FORE_CYAN :
            newColor = (newColor & 0xF8) | WIN_FORE_CYAN;
            break;
            case NIX_FORE_GRAY :
            newColor = (newColor & 0xF8) | WIN_FORE_GRAY;
            break;
            default:break;
          }
        }
        it = it.mid(indexOfM + 1);

        SetConsoleTextAttribute(hConsole, newColor);
      }
    }

    wideMessage = new wchar_t [it.size()];
    actualSize = it.toWCharArray(wideMessage);
    WriteConsoleW(hConsole, wideMessage, actualSize, &out, 0);
    delete [] wideMessage;
  }
  // load old colors
  SetConsoleTextAttribute(hConsole, cbi.wAttributes);

  //qDebug() << colorizedMessage;

}
#endif

namespace Log4Qt {

  /**************************************************************************
   * Declarations
   **************************************************************************/

  /**************************************************************************
   * C helper functions
   **************************************************************************/

  /**************************************************************************
   * Class implementation: ColorConsoleAppender
   **************************************************************************/

  ColorConsoleAppender::ColorConsoleAppender(QObject *pParent) :
    ConsoleAppender(pParent)
  {
  }

  ColorConsoleAppender::ColorConsoleAppender(Layout *pLayout, QObject *pParent) :
    ConsoleAppender(pLayout, pParent)
  {
  }

  ColorConsoleAppender::ColorConsoleAppender(Layout *pLayout,
    const QString &rTarget, QObject *pParent) :
    ConsoleAppender(pLayout, rTarget, pParent)
  {
  }

  ColorConsoleAppender::ColorConsoleAppender(Layout *pLayout, Target target,
    QObject *pParent) :
    ConsoleAppender(pLayout, target, pParent)
  {
  }

#if defined(__WIN32__) || defined(WIN) || defined(WIN32) || defined(Q_OS_WIN32)
void ColorConsoleAppender::append(const LoggingEvent &rEvent)
{
  QString message = layout()->format(rEvent);

  colorOutputString(hConsole, message);

  // обрабатываем ошибки, по умолчанию метод не реализован
  if (handleIoErrors())
  return;

  if (immediateFlush())
  {
    writer()->flush();
    if (handleIoErrors())
    return;
  }
}

void ColorConsoleAppender::activateOptions()
{
  ConsoleAppender::activateOptions();

  if (target() == "STDOUT_TARGET")
  hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
  else
  hConsole = GetStdHandle(STD_ERROR_HANDLE);
}

void ColorConsoleAppender::close()
{
  ConsoleAppender::close();
  CloseHandle(hConsole);
}

#endif

/******************************************************************************
 * Implementation: Operators, Helper
 ******************************************************************************/

} // namespace Log4Qt