Bug Summary

File:/rootdir/_build/../src/bteseq.cc
Warning:line 4756, column 19
The left operand of '<=' is a garbage value

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name bteseq.cc -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -mframe-pointer=none -relaxed-aliasing -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/rootdir/_build -resource-dir /usr/lib/llvm-14/lib/clang/14.0.6 -I src/libbte-2.91.so.0.6500.0.p -I src -I ../src -I . -I .. -I src/bte -I ../src/bte -I /usr/include/glib-2.0 -I /usr/lib/x86_64-linux-gnu/glib-2.0/include -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/pango-1.0 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/fribidi -I /usr/include/uuid -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/p11-kit-1 -I /usr/include/ctk-3.0 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/x86_64-linux-gnu -I /usr/include/gio-unix-2.0 -I /usr/include/atk-1.0 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/at-spi-2.0 -I /usr/include/dbus-1.0 -I /usr/lib/x86_64-linux-gnu/dbus-1.0/include -D _FILE_OFFSET_BITS=64 -D G_LOG_DOMAIN="BTE" -D LOCALEDIR="/usr/local/share/locale" -D BTE_DISABLE_DEPRECATION_WARNINGS -D BTE_COMPILATION -U PARSER_INCLUDE_NOP -D CDK_VERSION_MIN_REQUIRED=(G_ENCODE_VERSION(3,18)) -D CDK_VERSION_MAX_ALLOWED=(G_ENCODE_VERSION(3,20)) -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/12/../../../../include/c++/12 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/12/../../../../include/x86_64-linux-gnu/c++/12 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/12/../../../../include/c++/12/backward -internal-isystem /usr/lib/llvm-14/lib/clang/14.0.6/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/12/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O3 -Wno-address-of-packed-member -Wno-missing-field-initializers -Wno-packed -Wno-switch-enum -Wno-unused-parameter -Wwrite-strings -std=gnu++17 -fdeprecated-macro -fdebug-compilation-dir=/rootdir/_build -ferror-limit 19 -fvisibility hidden -fvisibility-inlines-hidden -stack-protector 2 -fgnuc-version=4.2.1 -fcxx-exceptions -fexceptions -fcolor-diagnostics -vectorize-loops -vectorize-slp -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2022-12-31-022803-10898-1 -x c++ ../src/bteseq.cc
1/*
2 * Copyright © 2001-2004 Red Hat, Inc.
3 * Copyright © 2015 David Herrmann <dh.herrmann@gmail.com>
4 * Copyright © 2008-2018 Christian Persch
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 3 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21#include "config.h"
22
23#include <search.h>
24#include <stdlib.h>
25#include <string.h>
26#include <limits.h>
27#ifdef HAVE_SYS_SYSLIMITS_H
28#include <sys/syslimits.h>
29#endif
30
31#include <glib.h>
32
33#include <bte/bte.h>
34#include "bteinternal.hh"
35#include "btectk.hh"
36#include "caps.hh"
37#include "debug.h"
38
39#define BEL_C0"\007" "\007"
40#define ST_C0"\033" "\\" _BTE_CAP_ST"\033" "\\"
41
42#include <algorithm>
43
44using namespace std::literals;
45
46enum {
47 BTE_XTERM_WM_RESTORE_WINDOW = 1,
48 BTE_XTERM_WM_MINIMIZE_WINDOW = 2,
49 BTE_XTERM_WM_SET_WINDOW_POSITION = 3,
50 BTE_XTERM_WM_SET_WINDOW_SIZE_PIXELS = 4,
51 BTE_XTERM_WM_RAISE_WINDOW = 5,
52 BTE_XTERM_WM_LOWER_WINDOW = 6,
53 BTE_XTERM_WM_REFRESH_WINDOW = 7,
54 BTE_XTERM_WM_SET_WINDOW_SIZE_CELLS = 8,
55 BTE_XTERM_WM_MAXIMIZE_WINDOW = 9,
56 BTE_XTERM_WM_FULLSCREEN_WINDOW = 10,
57 BTE_XTERM_WM_GET_WINDOW_STATE = 11,
58 BTE_XTERM_WM_GET_WINDOW_POSITION = 13,
59 BTE_XTERM_WM_GET_WINDOW_SIZE_PIXELS = 14,
60 BTE_XTERM_WM_GET_WINDOW_SIZE_CELLS = 18,
61 BTE_XTERM_WM_GET_SCREEN_SIZE_CELLS = 19,
62 BTE_XTERM_WM_GET_ICON_TITLE = 20,
63 BTE_XTERM_WM_GET_WINDOW_TITLE = 21,
64 BTE_XTERM_WM_TITLE_STACK_PUSH = 22,
65 BTE_XTERM_WM_TITLE_STACK_POP = 23,
66};
67
68enum {
69 BTE_SGR_COLOR_SPEC_RGB = 2,
70 BTE_SGR_COLOR_SPEC_LEGACY = 5
71};
72
73void
74bte::parser::Sequence::print() const noexcept
75{
76#ifdef BTE_DEBUG
77 auto c = m_seq != nullptr ? terminator() : 0;
78 char c_buf[7];
79 g_snprintf(c_buf, sizeof(c_buf), "%lc", c);
80 g_printerr("%s:%s [%s]", type_string(), command_string(),
81 g_unichar_isprint(c) ? c_buf : _bte_debug_sequence_to_string(c_buf, -1));
82 if (m_seq != nullptr && m_seq->n_args > 0) {
83 g_printerr("[ ");
84 for (unsigned int i = 0; i < m_seq->n_args; i++) {
85 if (i > 0)
86 g_print(", ");
87 g_printerr("%d", bte_seq_arg_value(m_seq->args[i]));
88 }
89 g_printerr(" ]");
90 }
91 if (m_seq->type == BTE_SEQ_OSC) {
92 char* str = string_param();
93 g_printerr(" \"%s\"", str);
94 g_free(str);
95 }
96 g_printerr("\n");
97#endif
98}
99
100char const*
101bte::parser::Sequence::type_string() const
102{
103 if (G_UNLIKELY(m_seq == nullptr)(__builtin_expect (__extension__ ({ int _g_boolean_var_; if (
m_seq == nullptr) _g_boolean_var_ = 1; else _g_boolean_var_ =
0; _g_boolean_var_; }), 0))
)
104 return "(nil)";
105
106 switch (type()) {
107 case BTE_SEQ_NONE: return "NONE";
108 case BTE_SEQ_IGNORE: return "IGNORE";
109 case BTE_SEQ_GRAPHIC: return "GRAPHIC";
110 case BTE_SEQ_CONTROL: return "CONTROL";
111 case BTE_SEQ_ESCAPE: return "ESCAPE";
112 case BTE_SEQ_CSI: return "CSI";
113 case BTE_SEQ_DCS: return "DCS";
114 case BTE_SEQ_OSC: return "OSC";
115 case BTE_SEQ_SCI: return "SCI";
116 case BTE_SEQ_APC: return "APC";
117 case BTE_SEQ_PM: return "PM";
118 case BTE_SEQ_SOS: return "SOS";
119 default:
120 g_assert(false)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (false) _g_boolean_var_ = 1; else _g_boolean_var_ = 0; _g_boolean_var_
; }), 1)) ; else g_assertion_message_expr ("BTE", "../src/bteseq.cc"
, 120, ((const char*) (__PRETTY_FUNCTION__)), "false"); } while
(0)
;
121 return nullptr;
122 }
123}
124
125char const*
126bte::parser::Sequence::command_string() const
127{
128 if (G_UNLIKELY(m_seq == nullptr)(__builtin_expect (__extension__ ({ int _g_boolean_var_; if (
m_seq == nullptr) _g_boolean_var_ = 1; else _g_boolean_var_ =
0; _g_boolean_var_; }), 0))
)
129 return "(nil)";
130
131 switch (command()) {
132#define _BTE_CMD(cmd) case BTE_CMD_##cmd: return #cmd;
133#define _BTE_NOP(cmd)
134#include "parser-cmd.hh"
135#undef _BTE_CMD
136#undef _BTE_NOP
137 default:
138 static char buf[32];
139 snprintf(buf, sizeof(buf), "NOP OR UNKOWN(%u)", command());
140 return buf;
141 }
142}
143
144// FIXMEchpe optimise this
145std::string
146bte::parser::Sequence::string_utf8() const noexcept
147{
148 std::string str;
149
150 size_t len;
151 auto buf = bte_seq_string_get(&m_seq->arg_str, &len);
152
153 char u[6];
154 for (size_t i = 0; i < len; ++i) {
155 auto ulen = g_unichar_to_utf8(buf[i], u);
156 str.append((char const*)u, ulen);
157 }
158
159 return str;
160}
161
162/* A couple are duplicated from bte.c, to keep them static... */
163
164/* Check how long a string of unichars is. Slow version. */
165static gsize
166bte_unichar_strlen(gunichar const* c)
167{
168 gsize i;
169 for (i = 0; c[i] != 0; i++) ;
170 return i;
171}
172
173/* Convert a wide character string to a multibyte string */
174/* Simplified from glib's g_ucs4_to_utf8() to simply allocate the maximum
175 * length instead of walking the input twice.
176 */
177char*
178bte::parser::Sequence::ucs4_to_utf8(gunichar const* str,
179 ssize_t len) const noexcept
180{
181 if (len < 0)
182 len = bte_unichar_strlen(str);
183 auto outlen = (len * BTE_UTF8_BPC(4)) + 1;
184
185 auto result = (char*)g_try_malloc(outlen);
186 if (result == nullptr)
187 return nullptr;
188
189 auto end = str + len;
190 auto p = result;
191 for (auto i = str; i < end; i++)
192 p += g_unichar_to_utf8(*i, p);
193 *p = '\0';
194
195 return result;
196}
197
198namespace bte {
199namespace terminal {
200
201/* Emit a "bell" signal. */
202void
203Terminal::emit_bell()
204{
205 _bte_debug_print(BTE_DEBUG_SIGNALS, "Emitting `bell'.\n")do { } while(0);
206 g_signal_emit(m_terminal, signals[SIGNAL_BELL], 0);
207}
208
209/* Emit a "resize-window" signal. (Grid size.) */
210void
211Terminal::emit_resize_window(guint columns,
212 guint rows)
213{
214 _bte_debug_print(BTE_DEBUG_SIGNALS, "Emitting `resize-window'.\n")do { } while(0);
215 g_signal_emit(m_terminal, signals[SIGNAL_RESIZE_WINDOW], 0, columns, rows);
216}
217
218/* Some common functions */
219
220/* In Xterm, upon printing a character in the last column the cursor doesn't
221 * advance. It's special cased that printing the following letter will first
222 * wrap to the next row.
223 *
224 * As a rule of thumb, escape sequences that move the cursor (e.g. cursor up)
225 * or immediately update the visible contents (e.g. clear in line) disable
226 * this special mode, whereas escape sequences with no immediate visible
227 * effect (e.g. color change) leave this special mode on. There are
228 * exceptions of course (e.g. scroll up).
229 *
230 * In BTE, a different technical approach is used. The cursor is advanced to
231 * the invisible column on the right, but it's set back to the visible
232 * rightmost column whenever necessary (that is, before handling any of the
233 * sequences that disable the special cased mode in xterm). (Bug 731155.)
234 */
235void
236Terminal::ensure_cursor_is_onscreen()
237{
238 if (G_UNLIKELY (m_screen->cursor.col >= m_column_count)(__builtin_expect (__extension__ ({ int _g_boolean_var_; if (
m_screen->cursor.col >= m_column_count) _g_boolean_var_
= 1; else _g_boolean_var_ = 0; _g_boolean_var_; }), 0))
)
239 m_screen->cursor.col = m_column_count - 1;
240}
241
242void
243Terminal::home_cursor()
244{
245 set_cursor_coords(0, 0);
246}
247
248void
249Terminal::clear_screen()
250{
251 auto row = m_screen->cursor.row - m_screen->insert_delta;
252 auto initial = _bte_ring_next(m_screen->row_data);
253 /* Add a new screen's worth of rows. */
254 for (auto i = 0; i < m_row_count; i++)
255 ring_append(true);
256 /* Move the cursor and insertion delta to the first line in the
257 * newly-cleared area and scroll if need be. */
258 m_screen->insert_delta = initial;
259 m_screen->cursor.row = row + m_screen->insert_delta;
260 adjust_adjustments();
261 /* Redraw everything. */
262 invalidate_all();
263 /* We've modified the display. Make a note of it. */
264 m_text_deleted_flag = TRUE(!(0));
265}
266
267/* Clear the current line. */
268void
269Terminal::clear_current_line()
270{
271 BteRowData *rowdata;
272
273 /* If the cursor is actually on the screen, clear data in the row
274 * which corresponds to the cursor. */
275 if (_bte_ring_next(m_screen->row_data) > m_screen->cursor.row) {
276 /* Get the data for the row which the cursor points to. */
277 rowdata = _bte_ring_index_writable(m_screen->row_data, m_screen->cursor.row);
278 g_assert(rowdata != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (rowdata != __null) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1)) ; else g_assertion_message_expr
("BTE", "../src/bteseq.cc", 278, ((const char*) (__PRETTY_FUNCTION__
)), "rowdata != NULL"); } while (0)
;
279 /* Remove it. */
280 _bte_row_data_shrink (rowdata, 0);
281 /* Add enough cells to the end of the line to fill out the row. */
282 _bte_row_data_fill (rowdata, &m_color_defaults, m_column_count);
283 set_hard_wrapped(m_screen->cursor.row);
284 rowdata->attr.bidi_flags = get_bidi_flags();
285 /* Repaint this row's paragraph (might need to extend upwards). */
286 invalidate_row_and_context(m_screen->cursor.row);
287 }
288
289 /* We've modified the display. Make a note of it. */
290 m_text_deleted_flag = TRUE(!(0));
291}
292
293/* Clear above the current line. */
294void
295Terminal::clear_above_current()
296{
297 /* Make the line just above the writable area hard wrapped. */
298 if (m_screen->insert_delta > _bte_ring_delta(m_screen->row_data)) {
299 set_hard_wrapped(m_screen->insert_delta - 1);
300 }
301 /* Clear data in all the writable rows above (excluding) the cursor's. */
302 for (auto i = m_screen->insert_delta; i < m_screen->cursor.row; i++) {
303 if (_bte_ring_next(m_screen->row_data) > i) {
304 /* Get the data for the row we're erasing. */
305 auto rowdata = _bte_ring_index_writable(m_screen->row_data, i);
306 g_assert(rowdata != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (rowdata != __null) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1)) ; else g_assertion_message_expr
("BTE", "../src/bteseq.cc", 306, ((const char*) (__PRETTY_FUNCTION__
)), "rowdata != NULL"); } while (0)
;
307 /* Remove it. */
308 _bte_row_data_shrink (rowdata, 0);
309 /* Add new cells until we fill the row. */
310 _bte_row_data_fill (rowdata, &m_color_defaults, m_column_count);
311 set_hard_wrapped(i);
312 rowdata->attr.bidi_flags = get_bidi_flags();
313 }
314 }
315 /* Repaint the cleared area. No need to extend, set_hard_wrapped() took care of
316 * invalidating the context lines if necessary. */
317 invalidate_rows(m_screen->insert_delta, m_screen->cursor.row - 1);
318 /* We've modified the display. Make a note of it. */
319 m_text_deleted_flag = TRUE(!(0));
320}
321
322/* Scroll the text, but don't move the cursor. Negative = up, positive = down. */
323void
324Terminal::scroll_text(bte::grid::row_t scroll_amount)
325{
326 bte::grid::row_t start, end;
327 if (m_scrolling_restricted) {
328 start = m_screen->insert_delta + m_scrolling_region.start;
329 end = m_screen->insert_delta + m_scrolling_region.end;
330 } else {
331 start = m_screen->insert_delta;
332 end = start + m_row_count - 1;
333 }
334
335 while (_bte_ring_next(m_screen->row_data) <= end)
336 ring_append(false);
337
338 if (scroll_amount > 0) {
339 /* Scroll down. */
340 for (auto i = 0; i < scroll_amount; i++) {
341 ring_remove(end);
342 ring_insert(start, true);
343 }
344 /* Set the boundaries to hard wrapped where we tore apart the contents.
345 * Need to do it after scrolling down, for the end row to be the desired one. */
346 set_hard_wrapped(start - 1);
347 set_hard_wrapped(end);
348 } else {
349 /* Set the boundaries to hard wrapped where we're about to tear apart the contents.
350 * Need to do it before scrolling up, for the end row to be the desired one. */
351 set_hard_wrapped(start - 1);
352 set_hard_wrapped(end);
353 /* Scroll up. */
354 for (auto i = 0; i < -scroll_amount; i++) {
355 ring_remove(start);
356 ring_insert(end, true);
357 }
358 }
359
360 /* Repaint the affected lines. No need to extend, set_hard_wrapped() took care of
361 * invalidating the context lines if necessary. */
362 invalidate_rows(start, end);
363
364 /* Adjust the scrollbars if necessary. */
365 adjust_adjustments();
366
367 /* We've modified the display. Make a note of it. */
368 m_text_inserted_flag = TRUE(!(0));
369 m_text_deleted_flag = TRUE(!(0));
370}
371
372void
373Terminal::restore_cursor()
374{
375 restore_cursor(m_screen);
376 ensure_cursor_is_onscreen();
377}
378
379void
380Terminal::save_cursor()
381{
382 save_cursor(m_screen);
383}
384
385/* Switch to normal screen. */
386void
387Terminal::switch_normal_screen()
388{
389 switch_screen(&m_normal_screen);
390}
391
392void
393Terminal::switch_screen(BteScreen *new_screen)
394{
395 /* if (new_screen == m_screen) return; ? */
396
397 /* The two screens use different hyperlink pools, so carrying on the idx
398 * wouldn't make sense and could lead to crashes.
399 * Ideally we'd carry the target URI itself, but I'm just lazy.
400 * Also, run a GC before we switch away from that screen. */
401 m_hyperlink_hover_idx = _bte_ring_get_hyperlink_at_position(m_screen->row_data, -1, -1, true, NULL__null);
402 g_assert (m_hyperlink_hover_idx == 0)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (m_hyperlink_hover_idx == 0) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1)) ; else g_assertion_message_expr
("BTE", "../src/bteseq.cc", 402, ((const char*) (__PRETTY_FUNCTION__
)), "m_hyperlink_hover_idx == 0"); } while (0)
;
403 m_hyperlink_hover_uri = NULL__null;
404 emit_hyperlink_hover_uri_changed(NULL__null); /* FIXME only emit if really changed */
405 m_defaults.attr.hyperlink_idx = _bte_ring_get_hyperlink_idx(m_screen->row_data, NULL__null);
406 g_assert (m_defaults.attr.hyperlink_idx == 0)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (m_defaults.attr.hyperlink_idx == 0) _g_boolean_var_ = 1
; else _g_boolean_var_ = 0; _g_boolean_var_; }), 1)) ; else g_assertion_message_expr
("BTE", "../src/bteseq.cc", 406, ((const char*) (__PRETTY_FUNCTION__
)), "m_defaults.attr.hyperlink_idx == 0"); } while (0)
;
407
408 /* cursor.row includes insert_delta, adjust accordingly */
409 auto cr = m_screen->cursor.row - m_screen->insert_delta;
410 auto cc = m_screen->cursor.col;
411 m_screen = new_screen;
412 m_screen->cursor.row = cr + m_screen->insert_delta;
413 m_screen->cursor.col = cc;
414
415 /* Make sure the ring is large enough */
416 ensure_row();
417}
418
419/* Switch to alternate screen. */
420void
421Terminal::switch_alternate_screen()
422{
423 switch_screen(&m_alternate_screen);
424}
425
426void
427Terminal::set_mode_ecma(bte::parser::Sequence const& seq,
428 bool set) noexcept
429{
430 auto const n_params = seq.size();
431 for (unsigned int i = 0; i < n_params; i = seq.next(i)) {
432 auto const param = seq.collect1(i);
433 auto const mode = m_modes_ecma.mode_from_param(param);
434
435 _bte_debug_print(BTE_DEBUG_MODES,do { } while(0)
436 "Mode %d (%s) %s\n",do { } while(0)
437 param, m_modes_ecma.mode_to_cstring(mode),do { } while(0)
438 set ? "set" : "reset")do { } while(0);
439
440 if (mode < 0)
441 continue;
442
443 m_modes_ecma.set(mode, set);
444
445 if (mode == m_modes_ecma.eBDSM) {
446 _bte_debug_print(BTE_DEBUG_BIDI,do { } while(0)
447 "BiDi %s mode\n",do { } while(0)
448 set ? "implicit" : "explicit")do { } while(0);
449 maybe_apply_bidi_attributes(BTE_BIDI_FLAG_IMPLICIT);
450 }
451 }
452}
453
454void
455Terminal::update_mouse_protocol() noexcept
456{
457 if (m_modes_private.XTERM_MOUSE_ANY_EVENT())
458 m_mouse_tracking_mode = MouseTrackingMode::eALL_MOTION_TRACKING;
459 else if (m_modes_private.XTERM_MOUSE_BUTTON_EVENT())
460 m_mouse_tracking_mode = MouseTrackingMode::eCELL_MOTION_TRACKING;
461 else if (m_modes_private.XTERM_MOUSE_VT220_HIGHLIGHT())
462 m_mouse_tracking_mode = MouseTrackingMode::eHILITE_TRACKING;
463 else if (m_modes_private.XTERM_MOUSE_VT220())
464 m_mouse_tracking_mode = MouseTrackingMode::eSEND_XY_ON_BUTTON;
465 else if (m_modes_private.XTERM_MOUSE_X10())
466 m_mouse_tracking_mode = MouseTrackingMode::eSEND_XY_ON_CLICK;
467 else
468 m_mouse_tracking_mode = MouseTrackingMode::eNONE;
469
470 m_mouse_smooth_scroll_delta = 0.0;
471
472 /* Mouse pointer might change */
473 apply_mouse_cursor();
474
475 _bte_debug_print(BTE_DEBUG_MODES,do { } while(0)
476 "Mouse protocol is now %d\n", (int)m_mouse_tracking_mode)do { } while(0);
477}
478
479void
480Terminal::set_mode_private(int mode,
481 bool set) noexcept
482{
483 /* Pre actions */
484 switch (mode) {
485 default:
486 break;
487 }
488
489 m_modes_private.set(mode, set);
490
491 /* Post actions */
492 switch (mode) {
493 case bte::terminal::modes::Private::eDEC_132_COLUMN:
494 /* DECCOLM: set/reset to 132/80 columns mode, clear screen and cursor home */
495 // FIXMEchpe don't do clear screen if DECNCSM is set
496 /* FIXMEchpe!!!
497 * Changing this mode resets the top, bottom, left, right margins;
498 * clears the screen (unless DECNCSM is set); resets DECLRMM; and clears
499 * the status line if host-writable.
500 */
501 if (m_modes_private.XTERM_DECCOLM()) {
502 emit_resize_window(set ? 132 : 80, m_row_count);
503 clear_screen();
504 home_cursor();
505 }
506 break;
507
508 case bte::terminal::modes::Private::eDEC_REVERSE_IMAGE:
509 invalidate_all();
510 break;
511
512 case bte::terminal::modes::Private::eDEC_ORIGIN:
513 /* Reposition the cursor in its new home position. */
514 home_cursor();
515 break;
516
517 case bte::terminal::modes::Private::eDEC_TEXT_CURSOR:
518 /* No need to invalidate the cursor here, this is done
519 * in process_incoming().
520 */
521 break;
522
523 case bte::terminal::modes::Private::eXTERM_ALTBUF:
524 [[fallthrough]];
525 case bte::terminal::modes::Private::eXTERM_OPT_ALTBUF:
526 [[fallthrough]];
527 case bte::terminal::modes::Private::eXTERM_OPT_ALTBUF_SAVE_CURSOR:
528 if (set) {
529 if (mode == bte::terminal::modes::Private::eXTERM_OPT_ALTBUF_SAVE_CURSOR)
530 save_cursor();
531
532 switch_alternate_screen();
533
534 /* Clear the alternate screen */
535 if (mode == bte::terminal::modes::Private::eXTERM_OPT_ALTBUF_SAVE_CURSOR)
536 clear_screen();
537 } else {
538 if (mode == bte::terminal::modes::Private::eXTERM_OPT_ALTBUF &&
539 m_screen == &m_alternate_screen)
540 clear_screen();
541
542 switch_normal_screen();
543
544 if (mode == bte::terminal::modes::Private::eXTERM_OPT_ALTBUF_SAVE_CURSOR)
545 restore_cursor();
546 }
547
548 /* Reset scrollbars and repaint everything. */
549 ctk_adjustment_set_value(m_vadjustment.get(),
550 m_screen->scroll_delta);
551 set_scrollback_lines(m_scrollback_lines);
552 queue_contents_changed();
553 invalidate_all();
554 break;
555
556 case bte::terminal::modes::Private::eXTERM_SAVE_CURSOR:
557 if (set)
558 save_cursor();
559 else
560 restore_cursor();
561 break;
562
563 case bte::terminal::modes::Private::eXTERM_MOUSE_X10:
564 case bte::terminal::modes::Private::eXTERM_MOUSE_VT220:
565 case bte::terminal::modes::Private::eXTERM_MOUSE_VT220_HIGHLIGHT:
566 case bte::terminal::modes::Private::eXTERM_MOUSE_BUTTON_EVENT:
567 case bte::terminal::modes::Private::eXTERM_MOUSE_ANY_EVENT:
568 case bte::terminal::modes::Private::eXTERM_MOUSE_EXT:
569 case bte::terminal::modes::Private::eXTERM_MOUSE_EXT_SGR:
570 update_mouse_protocol();
571 break;
572
573 case bte::terminal::modes::Private::eXTERM_FOCUS:
574 if (set)
575 feed_focus_event_initial();
576 break;
577
578 case bte::terminal::modes::Private::eBTE_BIDI_BOX_MIRROR:
579 _bte_debug_print(BTE_DEBUG_BIDI,do { } while(0)
580 "BiDi box drawing mirroring %s\n",do { } while(0)
581 set ? "enabled" : "disabled")do { } while(0);
582 maybe_apply_bidi_attributes(BTE_BIDI_FLAG_BOX_MIRROR);
583 break;
584
585 case bte::terminal::modes::Private::eBTE_BIDI_AUTO:
586 _bte_debug_print(BTE_DEBUG_BIDI,do { } while(0)
587 "BiDi dir autodetection %s\n",do { } while(0)
588 set ? "enabled" : "disabled")do { } while(0);
589 maybe_apply_bidi_attributes(BTE_BIDI_FLAG_AUTO);
590 break;
591
592 default:
593 break;
594 }
595}
596
597void
598Terminal::set_mode_private(bte::parser::Sequence const& seq,
599 bool set) noexcept
600{
601 auto const n_params = seq.size();
602 for (unsigned int i = 0; i < n_params; i = seq.next(i)) {
603 auto const param = seq.collect1(i);
604 auto const mode = m_modes_private.mode_from_param(param);
605
606 _bte_debug_print(BTE_DEBUG_MODES,do { } while(0)
607 "Private mode %d (%s) %s\n",do { } while(0)
608 param, m_modes_private.mode_to_cstring(mode),do { } while(0)
609 set ? "set" : "reset")do { } while(0);
610
611 if (mode < 0)
612 continue;
613
614 set_mode_private(mode, set);
615 }
616}
617
618void
619Terminal::save_mode_private(bte::parser::Sequence const& seq,
620 bool save) noexcept
621{
622 auto const n_params = seq.size();
623 for (unsigned int i = 0; i < n_params; i = seq.next(i)) {
624 auto const param = seq.collect1(i);
625 auto const mode = m_modes_private.mode_from_param(param);
626
627 if (mode < 0) {
628 _bte_debug_print(BTE_DEBUG_MODES,do { } while(0)
629 "Saving private mode %d (%s)\n",do { } while(0)
630 param, m_modes_private.mode_to_cstring(mode))do { } while(0);
631 continue;
632 }
633
634 if (save) {
635 _bte_debug_print(BTE_DEBUG_MODES,do { } while(0)
636 "Saving private mode %d (%s) is %s\n",do { } while(0)
637 param, m_modes_private.mode_to_cstring(mode),do { } while(0)
638 m_modes_private.get(mode) ? "set" : "reset")do { } while(0);
639
640 m_modes_private.push_saved(mode);
641 } else {
642 bool const set = m_modes_private.pop_saved(mode);
643
644 _bte_debug_print(BTE_DEBUG_MODES,do { } while(0)
645 "Restoring private mode %d (%s) to %s\n",do { } while(0)
646 param, m_modes_private.mode_to_cstring(mode),do { } while(0)
647 set ? "set" : "reset")do { } while(0);
648
649 set_mode_private(mode, set);
650 }
651 }
652}
653
654void
655Terminal::set_character_replacement(unsigned slot)
656{
657 g_assert(slot < G_N_ELEMENTS(m_character_replacements))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (slot < (sizeof (m_character_replacements) / sizeof (
(m_character_replacements)[0]))) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1)) ; else g_assertion_message_expr
("BTE", "../src/bteseq.cc", 657, ((const char*) (__PRETTY_FUNCTION__
)), "slot < G_N_ELEMENTS(m_character_replacements)"); } while
(0)
;
658 m_character_replacement = &m_character_replacements[slot];
659}
660
661/* Clear from the cursor position (inclusive!) to the beginning of the line. */
662void
663Terminal::clear_to_bol()
664{
665 ensure_cursor_is_onscreen();
666
667 /* Get the data for the row which the cursor points to. */
668 auto rowdata = ensure_row();
669 /* Clean up Tab/CJK fragments. */
670 cleanup_fragments(0, m_screen->cursor.col + 1);
671 /* Clear the data up to the current column with the default
672 * attributes. If there is no such character cell, we need
673 * to add one. */
674 bte::grid::column_t i;
675 for (i = 0; i <= m_screen->cursor.col; i++) {
676 if (i < (glong) _bte_row_data_length (rowdata)((rowdata)->len + 0)) {
677 /* Muck with the cell in this location. */
678 auto pcell = _bte_row_data_get_writable(rowdata, i);
679 *pcell = m_color_defaults;
680 } else {
681 /* Add new cells until we have one here. */
682 _bte_row_data_append (rowdata, &m_color_defaults);
683 }
684 }
685 /* Repaint this row's paragraph. */
686 invalidate_row_and_context(m_screen->cursor.row);
687
688 /* We've modified the display. Make a note of it. */
689 m_text_deleted_flag = TRUE(!(0));
690}
691
692/* Clear to the right of the cursor and below the current line. */
693void
694Terminal::clear_below_current()
695{
696 ensure_cursor_is_onscreen();
697
698 /* If the cursor is actually on the screen, clear the rest of the
699 * row the cursor is on and all of the rows below the cursor. */
700 BteRowData *rowdata;
701 auto i = m_screen->cursor.row;
702 if (i < _bte_ring_next(m_screen->row_data)) {
703 /* Get the data for the row we're clipping. */
704 rowdata = _bte_ring_index_writable(m_screen->row_data, i);
705 /* Clean up Tab/CJK fragments. */
706 if ((glong) _bte_row_data_length(rowdata)((rowdata)->len + 0) > m_screen->cursor.col)
707 cleanup_fragments(m_screen->cursor.col, _bte_row_data_length(rowdata)((rowdata)->len + 0));
708 /* Clear everything to the right of the cursor. */
709 if (rowdata)
710 _bte_row_data_shrink(rowdata, m_screen->cursor.col);
711 }
712 /* Now for the rest of the lines. */
713 for (i = m_screen->cursor.row + 1;
714 i < _bte_ring_next(m_screen->row_data);
715 i++) {
716 /* Get the data for the row we're removing. */
717 rowdata = _bte_ring_index_writable(m_screen->row_data, i);
718 /* Remove it. */
719 if (rowdata)
720 _bte_row_data_shrink (rowdata, 0);
721 }
722 /* Now fill the cleared areas. */
723 bool const not_default_bg = (m_color_defaults.attr.back() != BTE_DEFAULT_BG257);
724
725 for (i = m_screen->cursor.row;
726 i < m_screen->insert_delta + m_row_count;
727 i++) {
728 /* Retrieve the row's data, creating it if necessary. */
729 if (_bte_ring_contains(m_screen->row_data, i)) {
730 rowdata = _bte_ring_index_writable (m_screen->row_data, i);
731 g_assert(rowdata != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (rowdata != __null) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1)) ; else g_assertion_message_expr
("BTE", "../src/bteseq.cc", 731, ((const char*) (__PRETTY_FUNCTION__
)), "rowdata != NULL"); } while (0)
;
732 } else {
733 rowdata = ring_append(false);
734 }
735 /* Pad out the row. */
736 if (not_default_bg) {
737 _bte_row_data_fill(rowdata, &m_color_defaults, m_column_count);
738 }
739 set_hard_wrapped(i);
740 if (i > m_screen->cursor.row)
741 rowdata->attr.bidi_flags = get_bidi_flags();
742 }
743 /* Repaint the cleared area (might need to extend upwards). */
744 invalidate_rows_and_context(m_screen->cursor.row, m_screen->insert_delta + m_row_count - 1);
745
746 /* We've modified the display. Make a note of it. */
747 m_text_deleted_flag = TRUE(!(0));
748}
749
750/* Clear from the cursor position to the end of the line. */
751void
752Terminal::clear_to_eol()
753{
754 /* If we were to strictly emulate xterm, we'd ensure the cursor is onscreen.
755 * But due to https://bugzilla.gnome.org/show_bug.cgi?id=740789 we intentionally
756 * deviate and do instead what konsole does. This way emitting a \e[K doesn't
757 * influence the text flow, and serves as a perfect workaround against a new line
758 * getting painted with the active background color (except for a possible flicker).
759 */
760 /* ensure_cursor_is_onscreen(); */
761
762 /* Get the data for the row which the cursor points to. */
763 auto rowdata = ensure_cursor();
764 g_assert(rowdata != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (rowdata != __null) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1)) ; else g_assertion_message_expr
("BTE", "../src/bteseq.cc", 764, ((const char*) (__PRETTY_FUNCTION__
)), "rowdata != NULL"); } while (0)
;
765 if ((glong) _bte_row_data_length(rowdata)((rowdata)->len + 0) > m_screen->cursor.col) {
766 /* Clean up Tab/CJK fragments. */
767 cleanup_fragments(m_screen->cursor.col, _bte_row_data_length(rowdata)((rowdata)->len + 0));
768 /* Remove the data at the end of the array until the current column
769 * is the end of the array. */
770 _bte_row_data_shrink(rowdata, m_screen->cursor.col);
771 /* We've modified the display. Make a note of it. */
772 m_text_deleted_flag = TRUE(!(0));
773 }
774 bool const not_default_bg = (m_color_defaults.attr.back() != BTE_DEFAULT_BG257);
775
776 if (not_default_bg) {
777 /* Add enough cells to fill out the row. */
778 _bte_row_data_fill(rowdata, &m_color_defaults, m_column_count);
779 }
780 set_hard_wrapped(m_screen->cursor.row);
781 /* Repaint this row's paragraph. */
782 invalidate_row_and_context(m_screen->cursor.row);
783}
784
785/*
786 * Terminal::set_cursor_column:
787 * @col: the column. 0-based from 0 to m_column_count - 1
788 *
789 * Sets the cursor column to @col, clamped to the range 0..m_column_count-1.
790 */
791void
792Terminal::set_cursor_column(bte::grid::column_t col)
793{
794 _bte_debug_print(BTE_DEBUG_PARSER,do { } while(0)
795 "Moving cursor to column %ld.\n", col)do { } while(0);
796 m_screen->cursor.col = CLAMP(col, 0, m_column_count - 1)(((col) > (m_column_count - 1)) ? (m_column_count - 1) : (
((col) < (0)) ? (0) : (col)))
;
797}
798
799void
800Terminal::set_cursor_column1(bte::grid::column_t col)
801{
802 set_cursor_column(col - 1);
803}
804
805/*
806 * Terminal::set_cursor_row:
807 * @row: the row. 0-based and relative to the scrolling region
808 *
809 * Sets the cursor row to @row. @row is relative to the scrolling region
810 * (0 if restricted scrolling is off).
811 */
812void
813Terminal::set_cursor_row(bte::grid::row_t row)
814{
815 bte::grid::row_t start_row, end_row;
816 if (m_modes_private.DEC_ORIGIN() &&
817 m_scrolling_restricted) {
818 start_row = m_scrolling_region.start;
819 end_row = m_scrolling_region.end;
820 } else {
821 start_row = 0;
822 end_row = m_row_count - 1;
823 }
824 row += start_row;
825 row = CLAMP(row, start_row, end_row)(((row) > (end_row)) ? (end_row) : (((row) < (start_row
)) ? (start_row) : (row)))
;
826
827 m_screen->cursor.row = row + m_screen->insert_delta;
828}
829
830void
831Terminal::set_cursor_row1(bte::grid::row_t row)
832{
833 set_cursor_row(row - 1);
834}
835
836/*
837 * Terminal::get_cursor_row:
838 *
839 * Returns: the relative cursor row, 0-based and relative to the scrolling region
840 * if set (regardless of origin mode).
841 */
842bte::grid::row_t
843Terminal::get_cursor_row_unclamped() const
844{
845 auto row = m_screen->cursor.row - m_screen->insert_delta;
846 /* Note that we do NOT check DEC_ORIGIN mode here! */
847 if (m_scrolling_restricted) {
848 row -= m_scrolling_region.start;
849 }
850 return row;
851}
852
853bte::grid::column_t
854Terminal::get_cursor_column_unclamped() const
855{
856 return m_screen->cursor.col;
857}
858
859/*
860 * Terminal::set_cursor_coords:
861 * @row: the row. 0-based and relative to the scrolling region
862 * @col: the column. 0-based from 0 to m_column_count - 1
863 *
864 * Sets the cursor row to @row. @row is relative to the scrolling region
865 * (0 if restricted scrolling is off).
866 *
867 * Sets the cursor column to @col, clamped to the range 0..m_column_count-1.
868 */
869void
870Terminal::set_cursor_coords(bte::grid::row_t row,
871 bte::grid::column_t column)
872{
873 set_cursor_column(column);
874 set_cursor_row(row);
875}
876
877void
878Terminal::set_cursor_coords1(bte::grid::row_t row,
879 bte::grid::column_t column)
880{
881 set_cursor_column1(column);
882 set_cursor_row1(row);
883}
884
885/* Delete a character at the current cursor position. */
886void
887Terminal::delete_character()
888{
889 BteRowData *rowdata;
890 long col;
891
892 ensure_cursor_is_onscreen();
893
894 if (_bte_ring_next(m_screen->row_data) > m_screen->cursor.row) {
895 long len;
896 /* Get the data for the row which the cursor points to. */
897 rowdata = _bte_ring_index_writable(m_screen->row_data, m_screen->cursor.row);
898 g_assert(rowdata != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (rowdata != __null) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1)) ; else g_assertion_message_expr
("BTE", "../src/bteseq.cc", 898, ((const char*) (__PRETTY_FUNCTION__
)), "rowdata != NULL"); } while (0)
;
899 col = m_screen->cursor.col;
900 len = _bte_row_data_length (rowdata)((rowdata)->len + 0);
901
902 bool const not_default_bg = (m_color_defaults.attr.back() != BTE_DEFAULT_BG257);
903 if (not_default_bg) {
904 _bte_row_data_fill(rowdata, &basic_cell, m_column_count);
905 len = m_column_count;
906 }
907
908 /* Remove the column. */
909 if (col < len) {
910 /* Clean up Tab/CJK fragments. */
911 cleanup_fragments(col, col + 1);
912 _bte_row_data_remove (rowdata, col);
913
914 if (not_default_bg) {
915 _bte_row_data_fill(rowdata, &m_color_defaults, m_column_count);
916 len = m_column_count;
917 }
918 set_hard_wrapped(m_screen->cursor.row);
919 /* Repaint this row's paragraph. */
920 invalidate_row_and_context(m_screen->cursor.row);
921 }
922 }
923
924 /* We've modified the display. Make a note of it. */
925 m_text_deleted_flag = TRUE(!(0));
926}
927
928void
929Terminal::move_cursor_down(bte::grid::row_t rows)
930{
931 rows = CLAMP(rows, 1, m_row_count)(((rows) > (m_row_count)) ? (m_row_count) : (((rows) < (
1)) ? (1) : (rows)))
;
932
933 // FIXMEchpe why not do this afterwards?
934 ensure_cursor_is_onscreen();
935
936 bte::grid::row_t end;
937 // FIXMEchpe why not check DEC_ORIGIN here?
938 if (m_scrolling_restricted && m_screen->cursor.row <= m_screen->insert_delta + m_scrolling_region.end) {
939 end = m_screen->insert_delta + m_scrolling_region.end;
940 } else {
941 end = m_screen->insert_delta + m_row_count - 1;
942 }
943
944 m_screen->cursor.row = MIN(m_screen->cursor.row + rows, end)(((m_screen->cursor.row + rows) < (end)) ? (m_screen->
cursor.row + rows) : (end))
;
945}
946
947void
948Terminal::erase_characters(long count)
949{
950 BteCell *cell;
951 long col, i;
952
953 ensure_cursor_is_onscreen();
954
955 /* Clear out the given number of characters. */
956 auto rowdata = ensure_row();
957 if (_bte_ring_next(m_screen->row_data) > m_screen->cursor.row) {
958 g_assert(rowdata != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (rowdata != __null) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1)) ; else g_assertion_message_expr
("BTE", "../src/bteseq.cc", 958, ((const char*) (__PRETTY_FUNCTION__
)), "rowdata != NULL"); } while (0)
;
959 /* Clean up Tab/CJK fragments. */
960 cleanup_fragments(m_screen->cursor.col, m_screen->cursor.col + count);
961 /* Write over the characters. (If there aren't enough, we'll
962 * need to create them.) */
963 _bte_row_data_fill (rowdata, &basic_cell, m_screen->cursor.col);
964 for (i = 0; i < count; i++) {
965 col = m_screen->cursor.col + i;
966 if (col >= 0) {
967 if (col < (glong) _bte_row_data_length (rowdata)((rowdata)->len + 0)) {
968 /* Replace this cell with the current
969 * defaults. */
970 cell = _bte_row_data_get_writable (rowdata, col);
971 *cell = m_color_defaults;
972 } else {
973 /* Add new cells until we have one here. */
974 _bte_row_data_fill (rowdata, &m_color_defaults, col + 1);
975 }
976 }
977 }
978 /* Repaint this row's paragraph. */
979 invalidate_row_and_context(m_screen->cursor.row);
980 }
981
982 /* We've modified the display. Make a note of it. */
983 m_text_deleted_flag = TRUE(!(0));
984}
985
986/* Insert a blank character. */
987void
988Terminal::insert_blank_character()
989{
990 ensure_cursor_is_onscreen();
991
992 auto save = m_screen->cursor;
993 insert_char(' ', true, true);
994 m_screen->cursor = save;
995}
996
997void
998Terminal::move_cursor_backward(bte::grid::column_t columns)
999{
1000 ensure_cursor_is_onscreen();
1001
1002 auto col = get_cursor_column_unclamped();
1003 columns = CLAMP(columns, 1, col)(((columns) > (col)) ? (col) : (((columns) < (1)) ? (1)
: (columns)))
;
1004 set_cursor_column(col - columns);
1005}
1006
1007void
1008Terminal::move_cursor_forward(bte::grid::column_t columns)
1009{
1010 columns = CLAMP(columns, 1, m_column_count)(((columns) > (m_column_count)) ? (m_column_count) : (((columns
) < (1)) ? (1) : (columns)))
;
1011
1012 ensure_cursor_is_onscreen();
1013
1014 /* The cursor can be further to the right, don't move in that case. */
1015 auto col = get_cursor_column_unclamped();
1016 if (col < m_column_count) {
1017 /* There's room to move right. */
1018 set_cursor_column(col + columns);
1019 }
1020}
1021
1022void
1023Terminal::line_feed()
1024{
1025 ensure_cursor_is_onscreen();
1026 cursor_down(true);
1027 maybe_apply_bidi_attributes(BTE_BIDI_FLAG_ALL);
1028}
1029
1030void
1031Terminal::move_cursor_tab_backward(int count)
1032{
1033 if (count == 0)
1034 return;
1035
1036 auto const newcol = m_tabstops.get_previous(get_cursor_column(), count, 0);
1037 set_cursor_column(newcol);
1038}
1039
1040void
1041Terminal::move_cursor_tab_forward(int count)
1042{
1043 if (count == 0)
1044 return;
1045
1046 auto const col = get_cursor_column();
1047
1048 /* Find the next tabstop, but don't go beyond the end of the line */
1049 int const newcol = m_tabstops.get_next(col, count, m_column_count - 1);
1050
1051 /* Make sure we don't move cursor back (see bug #340631) */
1052 // FIXMEchpe how could this happen!?
1053 if (col >= newcol)
1054 return;
1055
1056 /* Smart tab handling: bug 353610
1057 *
1058 * If we currently don't have any cells in the space this
1059 * tab creates, we try to make the tab character copyable,
1060 * by appending a single tab char with lots of fragment
1061 * cells following it.
1062 *
1063 * Otherwise, just append empty cells that will show up
1064 * as a space each.
1065 */
1066
1067 BteRowData *rowdata = ensure_row();
1068 auto const old_len = _bte_row_data_length (rowdata)((rowdata)->len + 0);
1069 _bte_row_data_fill (rowdata, &basic_cell, newcol);
1070
1071 /* Insert smart tab if there's nothing in the line after
1072 * us, not even empty cells (with non-default background
1073 * color for example).
1074 *
1075 * Notable bugs here: 545924, 597242, 764330
1076 */
1077 if (col >= old_len && (newcol - col) <= BTE_TAB_WIDTH_MAX((1 << (4)) - 1)) {
1078 glong i;
1079 BteCell *cell = _bte_row_data_get_writable (rowdata, col);
1080 BteCell tab = *cell;
1081 tab.attr.set_columns(newcol - col);
1082 tab.c = '\t';
1083 /* Save tab char */
1084 *cell = tab;
1085 /* And adjust the fragments */
1086 for (i = col + 1; i < newcol; i++) {
1087 cell = _bte_row_data_get_writable (rowdata, i);
1088 cell->c = '\t';
1089 cell->attr.set_columns(1);
1090 cell->attr.set_fragment(true);
1091 }
1092 }
1093
1094 /* Repaint the cursor. */
1095 invalidate_row(m_screen->cursor.row);
1096 m_screen->cursor.col = newcol;
1097}
1098
1099void
1100Terminal::move_cursor_up(bte::grid::row_t rows)
1101{
1102 // FIXMEchpe allow 0 as no-op?
1103 rows = CLAMP(rows, 1, m_row_count)(((rows) > (m_row_count)) ? (m_row_count) : (((rows) < (
1)) ? (1) : (rows)))
;
1104
1105 //FIXMEchpe why not do this afterward?
1106 ensure_cursor_is_onscreen();
1107
1108 bte::grid::row_t start;
1109 //FIXMEchpe why not check DEC_ORIGIN mode here?
1110 if (m_scrolling_restricted && m_screen->cursor.row >= m_screen->insert_delta + m_scrolling_region.start) {
1111 start = m_screen->insert_delta + m_scrolling_region.start;
1112 } else {
1113 start = m_screen->insert_delta;
1114 }
1115
1116 m_screen->cursor.row = MAX(m_screen->cursor.row - rows, start)(((m_screen->cursor.row - rows) > (start)) ? (m_screen->
cursor.row - rows) : (start))
;
1117}
1118
1119/*
1120 * Parse parameters of SGR 38, 48 or 58, starting at @index within @seq.
1121 * Returns %true if @seq contained colour parameters at @index, or %false otherwise.
1122 * In each case, @idx is set to last consumed parameter,
1123 * and the colour is returned in @color.
1124 *
1125 * The format looks like:
1126 * - 256 color indexed palette:
1127 * - ^[[38:5:INDEXm (de jure standard: ITU-T T.416 / ISO/IEC 8613-6; we also allow and ignore further parameters)
1128 * - ^[[38;5;INDEXm (de facto standard, understood by probably all terminal emulators that support 256 colors)
1129 * - true colors:
1130 * - ^[[38:2:[id]:RED:GREEN:BLUE[:...]m (de jure standard: ITU-T T.416 / ISO/IEC 8613-6)
1131 * - ^[[38:2:RED:GREEN:BLUEm (common misinterpretation of the standard, FIXME: stop supporting it at some point)
1132 * - ^[[38;2;RED;GREEN;BLUEm (de facto standard, understood by probably all terminal emulators that support true colors)
1133 * See bugs 685759 and 791456 for details.
1134 */
1135template<unsigned int redbits, unsigned int greenbits, unsigned int bluebits>
1136bool
1137Terminal::seq_parse_sgr_color(bte::parser::Sequence const& seq,
1138 unsigned int &idx,
1139 uint32_t& color) const noexcept
1140{
1141 /* Note that we don't have to check if the index is after the end of
1142 * the parameters list, since dereferencing is safe and returns -1.
1143 */
1144
1145 if (seq.param_nonfinal(idx)) {
1146 /* Colon version */
1147 switch (seq.param(++idx)) {
1148 case BTE_SGR_COLOR_SPEC_RGB: {
1149 auto const n = seq.next(idx) - idx;
1150 if (n < 4)
1151 return false;
1152 if (n > 4) {
1153 /* Consume a colourspace parameter; it must be default */
1154 if (!seq.param_default(++idx))
1155 return false;
1156 }
1157
1158 int red = seq.param(++idx);
1159 int green = seq.param(++idx);
1160 int blue = seq.param(++idx);
1161 if ((red & 0xff) != red ||
1162 (green & 0xff) != green ||
1163 (blue & 0xff) != blue)
1164 return false;
1165
1166 color = BTE_RGB_COLOR(redbits, greenbits, bluebits, red, green, blue)((1U << ((bluebits) + (greenbits) + (redbits))) | ((((red
) >> (8 - (bluebits))) & ((1U << (bluebits)) -
1U)) << ((greenbits) + (redbits))) | ((((green) >>
(8 - (greenbits))) & ((1U << (greenbits)) - 1U)) <<
(redbits)) | (((blue) >> (8 - (redbits))) & ((1U <<
(redbits)) - 1U)))
;
1167 return true;
1168 }
1169 case BTE_SGR_COLOR_SPEC_LEGACY: {
1170 auto const n = seq.next(idx) - idx;
1171 if (n < 2)
1172 return false;
1173
1174 int v = seq.param(++idx);
1175 if (v < 0 || v >= 256)
1176 return false;
1177
1178 color = (uint32_t)v;
1179 return true;
1180 }
1181 }
1182 } else {
1183 /* Semicolon version */
1184
1185 idx = seq.next(idx);
1186 switch (seq.param(idx)) {
1187 case BTE_SGR_COLOR_SPEC_RGB: {
1188 /* Consume 3 more parameters */
1189 idx = seq.next(idx);
1190 int red = seq.param(idx);
1191 idx = seq.next(idx);
1192 int green = seq.param(idx);
1193 idx = seq.next(idx);
1194 int blue = seq.param(idx);
1195
1196 if ((red & 0xff) != red ||
1197 (green & 0xff) != green ||
1198 (blue & 0xff) != blue)
1199 return false;
1200
1201 color = BTE_RGB_COLOR(redbits, greenbits, bluebits, red, green, blue)((1U << ((bluebits) + (greenbits) + (redbits))) | ((((red
) >> (8 - (bluebits))) & ((1U << (bluebits)) -
1U)) << ((greenbits) + (redbits))) | ((((green) >>
(8 - (greenbits))) & ((1U << (greenbits)) - 1U)) <<
(redbits)) | (((blue) >> (8 - (redbits))) & ((1U <<
(redbits)) - 1U)))
;
1202 return true;
1203 }
1204 case BTE_SGR_COLOR_SPEC_LEGACY: {
1205 /* Consume 1 more parameter */
1206 idx = seq.next(idx);
1207 int v = seq.param(idx);
1208
1209 if ((v & 0xff) != v)
1210 return false;
1211
1212 color = (uint32_t)v;
1213 return true;
1214 }
1215 }
1216 }
1217
1218 return false;
1219}
1220
1221void
1222Terminal::erase_in_display(bte::parser::Sequence const& seq)
1223{
1224 /* We don't implement the protected attribute, so we can ignore selective:
1225 * bool selective = (seq.command() == BTE_CMD_DECSED);
1226 */
1227
1228 switch (seq.collect1(0)) {
1229 case -1: /* default */
1230 case 0:
1231 /* Clear below the current line. */
1232 clear_below_current();
1233 break;
1234 case 1:
1235 /* Clear above the current line. */
1236 clear_above_current();
1237 /* Clear everything to the left of the cursor, too. */
1238 /* FIXME: vttest. */
1239 clear_to_bol();
1240 break;
1241 case 2:
1242 /* Clear the entire screen. */
1243 clear_screen();
1244 break;
1245 case 3:
1246 /* Drop the scrollback. */
1247 drop_scrollback();
1248 break;
1249 default:
1250 break;
1251 }
1252 /* We've modified the display. Make a note of it. */
1253 m_text_deleted_flag = TRUE(!(0));
1254}
1255
1256void
1257Terminal::erase_in_line(bte::parser::Sequence const& seq)
1258{
1259 /* We don't implement the protected attribute, so we can ignore selective:
1260 * bool selective = (seq.command() == BTE_CMD_DECSEL);
1261 */
1262
1263 switch (seq.collect1(0)) {
1264 case -1: /* default */
1265 case 0:
1266 /* Clear to end of the line. */
1267 clear_to_eol();
1268 break;
1269 case 1:
1270 /* Clear to start of the line. */
1271 clear_to_bol();
1272 break;
1273 case 2:
1274 /* Clear the entire line. */
1275 clear_current_line();
1276 break;
1277 default:
1278 break;
1279 }
1280 /* We've modified the display. Make a note of it. */
1281 m_text_deleted_flag = TRUE(!(0));
1282}
1283
1284void
1285Terminal::insert_lines(bte::grid::row_t param)
1286{
1287 bte::grid::row_t start, end, i;
1288
1289 /* Find the region we're messing with. */
1290 auto row = m_screen->cursor.row;
1291 if (m_scrolling_restricted) {
1292 start = m_screen->insert_delta + m_scrolling_region.start;
1293 end = m_screen->insert_delta + m_scrolling_region.end;
1294 } else {
1295 start = m_screen->insert_delta;
1296 end = m_screen->insert_delta + m_row_count - 1;
1297 }
1298
1299 /* Don't do anything if the cursor is outside of the scrolling region: DEC STD 070 & bug #199. */
1300 if (m_screen->cursor.row < start || m_screen->cursor.row > end)
1301 return;
1302
1303 /* Only allow to insert as many lines as there are between this row
1304 * and the end of the scrolling region. See bug #676090.
1305 */
1306 auto limit = end - row + 1;
1307 param = MIN (param, limit)(((param) < (limit)) ? (param) : (limit));
1308
1309 for (i = 0; i < param; i++) {
1310 /* Clear a line off the end of the region and add one to the
1311 * top of the region. */
1312 ring_remove(end);
1313 ring_insert(row, true);
1314 }
1315
1316 /* Set the boundaries to hard wrapped where we tore apart the contents.
1317 * Need to do it after scrolling down, for the end row to be the desired one. */
1318 set_hard_wrapped(row - 1);
1319 set_hard_wrapped(end);
1320
1321 m_screen->cursor.col = 0;
1322
1323 /* Repaint the affected lines. No need to extend, set_hard_wrapped() took care of
1324 * invalidating the context lines if necessary. */
1325 invalidate_rows(row, end);
1326 /* Adjust the scrollbars if necessary. */
1327 adjust_adjustments();
1328 /* We've modified the display. Make a note of it. */
1329 m_text_inserted_flag = TRUE(!(0));
1330}
1331
1332void
1333Terminal::delete_lines(bte::grid::row_t param)
1334{
1335 bte::grid::row_t start, end, i;
1336
1337 /* Find the region we're messing with. */
1338 auto row = m_screen->cursor.row;
1339 if (m_scrolling_restricted) {
1340 start = m_screen->insert_delta + m_scrolling_region.start;
1341 end = m_screen->insert_delta + m_scrolling_region.end;
1342 } else {
1343 start = m_screen->insert_delta;
1344 end = m_screen->insert_delta + m_row_count - 1;
1345 }
1346
1347 /* Don't do anything if the cursor is outside of the scrolling region: DEC STD 070 & bug #199. */
1348 if (m_screen->cursor.row < start || m_screen->cursor.row > end)
1349 return;
1350
1351 /* Set the boundaries to hard wrapped where we're about to tear apart the contents.
1352 * Need to do it before scrolling up, for the end row to be the desired one. */
1353 set_hard_wrapped(row - 1);
1354 set_hard_wrapped(end);
1355
1356 /* Only allow to delete as many lines as there are between this row
1357 * and the end of the scrolling region. See bug #676090.
1358 */
1359 auto limit = end - row + 1;
1360 param = MIN (param, limit)(((param) < (limit)) ? (param) : (limit));
1361
1362 /* Clear them from below the current cursor. */
1363 for (i = 0; i < param; i++) {
1364 /* Insert a line at the end of the region and remove one from
1365 * the top of the region. */
1366 ring_remove(row);
1367 ring_insert(end, true);
1368 }
1369 m_screen->cursor.col = 0;
1370
1371 /* Repaint the affected lines. No need to extend, set_hard_wrapped() took care of
1372 * invalidating the context lines if necessary. */
1373 invalidate_rows(row, end);
1374 /* Adjust the scrollbars if necessary. */
1375 adjust_adjustments();
1376 /* We've modified the display. Make a note of it. */
1377 m_text_deleted_flag = TRUE(!(0));
1378}
1379
1380bool
1381Terminal::get_osc_color_index(int osc,
1382 int value,
1383 int& index) const noexcept
1384{
1385 if (value < 0)
1386 return false;
1387
1388 if (osc == BTE_OSC_XTERM_SET_COLOR ||
1389 osc == BTE_OSC_XTERM_RESET_COLOR) {
1390 if (value < BTE_DEFAULT_FG256) {
1391 index = value;
1392 return true;
1393 }
1394
1395 index = value - BTE_DEFAULT_FG256;
1396 } else {
1397 index = value;
1398 }
1399
1400 /* Translate OSC 5 numbers to color index.
1401 *
1402 * We return -1 for known but umimplemented special colors
1403 * so that we can send a dummy reply when queried.
1404 */
1405 switch (index) {
1406 case 0: index = BTE_BOLD_FG258; return true; /* Bold */
1407 case 1: index = -1; return true; /* Underline */
1408 case 2: index = -1; return true; /* Blink */
1409 case 3: index = -1; return true; /* Reverse */
1410 case 4: index = -1; return true; /* Italic */
1411 default: return false;
1412 }
1413}
1414
1415void
1416Terminal::set_color(bte::parser::Sequence const& seq,
1417 bte::parser::StringTokeniser::const_iterator& token,
1418 bte::parser::StringTokeniser::const_iterator const& endtoken,
1419 int osc) noexcept
1420{
1421 while (token != endtoken) {
1422 int value;
1423 bool has_value = token.number(value);
1424
1425 if (++token == endtoken)
1426 break;
1427
1428 int index;
1429 if (!has_value ||
1430 !get_osc_color_index(osc, value, index)) {
1431 ++token;
1432 continue;
1433 }
1434
1435 set_color_index(seq, token, endtoken, value, index, -1, osc);
1436 ++token;
1437 }
1438}
1439
1440void
1441Terminal::set_color_index(bte::parser::Sequence const& seq,
1442 bte::parser::StringTokeniser::const_iterator& token,
1443 bte::parser::StringTokeniser::const_iterator const& endtoken,
1444 int number,
1445 int index,
1446 int index_fallback,
1447 int osc) noexcept
1448{
1449 auto const str = *token;
1450
1451 if (str == "?"s) {
1452 bte::color::rgb color{0, 0, 0};
1453 if (index != -1) {
1454 auto const* c = get_color(index);
1455 if (c == nullptr && index_fallback != -1)
1456 c = get_color(index_fallback);
1457 if (c != nullptr)
1458 color = *c;
1459 }
1460
1461 if (number != -1)
1462 reply(seq, BTE_REPLY_OSC, {}, "%d;%d;rgb:%04x/%04x/%04x",
1463 osc, number, color.red, color.green, color.blue);
1464 else
1465 reply(seq, BTE_REPLY_OSC, {}, "%d;rgb:%04x/%04x/%04x",
1466 osc, color.red, color.green, color.blue);
1467 } else {
1468 bte::color::rgb color;
1469
1470 if (index != -1 &&
1471 color.parse(str.data())) {
1472 set_color(index, BTE_COLOR_SOURCE_ESCAPE0, color);
1473 }
1474 }
1475}
1476
1477void
1478Terminal::set_special_color(bte::parser::Sequence const& seq,
1479 bte::parser::StringTokeniser::const_iterator& token,
1480 bte::parser::StringTokeniser::const_iterator const& endtoken,
1481 int index,
1482 int index_fallback,
1483 int osc) noexcept
1484{
1485 if (token == endtoken)
1486 return;
1487
1488 set_color_index(seq, token, endtoken, -1, index, index_fallback, osc);
1489}
1490
1491void
1492Terminal::reset_color(bte::parser::Sequence const& seq,
1493 bte::parser::StringTokeniser::const_iterator& token,
1494 bte::parser::StringTokeniser::const_iterator const& endtoken,
1495 int osc) noexcept
1496{
1497 /* Empty param? Reset all */
1498 if (token == endtoken ||
1499 token.size_remaining() == 0) {
1500 if (osc == BTE_OSC_XTERM_RESET_COLOR) {
1501 for (unsigned int idx = 0; idx < BTE_DEFAULT_FG256; idx++)
1502 reset_color(idx, BTE_COLOR_SOURCE_ESCAPE0);
1503 }
1504
1505 reset_color(BTE_BOLD_FG258, BTE_COLOR_SOURCE_ESCAPE0);
1506 /* Add underline/blink/reverse/italic here if/when implemented */
1507
1508 return;
1509 }
1510
1511 while (token != endtoken) {
1512 int value;
1513 if (!token.number(value))
1514 continue;
1515
1516 int index;
1517 if (get_osc_color_index(osc, value, index) &&
1518 index != -1) {
1519 reset_color(index, BTE_COLOR_SOURCE_ESCAPE0);
1520 }
1521
1522 ++token;
1523 }
1524}
1525
1526void
1527Terminal::set_current_directory_uri(bte::parser::Sequence const& seq,
1528 bte::parser::StringTokeniser::const_iterator& token,
1529 bte::parser::StringTokeniser::const_iterator const& endtoken) noexcept
1530{
1531 std::string uri;
1532 if (token != endtoken && token.size_remaining() > 0) {
1533 uri = token.string_remaining();
1534
1535 auto filename = g_filename_from_uri(uri.data(), nullptr, nullptr);
1536 if (filename != nullptr) {
1537 g_free(filename);
1538 } else {
1539 /* invalid URI */
1540 uri.clear();
1541 }
1542 }
1543
1544 m_current_directory_uri_pending.swap(uri);
1545 m_current_directory_uri_changed = true;
1546}
1547
1548void
1549Terminal::set_current_file_uri(bte::parser::Sequence const& seq,
1550 bte::parser::StringTokeniser::const_iterator& token,
1551 bte::parser::StringTokeniser::const_iterator const& endtoken) noexcept
1552
1553{
1554 std::string uri;
1555 if (token != endtoken && token.size_remaining() > 0) {
1556 uri = token.string_remaining();
1557
1558 auto filename = g_filename_from_uri(uri.data(), nullptr, nullptr);
1559 if (filename != nullptr) {
1560 g_free(filename);
1561 } else {
1562 /* invalid URI */
1563 uri.clear();
1564 }
1565 }
1566
1567 m_current_file_uri_pending.swap(uri);
1568 m_current_file_uri_changed = true;
1569}
1570
1571void
1572Terminal::set_current_hyperlink(bte::parser::Sequence const& seq,
1573 bte::parser::StringTokeniser::const_iterator& token,
1574 bte::parser::StringTokeniser::const_iterator const& endtoken) noexcept
1575{
1576 if (token == endtoken)
1577 return; // FIXMEchpe or should we treat this as a reset?
1578
1579 /* Handle OSC 8 hyperlinks.
1580 * See bug 779734 and https://gist.github.com/egmontkob/eb114294efbcd5adb1944c9f3cb5feda
1581 */
1582
1583 if (!m_allow_hyperlink)
1584 return;
1585
1586 /* The hyperlink, as we carry around and store in the streams, is "id;uri" */
1587 std::string hyperlink;
1588
1589 /* First, find the ID */
1590 auto tokenstr = *token;
1591 bte::parser::StringTokeniser subtokeniser{tokenstr, ':'};
1592 for (auto subtoken : subtokeniser) {
1593 auto const len = subtoken.size();
1594 if (len < 3)
1595 continue;
1596
1597 if (subtoken[0] != 'i' || subtoken[1] != 'd' || subtoken[2] != '=')
1598 continue;
1599
1600 if (len > 3 + BTE_HYPERLINK_ID_LENGTH_MAX250) {
1601 _bte_debug_print (BTE_DEBUG_HYPERLINK, "Overlong \"id\" ignored: \"%s\"\n",do { } while(0)
1602 subtoken.data())do { } while(0);
1603 break;
1604 }
1605
1606 hyperlink = subtoken.substr(3);
1607 break;
1608 }
1609
1610 if (hyperlink.size() == 0) {
1611 /* Automatically generate a unique ID string. The colon makes sure
1612 * it cannot conflict with an explicitly specified one.
1613 */
1614 char idbuf[24];
1615 auto len = g_snprintf(idbuf, sizeof(idbuf), ":%ld", m_hyperlink_auto_id++);
1616 hyperlink.append(idbuf, len);
1617 _bte_debug_print (BTE_DEBUG_HYPERLINK, "Autogenerated id=\"%s\"\n", hyperlink.data())do { } while(0);
1618 }
1619
1620 /* Now get the URI */
1621 if (++token == endtoken)
1622 return; // FIXMEchpe or should we treat this the same as 0-length URI ?
1623
1624 hyperlink.push_back(';');
1625 guint idx;
1626 auto const len = token.size_remaining();
1627 if (len > 0 && len <= BTE_HYPERLINK_URI_LENGTH_MAX2083) {
1628 token.append_remaining(hyperlink);
1629
1630 _bte_debug_print (BTE_DEBUG_HYPERLINK, "OSC 8: id;uri=\"%s\"\n", hyperlink.data())do { } while(0);
1631
1632 idx = _bte_ring_get_hyperlink_idx(m_screen->row_data, hyperlink.data());
1633 } else {
1634 if (G_UNLIKELY(len > BTE_HYPERLINK_URI_LENGTH_MAX)(__builtin_expect (__extension__ ({ int _g_boolean_var_; if (
len > 2083) _g_boolean_var_ = 1; else _g_boolean_var_ = 0;
_g_boolean_var_; }), 0))
)
1635 _bte_debug_print (BTE_DEBUG_HYPERLINK, "Overlong URI ignored (len %" G_GSIZE_FORMAT ")\n", len)do { } while(0);
1636
1637 /* idx = 0; also remove the previous current_idx so that it can be GC'd now. */
1638 idx = _bte_ring_get_hyperlink_idx(m_screen->row_data, nullptr);
1639 }
1640
1641 m_defaults.attr.hyperlink_idx = idx;
1642}
1643
1644/*
1645 * Command Handlers
1646 * This is the unofficial documentation of all the BTE_CMD_* definitions.
1647 * Each handled command has a separate function with an extensive comment on
1648 * the semantics of the command.
1649 * Note that many semantics are unknown and need to be verified. This is mostly
1650 * about error-handling, though. Applications rarely rely on those features.
1651 */
1652
1653void
1654Terminal::NONE(bte::parser::Sequence const& seq)
1655{
1656}
1657
1658void
1659Terminal::GRAPHIC(bte::parser::Sequence const& seq)
1660{
1661#if 0
1662 struct bte_char ch = BTE_CHAR_NULL;
1663
1664 if (screen->state.cursor_x + 1 == screen->page->width
1665 && screen->flags & BTE_FLAG_PENDING_WRAP
1666 && screen->state.auto_wrap) {
1667 screen_cursor_down(screen, 1, true);
1668 screen_cursor_set(screen, 0, screen->state.cursor_y);
1669 }
1670
1671 screen_cursor_clear_wrap(screen);
1672
1673 ch = bte_char_merge(ch, screen_map(screen, seq->terminator));
1674 bte_page_write(screen->page,
1675 screen->state.cursor_x,
1676 screen->state.cursor_y,
1677 ch,
1678 1,
1679 &screen->state.attr,
1680 screen->age,
1681 false);
1682
1683 if (screen->state.cursor_x + 1 == screen->page->width)
1684 screen->flags |= BTE_FLAG_PENDING_WRAP;
1685 else
1686 screen_cursor_right(screen, 1);
1687
1688 return 0;
1689#endif
1690
1691 insert_char(seq.terminator(), false, false);
1692}
1693
1694void
1695Terminal::ACK(bte::parser::Sequence const& seq)
1696{
1697 /*
1698 * ACK - acknowledge
1699 *
1700 * References: ECMA-48 § 8.3.1
1701 * ECMA-16 § 3.1.6
1702 */
1703
1704 m_bell_pending = true;
1705}
1706
1707void
1708Terminal::ACS(bte::parser::Sequence const& seq)
1709{
1710 /* ACS - announce-code-structure
1711 *
1712 * The final byte of the sequence identifies the facility number
1713 * from 1 to 62 starting with 4/01.
1714 * DEC uses some final characters in the 3/00..3/15 range for
1715 * private purposes.
1716 *
1717 * References: ECMA-35 § 15.2
1718 * DEC VT525
1719 * DEC PPLV2
1720 */
1721
1722 /* Since we mostly don't implement ECMA-35 anymore, we can mostly ignore this */
1723
1724 switch (int(seq.terminator()) - 0x40) {
1725 case -10: /* '6' */
1726 /* S7C1R/DECTC1 - truncate C1 controls
1727 *
1728 * Masks the high bit from C1 controls and then
1729 * processes them as if received like that.
1730 *
1731 * References: DEC PPLV2
1732 */
1733 break;
1734 case -9: /* '7' */
1735 /* S8C1R/DECAC1 - accept C1 controls
1736 *
1737 * Accept both C0 and C1 controls.
1738 *
1739 * References: DEC PPLV2
1740 */
1741 break;
1742 case 6:
1743 /*
1744 * This causes the terminal to start sending C1 controls as 7bit
1745 * sequences instead of 8bit C1 controls.
1746 * This is ignored if the terminal is below level-2 emulation mode
1747 * (VT100 and below), the terminal already sends 7bit controls then.
1748 *
1749 * References: ECMA-35
1750 * VT525
1751 */
1752#if 0
1753 if (screen->conformance_level > BTE_CONFORMANCE_LEVEL_VT100)
1754 screen->flags |= BTE_FLAG_7BIT_MODE;
1755#endif
1756 break;
1757
1758 case 7:
1759 /*
1760 * This causes the terminal to start sending C1 controls as 8bit C1
1761 * control instead of 7bit sequences.
1762 * This is ignored if the terminal is below level-2 emulation mode
1763 * (VT100 and below). The terminal always sends 7bit controls in those
1764 * modes.
1765 *
1766 * References: ECMA-35
1767 * VT525
1768 */
1769#if 0
1770 if (screen->conformance_level > BTE_CONFORMANCE_LEVEL_VT100)
1771 screen->flags &= ~BTE_FLAG_7BIT_MODE;
1772#endif
1773 break;
1774
1775 case 12:
1776 /* Use Level 1 of ECMA-43
1777 *
1778 * Probably not worth implementing.
1779 */
1780 break;
1781 case 13:
1782 /* Use Level 2 of ECMA-43
1783 *
1784 * Probably not worth implementing.
1785 *
1786 * On a VTxxx, both levels 1 and 2 designate as follows:
1787 * G0 = ASCII (IR #6)
1788 * G1 = ISO_LATIN1_SUPPLEMENTAL
1789 * with G0 mapped to GL, G1 to GR.
1790 *
1791 * References: VT525
1792 */
1793 break;
1794 case 14:
1795 /* Use Level 3 of ECMA-43
1796 *
1797 * Probably not worth implementing.
1798 *
1799 * On a VTxxx, this designates as follows:
1800 * G0 = ASCII (IR #6)
1801 * with G0 mapped to GL.
1802 *
1803 *
1804 * References: VT525
1805 */
1806 break;
1807 }
1808}
1809
1810void
1811Terminal::BEL(bte::parser::Sequence const& seq)
1812{
1813 /*
1814 * BEL - sound bell tone
1815 * This command should trigger an acoustic bell.
1816 *
1817 * References: ECMA-48 § 8.3.3
1818 */
1819
1820 m_bell_pending = true;
1821}
1822
1823void
1824Terminal::BPH(bte::parser::Sequence const& seq)
1825{
1826 /*
1827 * BPH - break permitted here
1828 *
1829 * References: ECMA-48 § 8.3.4
1830 *
1831 * Not worth implementing.
1832 */
1833}
1834
1835void
1836Terminal::BS(bte::parser::Sequence const& seq)
1837{
1838 /*
1839 * BS - backspace
1840 * Move cursor one cell to the left. If already at the left margin,
1841 * nothing happens.
1842 *
1843 * References: ECMA-48 § 8.3.5
1844 */
1845
1846#if 0
1847 screen_cursor_clear_wrap(screen);
1848 screen_cursor_left(screen, 1);
1849#endif
1850
1851 ensure_cursor_is_onscreen();
1852
1853 if (m_screen->cursor.col > 0) {
1854 /* There's room to move left, so do so. */
1855 m_screen->cursor.col--;
1856 }
1857}
1858
1859void
1860Terminal::CBT(bte::parser::Sequence const& seq)
1861{
1862 /*
1863 * CBT - cursor-backward-tabulation
1864 * Move the cursor @args[0] tabs backwards (to the left). The
1865 * current cursor cell, in case it's a tab, is not counted.
1866 * Furthermore, the cursor cannot be moved beyond position 0 and
1867 * it will stop there.
1868 *
1869 * Defaults:
1870 * args[0]: 1
1871 *
1872 * References: ECMA-48 § 8.3.7
1873 */
1874#if 0
1875 screen_cursor_clear_wrap(screen);
1876#endif
1877
1878 move_cursor_tab_backward(seq.collect1(0, 1));
1879}
1880
1881void
1882Terminal::CCH(bte::parser::Sequence const& seq)
1883{
1884 /*
1885 * CCH - cancel character
1886 * Indicates that the CCH and the preceding graphic character
1887 * (including SPACE (2/0)) in the data stream should be ignored.
1888 * If CCH is not preceded by a graphic character but by a
1889 * control function instead, CCH is ignored.
1890 *
1891 * References: ECMA-48 § 8.3.8
1892 *
1893 * Not worth implementing.
1894 */
1895}
1896
1897void
1898Terminal::CHA(bte::parser::Sequence const& seq)
1899{
1900 /*
1901 * CHA - cursor-horizontal-absolute
1902 * Move the cursor to position @args[0] in the current line
1903 * (presentation).
1904 * The cursor cannot be moved beyond the rightmost cell; it will
1905 * stop there.
1906 *
1907 * Arguments:
1908 * args[0]: column
1909 *
1910 * Defaults:
1911 * args[0]: 1
1912 *
1913 * References: ECMA-48 § 8.3.9
1914 */
1915
1916#if 0
1917 unsigned int pos = 1;
1918
1919 if (seq->args[0] > 0)
1920 pos = seq->args[0];
1921
1922 screen_cursor_clear_wrap(screen);
1923 screen_cursor_set(screen, pos - 1, screen->state.cursor_y);
1924#endif
1925
1926 auto value = seq.collect1(0, 1, 1, m_column_count);
1927 set_cursor_column1(value);
1928}
1929
1930void
1931Terminal::CHT(bte::parser::Sequence const& seq)
1932{
1933 /*
1934 * CHT - cursor-horizontal-forward-tabulation
1935 * Move the cursor @args[0] tabs forward (to the right) (presentation).
1936 * The current cursor cell, in case it's a tab, is not counted.
1937 * Furthermore, the cursor cannot be moved beyond the rightmost cell
1938 * and will stop there.
1939 *
1940 * Arguments:
1941 * args[0]: count
1942 *
1943 * Defaults:
1944 * args[0]: 1
1945 *
1946 * References: ECMA-48 § 8.3.10
1947 */
1948#if 0
1949 screen_cursor_clear_wrap(screen);
1950#endif
1951
1952 move_cursor_tab_forward(seq.collect1(0, 1));
1953}
1954
1955void
1956Terminal::CMD(bte::parser::Sequence const& seq)
1957{
1958 /*
1959 * CMD - coding method delimiter
1960 *
1961 * References: ECMA-35 § 15.3
1962 * ECMA-48 § 8.3.11
1963 *
1964 * Not worth implementing.
1965 */
1966}
1967
1968void
1969Terminal::CNL(bte::parser::Sequence const& seq)
1970{
1971 /*
1972 * CNL - cursor-next-line
1973 * Move the cursor @args[0] lines down.
1974 *
1975 * TODO: Does this stop at the bottom or cause a scroll-up?
1976 *
1977 * Arguments:
1978 * args[0]: number of lines
1979 *
1980 * Defaults:
1981 * args[0]: 1
1982 *
1983 * References: ECMA-48 §8.3.12
1984 */
1985#if 0
1986 unsigned int num = 1;
1987
1988 if (seq->args[0] > 0)
1989 num = seq->args[0];
1990
1991 screen_cursor_clear_wrap(screen);
1992 screen_cursor_down(screen, num, false);
1993#endif
1994
1995 set_cursor_column1(1);
1996
1997 auto value = seq.collect1(0, 1);
1998 move_cursor_down(value);
1999}
2000
2001void
2002Terminal::CPL(bte::parser::Sequence const& seq)
2003{
2004 /*
2005 * CPL - cursor-preceding-line
2006 * Move the cursor @args[0] lines up, without scrolling.
2007 *
2008 * Arguments:
2009 * args[0]: number of lines
2010 *
2011 * Defaults:
2012 * args[0]: 1
2013 *
2014 * References: ECMA-48 § 8.3.13
2015 */
2016#if 0
2017 unsigned int num = 1;
2018
2019 if (seq->args[0] > 0)
2020 num = seq->args[0];
2021
2022 screen_cursor_clear_wrap(screen);
2023 screen_cursor_up(screen, num, false);
2024#endif
2025
2026 set_cursor_column(0);
2027
2028 auto const value = seq.collect1(0, 1);
2029 move_cursor_up(value);
2030}
2031
2032void
2033Terminal::CR(bte::parser::Sequence const& seq)
2034{
2035 /*
2036 * CR - carriage-return
2037 * Move the cursor to the left margin on the current line.
2038 *
2039 * References: ECMA-48 § 8.3.15
2040 */
2041#if 0
2042 screen_cursor_clear_wrap(screen);
2043 screen_cursor_set(screen, 0, screen->state.cursor_y);
2044#endif
2045
2046 set_cursor_column(0);
2047}
2048
2049void
2050Terminal::CTC(bte::parser::Sequence const& seq)
2051{
2052 /*
2053 * CTC - cursor tabulation control
2054 * Set/clear tabstops.
2055 *
2056 * For the cases @args[0] = 0, 2, 4, the effect depends on TSM mode.
2057 *
2058 * References: ECMA-48 § 8.3.17
2059 */
2060
2061 switch (seq.collect1(0)) {
2062 case -1:
2063 case 0:
2064 /* Set tabstop at the current cursor position */
2065 m_tabstops.set(get_cursor_column());
2066 break;
2067
2068 case 1:
2069 /* Sets line tabstop in the ative line (presentation) */
2070 break;
2071
2072 case 2:
2073 /* Clear tabstop at the current cursor position */
2074 m_tabstops.unset(get_cursor_column());
2075 break;
2076
2077 case 3:
2078 /* Clear line tabstop in the active line */
2079 break;
2080
2081 case 4:
2082 /* Clear all tabstops in the active line */
2083 [[fallthrough]];
2084 case 5:
2085 /* Clear all tabstops */
2086 m_tabstops.clear();
2087 break;
2088
2089 case 6:
2090 /* Clear all line tabstops */
2091 break;
2092
2093 default:
2094 break;
2095 }
2096}
2097
2098void
2099Terminal::CUB(bte::parser::Sequence const& seq)
2100{
2101 /*
2102 * CUB - cursor-backward
2103 * Move the cursor @args[0] positions to the left. The cursor stops
2104 * at the left-most position. (presentation)
2105 *
2106 * Arguments:
2107 * args[0]: number of positions
2108 *
2109 * Defaults:
2110 * args[0]: 1
2111 *
2112 * References: ECMA-48 § 8.3.18
2113 */
2114#if 0
2115 unsigned int num = 1;
2116
2117 if (seq->args[0] > 0)
2118 num = seq->args[0];
2119
2120 screen_cursor_clear_wrap(screen);
2121 screen_cursor_left(screen, num);
2122#endif
2123
2124 auto value = seq.collect1(0, 1);
2125 move_cursor_backward(value);
2126}
2127
2128void
2129Terminal::CUD(bte::parser::Sequence const& seq)
2130{
2131 /*
2132 * CUD - cursor-down
2133 * Move the cursor @args[0] positions down. The cursor stops at the
2134 * bottom margin. If it was already moved further, it stops at the
2135 * bottom line. (presentation)
2136 *
2137 * Arguments:
2138 * args[0]: number of positions
2139 *
2140 * Defaults:
2141 * args[0]: 1
2142 *
2143 * References: ECMA-48 § 8.3.19
2144 * DEC STD 070 page 5-43
2145 */
2146#if 0
2147 unsigned int num = 1;
2148
2149 if (seq->args[0] > 0)
2150 num = seq->args[0];
2151
2152 screen_cursor_clear_wrap(screen);
2153 screen_cursor_down(screen, num, false);
2154#endif
2155
2156 auto value = seq.collect1(0, 1);
2157 move_cursor_down(value);
2158}
2159
2160void
2161Terminal::CUF(bte::parser::Sequence const& seq)
2162{
2163 /*
2164 * CUF -cursor-forward
2165 * Move the cursor @args[0] positions to the right. The cursor stops
2166 * at the right-most position. (presentation)
2167 *
2168 * Arguments:
2169 * args[0]: number of positions
2170 *
2171 * Defaults:
2172 * args[0]: 1
2173 *
2174 * References: ECMA-48 § 8.3.20
2175 */
2176#if 0
2177 unsigned int num = 1;
2178
2179 if (seq->args[0] > 0)
2180 num = seq->args[0];
2181
2182 screen_cursor_clear_wrap(screen);
2183 screen_cursor_right(screen, num);
2184#endif
2185
2186 auto value = seq.collect1(0, 1);
2187 move_cursor_forward(value);
2188}
2189
2190void
2191Terminal::CUP(bte::parser::Sequence const& seq)
2192{
2193 /*
2194 * CUP - cursor-position
2195 * Moves the cursor to position @args[1] x @args[0]. If either is 0, it
2196 * is treated as 1. The positions are subject to the origin-mode and
2197 * clamped to the addressable width/height. (presentation)
2198 *
2199 * Arguments:
2200 * args[0]: line
2201 * args[0]: column
2202 *
2203 * Defaults:
2204 * args[0]: 1
2205 * args[1]: 1
2206 *
2207 * References: ECMA-48 § 8.3.21
2208 */
2209#if 0
2210 unsigned int x = 1, y = 1;
2211
2212 if (seq->args[0] > 0)
2213 y = seq->args[0];
2214 if (seq->args[1] > 0)
2215 x = seq->args[1];
2216
2217 screen_cursor_clear_wrap(screen);
2218 screen_cursor_set_rel(screen, x - 1, y - 1);
2219#endif
2220
2221 /* The first is the row, the second is the column. */
2222 auto rowvalue = seq.collect1(0, 1, 1, m_row_count);
2223 auto colvalue = seq.collect1(seq.next(0), 1, 1, m_column_count);
2224 set_cursor_coords1(rowvalue, colvalue);
2225}
2226
2227void
2228Terminal::CUU(bte::parser::Sequence const& seq)
2229{
2230 /*
2231 * CUU - cursor-up
2232 * Move the cursor @args[0] positions up. The cursor stops at the
2233 * top margin. If it was already moved further, it stops at the
2234 * top line. (presentation)
2235 *
2236 * Arguments:
2237 * args[0]: number of positions
2238 *
2239 * Defaults:
2240 * args[0]: 1
2241 *
2242 * References: ECMA-48 § 8.3.22
2243 * DEC STD 070 page 5-41
2244 */
2245#if 0
2246 unsigned int num = 1;
2247
2248 if (seq->args[0] > 0)
2249 num = seq->args[0];
2250
2251 screen_cursor_clear_wrap(screen);
2252 screen_cursor_up(screen, num, false);
2253#endif
2254
2255 auto const value = seq.collect1(0, 1);
2256 move_cursor_up(value);
2257}
2258
2259void
2260Terminal::CVT(bte::parser::Sequence const& seq)
2261{
2262 /*
2263 * CVT - cursor line tabulation
2264 * Move the cursor @args[0] positions down. The cursor stops at the
2265 * bottom margin. If it was already moved further, it stops at the
2266 * bottom line. (presentation)
2267 *
2268 * Arguments:
2269 * args[0]: number of positions
2270 *
2271 * Defaults:
2272 * args[0]: 1
2273 *
2274 * References: ECMA-48 § 8.3.23
2275 */
2276
2277 /* FIXME: implement this? */
2278}
2279
2280void
2281Terminal::CnD(bte::parser::Sequence const& seq)
2282{
2283 /*
2284 * CnD - Cn-designate
2285 *
2286 * Designate a set of control functions.
2287 *
2288 * References: ECMA-35 § 14.2
2289 * ISO 2375 IR
2290 */
2291
2292 /* Since we mostly don't implement ECMA-35 anymore, we can ignore this */
2293}
2294
2295void
2296Terminal::DA1(bte::parser::Sequence const& seq)
2297{
2298 /*
2299 * DA1 - primary-device-attributes
2300 * The primary DA asks for basic terminal features. We simply return
2301 * a hard-coded list of features we implement.
2302 * Note that the primary DA asks for supported features, not currently
2303 * enabled features.
2304 *
2305 * Reply: DECDA1R (CSI ? 65 ; ARGS c)
2306 *
2307 * The first argument, 65, is fixed and denotes a VT520 (a Level 5
2308 * terminal), the last DEC-term that extended this number.
2309 * All following arguments denote supported features. Note
2310 * that at most 15 features can be sent (max CSI args). It is safe to
2311 * send more, but clients might not be able to parse them. This is a
2312 * client's problem and we shouldn't care. There is no other way to
2313 * send those feature lists, so we have to extend them beyond 15 in
2314 * those cases.
2315 *
2316 * Known modes:
2317 * 1: 132 column mode
2318 * The 132 column mode is supported by the terminal.
2319 * 2: printer port
2320 * A priner-port is supported and can be addressed via
2321 * control-codes.
2322 * 3: ReGIS graphics
2323 * Support for ReGIS graphics is available. The ReGIS routines
2324 * provide the "remote graphics instruction set" and allow basic
2325 * vector-rendering.
2326 * 4: Sixel
2327 * Support of Sixel graphics is available. This provides access
2328 * to the sixel bitmap routines.
2329 * 6: selective erase
2330 * The terminal supports DECSCA and related selective-erase
2331 * functions. This allows to protect specific cells from being
2332 * erased, if specified.
2333 * 7: soft character set (DRCS)
2334 * TODO: ?
2335 * 8: user-defined keys (UDKs)
2336 * TODO: ?
2337 * 9: national-replacement character sets (NRCS)
2338 * National-replacement character-sets are available.
2339 * 12: Serbo-Croatian (SCS)
2340 * TODO: ?
2341 * 15: technical character set
2342 * The DEC technical-character-set is available.
2343 * 18: windowing capability
2344 * TODO: ?
2345 * 19: sessions capability
2346 * TODO: ?
2347 * 21: horizontal scrolling
2348 * TODO: ?
2349 * 22: ANSI color
2350 * TODO: ?
2351 * 23: Greek
2352 * TODO: ?
2353 * 24: Turkish
2354 * TODO: ?
2355 * 29: DECterm text locator
2356 * TODO: ?
2357 * 42: ISO Latin-2 character set
2358 * TODO: ?
2359 * 44: PCTerm
2360 * TODO: ?
2361 * 45: soft key mapping
2362 * TODO: ?
2363 * 46: ASCII emulation
2364 * TODO: ?
2365 *
2366 * Extensions which are implied by the level are not reported explicity
2367 * (e.g. 6, 8, 15 in level 5).
2368 *
2369 * Defaults:
2370 * args[0]: 0
2371 *
2372 * References: ECMA-48 § 8.3.24
2373 * VT525
2374 */
2375
2376 if (seq.collect1(0, 0) != 0)
2377 return;
2378
2379 reply(seq, BTE_REPLY_DECDA1R, {65, 1, 9});
2380}
2381
2382void
2383Terminal::DA2(bte::parser::Sequence const& seq)
2384{
2385 /*
2386 * DA2 - secondary-device-attributes
2387 * The secondary DA asks for the terminal-ID, firmware versions and
2388 * other non-primary attributes. All these values are
2389 * informational-only and should not be used by the host to detect
2390 * terminal features.
2391 *
2392 * Reply: DECDA2R (CSI > 65 ; FIRMWARE ; KEYBOARD c)
2393 * where 65 is fixed for VT525 color terminals, the last terminal-line that
2394 * increased this number (64 for VT520). FIRMWARE is the firmware
2395 * version encoded as major/minor (20 == 2.0) and KEYBOARD is 0 for STD
2396 * keyboard and 1 for PC keyboards.
2397 *
2398 * We replace the firmware-version with the BTE version so clients
2399 * can decode it again.
2400 *
2401 * References: VT525
2402 */
2403
2404 /* Param != 0 means this is a reply, not a request */
2405 if (seq.collect1(0, 0) != 0)
2406 return;
2407
2408 int const version = (BTE_MAJOR_VERSION(0) * 100 + BTE_MINOR_VERSION(65)) * 100 + BTE_MICRO_VERSION(0);
2409 reply(seq, BTE_REPLY_DECDA2R, {65, version, 1});
2410}
2411
2412void
2413Terminal::DA3(bte::parser::Sequence const& seq)
2414{
2415 /*
2416 * DA3 - tertiary-device-attributes
2417 * The tertiary DA is used to query the terminal-ID.
2418 *
2419 * Reply: DECRPTUI
2420 * DATA: four pairs of are hexadecimal number, encoded 4 bytes.
2421 * The first byte denotes the manufacturing site, the remaining
2422 * three is the terminal's ID.
2423 *
2424 * We always reply with '~BTE' encoded in hex.
2425 */
2426
2427 if (seq.collect1(0, 0) != 0)
2428 return;
2429
2430 reply(seq, BTE_REPLY_DECRPTUI, {});
2431}
2432
2433void
2434Terminal::DAQ(bte::parser::Sequence const& seq)
2435{
2436 /*
2437 * DAQ - define area qualification
2438 *
2439 * Arguments:
2440 * args[0]: type
2441 *
2442 * Defaults:
2443 * args[0]: 0
2444 *
2445 * References: ECMA-48 § 8.3.25, § 6.5.2
2446 */
2447}
2448
2449void
2450Terminal::DC1(bte::parser::Sequence const& seq)
2451{
2452 /*
2453 * DC1 - device-control-1 or XON
2454 * This clears any previous XOFF and resumes terminal-transmission.
2455 *
2456 * References: ECMA-48 § 8.3.28
2457 */
2458
2459 /* we do not support XON */
2460}
2461
2462void
2463Terminal::DC2(bte::parser::Sequence const& seq)
2464{
2465 /*
2466 * DC2 - device-control-2
2467 *
2468 * References: ECMA-48 § 8.3.29
2469 *
2470 * Not implemented.
2471 */
2472}
2473
2474void
2475Terminal::DC3(bte::parser::Sequence const& seq)
2476{
2477 /*
2478 * DC3 - device-control-3 or XOFF
2479 * Stops terminal transmission. No further characters are sent until
2480 * an XON is received.
2481 *
2482 * References: ECMA-48 § 8.3.30
2483 */
2484
2485 /* we do not support XOFF */
2486}
2487
2488void
2489Terminal::DC4(bte::parser::Sequence const& seq)
2490{
2491 /*
2492 * DC4 - device-control-4
2493 *
2494 * References: ECMA-48 § 8.3.31
2495 *
2496 * Not implemented.
2497 */
2498}
2499
2500void
2501Terminal::DCH(bte::parser::Sequence const& seq)
2502{
2503 /*
2504 * DCH - delete-character
2505 * This deletes @argv[0] characters at the current cursor position.
2506 *
2507 * Defaults:
2508 * args[0]: 1
2509 *
2510 * References: ECMA-48 § 8.3.26
2511 */
2512#if 0
2513 unsigned int num = 1;
2514
2515 if (seq->args[0] > 0)
2516 num = seq->args[0];
2517
2518 screen_cursor_clear_wrap(screen);
2519 bte_page_delete_cells(screen->page,
2520 screen->state.cursor_x,
2521 screen->state.cursor_y,
2522 num,
2523 &screen->state.attr,
2524 screen->age);
2525#endif
2526
2527 auto const value = seq.collect1(0, 1, 1, int(m_column_count - m_screen->cursor.col));
2528
2529 // FIXMEchpe pass count to delete_character() and simplify
2530 // to only cleanup fragments once
2531 for (auto i = 0; i < value; i++)
2532 delete_character();
2533}
2534
2535void
2536Terminal::DECAC(bte::parser::Sequence const& seq)
2537{
2538 /*
2539 * DECAC - assign color
2540 * Assign the color used for normal text.
2541 *
2542 * Arguments:
2543 * @args[0]: item; 1 for normal text, 2 for the text in the window frame
2544 * @args[1]: foreground color palette index (0..15)
2545 * @args[2]: background color palette index (0..15)
2546 *
2547 * References: VT525
2548 */
2549
2550 // FIXMEchpe maybe implement this, allowing our extended color
2551 // format instead of just palette colors
2552}
2553
2554void
2555Terminal::DECALN(bte::parser::Sequence const& seq)
2556{
2557 /*
2558 * DECALN - screen-alignment-pattern
2559 * Resets the margins, homes the cursor, and fills the screen
2560 * with 'E's.
2561 *
2562 * References: VT525
2563 */
2564
2565 // FIXMEchpe! reset margins and home cursor
2566
2567 for (auto row = m_screen->insert_delta;
2568 row < m_screen->insert_delta + m_row_count;
2569 row++) {
2570 /* Find this row. */
2571 while (_bte_ring_next(m_screen->row_data) <= row)
2572 ring_append(false);
2573 adjust_adjustments();
2574 auto rowdata = _bte_ring_index_writable (m_screen->row_data, row);
2575 g_assert(rowdata != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (rowdata != __null) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1)) ; else g_assertion_message_expr
("BTE", "../src/bteseq.cc", 2575, ((const char*) (__PRETTY_FUNCTION__
)), "rowdata != NULL"); } while (0)
;
2576 /* Clear this row. */
2577 _bte_row_data_shrink (rowdata, 0);
2578
2579 emit_text_deleted();
2580 /* Fill this row. */
2581 BteCell cell;
2582 cell.c = 'E';
2583 cell.attr = basic_cell.attr;
2584 cell.attr.set_columns(1);
2585 _bte_row_data_fill(rowdata, &cell, m_column_count);
2586 emit_text_inserted();
2587 }
2588 invalidate_all();
2589
2590 /* We modified the display, so make a note of it for completeness. */
2591 m_text_modified_flag = TRUE(!(0));
2592}
2593
2594void
2595Terminal::DECARR(bte::parser::Sequence const& seq)
2596{
2597 /*
2598 * DECARR - auto repeat rate
2599 * Sets the key autorepeat rate in from @args[0] in keys/s.
2600 * 0…5 are mapped to 0/s, 6…15 to 10/s, 16…30 to 30/s.
2601 * Other values are ignored. The default is 30.
2602 *
2603 * References: VT525
2604 *
2605 * Probably not worth implementing.
2606 */
2607}
2608
2609void
2610Terminal::DECATC(bte::parser::Sequence const& seq)
2611{
2612 /*
2613 * DECATC - alternate text color
2614 * Assign the color used for attribute combinations text.
2615 *
2616 * Arguments:
2617 * @args[0]: selects the attribute combinations from a
2618 * value table (0 = normal, 1 = bold, 2 = reverse,
2619 * 3 = (single) underline, 4 = blink; then 5…15
2620 * encode the combinations)
2621 * @args[1]: foreground color palette index (0..15)
2622 * @args[2]: background color palette index (0..15)
2623 *
2624 * References: VT525
2625 */
2626
2627 // FIXMEchpe maybe implement this, allowing our extended color
2628 // format instead of just palette colors
2629}
2630
2631void
2632Terminal::DECAUPSS(bte::parser::Sequence const& seq)
2633{
2634 /*
2635 * DECAUPSS - assign user preferred supplemental sets
2636 * Sets a supplemental charset as user preferred.
2637 * Arguments:
2638 * @args[0]: charset designator:
2639 * 0 = DEC, Latin 1/2
2640 * 1 = Latin 5/7, ISO Cyrillic, ISO Hebrew
2641 * DATA: the charset, as in a ECMA-35 charset designation
2642 * sequence (sans the ESC); but only some charsets are
2643 * supported.
2644 *
2645 * Default: DEC Supplemental Graphic set.
2646 *
2647 * References: VT525
2648 *
2649 * Probably not worth implementing.
2650 */
2651}
2652
2653void
2654Terminal::DECBI(bte::parser::Sequence const& seq)
2655{
2656 /*
2657 * DECBI - back-index
2658 * This control function moves the cursor backward one column. If the
2659 * cursor is at the left margin, then all screen data within the margin
2660 * moves one column to the right. The column that shifted past the right
2661 * margin is lost.
2662 * DECBI adds a new column at the left margin with no visual attributes.
2663 * DECBI does not affect the margins. If the cursor is beyond the
2664 * left-margin at the left border, then the terminal ignores DECBI.
2665 *
2666 * Probably not worth implementing.
2667 */
2668}
2669
2670void
2671Terminal::DECCARA(bte::parser::Sequence const& seq)
2672{
2673 /*
2674 * DECCARA - change-attributes-in-rectangular-area
2675 * Change some character attributes (bold, blink, reverse,
2676 * (single) underline) in the specified rectangle.
2677 * The characters in the area are unchanged.
2678 *
2679 * Arguments;
2680 * args[0..3]: top, left, bottom, right of the rectangle (1-based)
2681 * args[4:]: the character attributes to change; values as in SGR
2682 *
2683 * Defaults:
2684 * args[0]: 1
2685 * args[1]: 1
2686 * args[2]: height of current page
2687 * args[3]: width of current page
2688 * args[4:]: no defaults
2689 *
2690 * If the top > bottom or left > right, the command is ignored.
2691 *
2692 * These coordinates are interpreted according to origin mode (DECOM),
2693 * but unaffected by the page margins (DECSLRM?). Current SGR defaults
2694 * and cursor position are unchanged.
2695 *
2696 * Note: DECSACE selects whether this function operates on the
2697 * rectangular area or the data stream between the star and end
2698 * positions.
2699 *
2700 * References: VT525
2701 *
2702 * Probably not worth implementing.
2703 */
2704}
2705
2706void
2707Terminal::DECCKD(bte::parser::Sequence const& seq)
2708{
2709 /*
2710 * DECCKD - copy key default
2711 * Copy the defaults from one key to another.
2712 *
2713 * References: VT525
2714 *
2715 * Probably not worth implementing.
2716 */
2717}
2718
2719void
2720Terminal::DECCRA(bte::parser::Sequence const& seq)
2721{
2722 /*
2723 * DECCRA - copy-rectangular-area
2724 * Copies characters and their attributes from one rectangle to
2725 * another.
2726 *
2727 * Arguments;
2728 * args[0..3]: top, left, bottom, right of the source rectangle (1-based)
2729 * args[4..7]: top, left, bottom, right of the target rectangle (1-based)
2730 *
2731 * Defaults:
2732 * args[0]: 1
2733 * args[1]: 1
2734 * args[2]: height of current page
2735 * args[3]: width of current page
2736 * args[4]: 1
2737 * args[5]: 1
2738 * args[6]: height of current page
2739 * args[7]: width of current page
2740 *
2741 * If the top > bottom or left > right for either of the rectangles,
2742 * the command is ignored.
2743 *
2744 * These coordinates are interpreted according to origin mode (DECOM),
2745 * but unaffected by the page margins (DECSLRM?). Current SGR defaults
2746 * and cursor position are unchanged.
2747 *
2748 * Note: DECSACE selects whether this function operates on the
2749 * rectangular area or the data stream between the star and end
2750 * positions.
2751 *
2752 * References: VT525
2753 *
2754 * Probably not worth implementing.
2755 */
2756}
2757
2758void
2759Terminal::DECCRTST(bte::parser::Sequence const& seq)
2760{
2761 /*
2762 * DECCRTST - CRT saver time
2763 * Sets the CRT saver timer. When DECCRTSM is set, the
2764 * screen blanks when the time elapsed since the last
2765 * keystroke or output is greater than the time set here.
2766 *
2767 * Arguments:
2768 * args[0]: the time in minutes (0…60) (0 = never)
2769 *
2770 * Default: 15
2771 *
2772 * References: VT525
2773 *
2774 * Probably not worth implementing.
2775 */
2776}
2777
2778void
2779Terminal::DECDC(bte::parser::Sequence const& seq)
2780{
2781 /*
2782 * DECDC - delete-column
2783 *
2784 * References: VT525
2785 *
2786 * Probably not worth implementing.
2787 */
2788}
2789
2790void
2791Terminal::DECDHL_BH(bte::parser::Sequence const& seq)
2792{
2793 /*
2794 * DECDHL_BH - double-width-double-height-line: bottom half
2795 *
2796 * References: VT525
2797 *
2798 * Probably not worth implementing.
2799 */
2800}
2801
2802void
2803Terminal::DECDHL_TH(bte::parser::Sequence const& seq)
2804{
2805 /*
2806 * DECDHL_TH - double-width-double-height-line: top half
2807 *
2808 * References: VT525
2809 *
2810 * Probably not worth implementing.
2811 */
2812}
2813
2814void
2815Terminal::DECDLD(bte::parser::Sequence const& seq)
2816{
2817 /*
2818 * DECDLD - dynamically redefinable character sets extension
2819 * Loads a soft font for a DRCS charset from SIXEL data
2820 *
2821 * References: VT525
2822 *
2823 * Probably not worth implementing.
2824 */
2825}
2826
2827void
2828Terminal::DECDLDA(bte::parser::Sequence const& seq)
2829{
2830 /*
2831 * DECDLD - down line load allocation
2832 * Sets the number of DRCSes allowed per sesion
2833 * (monochrome terminals only).
2834 *
2835 * References: VT525
2836 *
2837 * Probably not worth implementing.
2838 */
2839}
2840
2841void
2842Terminal::DECDMAC(bte::parser::Sequence const& seq)
2843{
2844 /*
2845 * DECDMAC - define-macro
2846 * Define a macro that can be executed by DECINVM.
2847 *
2848 * References: VT525
2849 *
2850 * For security reasons, BTE does not implement this.
2851 */
2852}
2853
2854void
2855Terminal::DECDWL(bte::parser::Sequence const& seq)
2856{
2857 /*
2858 * DECDWL - double-width-single-height-line
2859 *
2860 * References: VT525
2861 *
2862 * Probably not worth implementing.
2863 */
2864}
2865
2866void
2867Terminal::DECEFR(bte::parser::Sequence const& seq)
2868{
2869 /*
2870 * DECEFR - enable-filter-rectangle
2871 * Defines the coordinates of a filter rectangle (top, left, bottom,
2872 * right as @args[0] to @args[3]) and activates it.
2873 * Anytime the locator is detected outside of the filter rectangle, an
2874 * outside rectangle event is generated and the rectangle is disabled.
2875 * Filter rectangles are always treated as "one-shot" events. Any
2876 * parameters that are omitted default to the current locator position.
2877 * If all parameters are omitted, any locator motion will be reported.
2878 * DECELR always cancels any prevous rectangle definition.
2879 *
2880 * The locator is usually associated with the mouse-cursor, but based
2881 * on cells instead of pixels. See DECELR how to initialize and enable
2882 * it. DECELR can also enable pixel-mode instead of cell-mode.
2883 *
2884 * References: VT525
2885 *
2886 * TODO: implement
2887 */
2888}
2889
2890void
2891Terminal::DECELF(bte::parser::Sequence const& seq)
2892{
2893 /*
2894 * DECELF - enable-local-functions
2895 * Enable or disable keys to perform local functions like
2896 * copy/paster, panning and window resize.
2897 *
2898 * References: VT525
2899 *
2900 * Probably not worth implementing.
2901 */
2902}
2903
2904void
2905Terminal::DECELR(bte::parser::Sequence const& seq)
2906{
2907 /*
2908 * DECELR - enable-locator-reporting
2909 * This changes the locator-reporting mode. @args[0] specifies the mode
2910 * to set, 0 disables locator-reporting, 1 enables it continuously, 2
2911 * enables it for a single report. @args[1] specifies the
2912 * precision-mode. 0 and 2 set the reporting to cell-precision, 1 sets
2913 * pixel-precision.
2914 *
2915 * Defaults:
2916 * args[0]: 0
2917 * args[1]: 0
2918 *
2919 * References: VT525
2920 *
2921 * TODO: implement
2922 */
2923}
2924
2925void
2926Terminal::DECERA(bte::parser::Sequence const& seq)
2927{
2928 /*
2929 * DECERA - erase-rectangular-area
2930 * Erases characters in the specified rectangle, replacing
2931 * them with SPACE (2/0). Character attributes are erased
2932 * too, but not line attributes (DECDHL, DECDWL).
2933 *
2934 * Arguments;
2935 * args[0..3]: top, left, bottom, right of the rectangle (1-based)
2936 *
2937 * Defaults:
2938 * args[0]: 1
2939 * args[1]: 1
2940 * args[2]: height of current page
2941 * args[3]: width of current page
2942 *
2943 * If the top > bottom or left > right, the command is ignored.
2944 *
2945 * These coordinates are interpreted according to origin mode (DECOM),
2946 * but unaffected by the page margins (DECSLRM?). Current SGR defaults
2947 * and cursor position are unchanged.
2948 *
2949 * Note: DECSACE selects whether this function operates on the
2950 * rectangular area or the data stream between the star and end
2951 * positions.
2952 *
2953 * References: VT525
2954 *
2955 * Probably not worth implementing.
2956 */
2957}
2958
2959void
2960Terminal::DECES(bte::parser::Sequence const& seq)
2961{
2962 /*
2963 * DECES - enable session
2964 * Makes this session active as if by the Session key;
2965 * that is, makes the session receiving this command the
2966 * session receiving keyboard input.
2967 *
2968 * References: VT525
2969 *
2970 * BTE does not support sessions.
2971 */
2972}
2973
2974void
2975Terminal::DECFI(bte::parser::Sequence const& seq)
2976{
2977 /*
2978 * DECFI - forward-index
2979 * This control function moves the cursor forward one column. If the
2980 * cursor is at the right margin, then all screen data within the
2981 * margins moves one column to the left. The column shifted past the
2982 * left margin is lost.
2983 * DECFI adds a new column at the right margin, with no visual
2984 * attributes. DECFI does not affect margins. If the cursor is beyond
2985 * the right margin at the border of the page when the terminal
2986 * receives DECFI, then the terminal ignores DECFI.
2987 *
2988 * References: VT525
2989 *
2990 * Probably not worth implementing.
2991 */
2992}
2993
2994void
2995Terminal::DECFNK(bte::parser::Sequence const& seq)
2996{
2997 /*
2998 * DECFNK - function key (or XTERM bracketed paste)
2999 *
3000 * References: VT525
3001 * XTERM
3002 */
3003}
3004
3005void
3006Terminal::DECFRA(bte::parser::Sequence const& seq)
3007{
3008 /*
3009 * DECFRA - fill-rectangular-area
3010 * Fills the specified rectangle with the specified character,
3011 * replacing the current characters in it. Character attributes
3012 * are replaced by the current default SGR. Does not change
3013 * line attributes (DECDHL, DECDWL).
3014 *
3015 * Arguments;
3016 * args[0]: the decimal value of the replacement character (GL or GR)
3017 * args[0..3]: top, left, bottom, right of the rectangle (1-based)
3018 *
3019 * Defaults:
3020 * args[0]: 1
3021 * args[1]: 1
3022 * args[2]: height of current page
3023 * args[3]: width of current page
3024 *
3025 * If the top > bottom or left > right, the command is ignored.
3026 * If the character is not in the GL or GR area, the command is ignored.
3027 *
3028 * These coordinates are interpreted according to origin mode (DECOM),
3029 * but unaffected by the page margins (DECSLRM?). Current SGR defaults
3030 * and cursor position are unchanged.
3031 *
3032 * Note: DECSACE selects whether this function operates on the
3033 * rectangular area or the data stream between the star and end
3034 * positions.
3035 *
3036 * References: VT525
3037 *
3038 * Probably not worth implementing.
3039 *
3040 * *If* we were to implement it, we should find a way to allow any
3041 * UTF-8 character, perhaps by using subparams to encode it. E.g.
3042 * either each UTF-8 byte in a subparam of its own, or just split
3043 * the unicode plane off into the leading subparam (plane:remaining 16 bits).
3044 * Or by using the last graphic character for it, like REP.
3045 */
3046}
3047
3048void
3049Terminal::DECIC(bte::parser::Sequence const& seq)
3050{
3051 /*
3052 * DECIC - insert-column
3053 *
3054 * Defaults:
3055 * args[0]: 1
3056 *
3057 * References: VT525
3058 *
3059 * Probably not worth implementing.
3060 */
3061}
3062
3063void
3064Terminal::DECINVM(bte::parser::Sequence const& seq)
3065{
3066 /*
3067 * DECINVM - invoke-macro
3068 * Invokes a macro defined by DECDMAC.
3069 *
3070 * References: VT525
3071 *
3072 * For security reasons, BTE does not implement this.
3073 */
3074}
3075
3076void
3077Terminal::DECKBD(bte::parser::Sequence const& seq)
3078{
3079 /*
3080 * DECKBD - keyboard-language-selection
3081 * Selects a keyboard language.
3082 *
3083 * References: VT525
3084 *
3085 * Probably not worth implementing.
3086 */
3087}
3088
3089void
3090Terminal::DECKPAM(bte::parser::Sequence const& seq)
3091{
3092 /*
3093 * DECKPAM - keypad-application-mode
3094 * Enables the keypad-application mode. If enabled, the keypad sends
3095 * special characters instead of the printed characters. This way,
3096 * applications can detect whether a numeric key was pressed on the
3097 * top-row or on the keypad.
3098 * Default is keypad-numeric-mode.
3099 *
3100 * References: VT525
3101 */
3102
3103 set_mode_private(bte::terminal::modes::Private::eDEC_APPLICATION_KEYPAD, true);
3104}
3105
3106void
3107Terminal::DECKPNM(bte::parser::Sequence const& seq)
3108{
3109 /*
3110 * DECKPNM - keypad-numeric-mode
3111 * This disables the keypad-application-mode (DECKPAM) and returns to
3112 * the keypad-numeric-mode. Keypresses on the keypad generate the same
3113 * sequences as corresponding keypresses on the main keyboard.
3114 * Default is keypad-numeric-mode.
3115 *
3116 * References: VT525
3117 */
3118 set_mode_private(bte::terminal::modes::Private::eDEC_APPLICATION_KEYPAD, false);
3119}
3120
3121void
3122Terminal::DECLANS(bte::parser::Sequence const& seq)
3123{
3124 /*
3125 * DECLANS - load answerback message
3126 *
3127 * References: VT525
3128 *
3129 * For security reasons, BTE does not implement this.
3130 */
3131}
3132
3133void
3134Terminal::DECLBAN(bte::parser::Sequence const& seq)
3135{
3136 /*
3137 * DECLBAN - load banner message
3138 * Loads a banner message that will be displayed in double size
3139 * characters when the terminal powers up.
3140 *
3141 * References: VT525
3142 *
3143 * Probably not worth implementing.
3144 */
3145}
3146
3147void
3148Terminal::DECLBD(bte::parser::Sequence const& seq)
3149{
3150 /*
3151 * DECLBD - locator button define
3152 *
3153 * References: VT330
3154 */
3155}
3156
3157void
3158Terminal::DECLFKC(bte::parser::Sequence const& seq)
3159{
3160 /*
3161 * DECLFKC - local-function-key-control
3162 * Select the action for local function keys.
3163 *
3164 * References: VT525
3165 *
3166 * Probably not worth implementing.
3167 */
3168}
3169
3170void
3171Terminal::DECLL(bte::parser::Sequence const& seq)
3172{
3173 /*
3174 * DECLL - load-leds
3175 * Sets the keyboard LEDs when in DECKLHIM mode.
3176 *
3177 * Arguments:
3178 * args[0]: which LED to change to which state
3179 * 0: NumLock, CapsLock, ScrollLock off
3180 * 1, 21: NumLock on/off
3181 * 2, 22: CapsLock on/off
3182 * 3, 23: ScrollLock on/off
3183 *
3184 * References: VT525
3185 *
3186 * Probably not worth implementing.
3187 */
3188}
3189
3190void
3191Terminal::DECLTOD(bte::parser::Sequence const& seq)
3192{
3193 /*
3194 * DECLTOD - load-time-of-day
3195 * Sets the clock.
3196 *
3197 * References: VT525
3198 *
3199 * Probably not worth implementing.
3200 */
3201}
3202
3203void
3204Terminal::DECPAK(bte::parser::Sequence const& seq)
3205{
3206 /*
3207 * DECPAK - program alphanumeric key
3208 * Program alphanumeric keys to send different codes or perform actions.
3209 *
3210 * References: VT525
3211 *
3212 * For security reasons, BTE does not implement this.
3213 */
3214}
3215
3216void
3217Terminal::DECPCTERM(bte::parser::Sequence const& seq)
3218{
3219 /*
3220 * DECPCTERM - pcterm-mode
3221 * This enters/exits the PCTerm mode. Default mode is VT-mode. It can
3222 * also select parameters for scancode/keycode mappings in SCO mode.
3223 *
3224 * References: VT525
3225 *
3226 * Definitely not worth implementing.
3227 */
3228}
3229
3230void
3231Terminal::DECPCTERM_OR_XTERM_RPM(bte::parser::Sequence const& seq)
3232{
3233 /*
3234 * There's a conflict between DECPCTERM and XTERM_RPM.
3235 * XTERM_RPM takes a single argument, DECPCTERM takes 2.
3236 * Note that since both admit default values (which may be
3237 * omitted at the end of the sequence), this only an approximation.
3238 */
3239 if (seq.size_final() <= 1)
3240 XTERM_RPM(seq);
3241 #ifdef PARSER_INCLUDE_NOP
3242 else
3243 DECPCTERM(seq);
3244 #endif
3245}
3246
3247void
3248Terminal::DECPFK(bte::parser::Sequence const& seq)
3249{
3250 /*
3251 * DECPFK - program function key
3252 * Program function keys to send different codes or perform actions.
3253 *
3254 * References: VT525
3255 *
3256 * For security reasons, BTE does not implement this.
3257 */
3258}
3259
3260void
3261Terminal::DECPKA(bte::parser::Sequence const& seq)
3262{
3263 /*
3264 * DECPKA - program-key-action
3265 * Sets whether DECPFK, DECPAK, DECCD, DECUDK can reprogram keys.
3266 *
3267 * Arguments:
3268 * args[0]:
3269 *
3270 * Defaults:
3271 * args[0]: 0
3272 *
3273 * References: VT525
3274 *
3275 * For security reasons, BTE does not implement this.
3276 */
3277}
3278
3279void
3280Terminal::DECPKFMR(bte::parser::Sequence const& seq)
3281{
3282 /*
3283 * DECPKFMR - program-key-free-memory-report
3284 *
3285 * References: VT525
3286 *
3287 * Probably not worth implementing.
3288 */
3289}
3290
3291void
3292Terminal::DECPS(bte::parser::Sequence const& seq)
3293{
3294 /*
3295 * DECPS - play sound
3296 * Plays a note. Arguments:
3297 * @args[0]: the volume. 0 = off, 1…3 = low, 4…7 = high
3298 * @args[1]: the duration, in multiples of 1s/32
3299 * @args[2]: the note; from 1 = C5, 2 = C♯5 … to 25 = C7
3300 *
3301 * Defaults:
3302 * @args[0]: no default
3303 * @args[1]: no default
3304 * @args[2]: no default
3305 *
3306 * Note that a VT525 is specified to store only 16 notes at a time.
3307 *
3308 * References: VT525
3309 *
3310 * Probably not worth implementing.
3311 */
3312}
3313
3314void
3315Terminal::DECRARA(bte::parser::Sequence const& seq)
3316{
3317 /*
3318 * DECRARA - reverse-attributes-in-rectangular-area
3319 * Reverse some character attributes (bold, blink, reverse,
3320 * (single) underline) in the specified rectangle.
3321 * The characters in the area are unchanged, as are the
3322 * other character attributes.
3323 *
3324 * Arguments;
3325 * args[0..3]: top, left, bottom, right of the rectangle (1-based)
3326 * args[4:]: the character attributes to change; values as in SGR
3327 * except that only bold, blink, reverse, (single) underline are
3328 * supported; 0 to reverse all of these.
3329 *
3330 * Defaults:
3331 * args[0]: 1
3332 * args[1]: 1
3333 * args[2]: height of current page
3334 * args[3]: width of current page
3335 * args[4:]: no defaults
3336 *
3337 * If the top > bottom or left > right, the command is ignored.
3338 *
3339 * These coordinates are interpreted according to origin mode (DECOM),
3340 * but unaffected by the page margins (DECSLRM?). Current SGR defaults
3341 * and cursor position are unchanged.
3342 *
3343 * Note: DECSACE selects whether this function operates on the
3344 * rectangular area or the data stream between the star and end
3345 * positions.
3346 *
3347 * References: VT525
3348 *
3349 * Probably not worth implementing.
3350 */
3351}
3352
3353void
3354Terminal::DECRC(bte::parser::Sequence const& seq)
3355{
3356 /*
3357 * DECRC - restore-cursor
3358 * Restores the terminal to the state saved by the save cursor (DECSC)
3359 * function. If there was not a previous DECSC, then this does:
3360 * * Home the cursor
3361 * * Resets DECOM
3362 * * Resets the SGR attributes
3363 * * Designates ASCII (IR #6) to GL, and DEC Supplemental Graphics to GR
3364 *
3365 * Note that the status line has its own DECSC buffer.
3366 *
3367 * References: VT525
3368 */
3369#if 0
3370 screen_restore_state(screen, &screen->saved);
3371#endif
3372
3373 restore_cursor();
3374}
3375
3376void
3377Terminal::DECREGIS(bte::parser::Sequence const& seq)
3378{
3379 /*
3380 * DECREGIS - ReGIS graphics
3381 *
3382 * References: VT330
3383 */
3384}
3385
3386void
3387Terminal::DECREQTPARM(bte::parser::Sequence const& seq)
3388{
3389 /*
3390 * DECREQTPARM - request-terminal-parameters
3391 * The sequence DECREPTPARM is sent by the terminal controller to notify
3392 * the host of the status of selected terminal parameters. The status
3393 * sequence may be sent when requested by the host or at the terminal's
3394 * discretion. DECREPTPARM is sent upon receipt of a DECREQTPARM.
3395 *
3396 * If @args[0] is 0, this marks a request and the terminal is allowed
3397 * to send DECREPTPARM messages without request. If it is 1, the same
3398 * applies but the terminal should no longer send DECREPTPARM
3399 * unrequested.
3400 * 2 and 3 mark a report, but 3 is only used if the terminal answers as
3401 * an explicit request with @args[0] == 1.
3402 *
3403 * The other arguments are ignored in requests, but have the following
3404 * meaning in responses:
3405 * args[1]: 1=no-parity-set 4=parity-set-and-odd 5=parity-set-and-even
3406 * args[2]: 1=8bits-per-char 2=7bits-per-char
3407 * args[3]: transmission-speed
3408 * args[4]: receive-speed
3409 * args[5]: 1=bit-rate-multiplier-is-16
3410 * args[6]: This value communicates the four switch values in block 5
3411 * of SETUP B, which are only visible to the user when an STP
3412 * option is installed. These bits may be assigned for an STP
3413 * device. The four bits are a decimal-encoded binary number.
3414 * Value between 0-15.
3415 *
3416 * The transmission/receive speeds have mappings for number => bits/s
3417 * which are quite weird. Examples are: 96->3600, 112->9600, 120->19200
3418 *
3419 * Defaults:
3420 * args[0]: 0
3421 *
3422 * References: VT100
3423 *
3424 * Alternatively:
3425 *
3426 * WYCDIR - set current character color and attributes
3427 *
3428 * References: WY370
3429 */
3430
3431 switch (seq.collect1(0)) {
3432 case -1:
3433 case 0:
3434 #if 0
3435 screen->flags &= ~BTE_FLAG_INHIBIT_TPARM;
3436 #endif
3437 reply(seq, BTE_REPLY_DECREPTPARM,
3438 {2, 1, 1, 120, 120, 1, 0});
3439 break;
3440 case 1:
3441 #if 0
3442 screen->flags |= BTE_FLAG_INHIBIT_TPARM;
3443 #endif
3444 reply(seq, BTE_REPLY_DECREPTPARM,
3445 {3, 1, 1, 120, 120, 1, 0});
3446 break;
3447 case 2:
3448 case 3:
3449 /* This is a report, not a request */
3450 default:
3451 break;
3452 }
3453}
3454
3455void
3456Terminal::DECRQCRA(bte::parser::Sequence const& seq)
3457{
3458 /*
3459 * DECRQCRA - request checksum of rectangular area
3460 * Computes a simple checksum of the characters in the rectangular
3461 * area. args[0] is an identifier, which the response must use.
3462 * args[1] is the page number; if it's 0 or default then the
3463 * checksum is computed over all pages; if it's greater than the
3464 * number of pages, then the checksum is computed only over the
3465 * last page. args[2]..args[5] describe the area to compute the
3466 * checksum from, denoting the top, left, bottom, right, resp
3467 * (1-based). It's required that top ≤ bottom, and left ≤ right.
3468 * These coordinates are interpreted according to origin mode.
3469 *
3470 * NOTE: Since this effectively allows to read the screen
3471 * (by using a 1x1 rectangle on each cell), we normally only
3472 * send a dummy reply, and only reply with the actual checksum
3473 * when in test mode.
3474 *
3475 * Defaults:
3476 * args[0]: no default
3477 * args[1]: 0
3478 * args[2]: 1
3479 * args[3]: no default (?)
3480 * args[4]: height of current page
3481 * args[5]: width of current page
3482 *
3483 * Reply: DECCKSR
3484 * @args[0]: the identifier from the request
3485 * DATA: the checksum as a 4-digit hex number
3486 *
3487 * References: VT525
3488 * XTERM
3489 */
3490
3491 unsigned int idx = 0;
3492 int id = seq.collect1(idx);
3493
3494#ifndef BTE_DEBUG
3495 /* Send a dummy reply */
3496 return reply(seq, BTE_REPLY_DECCKSR, {id}, "0000");
3497#else
3498
3499 /* Not in test mode? Send a dummy reply */
3500 if ((g_test_flags & BTE_TEST_FLAG_DECRQCRA((1UL) << 0)) == 0) {
3501 return reply(seq, BTE_REPLY_DECCKSR, {id}, "0000");
3502 }
3503
3504 idx = seq.next(idx);
3505
3506 /* We only support 1 'page', so ignore args[1] */
3507 idx = seq.next(idx);
3508
3509 int top = seq.collect1(idx, 1, 1, m_row_count);
3510 idx = seq.next(idx);
3511 int left = seq.collect1(idx, 1, 1, m_column_count); /* use 1 as default here */
3512 idx = seq.next(idx);
3513 int bottom = seq.collect1(idx, m_row_count, 1, m_row_count);
3514 idx = seq.next(idx);
3515 int right = seq.collect1(idx, m_column_count, 1, m_column_count);
3516
3517 if (m_modes_private.DEC_ORIGIN() &&
3518 m_scrolling_restricted) {
3519 top += m_scrolling_region.start;
3520
3521 bottom += m_scrolling_region.start;
3522 bottom = std::min(bottom, m_scrolling_region.end);
3523
3524 }
3525
3526 unsigned int checksum;
3527 if (bottom < top || right < left)
3528 checksum = 0; /* empty area */
3529 else
3530 checksum = checksum_area(top -1 + m_screen->insert_delta,
3531 left - 1,
3532 bottom - 1 + m_screen->insert_delta,
3533 right - 1);
3534
3535 reply(seq, BTE_REPLY_DECCKSR, {id}, "%04X", checksum);
3536#endif /* BTE_DEBUG */
3537}
3538
3539void
3540Terminal::DECRQDE(bte::parser::Sequence const& seq)
3541{
3542 /*
3543 * DECRQDE - request-display-extent
3544 * Request how much of the curren tpage is shown on screen.
3545 *
3546 * References: VT525
3547 *
3548 * Probably not worth implementing.
3549 */
3550}
3551
3552void
3553Terminal::DECRQKT(bte::parser::Sequence const& seq)
3554{
3555 /*
3556 * DECRQKT - request-key-type
3557 *
3558 * References: VT525
3559 *
3560 * Probably not worth implementing.
3561 */
3562}
3563
3564void
3565Terminal::DECRQLP(bte::parser::Sequence const& seq)
3566{
3567 /*
3568 * DECRQLP - request-locator-position
3569 * See DECELR for locator-information.
3570 *
3571 * References: VT525
3572 *
3573 * TODO: document and implement
3574 */
3575}
3576
3577void
3578Terminal::DECRQM_ECMA(bte::parser::Sequence const& seq)
3579{
3580 /*
3581 * DECRQM_ECMA - request-mode-ecma
3582 * The host sends this control function to find out if a particular mode
3583 * is set or reset. The terminal responds with a report mode function.
3584 * @args[0] contains the mode to query.
3585 *
3586 * Response is DECRPM with the first argument set to the mode that was
3587 * queried, second argument is 0 if mode is invalid, 1 if mode is set,
3588 * 2 if mode is not set (reset), 3 if mode is permanently set and 4 if
3589 * mode is permanently not set (reset):
3590 * ECMA: ^[ MODE ; VALUE $ y
3591 * DEC: ^[ ? MODE ; VALUE $ y
3592 *
3593 * References: VT525
3594 */
3595
3596 auto const param = seq.collect1(0);
3597 auto const mode = m_modes_ecma.mode_from_param(param);
3598
3599 int value;
3600 switch (mode) {
3601 case bte::terminal::modes::ECMA::eUNKNOWN: value = 0; break;
3602 case bte::terminal::modes::ECMA::eALWAYS_SET: value = 3; break;
3603 case bte::terminal::modes::ECMA::eALWAYS_RESET: value = 4; break;
3604 default: assert(mode >= 0)(static_cast <bool> (mode >= 0) ? void (0) : __assert_fail
("mode >= 0", "../src/bteseq.cc", 3604, __extension__ __PRETTY_FUNCTION__
))
; value = m_modes_ecma.get(mode) ? 1 : 2; break;
3605 }
3606
3607 _bte_debug_print(BTE_DEBUG_MODES,do { } while(0)
3608 "Reporting mode %d (%s) is %d\n",do { } while(0)
3609 param, m_modes_ecma.mode_to_cstring(mode),do { } while(0)
3610 value)do { } while(0);
3611
3612 reply(seq, BTE_REPLY_DECRPM_ECMA, {param, value});
3613}
3614
3615void
3616Terminal::DECRQM_DEC(bte::parser::Sequence const& seq)
3617{
3618 /*
3619 * DECRQM_DEC - request-mode-dec
3620 * Same as DECRQM_ECMA but for DEC modes.
3621 *
3622 * References: VT525
3623 */
3624
3625 auto const param = seq.collect1(0);
3626 auto const mode = m_modes_private.mode_from_param(param);
3627
3628 int value;
3629 switch (mode) {
3630 case bte::terminal::modes::ECMA::eUNKNOWN: value = 0; break;
3631 case bte::terminal::modes::ECMA::eALWAYS_SET: value = 3; break;
3632 case bte::terminal::modes::ECMA::eALWAYS_RESET: value = 4; break;
3633 default: assert(mode >= 0)(static_cast <bool> (mode >= 0) ? void (0) : __assert_fail
("mode >= 0", "../src/bteseq.cc", 3633, __extension__ __PRETTY_FUNCTION__
))
; value = m_modes_private.get(mode) ? 1 : 2; break;
3634 }
3635
3636 _bte_debug_print(BTE_DEBUG_MODES,do { } while(0)
3637 "Reporting private mode %d (%s) is %d\n",do { } while(0)
3638 param, m_modes_private.mode_to_cstring(mode),do { } while(0)
3639 value)do { } while(0);
3640
3641 reply(seq, BTE_REPLY_DECRPM_DEC, {param, value});
3642}
3643
3644void
3645Terminal::DECRQPKFM(bte::parser::Sequence const& seq)
3646{
3647 /*
3648 * DECRQPKFM - request-program-key-free-memory
3649 *
3650 * References: VT525
3651 *
3652 * Probably not worth implementing.
3653 */
3654}
3655
3656void
3657Terminal::DECRQPSR(bte::parser::Sequence const& seq)
3658{
3659 /*
3660 * DECRQPSR - request-presentation-state-report
3661 * Requests a report of the terminal state, that can later
3662 * be restored with DECRSPS.
3663 *
3664 * References: VT525
3665 */
3666
3667 switch (seq.collect1(0)) {
3668 case -1:
3669 case 0:
3670 /* Error; ignore request */
3671 break;
3672
3673 case 1:
3674 /* Cursor information report. This contains:
3675 * - the cursor position, including character attributes and
3676 * character protection attribute,
3677 * - origin mode (DECOM),
3678 * - the character sets designated to the G0, G1, G2, and G3 sets.
3679 *
3680 * Reply: DECCIR
3681 * DATA: the report in a unspecified format
3682 * See WY370 for a possible format to use.
3683 */
3684 break;
3685
3686 case 2:
3687 /* Tabstop report.
3688 *
3689 * Reply: DECTABSR
3690 */
3691 break;
3692
3693 default:
3694 break;
3695 }
3696}
3697
3698void
3699Terminal::DECRQSS(bte::parser::Sequence const& seq)
3700{
3701 /*
3702 * DECRQSS - request selection or setting
3703 * The DATA string contains the intermediate(s) and final
3704 * character of a CSI sequence that codes for which
3705 * selection or setting to report.
3706 *
3707 * Reply: DECRPSS
3708 * @args[0]: 1 if the request was valid, otherwise 0
3709 * DATA: the current value of the selection or setting
3710 *
3711 * Note that the VT525 documentation is buggy, is says it
3712 * sends 0 for a valid and 1 or an invalid request; we
3713 * follow the STD 070 and XTERM behaviour.
3714 *
3715 * References: VT525
3716 */
3717
3718 /* Use a subparser to get the command from the request */
3719 bte::parser::Parser parser{};
3720 parser.feed(0x9b); /* CSI */
3721
3722 int rv = BTE_SEQ_NONE;
3723
3724 /* If at the end, the parser returns a BTE_SEQ_CSI sequence,
3725 * we interpret that; otherwise we ignore the request and
3726 * send only a dummy reply.
3727 * Note that this makes sure there is only one setting
3728 * requested; if there were more than one, the parser would
3729 * parse them as GRAPHIC and thus we reply 'invalid'.
3730 */
3731 auto const str = seq.string();
3732 size_t i;
3733 for (i = 0; i < str.size(); ++i) {
3734 auto const c = str[i];
3735 if (c < 0x20 || c >= 0x7f)
3736 break;
3737 rv = parser.feed(c);
3738 }
3739
3740 bte::parser::Sequence request{parser};
3741 /* If not the whole string was parsed, or the sequence
3742 * is not a CSI sequence, or it has parameters, reject
3743 * the request as invalid.
3744 */
3745 if (i != str.size() || rv != BTE_SEQ_CSI || request.size() > 0 /* any parameters */)
3746 return reply(seq, BTE_REPLY_DECRPSS, {0});
3747
3748 switch (request.command()) {
3749
3750 case BTE_CMD_DECSCUSR:
3751 return reply(seq, BTE_REPLY_DECRPSS, {1}, {BTE_REPLY_DECSCUSR, {int(m_cursor_style)}});
3752
3753 case BTE_CMD_DECSTBM:
3754 if (m_scrolling_restricted)
3755 return reply(seq, BTE_REPLY_DECRPSS, {1},
3756 {BTE_REPLY_DECSTBM,
3757 {m_scrolling_region.start + 1,
3758 m_scrolling_region.end + 1}});
3759 else
3760 return reply(seq, BTE_REPLY_DECRPSS, {1}, {BTE_REPLY_DECSTBM, {}});
3761
3762 case BTE_CMD_DECAC:
3763 case BTE_CMD_DECARR:
3764 case BTE_CMD_DECATC:
3765 case BTE_CMD_DECCRTST:
3766 case BTE_CMD_DECDLDA:
3767 case BTE_CMD_DECSACE:
3768 case BTE_CMD_DECSASD:
3769 case BTE_CMD_DECSCA:
3770 case BTE_CMD_DECSCL:
3771 case BTE_CMD_DECSCP:
3772 case BTE_CMD_DECSCPP:
3773 case BTE_CMD_DECSCS:
3774 case BTE_CMD_DECSDDT:
3775 case BTE_CMD_DECSDPT:
3776 case BTE_CMD_DECSEST:
3777 case BTE_CMD_DECSFC:
3778 case BTE_CMD_DECSKCV:
3779 case BTE_CMD_DECSLCK:
3780 case BTE_CMD_DECSLPP:
3781 case BTE_CMD_DECSLRM:
3782 case BTE_CMD_DECSMBV:
3783 case BTE_CMD_DECSNLS:
3784 case BTE_CMD_DECSPMA:
3785 case BTE_CMD_DECSPP:
3786 case BTE_CMD_DECSPPCS:
3787 case BTE_CMD_DECSPRTT:
3788 case BTE_CMD_DECSSCLS:
3789 case BTE_CMD_DECSSDT:
3790 case BTE_CMD_DECSSL:
3791 case BTE_CMD_DECSTGLT:
3792 case BTE_CMD_DECSTRL:
3793 case BTE_CMD_DECSWBV:
3794 case BTE_CMD_DECSZS:
3795 case BTE_CMD_DECTME:
3796 case BTE_CMD_SGR:
3797 default:
3798 return reply(seq, BTE_REPLY_DECRPSS, {0});
3799 }
3800}
3801
3802void
3803Terminal::DECRQTSR(bte::parser::Sequence const& seq)
3804{
3805 /*
3806 * DECRQTSR - request-terminal-state-report
3807 * Requests a report of the terminal state, that can later
3808 * be restored by DECRSTS.
3809 *
3810 * References: VT525
3811 */
3812
3813 switch (seq.collect1(0)) {
3814 case -1:
3815 case 0:
3816 /* Ignore */
3817 break;
3818
3819 case 1:
3820 /* Terminal state report.
3821 *
3822 * Reply: DECTSR
3823 * DATA: the report in an unspecified format
3824 */
3825 /* return reply(seq, BTE_REPLY_DECTSR, {1}, "FIXME"); */
3826 break;
3827
3828 case 2:
3829 /* Color table report.
3830 *
3831 * Arguments:
3832 * args[1]: color coordinate system
3833 * 0: invalid
3834 * 1: HLS (0…360, 0…100, 0…100)
3835 * 2: RGB (0…100, 0…100, 0…100) (yes, really!)
3836 *
3837 * Reply: DECTSR
3838 * DATA: the report
3839 */
3840 /* return reply(seq, BTE_REPLY_DECTSR, {2}, "FIXME"); */
3841 break;
3842
3843 default:
3844 break;
3845 }
3846}
3847
3848void
3849Terminal::DECRQUPSS(bte::parser::Sequence const& seq)
3850{
3851 /*
3852 * DECRQUPSS - request-user-preferred-supplemental-set
3853 * Requests the user-preferred supplemental set.
3854 *
3855 * Reply: DECAUPSS
3856 *
3857 * References: VT525
3858 *
3859 * Probably not worth implementing.
3860 */
3861
3862 // FIXMEchpe send a dummy reply?
3863}
3864
3865void
3866Terminal::DECRSPS(bte::parser::Sequence const& seq)
3867{
3868 /*
3869 * DECRSPS - restore presentation state
3870 * Restores terminal state from a DECRQPSR response.
3871 *
3872 * References: VT525
3873 */
3874
3875 switch (seq.collect1(0)) {
3876 case -1:
3877 case 0:
3878 /* Error; ignore */
3879 break;
3880
3881 case 1:
3882 /* Cursor information report*/
3883 break;
3884
3885 case 2:
3886 /* Tabstop report */
3887 break;
3888
3889 default:
3890 break;
3891 }
3892}
3893
3894void
3895Terminal::DECRSTS(bte::parser::Sequence const& seq)
3896{
3897 /*
3898 * DECRSTS - restore terminal state
3899 * Restore terminal state from a DECRQTSR response.
3900 *
3901 * References: VT525
3902 */
3903
3904 switch (seq.collect1(0)) {
3905 case -1:
3906 case 0:
3907 /* Ignore */
3908 break;
3909
3910 case 1:
3911 /* Terminal state report */
3912 break;
3913
3914 case 2:
3915 /* Color table report */
3916 break;
3917
3918 default:
3919 break;
3920 }
3921}
3922
3923void
3924Terminal::DECSACE(bte::parser::Sequence const& seq)
3925{
3926 /*
3927 * DECSACE - select-attribute-change-extent
3928 * Selects which positions a rectangle command (DECCARA, DECCRA,
3929 * DECERA, DECFRA, DECRARA, DECSERA) affects.
3930 *
3931 * Arguments:
3932 * args[0]:
3933 * 0, 1: the stream of positions beginning at the
3934 * (top, left) and ending at the (bottom, right)
3935 * position
3936 * 2: the positions in the rectangle with corners
3937 * (top, left) and (bottom, right)
3938 *
3939 * Defaults;
3940 * args[0]: 0
3941 *
3942 * References: VT525
3943 *
3944 * Not worth implementing unless we implement all the rectangle functions.
3945 */
3946}
3947
3948void
3949Terminal::DECSASD(bte::parser::Sequence const& seq)
3950{
3951 /*
3952 * DECSASD - select-active-status-display
3953 * Selects between main screen and status line.
3954 *
3955 * Arguments:
3956 * args[0]:
3957 * 0: main screen
3958 * 1: status line
3959 *
3960 * Defaults:
3961 * args[0]: 0
3962 *
3963 * References: VT525
3964 *
3965 * Probably not worth implementing.
3966 */
3967}
3968
3969void
3970Terminal::DECSC(bte::parser::Sequence const& seq)
3971{
3972 /*
3973 * DECSC - save-cursor
3974 * Save cursor and terminal state so it can be restored later on.
3975 * This stores:
3976 * * Cursor position
3977 * * SGR attributes
3978 * * Charset designations for GL and GR
3979 * * Wrap flag
3980 * * DECOM state
3981 * * Selective erase attribute
3982 * * Any SS2 or SS3 sent
3983 *
3984 * References: VT525
3985 */
3986#if 0
3987 screen_save_state(screen, &screen->saved);
3988#endif
3989
3990 save_cursor();
3991}
3992
3993void
3994Terminal::DECSCA(bte::parser::Sequence const& seq)
3995{
3996 /*
3997 * DECSCA - select character protection attribute
3998 * Sets whether characters inserted are protected or not.
3999 * Protected characters will not be erased by DECSED or DECSEL.
4000 * SGR attributes are unchanged.
4001 *
4002 * Arguments:
4003 * args[0]:
4004 * 0, 2: not protected
4005 * 1: protected
4006 *
4007 * Defaults:
4008 * args[0]: 0
4009 *
4010 * References: VT525
4011 */
4012#if 0
4013 unsigned int mode = 0;
4014
4015 if (seq->args[0] > 0)
4016 mode = seq->args[0];
4017
4018 switch (mode) {
4019 case 0:
4020 case 2:
4021 screen->state.attr.protect = 0;
4022 break;
4023 case 1:
4024 screen->state.attr.protect = 1;
4025 break;
4026 }
4027#endif
4028}
4029
4030void
4031Terminal::DECSCL(bte::parser::Sequence const& seq)
4032{
4033 /*
4034 * DECSCL - select-conformance-level
4035 * Select the terminal's operating level. The factory default is
4036 * level 4 (VT Level 4 mode, 7-bit controls).
4037 * When you change the conformance level, the terminal performs a hard
4038 * reset (RIS).
4039 *
4040 * @args[0] defines the conformance-level, valid values are:
4041 * 61: Level 1 (VT100)
4042 * 62: Level 2 (VT200)
4043 * 63: Level 3 (VT300)
4044 * 64: Level 4 (VT400)
4045 * @args[1] defines the 8bit-mode, valid values are:
4046 * 0: 8-bit controls
4047 * 1: 7-bit controls
4048 * 2: 8-bit controls (same as 0)
4049 *
4050 * If @args[0] is 61, then @args[1] is ignored and 7bit controls are
4051 * enforced.
4052 *
4053 * Defaults:
4054 * args[0]: 64
4055 * args[1]: 0
4056 *
4057 * References: VT525
4058 */
4059#if 0
4060 unsigned int level = 64, bit = 0;
4061
4062 if (seq->n_args > 0) {
4063 level = seq->args[0];
4064 if (seq->n_args > 1)
4065 bit = seq->args[1];
4066 }
4067
4068 bte_screen_hard_reset(screen);
4069
4070 switch (level) {
4071 case 61:
4072 screen->conformance_level = BTE_CONFORMANCE_LEVEL_VT100;
4073 screen->flags |= BTE_FLAG_7BIT_MODE;
4074 break;
4075 case 62 ... 69:
4076 screen->conformance_level = BTE_CONFORMANCE_LEVEL_VT400;
4077 if (bit == 1)
4078 screen->flags |= BTE_FLAG_7BIT_MODE;
4079 else
4080 screen->flags &= ~BTE_FLAG_7BIT_MODE;
4081 break;
4082 }
4083#endif
4084}
4085
4086void
4087Terminal::DECSCP(bte::parser::Sequence const& seq)
4088{
4089 /*
4090 * DECSCP - select-communication-port
4091 *
4092 * References: VT525
4093 *
4094 * Probably not worth implementing.
4095 */
4096}
4097
4098void
4099Terminal::DECSCPP(bte::parser::Sequence const& seq)
4100{
4101 /*
4102 * DECSCPP - select-columns-per-page
4103 * Select columns per page. The number of rows is unaffected by this.
4104 * @args[0] selectes the number of columns (width), DEC only defines 80
4105 * and 132, but we allow any integer here. 0 is equivalent to 80.
4106 * Page content is *not* cleared and the cursor is left untouched.
4107 * However, if the page is reduced in width and the cursor would be
4108 * outside the visible region, it's set to the right border. Newly added
4109 * cells are cleared. No data is retained outside the visible region.
4110 *
4111 * Defaults:
4112 * args[0]: 0
4113 *
4114 * References: VT525
4115 *
4116 * FIXMEchpe: implement this instead of deprecated DECCOLM
4117 */
4118}
4119
4120void
4121Terminal::DECSCS(bte::parser::Sequence const& seq)
4122{
4123 /*
4124 * DECSCS - select-communication-speed
4125 *
4126 * References: VT525
4127 *
4128 * Probably not worth implementing.
4129 */
4130}
4131
4132void
4133Terminal::DECSCUSR(bte::parser::Sequence const& seq)
4134{
4135 /*
4136 * DECSCUSR - set-cursor-style
4137 * This changes the style of the cursor. @args[0] can be one of:
4138 * 0, 1: blinking block
4139 * 2: steady block
4140 * 3: blinking underline
4141 * 4: steady underline
4142 * 5: blinking ibeam (XTERM)
4143 * 6: steady ibeam (XTERM)
4144 * Changing this setting does _not_ affect the cursor visibility itself.
4145 * Use DECTCEM for that.
4146 *
4147 * Defaults:
4148 * args[0]: 0
4149 *
4150 * References: VT525 5–126
4151 * XTERM
4152 */
4153
4154 auto param = seq.collect1(0, 0);
4155 switch (param) {
4156 case 0 ... 6:
4157 set_cursor_style(CursorStyle(param));
4158 break;
4159 default:
4160 break;
4161 }
4162}
4163
4164void
4165Terminal::DECSDDT(bte::parser::Sequence const& seq)
4166{
4167 /*
4168 * DECSDDT - select-disconnect-delay-time
4169 *
4170 * References: VT525
4171 *
4172 * Probably not worth implementing.
4173 */
4174}
4175
4176void
4177Terminal::DECSDPT(bte::parser::Sequence const& seq)
4178{
4179 /*
4180 * DECSDPT - select-digital-printed-data-type
4181 *
4182 * References: VT525
4183 *
4184 * Probably not worth implementing.
4185 */
4186}
4187
4188void
4189Terminal::DECSED(bte::parser::Sequence const& seq)
4190{
4191 /*
4192 * DECSED - selective-erase-in-display
4193 * This control function erases some or all of the erasable characters
4194 * in the display. DECSED can only erase characters defined as erasable
4195 * by the DECSCA control function. DECSED works inside or outside the
4196 * scrolling margins.
4197 *
4198 * @args[0] defines which regions are erased. If it is 0, all cells from
4199 * the cursor (inclusive) till the end of the display are erase. If it
4200 * is 1, all cells from the start of the display till the cursor
4201 * (inclusive) are erased. If it is 2, all cells are erased.
4202 *
4203 * Defaults:
4204 * args[0]: 0
4205 */
4206
4207 erase_in_display(seq);
4208}
4209
4210void
4211Terminal::DECSEL(bte::parser::Sequence const& seq)
4212{
4213 /*
4214 * DECSEL - selective-erase-in-line
4215 * This control function erases some or all of the erasable characters
4216 * in a single line of text. DECSEL erases only those characters defined
4217 * as erasable by the DECSCA control function. DECSEL works inside or
4218 * outside the scrolling margins.
4219 *
4220 * @args[0] defines the region to be erased. If it is 0, all cells from
4221 * the cursor (inclusive) till the end of the line are erase. If it is
4222 * 1, all cells from the start of the line till the cursor (inclusive)
4223 * are erased. If it is 2, the whole line of the cursor is erased.
4224 *
4225 * Defaults:
4226 * args[0]: 0
4227 */
4228
4229 erase_in_line(seq);
4230}
4231
4232void
4233Terminal::DECSERA(bte::parser::Sequence const& seq)
4234{
4235 /*
4236 * DECSERA - selective-erase-rectangular-area
4237 * Selectively erases characters in the specified rectangle,
4238 * replacing them with SPACE (2/0). Character attributes,
4239 * protection attribute (DECSCA) and line attributes (DECDHL,
4240 * DECDWL) are unchanged.
4241 *
4242 * Arguments;
4243 * args[0..3]: top, left, bottom, right of the source rectangle (1-based)
4244 *
4245 * Defaults:
4246 * args[0]: 1
4247 * args[1]: 1
4248 * args[2]: height of current page
4249 * args[3]: width of current page
4250 *
4251 * If the top > bottom or left > right the command is ignored.
4252 *
4253 * These coordinates are interpreted according to origin mode (DECOM),
4254 * but unaffected by the page margins (DECSLRM?). Current SGR defaults
4255 * and cursor position are unchanged.
4256 *
4257 * Note: DECSACE selects whether this function operates on the
4258 * rectangular area or the data stream between the star and end
4259 * positions.
4260 *
4261 * References: VT525
4262 *
4263 * Probably not worth implementing.
4264 */
4265}
4266
4267void
4268Terminal::DECSEST(bte::parser::Sequence const& seq)
4269{
4270 /*
4271 * DECSEST - energy saver time
4272 * Sets the enerty saver timer. When DECCRTSM is set, the
4273 * screen switches to suspend mode when the time elapsed
4274 * since the last keystroke or output is greater than the
4275 * time set here.
4276 *
4277 * Arguments:
4278 * args[0]: the time in minutes (0…60) (0 = never)
4279 *
4280 * Default: 15
4281 *
4282 * References: VT525
4283 *
4284 * Probably not worth implementing.
4285 */
4286}
4287
4288void
4289Terminal::DECSFC(bte::parser::Sequence const& seq)
4290{
4291 /*
4292 * DECSFC - select-flow-control
4293 *
4294 * References: VT525
4295 *
4296 * Probably not worth implementing.
4297 */
4298}
4299
4300void
4301Terminal::DECSGR(bte::parser::Sequence const& seq)
4302{
4303 /*
4304 * DECSGR - DEC select graphics rendition
4305 * Selects the character attributes to use for newly inserted
4306 * characters.
4307 *
4308 * Arguments:
4309 * args[0:]: the attributes
4310 * 0 = reset all attributes (deprecated; same as SGR 0)
4311 * 4 = set superscript and reset subscript
4312 * 5 = set subscript and reset superscript
4313 * 6 = set overline (deprecated; same as SGR 53)
4314 * 8 = set transparency mode
4315 * 24 = reset superscript and subscript
4316 * 26 = reset overline (deprecated; same as SGR 55)
4317 * 28 = reset transparency mode
4318 *
4319 * Defaults:
4320 * args[0]: 0 (reset all attributes)
4321 *
4322 * References: DEC PPLV2
4323 * DEC LJ250
4324 */
4325 /* TODO: consider implementing sub/superscript? */
4326}
4327
4328void
4329Terminal::DECSIXEL(bte::parser::Sequence const& seq)
4330{
4331 /*
4332 * DECSIXEL - SIXEL graphics
4333 *
4334 * References: VT330
4335 */
4336}
4337
4338void
4339Terminal::DECSKCV(bte::parser::Sequence const& seq)
4340{
4341 /*
4342 * DECSKCV - set-key-click-volume
4343 * Sets the key click volume.
4344 *
4345 * Arguments:
4346 * args[0]: the volume setting
4347 * 0, 5…8: high
4348 * 1: off
4349 * 2…4: low
4350 *
4351 * Defaults:
4352 * args[0]: 0
4353 *
4354 * References: VT525
4355 *
4356 * Probably not worth implementing.
4357 */
4358}
4359
4360void
4361Terminal::DECSLCK(bte::parser::Sequence const& seq)
4362{
4363 /*
4364 * DECSLCK - set-lock-key-style
4365 * Allow host control of the CapsLock key
4366 *
4367 * References: VT525
4368 *
4369 * Probably not worth implementing.
4370 */
4371}
4372
4373void
4374Terminal::DECSLE(bte::parser::Sequence const& seq)
4375{
4376 /*
4377 * DECSLE - select-locator-events
4378 *
4379 * References: VT330
4380 *
4381 * TODO: implement
4382 */
4383}
4384
4385void
4386Terminal::DECSLPP(bte::parser::Sequence const& seq)
4387{
4388 /*
4389 * DECSLPP - set-lines-per-page
4390 * Set the number of lines per page.
4391 *
4392 * Arguments:
4393 * args[0]: the number of lines per page
4394 *
4395 * Defaults:
4396 * args[0]: 0 (meaning 24)
4397 *
4398 * Note that VT525 only allows a limited number of choices,
4399 * (24, 25, 36, 41, 42, 48, 52, 53, 72); BTE is not so limited
4400 * and supports any value >= 24.
4401 *
4402 * Top and bottom scrolling margins are unaffected, unless their
4403 * current values exceed the new page size, in which case they are
4404 * reset to the default.
4405 *
4406 * References: VT525
4407 */
4408
4409 auto param = seq.collect1(0);
4410 if (param == 0)
4411 param = 24;
4412 else if (param < 24)
4413 return;
4414
4415 _bte_debug_print(BTE_DEBUG_EMULATION, "Resizing to %d rows.\n", param)do { } while(0);
4416
4417 emit_resize_window(m_column_count, param);
4418}
4419
4420void
4421Terminal::DECSLRM(bte::parser::Sequence const& seq)
4422{
4423 /*
4424 * DECSLRM - set left and right margins
4425 * Sets the left and right margins of the scrolling region.
4426 * This is only applicable if the vertical split-screen mode
4427 * (DECLRMM) is set.
4428 *
4429 * Arguments:
4430 * args[0]: left margin
4431 * args[1]: right margin
4432 *
4433 * Default:
4434 * args[0]: 1
4435 * args[2]: page width
4436 *
4437 * If left > right, the command is ignored.
4438 * The maximum of right is the page size (set with DECSCPP);
4439 * the minimum size of the scrolling region is 2 columns.
4440 *
4441 * Homes to cursor to (1,1) of the page (scrolling region?).
4442 *
4443 * References: VT525
4444 *
4445 * FIXMEchpe: Consider implementing this.
4446 */
4447}
4448
4449void
4450Terminal::DECSLRM_OR_SCOSC(bte::parser::Sequence const& seq)
4451{
4452 /*
4453 * set left and right margins or SCO restore cursor - DECSLRM or SCOSC
4454 * There is a conflict between SCOSC and DECSLRM that both are
4455 * CSI s (CSI 7/3). SCOSC has 0 parameters, and DECSLRM has 2
4456 * parameters which both have default values, and my reading
4457 * of ECMA-48 § 5.4.2h says that this allows for an empty
4458 * parameter string to represent them.
4459 *
4460 * While the DEC manuals say that SCOSC/SCORC only operates in
4461 * "SCO Console Mode" (which is entered by DECTME 13), and not in
4462 * "VT mode" (i.e. native mode), we instead distinguish the cases
4463 * by private mode DECLRMM: If DECLRMM is set, dispatch DECSLRM;
4464 * if it's reset, dispatch SCOSC.
4465 *
4466 * See issue #48.
4467 */
4468
4469#ifdef PARSER_INCLUDE_NOP
4470 if (m_modes_private.DECLRMM())
4471 DECSLRM(seq);
4472 else
4473#endif
4474 SCOSC(seq);
4475}
4476
4477void
4478Terminal::DECSMBV(bte::parser::Sequence const& seq)
4479{
4480 /*
4481 * DECSMBV - set-margin-bell-volume
4482 * Sets the margin bell volume.
4483 *
4484 * Arguments:
4485 * args[0]: the volume setting
4486 * 0, 1: off
4487 * 2…4: low
4488 * 5…8: high
4489 *
4490 * Defaults:
4491 * args[0]: 0
4492 *
4493 * References: VT525
4494 *
4495 * Probably not worth implementing.
4496 */
4497}
4498
4499void
4500Terminal::DECSMKR(bte::parser::Sequence const& seq)
4501{
4502 /*
4503 * DECSMKR - select-modifier-key-reporting
4504 * Make modifier keys send extended keyboard reports (DECEKBD)
4505 * when pressed or released in key position mode (DECKPM).
4506 * [...]
4507 *
4508 * References: VT525
4509 *
4510 * Probably not worth implementing.
4511 */
4512}
4513
4514void
4515Terminal::DECSNLS(bte::parser::Sequence const& seq)
4516{
4517 /*
4518 * DECSNLS - set-lines-per-screen
4519 * Sets the number of lines per screen.
4520 * DEC only supports 26, 42, 53 lines here; but BTE has no
4521 * such restriction.
4522 *
4523 * Arguments:
4524 * args[0]: the number of lines
4525 *
4526 * Defaults:
4527 * args[0]: no default
4528 *
4529 * References: VT525
4530 *
4531 * FIXMEchpe: implement this
4532 */
4533}
4534
4535void
4536Terminal::DECSPMA(bte::parser::Sequence const& seq)
4537{
4538 /*
4539 * DECSPMA - session page memory allocation
4540 * Allocate pages of 25 lines to each session.
4541 *
4542 * References: VT525
4543 *
4544 * BTE does not support sessions.
4545 */
4546}
4547
4548void
4549Terminal::DECSPP(bte::parser::Sequence const& seq)
4550{
4551 /*
4552 * DECSPP - set-port-parameter
4553 * Sets parameters for the communications or printer port.
4554 * [...]
4555 *
4556 * References: VT525
4557 *
4558 * Probably not worth implementing.
4559 */
4560}
4561
4562void
4563Terminal::DECSPPCS(bte::parser::Sequence const& seq)
4564{
4565 /*
4566 * DECSPPCS - select-pro-printer-character-set
4567 * [...]
4568 *
4569 * References: VT525
4570 *
4571 * Probably not worth implementing.
4572 */
4573}
4574
4575void
4576Terminal::DECSPRTT(bte::parser::Sequence const& seq)
4577{
4578 /*
4579 * DECSPRTT - select-printer-type
4580 * [...]
4581 *
4582 * References: VT525
4583 *
4584 * Probably not worth implementing.
4585 */
4586}
4587
4588void
4589Terminal::DECSR(bte::parser::Sequence const& seq)
4590{
4591 /*
4592 * DECSR - secure-reset
4593 * Hard reset, with confirmation.
4594 * Like RIS, but the terminal replies with the token.
4595 * [long list of things this resets]
4596 *
4597 * Arguments:
4598 * args[0]: a token
4599 *
4600 * Defaults:
4601 * args[0]: no default
4602 *
4603 * Reply: DECSRC
4604 * args[0]: the token
4605 *
4606 * References: VT525
4607 */
4608
4609 /* Note: reset() wipes out @seq, so we need to get the
4610 * param beforehand, and use send() instead of reply().
4611 */
4612 auto const token = seq.collect1(0);
4613 reset(true, true);
4614 send(BTE_REPLY_DECSRC, {token});
4615}
4616
4617void
4618Terminal::DECSRFR(bte::parser::Sequence const& seq)
4619{
4620 /*
4621 * DECSRFR - select-refresh-rate
4622 * [...]
4623 *
4624 * References: VT510
4625 *
4626 * Probably not worth implementing.
4627 */
4628}
4629
4630void
4631Terminal::DECSSCLS(bte::parser::Sequence const& seq)
4632{
4633 /*
4634 * DECSSCLS - set-scroll-speed
4635 * [...]
4636 *
4637 * References: VT525
4638 *
4639 * Probably not worth implementing.
4640 */
4641}
4642
4643void
4644Terminal::DECSSDT(bte::parser::Sequence const& seq)
4645{
4646 /*
4647 * DECSSDT - select-status-display-line-type
4648 * Sets the type of status line shown.
4649 *
4650 * Arguments:
4651 * args[0]: the type
4652 * 0: no status line
4653 * 1: indicator status line
4654 * 2: host-writable status line
4655 *
4656 * Defaults:
4657 * args[0]: 0
4658 *
4659 * References: VT525
4660 *
4661 * Not worth implementing.
4662 */
4663}
4664
4665void
4666Terminal::DECSSL(bte::parser::Sequence const& seq)
4667{
4668 /*
4669 * DECSSL - select-setup-language
4670 *
4671 * Selects set-up language
4672 *
4673 * References: VT525
4674 *
4675 * BTE does not implement a set-up.
4676 *
4677 * or:
4678 *
4679 * WYDRBX - draw a box
4680 *
4681 * References: WY370
4682 */
4683}
4684
4685void
4686Terminal::DECST8C(bte::parser::Sequence const& seq)
4687{
4688 /*
4689 * DECST8C - set-tab-at-every-8-columns
4690 * Clear the tab-ruler and reset it to a tab at every 8th column,
4691 * starting at 9 (though, setting a tab at 1 is fine as it has no
4692 * effect).
4693 *
4694 * References: VT525
4695 */
4696
4697 if (seq.collect1(0) != 5)
4698 return;
4699
4700 m_tabstops.reset(8);
4701 m_tabstops.unset(0);
4702}
4703
4704void
4705Terminal::DECSTBM(bte::parser::Sequence const& seq)
4706{
4707 /*
4708 * DECSTBM - set-top-and-bottom-margins
4709 * Sets the top and bottom scrolling margins.
4710 * Arguments:
4711 * args[0]: the top margin
4712 * args[1]: the bottom margin
4713 *
4714 * Defaults:
4715 * args[0]: 1
4716 * args[1]: number of lines
4717 *
4718 * If top > bottom, the command is ignored.
4719 * The maximum size of the scrolling region is the whole page.
4720 * Homes the cursor to position (1,1) (of the scrolling region?).
4721 *
4722 * References: VT525 5–149
4723 */
4724#if 0
4725 unsigned int top, bottom;
4726
4727 top = 1;
4728 bottom = screen->page->height;
4729
4730 if (seq->args[0] > 0)
4731 top = seq->args[0];
4732 if (seq->args[1] > 0)
4733 bottom = seq->args[1];
4734
4735 if (top > screen->page->height)
4736 top = screen->page->height;
4737 if (bottom > screen->page->height)
4738 bottom = screen->page->height;
4739
4740 if (top >= bottom ||
4741 top > screen->page->height ||
4742 bottom > screen->page->height) {
4743 top = 1;
4744 bottom = screen->page->height;
4745 }
4746
4747 bte_page_set_scroll_region(screen->page, top - 1, bottom - top + 1);
4748 screen_cursor_clear_wrap(screen);
4749 screen_cursor_set(screen, 0, 0);
4750#endif
4751
4752 int start, end;
1
'start' declared without an initial value
4753 seq.collect(0, {&start, &end});
4754
4755 /* Defaults */
4756 if (start <= 0)
2
The left operand of '<=' is a garbage value
4757 start = 1;
4758 if (end == -1)
4759 end = m_row_count;
4760
4761 if (start > m_row_count ||
4762 end <= start) {
4763 m_scrolling_restricted = FALSE(0);
4764 home_cursor();
4765 return;
4766 }
4767
4768 if (end > m_row_count)
4769 end = m_row_count;
4770
4771 /* Set the right values. */
4772 m_scrolling_region.start = start - 1;
4773 m_scrolling_region.end = end - 1;
4774 m_scrolling_restricted = TRUE(!(0));
4775 if (m_scrolling_region.start == 0 &&
4776 m_scrolling_region.end == m_row_count - 1) {
4777 /* Special case -- run wild, run free. */
4778 m_scrolling_restricted = FALSE(0);
4779 } else {
4780 /* Maybe extend the ring -- bug 710483 */
4781 while (_bte_ring_next(m_screen->row_data) < m_screen->insert_delta + m_row_count)
4782 _bte_ring_insert(m_screen->row_data, _bte_ring_next(m_screen->row_data), get_bidi_flags());
4783 }
4784
4785 home_cursor();
4786}
4787
4788void
4789Terminal::DECSTGLT(bte::parser::Sequence const& seq)
4790{
4791 /*
4792 * DECSTGLT - select color lookup table
4793 * Selects color mapping.
4794 *
4795 * Arguments:
4796 * args[0]: mode
4797 * 0: Text colors are shown in monochrome or grey levels
4798 * 1: Text attributes (bold, blink, reverse, (single) underline,
4799 * and any combinations thereof) are shown with alternate
4800 * colors (defined by set-up), plus the attribute
4801 * 2: Like 1, but attributes are only represented by the color
4802 * 3: Text color as specified by SGR, and attributes
4803 * as specified.
4804 *
4805 * Defaults:
4806 * args[0]: 3
4807 *
4808 * Set-up default: 3
4809 *
4810 * References: VT525
4811 *
4812 * Maybe worth implementing.
4813 */
4814}
4815
4816void
4817Terminal::DECSTR(bte::parser::Sequence const& seq)
4818{
4819 /*
4820 * DECSTR - soft-terminal-reset
4821 * Perform a soft reset to the default values.
4822 * [list of default values]
4823 *
4824 * References: VT525
4825 */
4826
4827 reset(false, false);
4828}
4829
4830void
4831Terminal::DECSTRL(bte::parser::Sequence const& seq)
4832{
4833 /*
4834 * DECSTRL - set-transmit-rate-limit
4835 *
4836 * References: VT525
4837 *
4838 * Probably not worth implementing.
4839 */
4840}
4841
4842void
4843Terminal::DECSTUI(bte::parser::Sequence const& seq)
4844{
4845 /*
4846 * DECSTUI - set terminal unit ID
4847 * Sets the terminal unit ID that DA3 reports.
4848 *
4849 * References: VT525
4850 *
4851 * BTE does not implement this.
4852 */
4853}
4854
4855void
4856Terminal::DECSWBV(bte::parser::Sequence const& seq)
4857{
4858 /*
4859 * DECSWBV - set-warning-bell-volume
4860 * Sets the warning bell volume.
4861 *
4862 * Arguments:
4863 * args[0]: the volume setting
4864 * 0, 5…8: high
4865 * 1: off
4866 * 2…4: low
4867 *
4868 * Defaults:
4869 * args[0]: 0
4870 *
4871 * References: VT525
4872 *
4873 * Probably not worth implementing.
4874 */
4875}
4876
4877void
4878Terminal::DECSWL(bte::parser::Sequence const& seq)
4879{
4880 /*
4881 * DECSWL - single-width-single-height-line
4882 *
4883 * References: VT525
4884 *
4885 * Probably not worth implementing.
4886 */
4887}
4888
4889void
4890Terminal::DECSZS(bte::parser::Sequence const& seq)
4891{
4892 /*
4893 * DECSZS - select zero symbol
4894 * Selects the zero glyph shape.
4895 *
4896 * Aguments:
4897 * args[0]: shape
4898 * 0: oval zero
4899 * 1: zero with slash
4900 * 2: zero with dot
4901 *
4902 * Default:
4903 * args[0]: 0
4904 *
4905 * References: VT525
4906 *
4907 * Maybe worth implementing; could use the opentype "zero" feature
4908 * to get the slashed zero.
4909 */
4910}
4911
4912void
4913Terminal::DECTID(bte::parser::Sequence const& seq)
4914{
4915 /*
4916 * DECTID - select-terminal-id
4917 * Selects the response to DA1.
4918 * [...]
4919 *
4920 * References: VT525
4921 *
4922 * Probably not worth implementing.
4923 */
4924}
4925
4926void
4927Terminal::DECTME(bte::parser::Sequence const& seq)
4928{
4929 /*
4930 * DECTME - terminal-mode-emulation
4931 * Selects the terminal emulation mode.
4932 * Available values are various VTxxx, Wyse, TVI, ADDS, SCO
4933 * terminals.
4934 * Changing the emulation mode effects a soft reset.
4935 *
4936 * References: VT525
4937 *
4938 * Not worth implementing.
4939 */
4940}
4941
4942void
4943Terminal::DECTST(bte::parser::Sequence const& seq)
4944{
4945 /*
4946 * DECTST - invoke-confidence-test
4947 * Executes self-tests.
4948 *
4949 * Arguments:
4950 * args[0]: 4
4951 * args[1]: which test to perform
4952 *
4953 * References: VT525
4954 *
4955 * Not worth implementing.
4956 */
4957}
4958
4959void
4960Terminal::DECUDK(bte::parser::Sequence const& seq)
4961{
4962 /*
4963 * DECUDK - user define keys
4964 * Loads key definitions.
4965 *
4966 * References: VT525
4967 *
4968 * For security reasons, BTE does not implement this.
4969 */
4970}
4971
4972void
4973Terminal::DECUS(bte::parser::Sequence const& seq)
4974{
4975 /*
4976 * DECUS - update session
4977 *
4978 * References: VT525
4979 *
4980 * BTE does not support sessions.
4981 */
4982}
4983
4984void
4985Terminal::DL(bte::parser::Sequence const& seq)
4986{
4987 /*
4988 * DL - delete-line
4989 * Delete lines starting from the active line (presentation).
4990 *
4991 * Depending on DCSM, this function works on the presentation
4992 * or data position. Terminal-wg/bidi forces DCSM to DATA.
4993 *
4994 * Also affected by TSM and VEM modes, and the SLH and SEE
4995 * functions.
4996 *
4997 * Arguments:
4998 * args[0]: number of lines to delete
4999 *
5000 * Defaults:
5001 * args[0]: 1
5002 *
5003 * References: ECMA-48 § 8.3.32
5004 * DEC STD 070 page 5-148
5005 * Terminal-wg/bidi
5006 */
5007#if 0
5008 unsigned int num = 1;
5009
5010 if (seq->args[0] > 0)
5011 num = seq->args[0];
5012
5013 bte_page_delete_lines(screen->page,
5014 screen->state.cursor_y,
5015 num,
5016 &screen->state.attr,
5017 screen->age);
5018#endif
5019
5020 auto const count = seq.collect1(0, 1);
5021 delete_lines(count);
5022}
5023
5024void
5025Terminal::DLE(bte::parser::Sequence const& seq)
5026{
5027 /*
5028 * DLE - data link escape
5029 * Supplementary transmission control functions.
5030 *
5031 * References: ECMA-48 § 8.3.33
5032 * ECMA-16 § 3.1.7
5033 * ECMA-37
5034 *
5035 * Not worth implementing.
5036 */
5037}
5038
5039void
5040Terminal::DMI(bte::parser::Sequence const& seq)
5041{
5042 /*
5043 * DMI - disable manual input
5044 *
5045 * References: ECMA-48 § 8.3.34
5046 *
5047 * Probably not worth implementing.
5048 */
5049}
5050
5051void
5052Terminal::DOCS(bte::parser::Sequence const& seq)
5053{
5054 /*
5055 * DOCS - designate other coding systyem
5056 *
5057 * References: ECMA-35 § 15.4
5058 * ISO 2375 IR
5059 *
5060 * TODO: implement (bug #787228)
5061 */
5062}
5063
5064void
5065Terminal::DSR_ECMA(bte::parser::Sequence const& seq)
5066{
5067 /*
5068 * DSR_ECMA - Device Status Report
5069 *
5070 * Reports status, or requests a status report.
5071 *
5072 * Arguments:
5073 * args[0]: type
5074 *
5075 * Defaults:
5076 * arg[0]: 0
5077 *
5078 * References: ECMA-48 § 8.3.35
5079 */
5080
5081 switch (seq.collect1(0)) {
5082 case -1:
5083 case 0:
5084 case 1:
5085 case 2:
5086 case 3:
5087 case 4:
5088 /* This is a status report */
5089 break;
5090
5091 case 5:
5092 /* Request operating status report.
5093 * Reply: DSR
5094 * @arg[0]: status
5095 * 0 = ok
5096 * 3 = malfunction
5097 */
5098 reply(seq, BTE_REPLY_DSR, {0});
5099 break;
5100
5101 case 6:
5102 /* Request cursor position report
5103 * Reply: CPR
5104 * @arg[0]: line
5105 * @arg[1]: column
5106 */
5107 bte::grid::row_t rowval, origin, rowmax;
5108 if (m_modes_private.DEC_ORIGIN() &&
5109 m_scrolling_restricted) {
5110 origin = m_scrolling_region.start;
5111 rowmax = m_scrolling_region.end;
5112 } else {
5113 origin = 0;
5114 rowmax = m_row_count - 1;
5115 }
5116 // FIXMEchpe this looks wrong. shouldn't this first clamp to origin,rowmax and *then* subtract origin?
5117 rowval = m_screen->cursor.row - m_screen->insert_delta - origin;
5118 rowval = CLAMP(rowval, 0, rowmax)(((rowval) > (rowmax)) ? (rowmax) : (((rowval) < (0)) ?
(0) : (rowval)))
;
5119
5120 reply(seq, BTE_REPLY_CPR,
5121 {int(rowval + 1), int(CLAMP(m_screen->cursor.col + 1, 1, m_column_count)(((m_screen->cursor.col + 1) > (m_column_count)) ? (m_column_count
) : (((m_screen->cursor.col + 1) < (1)) ? (1) : (m_screen
->cursor.col + 1)))
)});
5122 break;
5123
5124 default:
5125 break;
5126 }
5127}
5128
5129void
5130Terminal::DSR_DEC(bte::parser::Sequence const& seq)
5131{
5132 /*
5133 * DSR_DEC - device-status-report-dec
5134 *
5135 * Reports status, or requests a status report.
5136 *
5137 * Defaults:
5138 * arg[0]: 0
5139 *
5140 * References: VT525 5–173
5141 * VT330
5142 * XTERM
5143 */
5144
5145 switch (seq.collect1(0)) {
5146 case 6:
5147 /* Request extended cursor position report
5148 * Reply: DECXCPR
5149 * @arg[0]: line
5150 * @arg[1]: column
5151 * @arg[2]: page
5152 * Always report page 1 here (per XTERM source code).
5153 */
5154 bte::grid::row_t rowval, origin, rowmax;
5155 if (m_modes_private.DEC_ORIGIN() &&
5156 m_scrolling_restricted) {
5157 origin = m_scrolling_region.start;
5158 rowmax = m_scrolling_region.end;
5159 } else {
5160 origin = 0;
5161 rowmax = m_row_count - 1;
5162 }
5163 // FIXMEchpe this looks wrong. shouldn't this first clamp to origin,rowmax and *then* subtract origin?
5164 rowval = m_screen->cursor.row - m_screen->insert_delta - origin;
5165 rowval = CLAMP(rowval, 0, rowmax)(((rowval) > (rowmax)) ? (rowmax) : (((rowval) < (0)) ?
(0) : (rowval)))
;
5166
5167 reply(seq, BTE_REPLY_DECXCPR,
5168 {int(rowval + 1), int(CLAMP(m_screen->cursor.col + 1, 1, m_column_count)(((m_screen->cursor.col + 1) > (m_column_count)) ? (m_column_count
) : (((m_screen->cursor.col + 1) < (1)) ? (1) : (m_screen
->cursor.col + 1)))
), 1});
5169 break;
5170
5171 case 15:
5172 /* Request printer port report
5173 * Reply: DECDSR
5174 * @arg[0]: status
5175 * 10 = printer ready
5176 * 11 = printer not ready
5177 * 13 = no printer
5178 * 18 = printer busy
5179 * 19 = printer assigned to another session
5180 */
5181 reply(seq, BTE_REPLY_DECDSR, {13});
5182 break;
5183
5184 case 25:
5185 /* Request user-defined keys report
5186 * Reply: DECDSR
5187 * @arg[0]: locked status
5188 * 20 = UDK unlocked
5189 * 21 = UDK locked
5190 *
5191 * Since we don't do UDK, we report them as locked.
5192 */
5193 reply(seq, BTE_REPLY_DECDSR, {21});
5194 break;
5195
5196 case 26:
5197 /* Request keyboard report
5198 * Reply: DECDSR
5199 * @arg[0]: 27
5200 * @arg[1]: Keyboard language
5201 * 0 = undetermined
5202 * 1..40
5203 *
5204 * @arg[2]: Keyboard status
5205 * 0 = ready
5206 * 3 = no keyboard
5207 * 8 = keyboard busy (used by other session)
5208 *
5209 * @arg[3]: Keyboard type
5210 * 0 = LK201 (XTERM response)
5211 * 4 = LK411
5212 * 5 = PCXAL
5213 */
5214 reply(seq, BTE_REPLY_DECDSR, {27, 0, 0, 5});
5215 break;
5216
5217 case 53:
5218 /* XTERM alias for 55 */
5219 [[fallthrough]];
5220 case 55:
5221 /* Request locator status report
5222 * Reply: DECDSR
5223 * @arg[0]: status
5224 * 50 = locator ready
5225 * 53 = no locator
5226 *
5227 * Since we don't implement the DEC locator mode,
5228 * we reply with 53.
5229 */
5230 reply(seq, BTE_REPLY_DECDSR, {53});
5231 break;
5232
5233 case 56:
5234 /* Request locator type report
5235 * Reply: DECDSR
5236 * @arg[0]: 57
5237 * @arg[1]: status
5238 * 0 = unknown
5239 * 1 = mouse
5240 *
5241 * Since we don't implement the DEC locator mode,
5242 * we reply with 0.
5243 */
5244 reply(seq, BTE_REPLY_DECDSR, {57, 0});
5245 break;
5246
5247 case 62:
5248 /* Request macro space report
5249 * Reply: DECMSR
5250 * @arg[0]: floor((number of bytes available) / 16); we report 0
5251 */
5252 reply(seq, BTE_REPLY_DECMSR, {0});
5253 break;
5254
5255 case 63:
5256 /* Request memory checksum report
5257 * Reply: DECCKSR
5258 * @arg[0]: PID
5259 * DATA: the checksum as a 4-digit hex number
5260 *
5261 * Reply with a dummy checksum.
5262 */
5263 reply(seq, BTE_REPLY_DECCKSR, {seq.collect1(1)}, "0000");
5264 break;
5265
5266 case 75:
5267 /* Request data integrity report
5268 * Reply: DECDSR
5269 * @arg[0]: status
5270 * 70 = no error, no power loss, no communication errors
5271 * 71 = malfunction or communication error
5272 * 73 = no data loss since last power-up
5273 */
5274 reply(seq, BTE_REPLY_DECDSR, {70});
5275 break;
5276
5277 case 85:
5278 /* Request multi-session status report
5279 * Reply: DECDSR
5280 * @arg[0]: status
5281 * ...
5282 * 83 = not configured
5283 */
5284 reply(seq, BTE_REPLY_DECDSR, {83});
5285 break;
5286
5287 default:
5288 break;
5289 }
5290}
5291
5292void
5293Terminal::DTA(bte::parser::Sequence const& seq)
5294{
5295 /*
5296 * DTA - dimension text area
5297 * Set the dimension of the text area.
5298 *
5299 * Arguments:
5300 * args[0]:
5301 * args[1]:
5302 *
5303 * Defaults:
5304 * args[0]: no default
5305 * args[0]: no default
5306 *
5307 * References: ECMA-48 § 8.3.36
5308 */
5309}
5310
5311void
5312Terminal::EA(bte::parser::Sequence const& seq)
5313{
5314 /*
5315 * EA - erase in area
5316 * Erase some/all character positions in the qualified area.
5317 *
5318 * Arguments:
5319 * args[0]: type
5320 * 0 = Erase the active position and all positions to the end
5321 * of the qualified area (inclusive).
5322 * 1 = Erase from the beginning of the qualified area to
5323 * the active position (inclusive).
5324 * 2 = Erase all of the qualified area.
5325 *
5326 * Defaults:
5327 * args[0]: 0
5328 *
5329 * If ERM is set, erases only non-protected areas; if
5330 * ERM is reset, erases all areas.
5331 *
5332 * Depending on DCSM, this function works on the presentation
5333 * or data position. Terminal-wg/bidi forces DCSM to DATA.
5334 *
5335 * References: ECMA-48 § 8.3.37
5336 * Terminal-wg/bidi
5337 */
5338
5339 switch (seq.collect1(0)) {
5340 case -1:
5341 case 0:
5342 break;
5343 }
5344}
5345
5346void
5347Terminal::ECH(bte::parser::Sequence const& seq)
5348{
5349 /*
5350 * ECH - erase-character
5351 * Erase characters from the active position.
5352 *
5353 * DSCM mode controls whether this function operates on the
5354 * presentation or data position.
5355 * Also affected by ERM mode.
5356 *
5357 * Arguments:
5358 * args[0]: number of characters to erase
5359 *
5360 * Defaults:
5361 * args[0]: 1
5362 *
5363 * If ERM is set, erases only non-protected characters; if
5364 * ERM is reset, erases all characters.
5365 *
5366 * Depending on DCSM, this function works on the presentation
5367 * or data position. Terminal-wg/bidi forces DCSM to DATA.
5368 *
5369 * References: ECMA-48 § 8.3.38
5370 * Terminal-wg/bidi
5371 */
5372#if 0
5373 unsigned int num = 1;
5374
5375 if (seq->args[0] > 0)
5376 num = seq->args[0];
5377
5378 bte_page_erase(screen->page,
5379 screen->state.cursor_x, screen->state.cursor_y,
5380 screen->state.cursor_x + num, screen->state.cursor_y,
5381 &screen->state.attr, screen->age, false);
5382#endif
5383
5384 /* Erase characters starting at the cursor position (overwriting N with
5385 * spaces, but not moving the cursor). */
5386
5387 // FIXMEchpe limit to column_count - cursor.x ?
5388 auto const count = seq.collect1(0, 1, 1, int(65535));
5389 erase_characters(count);
5390}
5391
5392void
5393Terminal::ED(bte::parser::Sequence const& seq)
5394{
5395 /*
5396 * ED - erase-in-display
5397 * Erases characters.
5398 * Line attributes of completely erased lines are reset to
5399 * single-width single-height, and all character attributes
5400 * are reset to default.
5401 *
5402 * Arguments:
5403 * args[0]: mode
5404 * 0 = erase from the cursor position to the end of the screen
5405 * 1 = erase from the beginning of the screen to the cursor
5406 * position (inclusive)
5407 * 2 = erase display
5408 * 3 = erase scrollback (XTERM extension)
5409 *
5410 * Defaults:
5411 * args[0]: 0
5412 *
5413 * This function does not respect the scrolling margins.
5414 *
5415 * If ERM is set, erases only non-protected characters; if
5416 * ERM is reset, erases all characters.
5417 *
5418 * Depending on DCSM, this function works on the presentation
5419 * or data position. Terminal-wg/bidi forces DCSM to DATA.
5420 *
5421 * References: ECMA-48 § 8.3.39
5422 * VT525
5423 * Terminal-wg/bidi
5424 */
5425
5426 erase_in_display(seq);
5427}
5428
5429void
5430Terminal::EF(bte::parser::Sequence const& seq)
5431{
5432 /*
5433 * EF - erase in field
5434 * Erases characters in the active field.
5435 *
5436 * Arguments:
5437 * args[0]: mode
5438 * 0 = Erase the active position and all positions to the end
5439 * of the field (inclusive).
5440 * 1 = Erase from the beginning of the field to
5441 * the active position (inclusive).
5442 * 2 = Erase all of the qualified area.
5443 *
5444 * Defaults:
5445 * args[0]: 0
5446 *
5447 * If ERM is set, erases only non-protected characters; if
5448 * ERM is reset, erases all characters.
5449 *
5450 * Depending on DCSM, this function works on the presentation
5451 * or data position. Terminal-wg/bidi forces DCSM to DATA.
5452 *
5453 * References: ECMA-48 § 8.3.40
5454 * Terminal-wg/bidi
5455 */
5456}
5457
5458void
5459Terminal::EL(bte::parser::Sequence const& seq)
5460{
5461 /*
5462 * EL - erase-in-line
5463 * Erases characters.
5464 *
5465 * Arguments:
5466 * args[0]: mode
5467 * 0 = erase from the cursor position to the end of the line
5468 * 1 = erase from the beginning of the line to the cursor
5469 * position (inclusive)
5470 * 2 = erase line (FIXME: does this clear line attributes?)
5471 *
5472 * Defaults:
5473 * args[0]: 0
5474 *
5475 * This function does not respect the scrolling margins.
5476 *
5477 * If ERM is set, erases only non-protected characters; if
5478 * ERM is reset, erases all characters.
5479 *
5480 * Depending on DCSM, this function works on the presentation
5481 * or data position. Terminal-wg/bidi forces DCSM to DATA.
5482 *
5483 * References: ECMA-48 § 8.3.41
5484 * VT525
5485 * Terminal-wg/bidi
5486 */
5487
5488 erase_in_line(seq);
5489}
5490
5491void
5492Terminal::EM(bte::parser::Sequence const& seq)
5493{
5494 /*
5495 * EM - end of medium
5496 *
5497 * References: ECMA-48 § 8.3.42
5498 */
5499}
5500
5501void
5502Terminal::EMI(bte::parser::Sequence const& seq)
5503{
5504 /*
5505 * DMI - enable manual input
5506 *
5507 * References: ECMA-48 § 8.3.43
5508 *
5509 * Probably not worth implementing.
5510 */
5511}
5512
5513void
5514Terminal::ENQ(bte::parser::Sequence const& seq)
5515{
5516 /*
5517 * ENQ - enquiry
5518 * Transmit the answerback-string. If none is set, do nothing.
5519 *
5520 * References: ECMA-48 § 8.3.44
5521 * ECMA-16 § 3.1.5
5522 */
5523
5524 /* No-op for security reasons */
5525}
5526
5527void
5528Terminal::EOT(bte::parser::Sequence const& seq)
5529{
5530 /*
5531 * EOT - end of transmission
5532 *
5533 * References: ECMA-48 § 8.3.45
5534 * ECMA-16 § 3.1.4
5535 *
5536 * Not worth implementing.
5537 */
5538}
5539
5540void
5541Terminal::EPA(bte::parser::Sequence const& seq)
5542{
5543 /*
5544 * EPA - end of guarded area
5545 * Marks the end of an area of positions (presentation)
5546 * that are protected; the beginning of the area was
5547 * marked by SPA.
5548 *
5549 * The contents of the area will be protected against
5550 * alteration, transfer (depending on the GATM setting),
5551 * and erasure (depending on the ERM setting).
5552 *
5553 * References: ECMA-48 § 8.3.46
5554 */
5555}
5556
5557void
5558Terminal::ESA(bte::parser::Sequence const& seq)
5559{
5560 /*
5561 * ESA - end of selected area
5562 * Marks the end of an area of positions (presentation)
5563 * that are selected for transfer; the beginning of the area
5564 * was marked by SSA.
5565 *
5566 * References: ECMA-48 § 8.3.47
5567 */
5568}
5569
5570void
5571Terminal::ETB(bte::parser::Sequence const& seq)
5572{
5573 /*
5574 * ETB - end of transmission block
5575 *
5576 * References: ECMA-48 § 8.3.49
5577 * ECMA-16 § 3.1.10
5578 *
5579 * Not worth implementing.
5580 */
5581}
5582
5583void
5584Terminal::ETX(bte::parser::Sequence const& seq)
5585{
5586 /*
5587 * ETX - end of text
5588 *
5589 * References: ECMA-48 § 8.3.49
5590 * ECMA-16 § 3.1.3
5591 *
5592 * Not worth implementing.
5593 */
5594}
5595
5596void
5597Terminal::FF(bte::parser::Sequence const& seq)
5598{
5599 /*
5600 * FF - form-feed
5601 * This causes the cursor to jump to the next line (presentation).
5602 *
5603 * References: ECMA-48 § 8.3.51
5604 */
5605
5606 LF(seq);
5607}
5608
5609void
5610Terminal::FNK(bte::parser::Sequence const& seq)
5611{
5612 /*
5613 * FNK - function key
5614 *
5615 * Arguments:
5616 * args[0]: function key that was operated
5617 *
5618 * Defaults:
5619 * args[0]: no default
5620 *
5621 * References: ECMA-48 § 8.3.52
5622 *
5623 * Probably not worth implementing.
5624 */
5625}
5626
5627void
5628Terminal::FNT(bte::parser::Sequence const& seq)
5629{
5630 /*
5631 * FNT - font selection
5632 * Select the font to be used by subsequent SGR 10…19.
5633 *
5634 * Arguments:
5635 * args[0]: the font 0…9
5636 * args[1]: font identifier
5637 *
5638 * Defaults:
5639 * args[0]: 0
5640 * args[1]: 0
5641 *
5642 * References: ECMA-48 § 8.3.53
5643 *
5644 * Probably not worth implementing.
5645 */
5646}
5647
5648void
5649Terminal::GCC(bte::parser::Sequence const& seq)
5650{
5651 /*
5652 * GCC - graphic character combination
5653 * Two or more graphic characters that follow should be
5654 * imaged as one symbol.
5655 *
5656 * Arguments:
5657 * args[0]: mode
5658 * 0 = Combine the following two graphic characters
5659 * 1 = Start of string of characters to be combined
5660 * 2 = End of string of characters to be combined
5661 *
5662 * Defaults:
5663 * args[0]: 0
5664 *
5665 * References: ECMA-48 § 8.3.54
5666 * ECMA-43 Annex C
5667 */
5668}
5669
5670void
5671Terminal::GSM(bte::parser::Sequence const& seq)
5672{
5673 /*
5674 * GSM - graphic size modification
5675 *
5676 * Arguments:
5677 * args[0]: height as percentage of height set by GSS
5678 * args[1]: width as percentage of width set by GSS
5679 *
5680 * Defaults:
5681 * args[0]: 100
5682 * args[0]: 100
5683 *
5684 * References: ECMA-48 § 8.3.55
5685 *
5686 * Not applicable to BTE.
5687 */
5688}
5689
5690void
5691Terminal::GSS(bte::parser::Sequence const& seq)
5692{
5693 /*
5694 * GSM - graphic size selection
5695 *
5696 * Arguments:
5697 * args[0]: size in the unit set by SSU
5698 *
5699 * Defaults:
5700 * args[0]: no default
5701 *
5702 * References: ECMA-48 § 8.3.56
5703 *
5704 * Not applicable to BTE.
5705 */
5706}
5707
5708void
5709Terminal::GnDm(bte::parser::Sequence const& seq)
5710{
5711 /*
5712 * GnDm - Gn-designate 9m-charset
5713 *
5714 * Designate character sets to G-sets.
5715 *
5716 * References: ECMA-35 § 14.3
5717 * ISO 2375 IR
5718 */
5719
5720 /* Since we mostly don't implement ECMA-35 anymore, we can mostly ignore this. */
5721
5722 BteCharacterReplacement replacement;
5723 switch (seq.charset()) {
5724 case BTE_CHARSET_DEC_SPECIAL_GRAPHIC:
5725 /* Some characters replaced by line drawing characters.
5726 * This is still used by ncurses :-(
5727 */
5728 replacement = BTE_CHARACTER_REPLACEMENT_LINE_DRAWING;
5729 break;
5730
5731 default:
5732 replacement = BTE_CHARACTER_REPLACEMENT_NONE;
5733 break;
5734 }
5735
5736 unsigned int slot = seq.slot();
5737 if (slot >= G_N_ELEMENTS(m_character_replacements)(sizeof (m_character_replacements) / sizeof ((m_character_replacements
)[0]))
)
5738 return;
5739
5740 m_character_replacements[slot] = replacement;
5741}
5742
5743void
5744Terminal::GnDMm(bte::parser::Sequence const& seq)
5745{
5746 /*
5747 * GnDm - Gn-designate multibyte 9m-charset
5748 *
5749 * Designate multibyte character sets to G-sets.
5750 *
5751 * References: ECMA-35 § 14.3
5752 * ISO 2375 IR
5753 */
5754
5755 /* Since we mostly don't implement ECMA-35 anymore, we can ignore this */
5756}
5757
5758void
5759Terminal::HPA(bte::parser::Sequence const& seq)
5760{
5761 /*
5762 * HPA - horizontal position absolute
5763 * Move the active position (data) to the position specified by @args[0]
5764 * in the active line.
5765 *
5766 * Arguments:
5767 * args[0]: position (data)
5768 *
5769 * Defaults:
5770 * args[0]: 1
5771 *
5772 * References: ECMA-48 § 8.3.57
5773 * VT525
5774 */
5775
5776#if 0
5777 unsigned int num = 1;
5778
5779 if (seq->args[0] > 0)
5780 num = seq->args[0];
5781
5782 screen_cursor_clear_wrap(screen);
5783 screen_cursor_set(screen, num - 1, screen->state.cursor_y);
5784#endif
5785
5786 auto value = seq.collect1(0, 1, 1, m_column_count);
5787 set_cursor_column1(value);
5788}
5789
5790void
5791Terminal::HPB(bte::parser::Sequence const& seq)
5792{
5793 /*
5794 * HPB - horizontal position backward
5795 * Move the active position (data) to the backward by @args[0] positions
5796 * in the active line.
5797 *
5798 * Arguments:
5799 * args[0]: number of positions to move
5800 *
5801 * Defaults:
5802 * args[0]: 1
5803 *
5804 * References: ECMA-48 § 8.3.58
5805 */
5806}
5807
5808void
5809Terminal::HPR(bte::parser::Sequence const& seq)
5810{
5811 /*
5812 * HPR - horizontal-position-relative
5813 * Move the active position (data) to the foward by @args[0] positions
5814 * in the active line.
5815 *
5816 * Arguments:
5817 * args[0]: number of positions to move
5818 *
5819 * Defaults:
5820 * args[0]: 1
5821 *
5822 * References: ECMA-48 § 8.3.59
5823 * VT525
5824 */
5825#if 0
5826 unsigned int num = 1;
5827
5828 if (seq->args[0] > 0)
5829 num = seq->args[0];
5830
5831 screen_cursor_clear_wrap(screen);
5832 screen_cursor_right(screen, num);
5833#endif
5834}
5835
5836void
5837Terminal::HT(bte::parser::Sequence const& seq)
5838{
5839 /*
5840 * HT - character tabulation
5841 * Move the active position (presentation) to the next tab stop.
5842 * If there are no more tab stops, the cursor moves to the right
5843 * margin. Does not cause text to auto wrap.
5844 *
5845 * (If that next tabstop was set by TAC, TALE, TATE or TCC,
5846 * the properties of that tabstop will determine how subsequently
5847 * inserted text is positioned.)
5848 *
5849 * References: ECMA-48 § 8.3.60
5850 * VT525
5851 */
5852#if 0
5853 screen_cursor_clear_wrap(screen);
5854#endif
5855
5856 move_cursor_tab_forward();
5857}
5858
5859void
5860Terminal::HTJ(bte::parser::Sequence const& seq)
5861{
5862 /*
5863 * HTJ - character tabulation with justification
5864 *
5865 * References: ECMA-48 § 8.3.61
5866 * VT525
5867 */
5868#if 0
5869 screen_cursor_clear_wrap(screen);
5870#endif
5871
5872 move_cursor_tab_forward();
5873}
5874
5875void
5876Terminal::HTS(bte::parser::Sequence const& seq)
5877{
5878 /*
5879 * HTS - horizontal-tab-set
5880 * Set a tabstop at the active position (presentation).
5881 *
5882 * Affected by TSM mode.
5883 *
5884 * References: ECMA-48 § 8.3.62
5885 * VT525
5886 */
5887
5888 m_tabstops.set(get_cursor_column());
5889}
5890
5891void
5892Terminal::HVP(bte::parser::Sequence const& seq)
5893{
5894 /*
5895 * HVP - horizontal-and-vertical-position
5896 * Sets the active position (data)
5897 *
5898 * Arguments:
5899 * args[0]: the line
5900 * args[1]: the column
5901 *
5902 * Defaults:
5903 * args[0]: 1
5904 * args[1]: 1
5905 *
5906 * If DECOM is set, the position is relative to the top/bottom
5907 * margins, and may not be outside it.
5908 *
5909 * References: ECMA-48 § 8.3.63
5910 * VT525
5911 */
5912
5913 CUP(seq);
5914}
5915
5916void
5917Terminal::ICH(bte::parser::Sequence const& seq)
5918{
5919 /*
5920 * ICH - insert-character
5921 * Inserts SPACE (2/0) character(s) at the cursor position.
5922 *
5923 * Arguments:
5924 * args[0]: the number of characters to insert
5925 *
5926 * Defaults:
5927 * args[0]: 1
5928 *
5929 * Depending on DCSM, this function works on the presentation
5930 * or data position. Terminal-wg/bidi forces DCSM to DATA.
5931
5932 * Also affected by HEM mode, and the SLH, and SEE functions.
5933 *
5934 * References: ECMA-48 §8.3.64
5935 * VT525
5936 * Terminal-wg/bidi
5937 */
5938#if 0
5939 unsigned int num = 1;
5940
5941 if (seq->args[0] > 0)
5942 num = seq->args[0];
5943
5944 screen_cursor_clear_wrap(screen);
5945 bte_page_insert_cells(screen->page,
5946 screen->state.cursor_x,
5947 screen->state.cursor_y,
5948 num,
5949 &screen->state.attr,
5950 screen->age);
5951#endif
5952
5953 auto const count = seq.collect1(0, 1, 1, int(m_column_count - m_screen->cursor.col));
5954
5955 /* TODOegmont: Insert them in a single run, so that we call cleanup_fragments only once. */
5956 for (auto i = 0; i < count; i++)
5957 insert_blank_character();
5958}
5959
5960void
5961Terminal::IDCS(bte::parser::Sequence const& seq)
5962{
5963 /*
5964 * IDCS - identify device control string
5965 *
5966 * Arguments:
5967 * args[0]: mode
5968 * 1 = reserved for use with SRTM mode
5969 * 2 = reservewd for DRCS according to ECMA-35
5970
5971 * Defaults:
5972 * args[0]: no default
5973 *
5974 * References: ECMA-48 § 8.3.65
5975 */
5976}
5977
5978void
5979Terminal::IGS(bte::parser::Sequence const& seq)
5980{
5981 /*
5982 * IGS - identify graphic subrepertoire
5983 * Specifies a repertoire of graphic characters to be used
5984 * in the following text.
5985 *
5986 * Arguments:
5987 * args[0]: identifier from ISO 7350 registry
5988
5989 * Defaults:
5990 * args[0]: no default
5991 *
5992 * References: ECMA-48 § 8.3.66
5993 * ISO/IEC 7350
5994 * ISO/IEC 10367
5995 *
5996 * Not worth implementing.
5997 */
5998}
5999
6000void
6001Terminal::IL(bte::parser::Sequence const& seq)
6002{
6003 /*
6004 * IL - insert-line
6005 * Insert (a) blank line(s) at the active position.
6006 *
6007 * Arguments:
6008 * args[0]: the number of lines
6009 *
6010 * Defaults:
6011 * args[0]: 1
6012 *
6013 * Depending on DCSM, this function works on the presentation
6014 * or data position. Terminal-wg/bidi forces DCSM to DATA.
6015 *
6016 * Also affected by the TSM and VEM modes,
6017 * and the SLH and SEE functions.
6018 *
6019 * References: ECMA-48 § 8.3.67
6020 * DEC STD 070 page 5-146
6021 * Terminal-wg/bidi
6022 */
6023#if 0
6024 unsigned int num = 1;
6025
6026 if (seq->args[0] > 0)
6027 num = seq->args[0];
6028
6029 screen_cursor_clear_wrap(screen);
6030 bte_page_insert_lines(screen->page,
6031 screen->state.cursor_y,
6032 num,
6033 &screen->state.attr,
6034 screen->age);
6035#endif
6036
6037 auto const count = seq.collect1(0, 1);
6038 insert_lines(count);
6039}
6040
6041void
6042Terminal::IND(bte::parser::Sequence const& seq)
6043{
6044 /*
6045 * IND - index - DEPRECATED
6046 *
6047 * References: ECMA-48 § F.8.2
6048 */
6049
6050 LF(seq);
6051}
6052
6053void
6054Terminal::INT(bte::parser::Sequence const& seq)
6055{
6056 /*
6057 * INT - interrupt
6058 *
6059 * References: ECMA-48 § 8.3.68
6060 */
6061}
6062
6063void
6064Terminal::IRR(bte::parser::Sequence const& seq)
6065{
6066 /*
6067 * IRR - identify-revised-registration
6068 *
6069 * References: ECMA-35 § 14.5
6070 *
6071 * Probably not worth implementing.
6072 */
6073
6074 /* Since we mostly don't implement ECMA-35 anymore, we can ignore this */
6075}
6076
6077void
6078Terminal::IS1(bte::parser::Sequence const& seq)
6079{
6080 /*
6081 * IS1 - information separator 1 / unit separator (US)
6082 *
6083 * References: ECMA-48 § 8.3.69, § 8.2.10
6084 */
6085}
6086
6087void
6088Terminal::IS2(bte::parser::Sequence const& seq)
6089{
6090 /*
6091 * IS2 - information separator 2 / record separator (RS)
6092 *
6093 * References: ECMA-48 § 8.3.70, § 8.2.10
6094 */
6095}
6096
6097void
6098Terminal::IS3(bte::parser::Sequence const& seq)
6099{
6100 /*
6101 * IS3 - information separator 3 / group separator (GS)
6102 *
6103 * References: ECMA-48 § 8.3.71, § 8.2.10
6104 */
6105}
6106
6107void
6108Terminal::IS4(bte::parser::Sequence const& seq)
6109{
6110 /*
6111 * IS4 - information separator 4 / file separator (FS)
6112 *
6113 * References: ECMA-48 § 8.3.72, § 8.2.10
6114 */
6115}
6116
6117void
6118Terminal::JFY(bte::parser::Sequence const& seq)
6119{
6120 /*
6121 * JFY - justify
6122 *
6123 * References: ECMA-48 § 8.3.73
6124 *
6125 * Probably not worth implementing.
6126 */
6127}
6128
6129void
6130Terminal::LF(bte::parser::Sequence const& seq)
6131{
6132 /*
6133 * LF - line-feed
6134 * XXXX
6135 *
6136 * References: ECMA-48 § 8.3.74
6137 */
6138
6139#if 0
6140 screen_cursor_down(screen, 1, true);
6141 if (screen->flags & BTE_FLAG_NEWLINE_MODE)
6142 screen_cursor_left(screen, screen->state.cursor_x);
6143#endif
6144
6145 line_feed();
6146}
6147
6148void
6149Terminal::LS0(bte::parser::Sequence const& seq)
6150{
6151 /*
6152 * LS0 -locking shift 0 (8 bit)
6153 * SI - shift-in (7 bit)
6154 *
6155 * Map G0 into GL.
6156 *
6157 * References: ECMA-35 § 9.3.1
6158 * ECMA-48 § 8.3.75, 8.3.119
6159 */
6160#if 0
6161 screen->state.gl = &screen->g0;
6162#endif
6163
6164 set_character_replacement(0);
6165}
6166
6167void
6168Terminal::LS1(bte::parser::Sequence const& seq)
6169{
6170 /*
6171 * LS1 -locking shift 1 (8 bit)
6172 * SO - shift-out (7 bit)
6173 *
6174 * Map G1 into GL.
6175 *
6176 * References: ECMA-35 § 9.3.1
6177 * ECMA-48 § 8.3.76, 8.3.126
6178 */
6179#if 0
6180 screen->state.gl = &screen->g1;
6181#endif
6182
6183 set_character_replacement(1);
6184}
6185
6186void
6187Terminal::LS1R(bte::parser::Sequence const& seq)
6188{
6189 /*
6190 * LS1R - locking-shift-1-right
6191 * Map G1 into GR.
6192 *
6193 * References: ECMA-35 § 9.3.2
6194 * ECMA-48 § 8.3.77
6195 */
6196#if 0
6197 screen->state.gr = &screen->g1;
6198#endif
6199}
6200
6201void
6202Terminal::LS2(bte::parser::Sequence const& seq)
6203{
6204 /*
6205 * LS2 - locking-shift-2
6206 * Map G2 into GL.
6207 *
6208 * References: ECMA-35 § 9.3.1
6209 * ECMA-48 § 8.3.78
6210 */
6211#if 0
6212 screen->state.gl = &screen->g2;
6213#endif
6214}
6215
6216void
6217Terminal::LS2R(bte::parser::Sequence const& seq)
6218{
6219 /*
6220 * LS2R - locking-shift-2-right
6221 * Map G2 into GR.
6222 *
6223 * References: ECMA-35 § 9.3.2
6224 * ECMA-48 § 8.3.79
6225 */
6226#if 0
6227 screen->state.gr = &screen->g2;
6228#endif
6229}
6230
6231void
6232Terminal::LS3(bte::parser::Sequence const& seq)
6233{
6234 /*
6235 * LS3 - locking-shift-3
6236 * Map G3 into GL.
6237 *
6238 * References: ECMA-35 § 9.3.1
6239 * ECMA-48 § 8.3.80
6240 */
6241
6242#if 0
6243 screen->state.gl = &screen->g3;
6244#endif
6245}
6246
6247void
6248Terminal::LS3R(bte::parser::Sequence const& seq)
6249{
6250 /*
6251 * LS3R - locking-shift-3-right
6252 * Map G3 into GR.
6253 *
6254 * References: ECMA-35 § 9.3.2
6255 * ECMA-48 § 8.3.81
6256 */
6257#if 0
6258 screen->state.gr = &screen->g3;
6259#endif
6260}
6261
6262void
6263Terminal::MC_ECMA(bte::parser::Sequence const& seq)
6264{
6265 /*
6266 * MC_ECMA - media-copy-ecma
6267 *
6268 * References: ECMA-48 § 8.3.82
6269 * VT525
6270 *
6271 * Probably not worth implementing.
6272 */
6273}
6274
6275void
6276Terminal::MC_DEC(bte::parser::Sequence const& seq)
6277{
6278 /*
6279 * MC_DEC - media-copy-dec
6280 *
6281 * References: VT525
6282 *
6283 * Probably not worth implementing.
6284 */
6285}
6286
6287void
6288Terminal::MW(bte::parser::Sequence const& seq)
6289{
6290 /*
6291 * MW - message waiting
6292 *
6293 * References: ECMA-48 § 8.3.83
6294 *
6295 * Not worth implementing.
6296 */
6297}
6298
6299void
6300Terminal::NAK(bte::parser::Sequence const& seq)
6301{
6302 /*
6303 * NAK - negative acknowledge
6304 *
6305 * References: ECMA-48 § 8.3.84
6306 * ECMA-16 § 3.1.8
6307 *
6308 * Not worth implementing.
6309 */
6310}
6311
6312void
6313Terminal::NBH(bte::parser::Sequence const& seq)
6314{
6315 /*
6316 * BPH - no break permitted here
6317 *
6318 * References: ECMA-48 § 8.3.85
6319 *
6320 * Not worth implementing.
6321 */
6322}
6323
6324void
6325Terminal::NEL(bte::parser::Sequence const& seq)
6326{
6327 /*
6328 * NEL - next-line
6329 * Moves the cursor to the first column in the next line.
6330 * If the cursor is on the bottom margin, this scrolls up.
6331 *
6332 * References: ECMA-48 § 8.3.86
6333 */
6334#if 0
6335 screen_cursor_clear_wrap(screen);
6336 screen_cursor_down(screen, 1, true);
6337 screen_cursor_set(screen, 0, screen->state.cursor_y);
6338#endif
6339
6340 set_cursor_column(0);
6341 cursor_down(true);
6342}
6343
6344void
6345Terminal::NP(bte::parser::Sequence const& seq)
6346{
6347 /*
6348 * NP - next-page
6349 * Move cursor to home on the next page (presentation).
6350 * (Ignored if there is only one page.)
6351 *
6352 * Arguments:
6353 * args[0]: number of pages to move forward
6354 *
6355 * Defaults:
6356 * args[0]: 1
6357 *
6358 * References: ECMA-48 § 8.3.87
6359 * VT525
6360 *
6361 * Since BTE only has one page, this is ignored.
6362 */
6363}
6364
6365void
6366Terminal::NUL(bte::parser::Sequence const& seq)
6367{
6368 /*
6369 * NUL - nothing
6370 *
6371 * References: ECMA-48 § 8.3.88
6372 */
6373}
6374
6375void
6376Terminal::OSC(bte::parser::Sequence const& seq)
6377{
6378 /*
6379 * OSC - operating system command
6380 *
6381 * References: ECMA-48 § 8.3.89
6382 * XTERM
6383 */
6384
6385 /* Our OSC have the format
6386 * OSC number ; rest of string ST
6387 * where the rest of the string may or may not contain more semicolons.
6388 *
6389 * First, extract the number.
6390 */
6391
6392 auto str = seq.string_utf8();
6393 bte::parser::StringTokeniser tokeniser{str, ';'};
6394 auto it = tokeniser.cbegin();
6395 int osc;
6396 if (!it.number(osc))
6397 return;
6398
6399 auto const cend = tokeniser.cend();
6400 ++it; /* could now be cend */
6401
6402 switch (osc) {
6403 case BTE_OSC_BTECWF:
6404 set_current_file_uri(seq, it, cend);
6405 break;
6406
6407 case BTE_OSC_BTECWD:
6408 set_current_directory_uri(seq, it, cend);
6409 break;
6410
6411 case BTE_OSC_BTEHYPER:
6412 set_current_hyperlink(seq, it, cend);
6413 break;
6414
6415 case -1: /* default */
6416 case BTE_OSC_XTERM_SET_WINDOW_AND_ICON_TITLE: {
6417 std::string title;
6418 if (it != cend)
6419 title = it.string_remaining();
6420 m_icon_title_pending = title;
6421 m_window_title_pending.swap(title);
6422 m_icon_title_changed = true;
6423 m_window_title_changed = true;
6424 break;
6425 }
6426
6427 case BTE_OSC_XTERM_SET_ICON_TITLE: {
6428 std::string title;
6429 if (it != cend)
6430 title = it.string_remaining();
6431 m_icon_title_pending.swap(title);
6432 m_icon_title_changed = true;
6433 break;
6434 }
6435
6436 case BTE_OSC_XTERM_SET_WINDOW_TITLE: {
6437 std::string title;
6438 if (it != cend &&
6439 it.size_remaining() < BTE_WINDOW_TITLE_MAX_LENGTH(1024))
6440 title = it.string_remaining();
6441 m_window_title_pending.swap(title);
6442 m_window_title_changed = true;
6443 break;
6444 }
6445
6446 case BTE_OSC_XTERM_SET_COLOR:
6447 case BTE_OSC_XTERM_SET_COLOR_SPECIAL:
6448 set_color(seq, it, cend, osc);
6449 break;
6450
6451 case BTE_OSC_XTERM_SET_COLOR_TEXT_FG:
6452 set_special_color(seq, it, cend, BTE_DEFAULT_FG256, -1, osc);
6453 break;
6454
6455 case BTE_OSC_XTERM_SET_COLOR_TEXT_BG:
6456 set_special_color(seq, it, cend, BTE_DEFAULT_BG257, -1, osc);
6457 break;
6458
6459 case BTE_OSC_XTERM_SET_COLOR_CURSOR_BG:
6460 set_special_color(seq, it, cend, BTE_CURSOR_BG261, BTE_DEFAULT_FG256, osc);
6461 break;
6462
6463 case BTE_OSC_XTERM_SET_COLOR_HIGHLIGHT_BG:
6464 set_special_color(seq, it, cend, BTE_HIGHLIGHT_BG260, BTE_DEFAULT_FG256, osc);
6465 break;
6466
6467 case BTE_OSC_XTERM_SET_COLOR_HIGHLIGHT_FG:
6468 set_special_color(seq, it, cend, BTE_HIGHLIGHT_FG259, BTE_DEFAULT_BG257, osc);
6469 break;
6470
6471 case BTE_OSC_XTERM_RESET_COLOR:
6472 case BTE_OSC_XTERM_RESET_COLOR_SPECIAL:
6473 reset_color(seq, it, cend, osc);
6474 break;
6475
6476 case BTE_OSC_XTERM_RESET_COLOR_TEXT_FG:
6477 reset_color(BTE_DEFAULT_FG256, BTE_COLOR_SOURCE_ESCAPE0);
6478 break;
6479
6480 case BTE_OSC_XTERM_RESET_COLOR_TEXT_BG:
6481 reset_color(BTE_DEFAULT_BG257, BTE_COLOR_SOURCE_ESCAPE0);
6482 break;
6483
6484 case BTE_OSC_XTERM_RESET_COLOR_CURSOR_BG:
6485 reset_color(BTE_CURSOR_BG261, BTE_COLOR_SOURCE_ESCAPE0);
6486 break;
6487
6488 case BTE_OSC_XTERM_RESET_COLOR_HIGHLIGHT_BG:
6489 reset_color(BTE_HIGHLIGHT_BG260, BTE_COLOR_SOURCE_ESCAPE0);
6490 break;
6491
6492 case BTE_OSC_XTERM_RESET_COLOR_HIGHLIGHT_FG:
6493 reset_color(BTE_HIGHLIGHT_FG259, BTE_COLOR_SOURCE_ESCAPE0);
6494 break;
6495
6496 case BTE_OSC_XTERM_SET_XPROPERTY:
6497 case BTE_OSC_XTERM_SET_COLOR_MOUSE_CURSOR_FG:
6498 case BTE_OSC_XTERM_SET_COLOR_MOUSE_CURSOR_BG:
6499 case BTE_OSC_XTERM_SET_COLOR_TEK_FG:
6500 case BTE_OSC_XTERM_SET_COLOR_TEK_BG:
6501 case BTE_OSC_XTERM_SET_COLOR_TEK_CURSOR:
6502 case BTE_OSC_XTERM_LOGFILE:
6503 case BTE_OSC_XTERM_SET_FONT:
6504 case BTE_OSC_XTERM_SET_XSELECTION:
6505 case BTE_OSC_XTERM_SET_COLOR_MODE:
6506 case BTE_OSC_XTERM_RESET_COLOR_MOUSE_CURSOR_FG:
6507 case BTE_OSC_XTERM_RESET_COLOR_MOUSE_CURSOR_BG:
6508 case BTE_OSC_XTERM_RESET_COLOR_TEK_FG:
6509 case BTE_OSC_XTERM_RESET_COLOR_TEK_BG:
6510 case BTE_OSC_XTERM_RESET_COLOR_TEK_CURSOR:
6511 case BTE_OSC_EMACS_51:
6512 case BTE_OSC_ITERM2_133:
6513 case BTE_OSC_ITERM2_1337:
6514 case BTE_OSC_ITERM2_GROWL:
6515 case BTE_OSC_KONSOLE_30:
6516 case BTE_OSC_KONSOLE_31:
6517 case BTE_OSC_RLOGIN_SET_KANJI_MODE:
6518 case BTE_OSC_RLOGIN_SPEECH:
6519 case BTE_OSC_RXVT_SET_BACKGROUND_PIXMAP:
6520 case BTE_OSC_RXVT_SET_COLOR_FG:
6521 case BTE_OSC_RXVT_SET_COLOR_BG:
6522 case BTE_OSC_RXVT_DUMP_SCREEN:
6523 case BTE_OSC_URXVT_SET_LOCALE:
6524 case BTE_OSC_URXVT_VERSION:
6525 case BTE_OSC_URXVT_SET_COLOR_TEXT_ITALIC:
6526 case BTE_OSC_URXVT_SET_COLOR_TEXT_BOLD:
6527 case BTE_OSC_URXVT_SET_COLOR_UNDERLINE:
6528 case BTE_OSC_URXVT_SET_COLOR_BORDER:
6529 case BTE_OSC_URXVT_SET_FONT:
6530 case BTE_OSC_URXVT_SET_FONT_BOLD:
6531 case BTE_OSC_URXVT_SET_FONT_ITALIC:
6532 case BTE_OSC_URXVT_SET_FONT_BOLD_ITALIC:
6533 case BTE_OSC_URXVT_VIEW_UP:
6534 case BTE_OSC_URXVT_VIEW_DOWN:
6535 case BTE_OSC_URXVT_EXTENSION:
6536 case BTE_OSC_YF_RQGWR:
6537 default:
6538 break;
6539 }
6540}
6541
6542void
6543Terminal::PEC(bte::parser::Sequence const& seq)
6544{
6545 /*
6546 * PEC - presentation expand or contract
6547 *
6548 * References: ECMA-48 § 8.3.90
6549 *
6550 * Not applicable in BTE.
6551 */
6552}
6553
6554void
6555Terminal::PFS(bte::parser::Sequence const& seq)
6556{
6557 /*
6558 * PFS - page format selection
6559 *
6560 * References: ECMA-48 § 8.3.91
6561 *
6562 * Not applicable in BTE.
6563 */
6564}
6565
6566void
6567Terminal::PLD(bte::parser::Sequence const& seq)
6568{
6569 /*
6570 * PLD - partial line forward
6571 *
6572 * References: ECMA-48 § 8.3.92
6573 *
6574 * Could use this to implement subscript text.
6575 */
6576}
6577
6578void
6579Terminal::PLU(bte::parser::Sequence const& seq)
6580{
6581 /*
6582 * PLU - partial line backward
6583 *
6584 * References: ECMA-48 § 8.3.93
6585 *
6586 * Could use this to implement superscript text.
6587 */
6588}
6589
6590void
6591Terminal::PP(bte::parser::Sequence const& seq)
6592{
6593 /*
6594 * PP - preceding page
6595 * Move cursor to home on the previous page (presentation).
6596 * (Ignored if there is only one page.)
6597 *
6598 * Arguments:
6599 * args[0]: number of pages to move backward
6600 *
6601 * Defaults:
6602 * args[0]: 1
6603 *
6604 * References: ECMA-48 § 8.3.95
6605 * VT525
6606 *
6607 * Since BTE only has one page, this is ignored.
6608 */
6609}
6610
6611void
6612Terminal::PPA(bte::parser::Sequence const& seq)
6613{
6614 /*
6615 * PPA - page position absolute
6616 * Move the cursor to the current position on the specified page
6617 * (data).
6618 * (Ignored if there is only one page.)
6619 *
6620 * Arguments:
6621 * args[0]: absolute page number
6622 *
6623 * Defaults:
6624 * args[0]: 1
6625 *
6626 * References: ECMA-48 § 8.3.96
6627 * VT525
6628 *
6629 * Since BTE only has one page, this is ignored.
6630 */
6631}
6632
6633void
6634Terminal::PPB(bte::parser::Sequence const& seq)
6635{
6636 /*
6637 * PPB - page position backward
6638 * Move the cursor to the current position on a preceding page (data).
6639 * (Ignored if there is only one page.)
6640 *
6641 * Arguments:
6642 * args[0]: number of pages to move backward
6643 *
6644 * Defaults:
6645 * args[0]: 1
6646 *
6647 * References: ECMA-48 § 8.3.97
6648 * VT525
6649 *
6650 * Since BTE only has one page, this is ignored.
6651 */
6652}
6653
6654void
6655Terminal::PPR(bte::parser::Sequence const& seq)
6656{
6657 /*
6658 * PPR - page position foward
6659 * Move the cursor to the current position on a following page (data).
6660 * (Ignored if there is only one page.)
6661 *
6662 * Arguments:
6663 * args[0]: number of pages to move forward
6664 *
6665 * Defaults:
6666 * args[0]: 1
6667 *
6668 * References: ECMA-48 § 8.3.98
6669 * VT525
6670 *
6671 * Since BTE only has one page, this is ignored.
6672 */
6673}
6674
6675void
6676Terminal::PTX(bte::parser::Sequence const& seq)
6677{
6678 /*
6679 * PTX - parallel texts
6680 *
6681 * Arguments:
6682 * args[0]: mode
6683 * 0 = End of parallel texts
6684 * 1 = Start of a string of principal parallel text
6685 * 2 = Start of a string of supplementary parallel text
6686 * 3 = Start of a string of supplementary japanese
6687 * phonetic annotations
6688 * 4 = Start of a string of supplementary chinese
6689 * phonetic annotations
6690 * 5 = Start of a string of supplementary phonetic
6691 * annotations
6692 *
6693 * Defaults:
6694 * args[0]: 0
6695 *
6696 * References: ECMA-48 § 8.3.99
6697 * VT525
6698 *
6699 * Since BTE only has one page, this is ignored.
6700 */
6701}
6702
6703void
6704Terminal::PU1(bte::parser::Sequence const& seq)
6705{
6706 /*
6707 * PU1 - private use 1
6708 *
6709 * References: ECMA-48 § 8.3.100
6710 *
6711 * Not worth implementing.
6712 */
6713}
6714
6715void
6716Terminal::PU2(bte::parser::Sequence const& seq)
6717{
6718 /*
6719 * PU1 - private use 2
6720 *
6721 * References: ECMA-48 § 8.3.101
6722 *
6723 * Not worth implementing.
6724 */
6725}
6726
6727void
6728Terminal::QUAD(bte::parser::Sequence const& seq)
6729{
6730 /*
6731 * QUAD - quad
6732 *
6733 * References: ECMA-48 § 8.3.102
6734 *
6735 * Probably not worth implementing.
6736 */
6737}
6738
6739void
6740Terminal::REP(bte::parser::Sequence const& seq)
6741{
6742 /*
6743 * REP - repeat
6744 * Repeat the preceding graphics-character the given number of times.
6745 * @args[0] specifies how often it shall be repeated. 0 is treated as 1.
6746 *
6747 * Defaults:
6748 * args[0]: 1
6749 *
6750 * References: ECMA-48 § 8.3.103
6751 */
6752
6753 if (m_last_graphic_character == 0)
6754 return;
6755
6756 auto const count = seq.collect1(0, 1, 1, int(m_column_count - m_screen->cursor.col));
6757
6758 // FIXMEchpe insert in one run so we only clean up fragments once
6759 for (auto i = 0; i < count; i++)
6760 insert_char(m_last_graphic_character, false, true);
6761}
6762
6763void
6764Terminal::RI(bte::parser::Sequence const& seq)
6765{
6766 /*
6767 * RI - reverse-index
6768 * Moves the cursor up one line in the same column. If the cursor is at
6769 * the top margin, the page scrolls down.
6770 *
6771 * References: ECMA-48 § 8.3.104
6772 */
6773#if 0
6774 screen_cursor_up(screen, 1, true);
6775#endif
6776
6777 ensure_cursor_is_onscreen();
6778
6779 bte::grid::row_t start, end;
6780 if (m_scrolling_restricted) {
6781 start = m_scrolling_region.start + m_screen->insert_delta;
6782 end = m_scrolling_region.end + m_screen->insert_delta;
6783 } else {
6784 start = m_screen->insert_delta;
6785 end = start + m_row_count - 1;
6786 }
6787
6788 if (m_screen->cursor.row == start) {
6789 /* If we're at the top of the scrolling region, add a
6790 * line at the top to scroll the bottom off. */
6791 ring_remove(end);
6792 ring_insert(start, true);
6793
6794 /* Set the boundaries to hard wrapped where we tore apart the contents.
6795 * Need to do it after scrolling down, for the end row to be the desired one. */
6796 set_hard_wrapped(start - 1);
6797 set_hard_wrapped(end);
6798
6799 /* Repaint the affected lines. No need to extend, set_hard_wrapped() took care of
6800 * invalidating the context lines if necessary. */
6801 invalidate_rows(start, end);
6802 } else {
6803 /* Otherwise, just move the cursor up. */
6804 m_screen->cursor.row--;
6805 }
6806 /* Adjust the scrollbars if necessary. */
6807 adjust_adjustments();
6808 /* We modified the display, so make a note of it. */
6809 m_text_modified_flag = TRUE(!(0));
6810}
6811
6812void
6813Terminal::RIS(bte::parser::Sequence const& seq)
6814{
6815 /*
6816 * RIS - reset-to-initial-state
6817 * Reset to initial state.
6818 * [list of things reset]
6819 *
6820 * References: ECMA-48 § 8.3.105
6821 */
6822
6823 reset(true, true);
6824}
6825
6826void
6827Terminal::RLOGIN_MML(bte::parser::Sequence const& seq)
6828{
6829 /*
6830 * RLOGIN_MML - RLogin music markup language
6831 *
6832 * Probably not worth implementing.
6833 *
6834 * References: RLogin
6835 */
6836}
6837
6838void
6839Terminal::RM_ECMA(bte::parser::Sequence const& seq)
6840{
6841 /*
6842 * RM_ECMA - reset-mode-ecma
6843 *
6844 * Defaults: none
6845 *
6846 * References: ECMA-48 § 8.3.106
6847 */
6848
6849 set_mode_ecma(seq, false);
6850}
6851
6852void
6853Terminal::RM_DEC(bte::parser::Sequence const& seq)
6854{
6855 /*
6856 * RM_DEC - reset-mode-dec
6857 * This is the same as RM_ECMA but for DEC modes.
6858 *
6859 * Defaults: none
6860 *
6861 * References: VT525
6862 */
6863
6864 set_mode_private(seq, false);
6865}
6866
6867void
6868Terminal::SCORC(bte::parser::Sequence const& seq)
6869{
6870 /*
6871 * SCORC - SCO restore cursor
6872 * Works like DECRC, except in that it does not restore the page.
6873 * While this is an obsolete sequence from an obsolete terminal,
6874 * and not used in terminfo, there still are some programmes
6875 * that use it and break when it's not implemented; see issue#48.
6876 *
6877 * References: VT525
6878 */
6879
6880 if (m_modes_private.DECLRMM())
6881 return;
6882
6883 restore_cursor();
6884}
6885
6886void
6887Terminal::SCOSC(bte::parser::Sequence const& seq)
6888{
6889 /*
6890 * SCORC - SCO save cursor
6891 * Works like DECSC, except in that it does not save the page.
6892 * While this is an obsolete sequence from an obsolete terminal,
6893 * and not used in terminfo, there still are some programmes
6894 * that use it and break when it's not implemented; see issue#48.
6895 *
6896 * References: VT525
6897 */
6898
6899 save_cursor();
6900}
6901
6902void
6903Terminal::SACS(bte::parser::Sequence const& seq)
6904{
6905 /*
6906 * SACS - set additional character separation
6907 *
6908 * Arguments:
6909 * args[0]: spacing (in the unit set by SSU)
6910 *
6911 * Defaults:
6912 * args[0]: 0
6913 *
6914 * References: ECMA-48 § 8.3.107
6915 *
6916 * Not applicable in BTE.
6917 */
6918}
6919
6920void
6921Terminal::SAPV(bte::parser::Sequence const& seq)
6922{
6923 /*
6924 * SAPV - select alternative presentation variants
6925 * Set variants for the presentation of following text.
6926 *
6927 * Arguments:
6928 * args[0]: type
6929 * 0 = default presentation; cancels the previous SAPV
6930 * ...
6931 *
6932 * Defaults:
6933 * args[0]: 0
6934 *
6935 * References: ECMA-48 § 8.3.108
6936 */
6937}
6938
6939void
6940Terminal::SCO(bte::parser::Sequence const& seq)
6941{
6942 /*
6943 * SCO - select character orientation
6944 * Set the rotation for the presentation of following text.
6945 * (positive orientation).
6946 *
6947 * Arguments:
6948 * args[0]: orientation 0…7 specifying a multiple of 45°
6949 *
6950 * Defaults:
6951 * args[0]: 0
6952 *
6953 * References: ECMA-48 § 8.3.110
6954 */
6955}
6956
6957void
6958Terminal::SCP(bte::parser::Sequence const& seq)
6959{
6960 /*
6961 * SCP - select character path
6962 * Set the character path relative to the line orientation
6963 * (presentation).
6964 *
6965 * Arguments:
6966 * args[0]: path
6967 * 0 in Terminal-wg/bidi and BTE = terminal's default
6968 * 1 = LTR or TTB (for horizontal/vertical line orientation)
6969 * 2 = RTL or BTT (for horizontal/vertical line orientation)
6970 * args[1]: effect
6971 * 0 in ECMA = implementation-defined
6972 * 0 in Terminal-wg/bidi and BTE = see Terminal-wg/bidi
6973 * 1 = ...
6974 * 2 = ...
6975 *
6976 * Defaults:
6977 * args[0] in ECMA: no default
6978 * args[1] in ECMA: no default
6979 * args[0] in Terminal-wg/bidi: 0
6980 * args[1] in Terminal-wg/bidi: 0
6981 *
6982 * References: ECMA-48 § 8.3.111
6983 * Terminal-wg/bidi
6984 */
6985
6986 auto const param = seq.collect1(0);
6987 switch (param) {
6988 case -1:
6989 case 0:
6990 /* FIXME switch to the emulator's default, once we have that concept */
6991 m_bidi_rtl = FALSE(0);
6992 _bte_debug_print(BTE_DEBUG_BIDI, "BiDi: default direction restored\n")do { } while(0);
6993 break;
6994 case 1:
6995 m_bidi_rtl = FALSE(0);
6996 _bte_debug_print(BTE_DEBUG_BIDI, "BiDi: switch to LTR\n")do { } while(0);
6997 break;
6998 case 2:
6999 m_bidi_rtl = TRUE(!(0));
7000 _bte_debug_print(BTE_DEBUG_BIDI, "BiDi: switch to RTL\n")do { } while(0);
7001 break;
7002 default:
7003 return;
7004 }
7005
7006 maybe_apply_bidi_attributes(BTE_BIDI_FLAG_RTL);
7007}
7008
7009void
7010Terminal::SCS(bte::parser::Sequence const& seq)
7011{
7012 /*
7013 * SCS - set character spacing
7014 *
7015 * Arguments:
7016 * args[0]: spacing (in the unit set by SSU)
7017 *
7018 * Defaults:
7019 * args[0]: no default
7020 *
7021 * References: ECMA-48 § 8.3.112
7022 */
7023}
7024
7025void
7026Terminal::SD(bte::parser::Sequence const& seq)
7027{
7028 /*
7029 * SD - scroll down / pan up
7030 * Scrolls down a number of lines (presentation).
7031 *
7032 * Arguments:
7033 * args[0]: number of lines to scroll
7034 *
7035 * Defaults:
7036 * args[0]: 1
7037 *
7038 * References: ECMA-48 § 8.3.113
7039 * VT525
7040 */
7041#if 0
7042 unsigned int num = 1;
7043
7044 if (seq->args[0] > 0)
7045 num = seq->args[0];
7046
7047 bte_page_scroll_down(screen->page,
7048 num,
7049 &screen->state.attr,
7050 screen->age,
7051 NULL__null);
7052#endif
7053
7054 /* Scroll the text down N lines, but don't move the cursor. */
7055 auto value = std::max(seq.collect1(0, 1), int(1));
7056 scroll_text(value);
7057}
7058
7059void
7060Terminal::SD_OR_XTERM_IHMT(bte::parser::Sequence const& seq)
7061{
7062 /*
7063 * There's a conflict between SD and XTERM IHMT that we
7064 * have to resolve by checking the parameter count.
7065 * XTERM_IHMT needs exactly 5 arguments, SD takes 0 or 1.
7066 */
7067 if (seq.size_final() <= 1)
7068 SD(seq);
7069 #ifdef PARSER_INCLUDE_NOP
7070 else
7071 XTERM_IHMT(seq);
7072 #endif
7073}
7074
7075void
7076Terminal::SDS(bte::parser::Sequence const& seq)
7077{
7078 /*
7079 * SDS - start directed string
7080 *
7081 * Arguments:
7082 * args[0]: direction
7083 * 0 = End of directed string
7084 * 1 = Start of LTR string
7085 * 2 = Start of RTL string
7086 *
7087 * Defaults:
7088 * args[0]: 0
7089 *
7090 * References: ECMA-48 § 8.3.114
7091 */
7092}
7093
7094void
7095Terminal::SEE(bte::parser::Sequence const& seq)
7096{
7097 /*
7098 * SEE - select editing extent
7099 *
7100 * Arguments:
7101 * args[0]: extent
7102 * 0 = ...
7103 * 1 = ...
7104 * 2 = ...
7105 * 3 = ...
7106 * 4 = ...
7107 *
7108 * Defaults:
7109 * args[0]: 0
7110 *
7111 * References: ECMA-48 § 8.3.115
7112 */
7113}
7114
7115void
7116Terminal::SEF(bte::parser::Sequence const& seq)
7117{
7118 /*
7119 * SEF - sheet eject and feed
7120 *
7121 * Arguments:
7122 * args[0]:
7123 * args[1]:
7124 *
7125 * Defaults:
7126 * args[0]: 0
7127 * args[1]: 0
7128 *
7129 * References: ECMA-48 § 8.3.116
7130 *
7131 * Probably not worth implementing.
7132 */
7133}
7134
7135void
7136Terminal::SGR(bte::parser::Sequence const& seq)
7137{
7138 /*
7139 * SGR - select-graphics-rendition
7140 * Selects the character attributes to use for newly inserted
7141 * characters.
7142 *
7143 * Arguments:
7144 * args[0:]: the attributes
7145 * 0 = reset all attributes
7146 *
7147 * Defaults:
7148 * args[0]: 0 (reset all attributes)
7149 *
7150 * References: ECMA-48 § 8.3.117
7151 * VT525
7152 */
7153 auto const n_params = seq.size();
7154
7155 /* If we had no parameters, default to the defaults. */
7156 if (n_params == 0) {
7157 reset_default_attributes(false);
7158 return;
7159 }
7160
7161 for (unsigned int i = 0; i < n_params; i = seq.next(i)) {
7162 auto const param = seq.param(i);
7163 switch (param) {
7164 case -1:
7165 case BTE_SGR_RESET_ALL:
7166 reset_default_attributes(false);
7167 break;
7168 case BTE_SGR_SET_BOLD:
7169 m_defaults.attr.set_bold(true);
7170 break;
7171 case BTE_SGR_SET_DIM:
7172 m_defaults.attr.set_dim(true);
7173 break;
7174 case BTE_SGR_SET_ITALIC:
7175 m_defaults.attr.set_italic(true);
7176 break;
7177 case BTE_SGR_SET_UNDERLINE: {
7178 unsigned int v = 1;
7179 /* If we have a subparameter, get it */
7180 if (seq.param_nonfinal(i)) {
7181 v = seq.param(i + 1, 1, 0, 3);
7182 }
7183 m_defaults.attr.set_underline(v);
7184 break;
7185 }
7186 case BTE_SGR_SET_BLINK:
7187 case BTE_SGR_SET_BLINK_RAPID:
7188 m_defaults.attr.set_blink(true);
7189 break;
7190 case BTE_SGR_SET_REVERSE:
7191 m_defaults.attr.set_reverse(true);
7192 break;
7193 case BTE_SGR_SET_INVISIBLE:
7194 m_defaults.attr.set_invisible(true);
7195 break;
7196 case BTE_SGR_SET_STRIKETHROUGH:
7197 m_defaults.attr.set_strikethrough(true);
7198 break;
7199 case BTE_SGR_SET_UNDERLINE_DOUBLE:
7200 m_defaults.attr.set_underline(2);
7201 break;
7202 case BTE_SGR_RESET_BOLD_AND_DIM:
7203 m_defaults.attr.unset(BTE_ATTR_BOLD_MASK((((1U << ((1))) - 1U) << ((((0) + (4)) + (1))))) | BTE_ATTR_DIM_MASK((((1U << ((1))) - 1U) << (((((((((((0) + (4)) + (
1)) + (1)) + (1)) + (2)) + (1)) + (1)) + (1)) + (1)))))
);
7204 break;
7205 case BTE_SGR_RESET_ITALIC:
7206 m_defaults.attr.set_italic(false);
7207 break;
7208 case BTE_SGR_RESET_UNDERLINE:
7209 m_defaults.attr.set_underline(0);
7210 break;
7211 case BTE_SGR_RESET_BLINK:
7212 m_defaults.attr.set_blink(false);
7213 break;
7214 case BTE_SGR_RESET_REVERSE:
7215 m_defaults.attr.set_reverse(false);
7216 break;
7217 case BTE_SGR_RESET_INVISIBLE:
7218 m_defaults.attr.set_invisible(false);
7219 break;
7220 case BTE_SGR_RESET_STRIKETHROUGH:
7221 m_defaults.attr.set_strikethrough(false);
7222 break;
7223 case BTE_SGR_SET_FORE_LEGACY_START ... BTE_SGR_SET_FORE_LEGACY_END:
7224 m_defaults.attr.set_fore(BTE_LEGACY_COLORS_OFFSET(1U << 9) + (param - 30));
7225 break;
7226 case BTE_SGR_SET_FORE_SPEC: {
7227 uint32_t fore;
7228 if (G_LIKELY((seq_parse_sgr_color<8, 8, 8>(seq, i, fore)))(__builtin_expect (__extension__ ({ int _g_boolean_var_; if (
(seq_parse_sgr_color<8, 8, 8>(seq, i, fore))) _g_boolean_var_
= 1; else _g_boolean_var_ = 0; _g_boolean_var_; }), 1))
)
7229 m_defaults.attr.set_fore(fore);
7230 break;
7231 }
7232 case BTE_SGR_RESET_FORE:
7233 /* default foreground */
7234 m_defaults.attr.set_fore(BTE_DEFAULT_FG256);
7235 break;
7236 case BTE_SGR_SET_BACK_LEGACY_START ... BTE_SGR_SET_BACK_LEGACY_END:
7237 m_defaults.attr.set_back(BTE_LEGACY_COLORS_OFFSET(1U << 9) + (param - 40));
7238 break;
7239 case BTE_SGR_SET_BACK_SPEC: {
7240 uint32_t back;
7241 if (G_LIKELY((seq_parse_sgr_color<8, 8, 8>(seq, i, back)))(__builtin_expect (__extension__ ({ int _g_boolean_var_; if (
(seq_parse_sgr_color<8, 8, 8>(seq, i, back))) _g_boolean_var_
= 1; else _g_boolean_var_ = 0; _g_boolean_var_; }), 1))
)
7242 m_defaults.attr.set_back(back);
7243 break;
7244 }
7245 case BTE_SGR_RESET_BACK:
7246 /* default background */
7247 m_defaults.attr.set_back(BTE_DEFAULT_BG257);
7248 break;
7249 case BTE_SGR_SET_OVERLINE:
7250 m_defaults.attr.set_overline(true);
7251 break;
7252 case BTE_SGR_RESET_OVERLINE:
7253 m_defaults.attr.set_overline(false);
7254 break;
7255 case BTE_SGR_SET_DECO_SPEC: {
7256 uint32_t deco;
7257 if (G_LIKELY((seq_parse_sgr_color<4, 5, 4>(seq, i, deco)))(__builtin_expect (__extension__ ({ int _g_boolean_var_; if (
(seq_parse_sgr_color<4, 5, 4>(seq, i, deco))) _g_boolean_var_
= 1; else _g_boolean_var_ = 0; _g_boolean_var_; }), 1))
)
7258 m_defaults.attr.set_deco(deco);
7259 break;
7260 }
7261 case BTE_SGR_RESET_DECO:
7262 /* default decoration color, that is, same as the cell's foreground */
7263 m_defaults.attr.set_deco(BTE_DEFAULT_FG256);
7264 break;
7265 case BTE_SGR_SET_FORE_LEGACY_BRIGHT_START ... BTE_SGR_SET_FORE_LEGACY_BRIGHT_END:
7266 m_defaults.attr.set_fore(BTE_LEGACY_COLORS_OFFSET(1U << 9) + (param - 90) +
7267 BTE_COLOR_BRIGHT_OFFSET8);
7268 break;
7269 case BTE_SGR_SET_BACK_LEGACY_BRIGHT_START ... BTE_SGR_SET_BACK_LEGACY_BRIGHT_END:
7270 m_defaults.attr.set_back(BTE_LEGACY_COLORS_OFFSET(1U << 9) + (param - 100) +
7271 BTE_COLOR_BRIGHT_OFFSET8);
7272 break;
7273 }
7274 }
7275
7276 /* Save the new colors. */
7277 m_color_defaults.attr.copy_colors(m_defaults.attr);
7278}
7279
7280void
7281Terminal::SHS(bte::parser::Sequence const& seq)
7282{
7283 /*
7284 * SHS - select character spacing
7285 *
7286 * Arguments:
7287 * args[0]: spacing (in the unit set by SSU)
7288 *
7289 * Defaults:
7290 * args[0]: 0
7291 *
7292 * References: ECMA-48 § 8.3.118
7293 *
7294 * Not applicable in BTE.
7295 */
7296}
7297
7298void
7299Terminal::SIMD(bte::parser::Sequence const& seq)
7300{
7301 /*
7302 * SIMD - select implicit movement direction
7303 *
7304 * Arguments:
7305 * args[0]: direction
7306 * 0 = character progression
7307 * 1 = opposite of character progression
7308 *
7309 * Defaults:
7310 * args[0]: 0
7311 *
7312 * References: ECMA-48 § 8.3.120
7313 */
7314}
7315
7316void
7317Terminal::SL(bte::parser::Sequence const& seq)
7318{
7319 /*
7320 * SL - scroll left
7321 *
7322 * Arguments:
7323 * args[0]: number of character positions (presentation)
7324 *
7325 * Defaults:
7326 * args[0]: 1
7327 *
7328 * References: ECMA-48 § 8.3.121
7329 *
7330 * Probably not worth implementing.
7331 */
7332}
7333
7334void
7335Terminal::SLH(bte::parser::Sequence const& seq)
7336{
7337 /*
7338 * SLH - set line home
7339 *
7340 * Arguments:
7341 * args[0]: position in the active line
7342 *
7343 * Defaults:
7344 * args[0]: no default
7345 *
7346 * Depending on DCSM, this function works on the presentation
7347 * or data position. Terminal-wg/bidi forces DCSM to DATA.
7348 *
7349 * References: ECMA-48 § 8.3.122
7350 * Terminal-wg/bidi
7351 */
7352}
7353
7354void
7355Terminal::SLL(bte::parser::Sequence const& seq)
7356{
7357 /*
7358 * SLL - set line limit
7359 *
7360 * Arguments:
7361 * args[0]: position in the active line
7362 *
7363 * Defaults:
7364 * args[0]: no default
7365 *
7366 * Depending on DCSM, this function works on the presentation
7367 * or data position. Terminal-wg/bidi forces DCSM to DATA.
7368 *
7369 * References: ECMA-48 § 8.3.123
7370 * Terminal-wg/bidi
7371 */
7372}
7373
7374void
7375Terminal::SLS(bte::parser::Sequence const& seq)
7376{
7377 /*
7378 * SLS - set line spacing
7379 *
7380 * Arguments:
7381 * args[0]: spacing (in the unit set by SSU)
7382 *
7383 * Defaults:
7384 * args[0]: no default
7385 *
7386 * References: ECMA-48 § 8.3.124
7387 *
7388 * Not applicable in BTE.
7389 */
7390}
7391
7392void
7393Terminal::SM_ECMA(bte::parser::Sequence const& seq)
7394{
7395 /*
7396 * SM_ECMA - set-mode-ecma
7397 *
7398 * Defaults: none
7399 *
7400 * References: ECMA-48 § 8.3.125
7401 */
7402
7403 set_mode_ecma(seq, true);
7404}
7405
7406void
7407Terminal::SM_DEC(bte::parser::Sequence const& seq)
7408{
7409 /*
7410 * SM_DEC - set-mode-dec
7411 * This is the same as SM_ECMA but for DEC modes.
7412 *
7413 * Defaults: none
7414 *
7415 * References: VT525
7416 */
7417
7418 set_mode_private(seq, true);
7419}
7420
7421void
7422Terminal::SOH(bte::parser::Sequence const& seq)
7423{
7424 /*
7425 * SOH - start of heading
7426 *
7427 * References: ECMA-48 § 8.3.127
7428 * ECMA-16 § 3.1.1
7429 */
7430}
7431
7432void
7433Terminal::SPA(bte::parser::Sequence const& seq)
7434{
7435 /*
7436 * SPA - start of protected area
7437 * Marks the start of an area of positions (presentation)
7438 * that are protected; the end of the area will be
7439 * marked by EPA.
7440 *
7441 * The contents of the area will be protected against
7442 * alteration, transfer (depending on the GATM setting),
7443 * and erasure (depending on the ERM setting).
7444 *
7445 * References: ECMA-48 § 8.3.129
7446 */
7447}
7448
7449void
7450Terminal::SPD(bte::parser::Sequence const& seq)
7451{
7452 /*
7453 * SPD - select presentation directions
7454 *
7455 * Arguments:
7456 * args[0]: line orientation, progression, character path
7457 * 0 = horizontal, TTB, LTR
7458 * 1 = vertical, RTL, TTB
7459 * 2 = vertical, LTR, TTB
7460 * 3 = horizontal, TTB, RTL
7461 * 4 = vertical, LTR, BTT
7462 * 5 = horizontal, BTT, RTL
7463 * 6 = horizontal, BTT, LTR
7464 * 7 = vertical, RTL, BTT
7465 *
7466 * args[1]: effect
7467 * 0 = implementation-defined
7468 * 1 = ...
7469 * 2 = ...
7470 *
7471 * Defaults:
7472 * args[0]: 0
7473 * args[1]: 0
7474 *
7475 * References: ECMA-48 § 8.3.130
7476 * Terminal-wg/bidi
7477 */
7478
7479 auto const param = seq.collect1(0);
7480 switch (param) {
7481 case -1:
7482 case 0:
7483 m_bidi_rtl = FALSE(0);
7484 _bte_debug_print(BTE_DEBUG_BIDI, "BiDi: switch to LTR\n")do { } while(0);
7485 break;
7486 case 3:
7487 m_bidi_rtl = TRUE(!(0));
7488 _bte_debug_print(BTE_DEBUG_BIDI, "BiDi: switch to RTL\n")do { } while(0);
7489 break;
7490 default:
7491 return;
7492 }
7493
7494 maybe_apply_bidi_attributes(BTE_BIDI_FLAG_RTL);
7495
7496 /* FIXME maybe apply to all the onscreen lines? */
7497}
7498
7499void
7500Terminal::SPH(bte::parser::Sequence const& seq)
7501{
7502 /*
7503 * SPH - set page home
7504 *
7505 * Arguments:
7506 * args[0]: position in the active page
7507 *
7508 * Defaults:
7509 * args[0]: no default
7510 *
7511 * Depending on DCSM, this function works on the presentation
7512 * or data position. Terminal-wg/bidi forces DCSM to DATA.
7513 *
7514 * References: ECMA-48 § 8.3.131
7515 * Terminal-wg/bidi
7516 */
7517}
7518
7519void
7520Terminal::SPI(bte::parser::Sequence const& seq)
7521{
7522 /*
7523 * SPI - spacing increment
7524 * Set line and character spacing for following text.
7525 *
7526 * Arguments:
7527 * args[0]: line spacing (in the unit set by SSU)
7528 * args[0]: character spacing (in the unit set by SSU)
7529 *
7530 * Defaults:
7531 * args[0]: no default
7532 * args[1]: no default
7533 *
7534 * References: ECMA-48 § 8.3.132
7535 */
7536}
7537
7538void
7539Terminal::SPL(bte::parser::Sequence const& seq)
7540{
7541 /*
7542 * SPL - set page limit
7543 *
7544 * Arguments:
7545 * args[0]: line position in the active page
7546 *
7547 * Defaults:
7548 * args[0]: no default
7549 *
7550 * Depending on DCSM, this function works on the presentation
7551 * or data position. Terminal-wg/bidi forces DCSM to DATA.
7552 *
7553 * References: ECMA-48 § 8.3.133
7554 * Terminal-wg/bidi
7555 */
7556}
7557
7558void
7559Terminal::SPQR(bte::parser::Sequence const& seq)
7560{
7561 /*
7562 * SPQR - select print quality and rapidity
7563 *
7564 * Arguments:
7565 * args[0]:
7566 *
7567 * Defaults:
7568 * args[0]: no default
7569 *
7570 * References: ECMA-48 § 8.3.134
7571 */
7572}
7573
7574void
7575Terminal::SR(bte::parser::Sequence const& seq)
7576{
7577 /*
7578 * SL - scroll right
7579 *
7580 * Arguments:
7581 * args[0]: number of character positions (presentation)
7582 *
7583 * Defaults:
7584 * args[0]: 1
7585 *
7586 * References: ECMA-48 § 8.3.135
7587 *
7588 * Probably not worth implementing.
7589 */
7590}
7591
7592void
7593Terminal::SRCS(bte::parser::Sequence const& seq)
7594{
7595 /*
7596 * SRCS - set reduced character separation
7597 *
7598 * Arguments:
7599 * args[0]: spacing (in the unit set by SSU)
7600 *
7601 * Defaults:
7602 * args[0]: 0
7603 *
7604 * References: ECMA-48 § 8.3.136
7605 *
7606 * Not applicable in BTE.
7607 */
7608}
7609
7610void
7611Terminal::SRS(bte::parser::Sequence const& seq)
7612{
7613 /*
7614 * SRS - start reversed string
7615 *
7616 * Arguments:
7617 * args[0]: direction
7618 * 0 = End of reversed string
7619 * 1 = Start of reversed string
7620 *
7621 * Defaults:
7622 * args[0]: 0
7623 *
7624 * References: ECMA-48 § 8.3.137
7625 */
7626}
7627
7628void
7629Terminal::SSA(bte::parser::Sequence const& seq)
7630{
7631 /*
7632 * SSA - start of selected area
7633 * Marks the start of an area of positions (presentation)
7634 * that are selected for transfer; the end of the area will
7635 * be marked by ESA.
7636 *
7637 * What will actually be transmitted depends on the setting
7638 * of the GATM mode, and areas set by the DAQ and SPA/EPA
7639 * functions.
7640 *
7641 * References: ECMA-48 § 8.3.138
7642 */
7643}
7644
7645void
7646Terminal::SSU(bte::parser::Sequence const& seq)
7647{
7648 /*
7649 * SSU - set size unit
7650 *
7651 * Arguments:
7652 * args[0]: unit
7653 *
7654 * Defaults:
7655 * args[0]: 0
7656 *
7657 * References: ECMA-48 § 8.3.139
7658 */
7659}
7660
7661void
7662Terminal::SSW(bte::parser::Sequence const& seq)
7663{
7664 /*
7665 * SSW - set space width
7666 *
7667 * Arguments:
7668 * args[0]: width (in the unit set by SSU)
7669 *
7670 * Defaults:
7671 * args[0]: no default
7672 *
7673 * References: ECMA-48 § 8.3.140
7674 */
7675}
7676
7677void
7678Terminal::SS2(bte::parser::Sequence const& seq)
7679{
7680 /*
7681 * SS2 - single-shift-2
7682 * Temporarily map G2 into GL for the next graphics character.
7683 *
7684 * References: ECMA-35 § 8.4, 9.4
7685 * ECMA-48 § 8.3.141
7686 * VT525
7687 */
7688#if 0
7689 screen->state.glt = &screen->g2;
7690#endif
7691}
7692
7693void
7694Terminal::SS3(bte::parser::Sequence const& seq)
7695{
7696 /*
7697 * SS3 - single-shift-3
7698 * Temporarily map G3 into GL for the next graphics character
7699 *
7700 * References: ECMA-35 § 8.4, 9.4
7701 * ECMA-48 § 8.3.142
7702 * VT525
7703 */
7704#if 0
7705 screen->state.glt = &screen->g3;
7706#endif
7707}
7708
7709void
7710Terminal::ST(bte::parser::Sequence const& seq)
7711{
7712 /*
7713 * ST - string-terminator
7714 * The string-terminator is usually part of control-sequences and
7715 * handled by the parser. In all other situations it is silently
7716 * ignored.
7717 *
7718 * References: ECMA-48 § 8.3.143
7719 */
7720}
7721
7722void
7723Terminal::STAB(bte::parser::Sequence const& seq)
7724{
7725 /*
7726 * STAB - selective tabulation
7727 *
7728 * Arguments:
7729 * args[0]:
7730 *
7731 * Defaults:
7732 * args[0]: no default
7733 *
7734 * References: ECMA-48 § 8.3.144
7735 * ITU-T Rec. T.416 (Open Document Architecture)
7736 */
7737}
7738
7739void
7740Terminal::STS(bte::parser::Sequence const& seq)
7741{
7742 /*
7743 * STS - set transmit state
7744 *
7745 * References: ECMA-48 § 8.3.145
7746 *
7747 * Not worth implementing.
7748 */
7749}
7750
7751void
7752Terminal::STX(bte::parser::Sequence const& seq)
7753{
7754 /*
7755 * STX - start of text
7756 *
7757 * References: ECMA-48 § 8.3.146
7758 * ECMA-16 § 3.1.2
7759 *
7760 * Not worth implementing.
7761 */
7762}
7763
7764void
7765Terminal::SU(bte::parser::Sequence const& seq)
7766{
7767 /*
7768 * SU - scroll-up / pan down
7769 * Scrolls up a number of lines (presentation).
7770 *
7771 * Arguments:
7772 * args[0]: number of lines to scroll
7773 *
7774 * Defaults:
7775 * args[0]: 1
7776 *
7777 * References: EMCA-48 § 8.3.147
7778 * VT525
7779 */
7780#if 0
7781 unsigned int num = 1;
7782
7783 if (seq->args[0] > 0)
7784 num = seq->args[0];
7785
7786 bte_page_scroll_up(screen->page,
7787 num,
7788 &screen->state.attr,
7789 screen->age,
7790 screen->history);
7791#endif
7792
7793 auto value = std::max(seq.collect1(0, 1), int(1));
7794 scroll_text(-value);
7795}
7796
7797void
7798Terminal::SUB(bte::parser::Sequence const& seq)
7799{
7800 /*
7801 * SUB - substitute
7802 * Cancel the current control-sequence and print a replacement
7803 * character. Our parser already handles this so all we have to do is
7804 * print the replacement character.
7805 *
7806 * References: ECMA-48 § 8.3.148
7807 */
7808
7809 insert_char(0xfffdu, false, true);
7810}
7811
7812void
7813Terminal::SVS(bte::parser::Sequence const& seq)
7814{
7815 /*
7816 * SVS - select line spacing
7817 *
7818 * Arguments:
7819 * args[0]: spacing
7820 * 0 = ...
7821 * ...
7822 * 9 = ...
7823 *
7824 * Defaults:
7825 * args[0]: 0
7826 *
7827 * References: ECMA-48 § 8.3.149
7828 */
7829}
7830
7831void
7832Terminal::SYN(bte::parser::Sequence const& seq)
7833{
7834 /*
7835 * SYN - synchronous idle
7836 *
7837 * References: ECMA-48 § 8.3.150
7838 * ECMA-16 § 3.1.9
7839 *
7840 * Not worth implementing.
7841 */
7842}
7843
7844void
7845Terminal::TAC(bte::parser::Sequence const& seq)
7846{
7847 /*
7848 * TAC - tabulation aligned centre
7849 *
7850 * Defaults:
7851 * args[0]: no default
7852 *
7853 * References: ECMA-48 § 8.3.151
7854 */
7855}
7856
7857void
7858Terminal::TALE(bte::parser::Sequence const& seq)
7859{
7860 /*
7861 * TALE - tabulation aligned leading edge
7862 *
7863 * Defaults:
7864 * args[0]: no default
7865 *
7866 * References: ECMA-48 § 8.3.152
7867 */
7868}
7869
7870void
7871Terminal::TATE(bte::parser::Sequence const& seq)
7872{
7873 /*
7874 * TATE - tabulation aligned trailing edge
7875 *
7876 * Defaults:
7877 * args[0]: no default
7878 *
7879 * References: ECMA-48 § 8.3.153
7880 */
7881}
7882
7883void
7884Terminal::TBC(bte::parser::Sequence const& seq)
7885{
7886 /*
7887 * TBC - tab-clear
7888 * Clears tab stops.
7889 *
7890 * Arguments:
7891 * args[0]: mode
7892 *
7893 * Defaults:
7894 * args[0]: 0
7895 *
7896 * References: ECMA-48 § 8.3.154
7897 */
7898
7899 auto const param = seq.collect1(0);
7900 switch (param) {
7901 case -1:
7902 case 0:
7903 /* Clear character tabstop at the current presentation position */
7904 m_tabstops.unset(get_cursor_column());
7905 break;
7906 case 1:
7907 /* Clear line tabstop at the current line */
7908 break;
7909 case 2:
7910 /* Clear all character tabstops in the current line */
7911 /* NOTE: vttest issues this but claims it's a 'no-op' */
7912 m_tabstops.clear();
7913 break;
7914 case 3:
7915 /* Clear all character tabstops */
7916 m_tabstops.clear();
7917 break;
7918 case 4:
7919 /* Clear all line tabstops */
7920 break;
7921 case 5:
7922 /* Clear all (character and line) tabstops */
7923 m_tabstops.clear();
7924 break;
7925 default:
7926 break;
7927 }
7928}
7929
7930void
7931Terminal::TCC(bte::parser::Sequence const& seq)
7932{
7933 /*
7934 * TCC - tabulation centred on character
7935 *
7936 * Defaults:
7937 * args[0]: no default
7938 * args[1]: 32 (SPACE)
7939 *
7940 * References: ECMA-48 § 8.3.155
7941 */
7942}
7943
7944void
7945Terminal::TSR(bte::parser::Sequence const& seq)
7946{
7947 /*
7948 * TSR - tabulation stop remove
7949 * This clears a tab stop at position @arg[0] in the active line (presentation),
7950 * and on any lines below it.
7951 *
7952 * Defaults:
7953 * args[0]: no default
7954 *
7955 * References: ECMA-48 § 8.3.156
7956 */
7957
7958 auto const pos = seq.collect1(0);
7959 if (pos < 1 || pos > m_column_count)
7960 return;
7961
7962 m_tabstops.unset(pos - 1);
7963}
7964
7965void
7966Terminal::TSS(bte::parser::Sequence const& seq)
7967{
7968 /*
7969 * TSS - thin space specification
7970 *
7971 * Arguments:
7972 * args[0]: width (in the unit set by SSU)
7973 *
7974 * Defaults:
7975 * args[0]: no default
7976 *
7977 * References: ECMA-48 § 8.3.157
7978 *
7979 * Not applicable in BTE.
7980 */
7981}
7982
7983void
7984Terminal::VPA(bte::parser::Sequence const& seq)
7985{
7986 /*
7987 * VPA - vertical line position absolute
7988 * Moves the cursor to the specified line on the current column (data).
7989 *
7990 * Arguments:
7991 * args[0]: line number
7992 *
7993 * Defaults:
7994 * args[0]: 1
7995 *
7996 * References: ECMA-48 § 8.3.158
7997 * VT525
7998 */
7999#if 0
8000 unsigned int pos = 1;
8001
8002 if (seq->args[0] > 0)
8003 pos = seq->args[0];
8004
8005 screen_cursor_clear_wrap(screen);
8006 screen_cursor_set_rel(screen, screen->state.cursor_x, pos - 1);
8007#endif
8008
8009 // FIXMEchpe shouldn't we ensure_cursor_is_onscreen AFTER setting the new cursor row?
8010 ensure_cursor_is_onscreen();
8011
8012 auto value = seq.collect1(0, 1, 1, m_row_count);
8013 set_cursor_row1(value);
8014}
8015
8016void
8017Terminal::VPB(bte::parser::Sequence const& seq)
8018{
8019 /*
8020 * VPB - line position backward
8021 * Moves the cursor up the specified number of lines on
8022 * the current column (data).
8023 *
8024 * Arguments:
8025 * args[0]: line number
8026 *
8027 * Defaults:
8028 * args[0]: 1
8029 *
8030 * References: ECMA-48 § 8.3.159
8031 * VT525
8032 */
8033#if 0
8034 unsigned int num = 1;
8035
8036 if (seq->args[0] > 0)
8037 num = seq->args[0];
8038
8039 screen_cursor_clear_wrap(screen);
8040 screen_cursor_down(screen, num, false);
8041#endif
8042}
8043
8044void
8045Terminal::VPR(bte::parser::Sequence const& seq)
8046{
8047 /*
8048 * VPR - vertical line position relative
8049 * Moves the cursor down the specified number of lines
8050 * on the current column (data).
8051 *
8052 * Arguments:
8053 * args[0]: line number
8054 *
8055 * Defaults:
8056 * args[0]: 1
8057 *
8058 * References: ECMA-48 § 8.3.160
8059 * VT525
8060 */
8061#if 0
8062 unsigned int num = 1;
8063
8064 if (seq->args[0] > 0)
8065 num = seq->args[0];
8066
8067 screen_cursor_clear_wrap(screen);
8068 screen_cursor_down(screen, num, false);
8069#endif
8070}
8071
8072void
8073Terminal::VT(bte::parser::Sequence const& seq)
8074{
8075 /*
8076 * VT - vertical-tab
8077 * This causes a vertical jump by one line. Terminals treat it exactly
8078 * the same as LF.
8079 *
8080 * References: ECMA-48 § 8.3.161
8081 */
8082
8083 LF(seq);
8084}
8085
8086void
8087Terminal::VTS(bte::parser::Sequence const& seq)
8088{
8089 /*
8090 * VTS - line tabulation set
8091 * Sets a tabstop in the active line (presentation).
8092 *
8093 * References: ECMA-48 § 8.3.162
8094 *
8095 * Not worth implementing.
8096 */
8097}
8098
8099void
8100Terminal::WYCAA(bte::parser::Sequence const& seq)
8101{
8102 /*
8103 * WYCAA - redefine character display attribute association
8104 *
8105 * Arguments:
8106 * args[0]: mode
8107 *
8108 * Defaults:
8109 * args[0]: no defaults
8110 *
8111 * Probably not worth implementing.
8112 *
8113 * References: WY370
8114 */
8115
8116 switch (seq.collect1(0)) {
8117 case -1:
8118 break;
8119
8120 case 0 ... 47:
8121 /* WYCAA - redefine character attribute association
8122 *
8123 * Arguments:
8124 * args[0]: character attribute association to be set (0…47)
8125 * args[1]: palette color index for foreground color (0…64)
8126 * args[2]: palette color index for background color (0…64)
8127 * args[3]: new definition for the attribute association @args[0]
8128 *
8129 * Defaults:
8130 * args[0]: ?
8131 * args[1]: ?
8132 * args[2]: ?
8133 * args[3]: ?
8134 */
8135 break;
8136
8137 case 48:
8138 /* WYCOLOR - select foreground color palette
8139 *
8140 * Arguments:
8141 * args[1]: color palette number 0…7
8142 *
8143 * Defaults:
8144 * args[1]: ?
8145 */
8146 break;
8147
8148 case 49:
8149 case 51 ... 52:
8150 /* WYCOLOR - select background (49)/screen border(51)/cursor(52) color
8151 * Selects the background (and screen border) color.
8152 *
8153 * Arguments:
8154 * args[1]: palette color index 0…64
8155 *
8156 * Defaults:
8157 * args[1]: ?
8158 */
8159 break;
8160
8161 case 50:
8162 /* WYCOLOR - restore fore- and background colors to set-up default */
8163 break;
8164
8165 case 53:
8166 /* WYSOVR - select overstrike position
8167 *
8168 * Arguments:
8169 * args[1]: scanline number in the charcell (0=top, …bottom) to
8170 * put the overstrike
8171 *
8172 * Defaults:
8173 * args[1]:
8174 */
8175 break;
8176
8177 case 54 ... 57:
8178 /* WYCOLOR - select attributes and colors
8179 * for user status line (54), system status line(55),
8180 * replacement character(56), noneraseable character(57).
8181 *
8182 * Arguments:
8183 * args[1]:
8184 * args[2]:
8185 *
8186 * Defaults:
8187 * args[1]:
8188 * args[2]:
8189 */
8190
8191 case 58:
8192 /* WYDTSET - set date and time */
8193 break;
8194
8195 case 59:
8196 /* WYDFPG - define page for session
8197 *
8198 * Arguments:
8199 * args[1]:
8200 * args[2]:
8201 * args[3]:
8202 * args[4]:
8203 *
8204 * Defaults:
8205 * args[1]:
8206 * args[2]:
8207 * args[3]:
8208 * args[4]:
8209 */
8210 break;
8211
8212 case 60:
8213 /* WYIND - restore default color index values */
8214 break;
8215
8216 case 61 ... 62:
8217 case 64 ... 65:
8218 /* WYIND - set current fore/background color
8219 * Sets the current fore- (61, 64) or background (62, 65)
8220 * color for eraseable (61, 62) or noneraseable (64, 65)
8221 * characters.
8222 *
8223 * Also turns on color index mode.
8224 *
8225 * Arguments:
8226 * args[1]: color index
8227 *
8228 * Defaults:
8229 * args[1]: ?
8230 */
8231 break;
8232
8233 case 63:
8234 /* WYIND - turn color index mode on/off
8235 *
8236 * Arguments:
8237 * args[1]: setting (0 = off, 1 = on)
8238 *
8239 * Defaults:
8240 * args[1]: ?
8241 */
8242 break;
8243
8244 case 66:
8245 /* WYIND - redefine color index
8246 *
8247 * Arguments:
8248 * args[1]: index
8249 * args[2]: value
8250 *
8251 * Defaults:
8252 * args[1]: ?
8253 * args[2]: ?
8254 */
8255 break;
8256 }
8257}
8258
8259void
8260Terminal::WYDHL_BH(bte::parser::Sequence const& seq)
8261{
8262 /*
8263 * WYDHL_BH - single width double height line: bottom half
8264 *
8265 * Probably not worth implementing.
8266 *
8267 * References: WY370
8268 */
8269}
8270
8271void
8272Terminal::WYDHL_TH(bte::parser::Sequence const& seq)
8273{
8274 /*
8275 * WYDHL_TH - single width double height line: top half
8276 *
8277 * Probably not worth implementing.
8278 *
8279 * References: WY370
8280 */
8281}
8282
8283void
8284Terminal::WYSCRATE(bte::parser::Sequence const& seq)
8285{
8286 /*
8287 * WYSCRATE - set smooth scroll rate
8288 * Selects scrolling rate if DECSCLM is set.
8289 *
8290 * Probably not worth implementing.
8291 *
8292 * References: WY370
8293 */
8294}
8295
8296void
8297Terminal::WYLSFNT(bte::parser::Sequence const& seq)
8298{
8299 /*
8300 * WYLSFNT - load soft font
8301 *
8302 * Probably not worth implementing.
8303 *
8304 * References: WY370
8305 */
8306}
8307
8308void
8309Terminal::XDGSYNC(bte::parser::Sequence const& seq)
8310{
8311 /*
8312 * XDGSYNC - synchronous update
8313 * Content received between BSU and ESU will be committed
8314 * atomically on ESU. This is to avoid half-drawn screen
8315 * content.
8316 * The terminal may ignore this, or apply a timeout, or
8317 * terminate the synchronous update prematurely for any
8318 * reason.
8319 *
8320 * Arguments:
8321 * args[0]:
8322 * 1: start (begin synchronous update, BSU)
8323 * 2: end (end synchronous update, ESU)
8324 *
8325 * Defaults:
8326 * args[0]: no defaults
8327 *
8328 * References: https://gitlab.com/gnachman/iterm2/wikis/synchronized-updates-spec
8329 */
8330
8331 /* TODO: implement this! https://gitlab.gnome.org/GNOME/bte/issues/15 */
8332}
8333
8334void
8335Terminal::XTERM_CHECKSUM_MODE(bte::parser::Sequence const& seq)
8336{
8337 /*
8338 * XTERM_CHECKSUM_MODE - xterm DECRQCRA checksum mode
8339 * Sets how DECRQCRA calculates the area checksum.
8340 *
8341 * Arguments:
8342 * args[0]: flag value composed of the following flags:
8343 * 1: no negation
8344 * 2: don't report attributes
8345 * 4: checksum trailing blanks
8346 * 8: don't checksum empty cells
8347 * 16: no 8-bit masking or ignoring combining characters
8348 * 32: no 7-bit masking
8349 *
8350 * Defaults:
8351 * args[0]: 0, matching the output from VTxxx terminals
8352 *
8353 * References: XTERM (since 335)
8354 *
8355 * Probably not worth implementing.
8356 */
8357}
8358
8359void
8360Terminal::XTERM_IHMT(bte::parser::Sequence const& seq)
8361{
8362 /*
8363 * XTERM_IHMT - xterm-initiate-highlight-mouse-tracking
8364 *
8365 * Probably not worth implementing.
8366 */
8367}
8368
8369void
8370Terminal::XTERM_MLHP(bte::parser::Sequence const& seq)
8371{
8372 /*
8373 * XTERM_MLHP - xterm-memory-lock-hp-bugfix
8374 *
8375 * Probably not worth implementing.
8376 */
8377}
8378
8379void
8380Terminal::XTERM_MUHP(bte::parser::Sequence const& seq)
8381{
8382 /*
8383 * XTERM_MUHP - xterm-memory-unlock-hp-bugfix
8384 *
8385 * Probably not worth implementing.
8386 */
8387}
8388
8389void
8390Terminal::XTERM_RPM(bte::parser::Sequence const& seq)
8391{
8392 /*
8393 * XTERM_RPM - xterm restore DEC private mode
8394 *
8395 * Defaults: none
8396 *
8397 * References: XTERM
8398 */
8399
8400 save_mode_private(seq, false);
8401}
8402
8403void
8404Terminal::XTERM_RQTCAP(bte::parser::Sequence const& seq)
8405{
8406 /*
8407 * XTERM_TQTCAP - xterm request termcap/terminfo
8408 *
8409 * Probably not worth implementing.
8410 */
8411}
8412
8413void
8414Terminal::XTERM_RRV(bte::parser::Sequence const& seq)
8415{
8416 /*
8417 * XTERM_RRV - xterm-reset-resource-value
8418 *
8419 * Probably not worth implementing.
8420 */
8421}
8422
8423void
8424Terminal::XTERM_RTM(bte::parser::Sequence const& seq)
8425{
8426 /*
8427 * XTERM_RTM - xterm-reset-title-mode
8428 *
8429 * Probably not worth implementing.
8430 */
8431}
8432
8433void
8434Terminal::XTERM_SGFX(bte::parser::Sequence const& seq)
8435{
8436 /*
8437 * XTERM_SGFX - xterm-sixel-graphics
8438 *
8439 * Probably not worth implementing.
8440 */
8441}
8442
8443void
8444Terminal::XTERM_SGR_REPORT(bte::parser::Sequence const& seq)
8445{
8446 /*
8447 * XTERM_SGR_REPORT: report SGR attributes in rectangular area
8448 * Report common character attributes in the specified rectangle.
8449 *
8450 * Arguments;
8451 * args[0..3]: top, left, bottom, right of the rectangle (1-based)
8452 *
8453 * Defaults:
8454 * args[0]: 1
8455 * args[1]: 1
8456 * args[2]: height of current page
8457 * args[3]: width of current page
8458 *
8459 * Reply: SGR
8460 *
8461 * If the top > bottom or left > right, the command is ignored.
8462 *
8463 * These coordinates are interpreted according to origin mode (DECOM),
8464 * but unaffected by the page margins (DECSLRM?).
8465 *
8466 * Note: DECSACE selects whether this function operates on the
8467 * rectangular area or the data stream between the star and end
8468 * positions.
8469 *
8470 * References: XTERM 334
8471 */
8472 /* TODO: Implement this */
8473}
8474
8475void
8476Terminal::XTERM_SGR_STACK_POP(bte::parser::Sequence const& seq)
8477{
8478 /*
8479 * XTERM_SGR_STACK_POP: pop SGR stack
8480 * Restore SGR attributes previously pushed to the stack
8481 * with XTERM_SGR_STACK_PUSH. If there is nothing on the
8482 * stack, does nothing.
8483 *
8484 * Arguments: none
8485 *
8486 * References: XTERM 334
8487 */
8488 /* TODO: Implement this: https://gitlab.gnome.org/GNOME/bte/issues/23 */
8489}
8490
8491void
8492Terminal::XTERM_SGR_STACK_PUSH(bte::parser::Sequence const& seq)
8493{
8494 /*
8495 * XTERM_SGR_STACK_PUSH: push SGR stack
8496 * Push current SGR attributes to the stack.
8497 * If the stack is full, drops the bottommost item before
8498 * pushing on the stack.
8499 *
8500 * If there are any arguments, they are interpreted as in SGR
8501 * to denote which attributes to save; if there are no arguments,
8502 * all attributes are saved.
8503 *
8504 * Arguments:
8505 * args[0:]: the attributes
8506 * 0 = save all attributes
8507 *
8508 * Defaults:
8509 * args[0]: 0 (save all attributes)
8510 *
8511 * References: XTERM 334
8512 */
8513 /* TODO: Implement this: https://gitlab.gnome.org/GNOME/bte/issues/23 */
8514}
8515
8516void
8517Terminal::XTERM_SPM(bte::parser::Sequence const& seq)
8518{
8519 /*
8520 * XTERM_SPM - xterm save DEC private mode
8521 *
8522 * Defaults: none
8523 *
8524 * References: XTERM
8525 */
8526
8527 save_mode_private(seq, true);
8528}
8529
8530void
8531Terminal::XTERM_PTRMODE(bte::parser::Sequence const& seq)
8532{
8533 /*
8534 * XTERM_PTRMODE - xterm set pointer mode
8535 *
8536 * Defaults: none
8537 *
8538 * References: XTERM
8539 *
8540 * Probably not worth implementing.
8541 */
8542}
8543
8544void
8545Terminal::XTERM_SRV(bte::parser::Sequence const& seq)
8546{
8547 /*
8548 * XTERM_SRV - xterm-set-resource-value
8549 *
8550 * Probably not worth implementing.
8551 */
8552}
8553
8554void
8555Terminal::XTERM_STM(bte::parser::Sequence const& seq)
8556{
8557 /*
8558 * XTERM_STM - xterm-set-title-mode
8559 *
8560 * Probably not worth implementing.
8561 */
8562}
8563
8564void
8565Terminal::XTERM_STCAP(bte::parser::Sequence const& seq)
8566{
8567 /*
8568 * XTERM_STCAP - xterm set termcap/terminfo
8569 *
8570 * Probably not worth implementing.
8571 */
8572}
8573
8574void
8575Terminal::XTERM_WM(bte::parser::Sequence const& seq)
8576{
8577 /*
8578 * XTERM_WM - xterm-window-management
8579 *
8580 * Window manipulation control sequences. Most of these are considered
8581 * bad ideas, but they're implemented as signals which the application
8582 * is free to ignore, so they're harmless. Handle at most one action,
8583 * see bug 741402.
8584 *
8585 * No parameter default values.
8586 *
8587 * References: XTERM
8588 * VT525
8589 */
8590
8591 #if 0
8592 char buf[128];
8593 #endif
8594
8595 int param = seq.collect1(0);
8596 switch (param) {
8597 case -1:
8598 case 0:
8599 break;
8600
8601 case BTE_XTERM_WM_RESTORE_WINDOW:
8602 m_xterm_wm_iconified = false;
8603 break;
8604
8605 case BTE_XTERM_WM_MINIMIZE_WINDOW:
8606 m_xterm_wm_iconified = true;
8607 break;
8608
8609 case BTE_XTERM_WM_SET_WINDOW_POSITION:
8610 /* No-op */
8611 break;
8612
8613 case BTE_XTERM_WM_SET_WINDOW_SIZE_PIXELS: {
8614 int width, height;
8615 seq.collect(1, {&height, &width});
8616
8617 if (width != -1 && height != -1) {
8618 _bte_debug_print(BTE_DEBUG_EMULATION,do { } while(0)
8619 "Resizing window to %dx%d pixels, grid size %dx%d.\n",do { } while(0)
8620 width, height,do { } while(0)
8621 width / int(m_cell_height), height / int(m_cell_width))do { } while(0);
8622 emit_resize_window(width / int(m_cell_height), height / int(m_cell_width));
8623 }
8624 break;
8625 }
8626
8627 case BTE_XTERM_WM_RAISE_WINDOW:
8628 break;
8629
8630 case BTE_XTERM_WM_LOWER_WINDOW:
8631 break;
8632
8633 case BTE_XTERM_WM_REFRESH_WINDOW:
8634 break;
8635
8636 case BTE_XTERM_WM_SET_WINDOW_SIZE_CELLS: {
8637 int width, height;
8638 seq.collect(1, {&height, &width});
8639
8640 if (width != -1 && height != -1) {
8641 _bte_debug_print(BTE_DEBUG_EMULATION,do { } while(0)
8642 "Resizing window to %d columns, %d rows.\n",do { } while(0)
8643 width, height)do { } while(0);
8644 emit_resize_window(width, height);
8645 }
8646 break;
8647 }
8648
8649 case BTE_XTERM_WM_MAXIMIZE_WINDOW:
8650 switch (seq.collect1(1)) {
8651 case -1: /* default */
8652 case 0:
8653 /* Restore */
8654 break;
8655 case 1:
8656 /* Maximise */
8657 break;
8658 case 2:
8659 /* Maximise Vertically */
8660 break;
8661 case 3:
8662 /* Maximise Horizontally */
8663 break;
8664 default:
8665 break;
8666 }
8667 break;
8668
8669 case BTE_XTERM_WM_FULLSCREEN_WINDOW:
8670 break;
8671
8672 case BTE_XTERM_WM_GET_WINDOW_STATE:
8673 reply(seq, BTE_REPLY_XTERM_WM, {m_xterm_wm_iconified ? 2 : 1});
8674 break;
8675
8676 case BTE_XTERM_WM_GET_WINDOW_POSITION:
8677 /* Reply with fixed origin. */
8678 reply(seq, BTE_REPLY_XTERM_WM, {3, 0, 0});
8679 break;
8680
8681 case BTE_XTERM_WM_GET_WINDOW_SIZE_PIXELS: {
8682 int width = m_row_count * m_cell_height;
8683 int height = m_column_count * m_cell_width;
8684 reply(seq, BTE_REPLY_XTERM_WM, {4, height, width});
8685 break;
8686 }
8687
8688 case BTE_XTERM_WM_GET_WINDOW_SIZE_CELLS:
8689 reply(seq, BTE_REPLY_XTERM_WM,
8690 {8, (int)m_row_count, (int)m_column_count});
8691 break;
8692
8693 case BTE_XTERM_WM_GET_SCREEN_SIZE_CELLS: {
8694 /* FIMXE: this should really report the monitor's workarea,
8695 * or even just a fixed value.
8696 */
8697 auto cdkscreen = ctk_widget_get_screen(m_widget);
8698 int height = cdk_screen_get_height(cdkscreen);
8699 int width = cdk_screen_get_width(cdkscreen);
8700 _bte_debug_print(BTE_DEBUG_EMULATION,do { } while(0)
8701 "Reporting screen size as %dx%d cells.\n",do { } while(0)
8702 height / int(m_cell_height), width / int(m_cell_width))do { } while(0);
8703
8704 reply(seq, BTE_REPLY_XTERM_WM,
8705 {9, height / int(m_cell_height), width / int(m_cell_width)});
8706 break;
8707 }
8708
8709 case BTE_XTERM_WM_GET_ICON_TITLE:
8710 /* Report a static icon title, since the real
8711 * icon title should NEVER be reported, as it
8712 * creates a security vulnerability. See
8713 * http://marc.info/?l=bugtraq&m=104612710031920&w=2
8714 * and CVE-2003-0070.
8715 */
8716 _bte_debug_print(BTE_DEBUG_EMULATION,do { } while(0)
8717 "Reporting empty icon title.\n")do { } while(0);
8718
8719 send(seq, bte::parser::u8SequenceBuilder{BTE_SEQ_OSC, "L"s});
8720 break;
8721
8722 case BTE_XTERM_WM_GET_WINDOW_TITLE:
8723 /* Report a static window title, since the real
8724 * window title should NEVER be reported, as it
8725 * creates a security vulnerability. See
8726 * http://marc.info/?l=bugtraq&m=104612710031920&w=2
8727 * and CVE-2003-0070.
8728 */
8729 _bte_debug_print(BTE_DEBUG_EMULATION,do { } while(0)
8730 "Reporting empty window title.\n")do { } while(0);
8731
8732 send(seq, bte::parser::u8SequenceBuilder{BTE_SEQ_OSC, "l"s});
8733 break;
8734
8735 case BTE_XTERM_WM_TITLE_STACK_PUSH:
8736 switch (seq.collect1(1)) {
8737 case -1:
8738 case BTE_OSC_XTERM_SET_WINDOW_AND_ICON_TITLE:
8739 case BTE_OSC_XTERM_SET_WINDOW_TITLE:
8740 if (m_window_title_stack.size() >= BTE_WINDOW_TITLE_STACK_MAX_DEPTH(8)) {
8741 /* Drop the bottommost item */
8742 m_window_title_stack.erase(m_window_title_stack.cbegin());
8743 }
8744
8745 if (m_window_title_changed)
8746 m_window_title_stack.emplace(m_window_title_stack.cend(),
8747 m_window_title_pending);
8748 else
8749 m_window_title_stack.emplace(m_window_title_stack.cend(),
8750 m_window_title);
8751
8752 g_assert_cmpuint(m_window_title_stack.size(), <=, BTE_WINDOW_TITLE_STACK_MAX_DEPTH)do { guint64 __n1 = (m_window_title_stack.size()), __n2 = ((8
)); if (__n1 <= __n2) ; else g_assertion_message_cmpnum ("BTE"
, "../src/bteseq.cc", 8752, ((const char*) (__PRETTY_FUNCTION__
)), "m_window_title_stack.size()" " " "<=" " " "BTE_WINDOW_TITLE_STACK_MAX_DEPTH"
, (long double) __n1, "<=", (long double) __n2, 'i'); } while
(0)
;
8753 break;
8754
8755 case BTE_OSC_XTERM_SET_ICON_TITLE:
8756 default:
8757 break;
8758 }
8759 break;
8760
8761 case BTE_XTERM_WM_TITLE_STACK_POP:
8762 switch (seq.collect1(1)) {
8763 case -1:
8764 case BTE_OSC_XTERM_SET_WINDOW_AND_ICON_TITLE:
8765 case BTE_OSC_XTERM_SET_WINDOW_TITLE:
8766 if (m_window_title_stack.empty())
8767 break;
8768
8769 m_window_title_changed = true;
8770 m_window_title_pending.swap(m_window_title_stack.back());
8771 m_window_title_stack.pop_back();
8772 break;
8773
8774 case BTE_OSC_XTERM_SET_ICON_TITLE:
8775 default:
8776 break;
8777 }
8778 break;
8779
8780 default:
8781 DECSLPP(seq);
8782 break;
8783 }
8784}
8785
8786} // namespace terminal
8787} // namespace bte