Terminal++ 3.1.0.4
A C++ library for interacting with ANSI terminal windows
Loading...
Searching...
No Matches
element_difference.hpp
1#pragma once
2
3#include "terminalpp/ansi/charset.hpp"
4#include "terminalpp/ansi/control_characters.hpp"
5#include "terminalpp/ansi/csi.hpp"
6#include "terminalpp/ansi/dec_private_mode.hpp"
7#include "terminalpp/ansi/graphics.hpp"
8#include "terminalpp/ansi/protocol.hpp"
9#include "terminalpp/attribute.hpp"
10#include "terminalpp/behaviour.hpp"
11#include "terminalpp/character_set.hpp"
12#include "terminalpp/colour.hpp"
13#include "terminalpp/core.hpp"
14#include "terminalpp/detail/overloaded.hpp"
15#include "terminalpp/effect.hpp"
16#include "terminalpp/element.hpp"
17
18#include <fmt/format.h>
19
20#include <optional>
21#include <utility>
22
23namespace terminalpp::detail {
24
25//* =========================================================================
27//* =========================================================================
28template <class WriteContinuation>
29constexpr void csi(
30 behaviour const & /*terminal_behaviour*/, WriteContinuation &&wc)
31{
32 wc({std::cbegin(ansi::control7::csi), std::cend(ansi::control7::csi)});
33}
34
35//* =========================================================================
37//* =========================================================================
38template <class WriteContinuation>
39constexpr void osc(
40 behaviour const & /*terminal_behaviour*/, WriteContinuation &&wc)
41{
42 wc({std::cbegin(ansi::control7::osc), std::cend(ansi::control7::osc)});
43}
44
45//* =========================================================================
47//* =========================================================================
48template <class WriteContinuation>
49constexpr void st(
50 behaviour const & /*terminal_behaviour*/, WriteContinuation &&wc)
51{
52 wc({std::cbegin(ansi::control7::st), std::cend(ansi::control7::st)});
53}
54
55//* =========================================================================
57//* =========================================================================
58template <class WriteContinuation>
59constexpr void dec_pm(
60 behaviour const &terminal_behaviour, WriteContinuation &&wc)
61{
62 csi(terminal_behaviour, wc);
63
64 std::initializer_list<byte> const dec_pm{
65 terminalpp::ansi::dec_private_mode[0]};
66
67 wc(dec_pm);
68}
69
70//* =========================================================================
73//* =========================================================================
74template <class WriteContinuation>
75constexpr void default_attribute(
76 behaviour const &terminal_behaviour, WriteContinuation &&wc)
77{
78 std::initializer_list<byte> const default_attribute_string = {
79 '0'_tb, terminalpp::ansi::csi::select_graphics_rendition};
80
81 csi(terminal_behaviour, wc);
82 wc(default_attribute_string);
83}
84
85//* =========================================================================
87//* =========================================================================
88template <class WriteContinuation>
89constexpr void designate_g0_charset(
90 character_set const &set,
91 behaviour const & /*terminal_behaviour*/,
92 WriteContinuation &&wc)
93{
94 bytes const select_g0_charset = {
95 std::cbegin(ansi::set_charset_g0), std::cend(ansi::set_charset_g0)};
96
97 wc(select_g0_charset);
98 wc(encode_character_set(set));
99}
100
101//* =========================================================================
103//* =========================================================================
104template <class WriteContinuation>
105constexpr void select_utf8_charset(WriteContinuation &&wc)
106{
107 bytes const select_utf8_charset_command = {
108 std::cbegin(ansi::select_utf8_character_set),
109 std::cend(ansi::select_utf8_character_set)};
110
111 wc(select_utf8_charset_command);
112}
113
114//* =========================================================================
116//* =========================================================================
117template <class WriteContinuation>
118constexpr void select_default_charset(WriteContinuation &&wc)
119{
120 bytes const select_default_charset_command = {
121 std::cbegin(ansi::select_default_character_set),
122 std::cend(ansi::select_default_character_set)};
123
124 wc(select_default_charset_command);
125}
126
127//* =========================================================================
130//* =========================================================================
131template <class WriteContinuation>
132constexpr void change_charset(
133 character_set const &source,
134 character_set const &dest,
135 behaviour const &terminal_behaviour,
136 WriteContinuation &&wc)
137{
138 if (source != dest)
139 {
140 if (dest == charset::utf8)
141 {
142 if (!terminal_behaviour.unicode_in_all_charsets)
143 {
144 change_charset(
145 source, charset::us_ascii, terminal_behaviour, wc);
146 }
147
148 select_utf8_charset(wc);
149 }
150 else
151 {
152 if (source == charset::utf8)
153 {
154 select_default_charset(wc);
155 }
156
157 designate_g0_charset(dest, terminal_behaviour, wc);
158 }
159 }
160}
161
162//* =========================================================================
164//* =========================================================================
165template <class EffectType, class WriteContinuation>
166constexpr void change_effect(
167 effect<EffectType> const &source,
168 effect<EffectType> const &dest,
169 bool &change_appended,
170 WriteContinuation &&wc)
171{
172 std::initializer_list<byte> const separator = {ansi::ps};
173
174 if (source != dest)
175 {
176 if constexpr (effect_has_normal<EffectType>::value)
177 {
178 if (source.value_ != EffectType::normal
179 && dest.value_ != EffectType::normal)
180 {
181 if (std::exchange(change_appended, true))
182 {
183 wc(separator);
184 }
185
186 wc(to_bytes(fmt::format("{}", int(EffectType::normal))));
187 }
188 }
189
190 if (std::exchange(change_appended, true))
191 {
192 wc(separator);
193 }
194
195 wc(to_bytes(fmt::format("{}", int(dest.value_))));
196 }
197}
198
199//* =========================================================================
201//* =========================================================================
202template <class WriteContinuation>
203constexpr void change_foreground_colour(
204 colour const &source,
205 colour const &dest,
206 bool &change_appended,
207 WriteContinuation &&wc)
208{
209 if (source != dest)
210 {
211 if (std::exchange(change_appended, true))
212 {
213 std::initializer_list<byte> const separator = {ansi::ps};
214 wc(separator);
215 }
216
217 std::visit(
218 overloaded{
219 [&wc](low_colour const &col) {
220 wc(to_bytes(fmt::format(
221 "{}",
222 static_cast<int>(col.value_)
223 + ansi::graphics::foreground_colour_base)));
224 },
225 [&wc](high_colour const &col) {
226 wc(to_bytes(
227 fmt::format("38;5;{}", static_cast<int>(col.value_))));
228 },
229 [&wc](greyscale_colour const &col) {
230 wc(to_bytes(
231 fmt::format("38;5;{}", static_cast<int>(col.shade_))));
232 },
233 [&wc](true_colour const &col) {
234 wc(to_bytes(fmt::format(
235 "38;2;{};{};{}",
236 static_cast<int>(col.red_),
237 static_cast<int>(col.green_),
238 static_cast<int>(col.blue_))));
239 }},
240 dest.value_);
241 }
242}
243
244//* =========================================================================
246//* =========================================================================
247template <class WriteContinuation>
248constexpr void change_background_colour(
249 colour const &source,
250 colour const &dest,
251 bool &change_appended,
252 WriteContinuation &&wc)
253{
254 if (source != dest)
255 {
256 if (std::exchange(change_appended, true))
257 {
258 std::initializer_list<byte> const separator = {ansi::ps};
259 wc(separator);
260 }
261
262 std::visit(
263 overloaded{
264 [&wc](low_colour const &col) {
265 wc(to_bytes(fmt::format(
266 "{}",
267 static_cast<int>(col.value_)
268 + ansi::graphics::background_colour_base)));
269 },
270 [&wc](high_colour const &col) {
271 wc(to_bytes(
272 fmt::format("48;5;{}", static_cast<int>(col.value_))));
273 },
274 [&wc](greyscale_colour const &col) {
275 wc(to_bytes(
276 fmt::format("48;5;{}", static_cast<int>(col.shade_))));
277 },
278 [&wc](true_colour const &col) {
279 wc(to_bytes(fmt::format(
280 "48;2;{};{};{}",
281 static_cast<int>(col.red_),
282 static_cast<int>(col.green_),
283 static_cast<int>(col.blue_))));
284 }},
285 dest.value_);
286 }
287}
288
289//* =========================================================================
291//* =========================================================================
292template <class WriteContinuation>
293constexpr void change_attribute(
294 attribute const &source,
295 attribute const &dest,
296 behaviour const &terminal_behaviour,
297 WriteContinuation &&wc)
298{
299 if (source == dest)
300 {
301 return;
302 }
303
304 if (dest == terminalpp::attribute{})
305 {
306 default_attribute(terminal_behaviour, wc);
307 return;
308 }
309
310 csi(terminal_behaviour, wc);
311
312 bool change_appended = false;
313 change_effect(source.intensity_, dest.intensity_, change_appended, wc);
314 change_effect(source.polarity_, dest.polarity_, change_appended, wc);
315 change_effect(source.underlining_, dest.underlining_, change_appended, wc);
316 change_foreground_colour(
317 source.foreground_colour_,
318 dest.foreground_colour_,
319 change_appended,
320 wc);
321 change_background_colour(
322 source.background_colour_,
323 dest.background_colour_,
324 change_appended,
325 wc);
326
327 std::initializer_list<byte> const sgr_trailer = {
328 ansi::csi::select_graphics_rendition};
329
330 wc(sgr_trailer);
331}
332
333//* =========================================================================
335//* =========================================================================
336template <class WriteContinuation>
337constexpr void change_to_default_attribute(
338 std::optional<element> &last_element,
339 behaviour const &beh,
340 WriteContinuation &&wc)
341{
342 if (last_element)
343 {
344 detail::change_attribute(last_element->attribute_, {}, beh, wc);
345 last_element->attribute_ = {};
346 }
347}
348
349} // namespace terminalpp::detail
A structure that carries around the presentation attributes of an ANSI element.
Definition attribute.hpp:17