-
Notifications
You must be signed in to change notification settings - Fork 4
Expand file tree
/
Copy pathColouredBuffer.hpp
More file actions
206 lines (165 loc) · 3.56 KB
/
ColouredBuffer.hpp
File metadata and controls
206 lines (165 loc) · 3.56 KB
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
#pragma once
#include <sstream>
#include "console-colour.h"
#ifdef CONMD_WINDOWS
#include <iostream>
#endif
namespace cmdmd
{
template <class C, class T = std::char_traits<C>, class A = std::allocator<C>>
class ColouredBuffer : public std::basic_stringbuf<C, T, A>
{
public:
static void StandardInstall();
private:
typedef
std::basic_stringbuf<C, T, A>
stringbuf_type;
typedef
std::basic_ostream<C, T>
ostream_type;
typedef
std::basic_streambuf<C, T>
streambuf_type;
typedef
typename T::int_type
int_type;
typedef
typename T::pos_type
pos_type;
typedef
typename T::off_type
off_type;
typedef
C
char_type;
typedef
T
traits_type;
typedef
std::streamsize
size_type;
streambuf_type &
buffer_;
ColouredBuffer() = delete;
#ifdef CONMD_WINDOWS
bool const
coloured_;
ostream_type*
src_;
HANDLE
handle_;
struct console_colour_stream_s
stream_;
struct console_colour_call_s
call_;
template <typename C2>
size_type WriteColouredX(C2 const * data, size_type len);
template <>
size_type WriteColouredX<char>(char const * data, size_type len)
{
return ::WriteColouredA(data, (int)len, &stream_);
}
template <>
size_type WriteColouredX<wchar_t>(wchar_t const * data, size_type len)
{
return ::WriteColouredW(data, (int)len, &stream_);
}
static int OutputC(void* data, wchar_t c, struct console_colour_stream_s* const stream);
static int OutputA(void* data, char const* c, int len, struct console_colour_stream_s* const stream);
static int OutputW(void* data, wchar_t const* c, int len, struct console_colour_stream_s* const stream);
static void OutputColour(void* data, unsigned short colour, struct console_colour_stream_s* const stream);
#endif
public:
#ifdef CONMD_WINDOWS
// cons
ColouredBuffer(ostream_type & src, bool coloured, bool err = false)
:
buffer_(*src.rdbuf()),
coloured_(coloured),
src_(&src),
handle_(GetStdHandle(err ? STD_ERROR_HANDLE : STD_OUTPUT_HANDLE)),
call_{
&OutputC,
&OutputA,
&OutputW,
&OutputColour,
(void *)this
},
stream_{
&call_,
&gConsoleStreamState,
}
{
src_->rdbuf(this);
CONSOLE_SCREEN_BUFFER_INFO
info;
HANDLE
handle = GetStdHandle(STD_OUTPUT_HANDLE);
GetConsoleScreenBufferInfo(handle, &info);
stream_.State->CurrentStyle = stream_.State->DefaultStyle = info.wAttributes;
}
// dest
~ColouredBuffer()
{
if (src_)
{
src_->rdbuf(&buffer_);
}
HANDLE
handle = GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleTextAttribute(handle, stream_.State->DefaultStyle);
}
#else
// cons
ColouredBuffer(ostream_type & src, bool coloured, bool err)
:
buffer_(*src.rdbuf())
{
}
// dest
~ColouredBuffer()
{
}
#endif
int_type overflow(int_type c) override
{
#ifdef CONMD_WINDOWS
char_type
s = (char_type)c;
return (int_type)WriteColouredX<char_type>(&s, 1);
#else
return buffer_.sputc(c);
#endif
}
protected:
size_type xsputn(char_type const * s, size_type n) override
{
#ifdef CONMD_WINDOWS
return (size_type)WriteColouredX<char_type>(s, n);
#else
return buffer_.sputn(s, n);
#endif
}
int sync() override
{
#ifdef CONMD_WINDOWS
// If they flush mid sequence there's not a lot we can do about it! We can't keep buffering
// characters under the hood, even via a state machine, if they explicitly requested a flush.
::Backout(&stream_);
return 0;
#else
return buffer_.pubsync();
#endif
}
};
#ifdef CONMD_WINDOWS
#pragma warning(push)
#pragma warning(disable: 4661)
#endif
template class ColouredBuffer<char>;
template class ColouredBuffer<wchar_t>;
#ifdef CONMD_WINDOWS
#pragma warning(pop)
#endif
}