[vte] parser: glue: Add sequence builder
- From: Christian Persch <chpe src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [vte] parser: glue: Add sequence builder
- Date: Tue, 27 Mar 2018 17:44:49 +0000 (UTC)
commit 6cd4713c561dba2188ecc78b6be648225cab7dda
Author: Christian Persch <chpe src gnome org>
Date: Tue Mar 27 19:40:12 2018 +0200
parser: glue: Add sequence builder
... and use it throughout.
src/Makefile.am | 3 +
src/debug.cc | 1 +
src/debug.h | 1 +
src/parser-arg.hh | 9 +
src/parser-cat.cc | 3 +
src/parser-glue.hh | 312 +++++++++++++++++++++++++++++++
src/parser-reply.hh | 54 ++++++
src/parser-test.cc | 15 ++
src/parser.hh | 42 ++++
src/vte.cc | 83 ++++++++-
src/vteinternal.hh | 15 ++
src/vteseq.cc | 515 ++++++++++++++++++++++++++++++---------------------
12 files changed, 836 insertions(+), 217 deletions(-)
---
diff --git a/src/Makefile.am b/src/Makefile.am
index 5e3dff4..f5f1434 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -66,6 +66,7 @@ libvte_@VTE_API_MAJOR_VERSION@_@VTE_API_MINOR_VERSION@_la_SOURCES = \
parser-cmd.hh \
parser-glue.hh \
parser-osc.hh \
+ parser-reply.hh \
parser-string.hh \
pty.cc \
reaper.cc \
@@ -250,6 +251,7 @@ parser_cat_SOURCES = \
parser-cmd.hh \
parser-glue.hh \
parser-osc.hh \
+ parser-reply.hh \
parser-string.hh \
parser-cat.cc \
vteconv.cc \
@@ -285,6 +287,7 @@ test_parser_SOURCES = \
parser-charset-tables.hh \
parser-glue.hh \
parser-osc.hh \
+ parser-reply.hh \
parser-string.hh \
$(NULL)
test_parser_CPPFLAGS = \
diff --git a/src/debug.cc b/src/debug.cc
index 0101f69..03f8fd0 100644
--- a/src/debug.cc
+++ b/src/debug.cc
@@ -56,6 +56,7 @@ _vte_debug_init(void)
{ "regex", VTE_DEBUG_REGEX },
{ "hyperlink", VTE_DEBUG_HYPERLINK },
{ "modes", VTE_DEBUG_MODES },
+ { "emulation", VTE_DEBUG_EMULATION },
};
_vte_debug_flags = g_parse_debug_string (g_getenv("VTE_DEBUG"),
diff --git a/src/debug.h b/src/debug.h
index e5222bd..d9eb601 100644
--- a/src/debug.h
+++ b/src/debug.h
@@ -63,6 +63,7 @@ typedef enum {
VTE_DEBUG_REGEX = 1 << 23,
VTE_DEBUG_HYPERLINK = 1 << 24,
VTE_DEBUG_MODES = 1 << 25,
+ VTE_DEBUG_EMULATION = 1 << 26,
} VteDebugFlags;
void _vte_debug_init(void);
diff --git a/src/parser-arg.hh b/src/parser-arg.hh
index 0f94832..a61d323 100644
--- a/src/parser-arg.hh
+++ b/src/parser-arg.hh
@@ -116,6 +116,15 @@ static inline void vte_seq_arg_finish(vte_seq_arg_t* arg,
*arg |= VTE_SEQ_ARG_FLAG_NONFINAL;
}
+static inline void vte_seq_arg_refinish(vte_seq_arg_t* arg,
+ bool nonfinal = false)
+{
+ if (nonfinal)
+ *arg |= VTE_SEQ_ARG_FLAG_NONFINAL;
+ else
+ *arg &= ~VTE_SEQ_ARG_FLAG_NONFINAL;
+}
+
/*
* vte_seq_arg_started:
* @arg:
diff --git a/src/parser-cat.cc b/src/parser-cat.cc
index 6953097..08d5412 100644
--- a/src/parser-cat.cc
+++ b/src/parser-cat.cc
@@ -45,6 +45,9 @@ seq_to_str(unsigned int type)
case VTE_SEQ_CSI: return "CSI";
case VTE_SEQ_DCS: return "DCS";
case VTE_SEQ_OSC: return "OSC";
+ case VTE_SEQ_APC: return "APC";
+ case VTE_SEQ_PM: return "PM";
+ case VTE_SEQ_SOS: return "SOS";
default:
assert(false);
}
diff --git a/src/parser-glue.hh b/src/parser-glue.hh
index 5e4303e..27bb680 100644
--- a/src/parser-glue.hh
+++ b/src/parser-glue.hh
@@ -334,6 +334,318 @@ private:
char const* command_string() const;
};
+/* Helper classes to unify UTF-32 and UTF-8 versions of SequenceBuilder.
+ * ::put will only be called with C1 controls, so it's ok to simplify
+ * the UTF-8 version to simply prepend 0xc2.
+ */
+template<typename C>
+class DirectEncoder {
+public:
+ using string_type = std::basic_string<C>;
+ inline void put(string_type& s, C const c) const noexcept
+ {
+ s.push_back(c);
+ }
+};
+
+class UTF8Encoder {
+public:
+ using string_type = std::basic_string<char>;
+ inline void put(string_type& s, unsigned char const c) const noexcept
+ {
+ s.push_back(0xc2);
+ s.push_back(c);
+ }
+};
+
+template<class S, class E = DirectEncoder<typename S::value_type>>
+class SequenceBuilder {
+public:
+ using string_type = S;
+ using encoder_type = E;
+
+private:
+ struct vte_seq m_seq;
+ string_type m_arg_str;
+ unsigned char m_intermediates[4];
+ unsigned char m_n_intermediates{0};
+ unsigned char m_param_intro{0};
+ encoder_type m_encoder;
+
+public:
+ SequenceBuilder(unsigned int type = VTE_SEQ_NONE)
+ {
+ memset(&m_seq, 0, sizeof(m_seq));
+ set_type(type);
+ }
+
+ SequenceBuilder(unsigned int type,
+ string_type const& str)
+ : SequenceBuilder(type)
+ {
+ set_string(str);
+ }
+
+ SequenceBuilder(unsigned int type,
+ string_type&& str)
+ : SequenceBuilder(type)
+ {
+ set_string(str);
+ }
+
+ SequenceBuilder(SequenceBuilder const&) = delete;
+ SequenceBuilder(SequenceBuilder&&) = delete;
+ ~SequenceBuilder() = default;
+
+ SequenceBuilder& operator= (SequenceBuilder const&) = delete;
+ SequenceBuilder& operator= (SequenceBuilder&&) = delete;
+
+ inline void set_type(unsigned int type) noexcept
+ {
+ m_seq.type = type;
+ }
+
+ inline void set_final(uint32_t t) noexcept
+ {
+ m_seq.terminator = t;
+ }
+
+ inline void append_intermediate(unsigned char i) noexcept
+ {
+ assert(unsigned(m_n_intermediates + 1) <=
(sizeof(m_intermediates)/sizeof(m_intermediates[0])));
+
+ m_seq.intermediates |= (1u << (i - 0x20));
+ m_intermediates[m_n_intermediates++] = i;
+ }
+
+ inline void append_intermediates(std::initializer_list<unsigned char> l) noexcept
+ {
+ assert(m_n_intermediates + l.size() <= (sizeof(m_intermediates)/sizeof(m_intermediates[0])));
+
+ for (uint32_t i : l) {
+ m_seq.intermediates |= (1u << (i - 0x20));
+ m_intermediates[m_n_intermediates++] = i;
+ }
+ }
+
+ inline void set_param_intro(unsigned char p) noexcept
+ {
+ m_param_intro = p;
+ if (p != 0) {
+ m_seq.intermediates |= (1u << (p - 0x20));
+ }
+ }
+
+ inline void append_params(std::initializer_list<int> params) noexcept
+ {
+ assert(m_seq.n_args + params.size() <= (sizeof(m_seq.args) / sizeof(m_seq.args[0])));
+ for (int p : params)
+ m_seq.args[m_seq.n_args++] = vte_seq_arg_init(std::min(p, 0xffff));
+ }
+
+ inline void append_subparams(std::initializer_list<int> subparams) noexcept
+ {
+ assert(m_seq.n_args + subparams.size() <= (sizeof(m_seq.args) / sizeof(m_seq.args[0])));
+ for (int p : subparams) {
+ int* arg = &m_seq.args[m_seq.n_args++];
+ *arg = vte_seq_arg_init(std::min(p, 0xffff));
+ vte_seq_arg_finish(arg, false);
+ }
+ vte_seq_arg_refinish(&m_seq.args[m_seq.n_args - 1], true);
+ }
+
+ inline void set_string(string_type const& str) noexcept
+ {
+ m_arg_str = str;
+ }
+
+ inline void set_string(string_type&& str) noexcept
+ {
+ m_arg_str = str;
+ }
+
+ enum class ST {
+ NONE,
+ DEFAULT,
+ C0,
+ C1,
+ BEL
+ };
+
+
+private:
+ void append_introducer(string_type& s,
+ bool c1 = true) const noexcept
+ {
+ /* Introducer */
+ if (c1) {
+ switch (m_seq.type) {
+ case VTE_SEQ_ESCAPE: m_encoder.put(s, 0x1b); break; // ESC
+ case VTE_SEQ_CSI: m_encoder.put(s, 0x9b); break; // CSI
+ case VTE_SEQ_DCS: m_encoder.put(s, 0x90); break; // DCS
+ case VTE_SEQ_OSC: m_encoder.put(s, 0x9d); break; // OSC
+ case VTE_SEQ_APC: m_encoder.put(s, 0x9f); break; // APC
+ case VTE_SEQ_PM: m_encoder.put(s, 0x9e); break; // PM
+ case VTE_SEQ_SOS: m_encoder.put(s, 0x98); break; // SOS
+ default: return;
+ }
+ } else {
+ s.push_back(0x1B); // ESC
+ switch (m_seq.type) {
+ case VTE_SEQ_ESCAPE: break; // nothing more
+ case VTE_SEQ_CSI: s.push_back(0x5b); break; // [
+ case VTE_SEQ_DCS: s.push_back(0x50); break; // P
+ case VTE_SEQ_OSC: s.push_back(0x5d); break; // ]
+ case VTE_SEQ_APC: s.push_back(0x5f); break; // _
+ case VTE_SEQ_PM: s.push_back(0x5e); break; // ^
+ case VTE_SEQ_SOS: s.push_back(0x58); break; // X
+ default: return;
+ }
+ }
+ }
+
+ void append_params(string_type& s) const noexcept
+ {
+ /* Parameters */
+ switch (m_seq.type) {
+ case VTE_SEQ_CSI:
+ case VTE_SEQ_DCS: {
+
+ if (m_param_intro != 0)
+ s.push_back(m_param_intro);
+ auto n_args = m_seq.n_args;
+ for (unsigned int n = 0; n < n_args; n++) {
+ auto arg = vte_seq_arg_value(m_seq.args[n]);
+ if (n > 0) {
+ s.push_back(";:"[vte_seq_arg_nonfinal(m_seq.args[n])]);
+ }
+ if (arg >= 0) {
+ char buf[16];
+ int l = g_snprintf(buf, sizeof(buf), "%d", arg);
+ for (int j = 0; j < l; j++)
+ s.push_back(buf[j]);
+ }
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ }
+
+ void append_intermediates_and_final(string_type& s) const noexcept
+ {
+ /* Intermediates and Final */
+ switch (m_seq.type) {
+ case VTE_SEQ_ESCAPE:
+ case VTE_SEQ_CSI:
+ case VTE_SEQ_DCS:
+ for (unsigned char n = 0; n < m_n_intermediates; n++)
+ s.push_back(m_intermediates[n]);
+
+ if (m_seq.terminator != 0)
+ s.push_back(m_seq.terminator);
+ break;
+ default:
+ break;
+ }
+ }
+
+ void append_arg_string(string_type& s,
+ bool c1 = false,
+ ssize_t max_arg_str_len = -1,
+ ST st = ST::DEFAULT) const noexcept
+ {
+ /* String and ST */
+ switch (m_seq.type) {
+ case VTE_SEQ_DCS:
+ case VTE_SEQ_OSC:
+
+ if (max_arg_str_len < 0)
+ s.append(m_arg_str, 0, max_arg_str_len);
+ else
+ s.append(m_arg_str);
+
+ switch (st) {
+ case ST::NONE:
+ // omit ST
+ break;
+ case ST::DEFAULT:
+ if (c1) {
+ // s.push_back(0xc2); // fixmechpe
+ m_encoder.put(s, 0x9c); // ST
+ } else {
+ s.push_back(0x1b); // ESC
+ s.push_back(0x5c); // BACKSLASH
+ }
+ break;
+ case ST::C0:
+ s.push_back(0x1b); // ESC
+ s.push_back(0x5c); // BACKSLASH
+ break;
+ case ST::C1:
+ m_encoder.put(s, 0x9c); // ST
+ break;
+ case ST::BEL:
+ s.push_back(0x7); // BEL
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+public:
+ void to_string(string_type& s,
+ bool c1 = false,
+ ssize_t max_arg_str_len = -1,
+ ST st = ST::DEFAULT) const noexcept
+ {
+ append_introducer(s, c1);
+ append_params(s);
+ append_intermediates_and_final(s);
+ append_arg_string(s, c1, max_arg_str_len, st);
+ }
+
+ void assert_equal(struct vte_seq* seq);
+ void assert_equal_full(struct vte_seq* seq);
+
+ void print(bool c1 = false);
+};
+
+using u8SequenceBuilder = SequenceBuilder<std::string, UTF8Encoder>;
+using u32SequenceBuilder = SequenceBuilder<std::u32string>;
+
+class ReplyBuilder : public u8SequenceBuilder {
+public:
+ ReplyBuilder(unsigned int reply,
+ std::initializer_list<int> params)
+ {
+ switch (reply) {
+#define _VTE_REPLY_PARAMS(params) append_params(params);
+#define _VTE_REPLY_STRING(str) set_string(str);
+#define _VTE_REPLY(cmd,type,final,pintro,intermediate,code) \
+ case VTE_REPLY_##cmd: \
+ set_type(VTE_SEQ_##type); \
+ set_final(final); \
+ set_param_intro(VTE_SEQ_INTERMEDIATE_##pintro); \
+ if (VTE_SEQ_INTERMEDIATE_##intermediate != VTE_SEQ_INTERMEDIATE_NONE) \
+ append_intermediate(VTE_SEQ_INTERMEDIATE_##intermediate); \
+ code \
+ break;
+#include "parser-reply.hh"
+#undef _VTE_REPLY
+#undef _VTE_REPLY_PARAMS
+#undef _VTE_REPLY_STRING
+ default:
+ assert(false);
+ break;
+ }
+ append_params(params);
+ }
+
+}; // class ReplyBuilder
+
class StringTokeniser {
public:
using string_type = std::string;
diff --git a/src/parser-reply.hh b/src/parser-reply.hh
new file mode 100644
index 0000000..b5d58b8
--- /dev/null
+++ b/src/parser-reply.hh
@@ -0,0 +1,54 @@
+/*
+ * Copyright © 2018 Christian Persch
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+_VTE_REPLY(NONE, NONE, 0, NONE, NONE,) /* placeholder */
+
+_VTE_REPLY(APC, APC, 0, NONE, NONE, ) /* application program command */
+_VTE_REPLY(CPR, CSI, 'R', NONE, NONE, ) /* cursor position report */
+_VTE_REPLY(DECAUPSS, DCS, 'u', NONE, BANG, ) /* assign user preferred supplemental set */
+_VTE_REPLY(DECDA1R, CSI, 'c', WHAT, NONE, ) /* DA1 report */
+_VTE_REPLY(DECDA2R, CSI, 'c', GT, NONE, ) /* DA2 report */
+_VTE_REPLY(DECCIR, DCS, 'u', NONE, CASH, _VTE_REPLY_PARAMS({1})) /* cursor information report */
+_VTE_REPLY(DECCTR, DCS, 's', NONE, CASH, _VTE_REPLY_PARAMS({2})) /* color table report */
+_VTE_REPLY(DECCKSR, DCS, '~', NONE, BANG, ) /* memory checksum report */
+_VTE_REPLY(DECEKBD, APC, 0, NONE, NONE, ) /* extended keyboard report */
+_VTE_REPLY(DECDSR, CSI, 'n', WHAT, NONE, ) /* device status report */
+_VTE_REPLY(DECMSR, CSI, '{', NONE, MULT, ) /* macro space report */
+_VTE_REPLY(DECPKMFR, CSI, 'y', NONE, PLUS, ) /* program key free memory report */
+_VTE_REPLY(DECREPTPARM, CSI, 'x', NONE, NONE, ) /* report terminal parameters */
+_VTE_REPLY(DECRPAK, DCS, '~', NONE, DQUOTE,) /* report all modifiers/alphanumeric key */
+_VTE_REPLY(DECRPDE, CSI, 'w', NONE, DQUOTE,) /* report displayed extent */
+_VTE_REPLY(DECRPFK, DCS, '}', NONE, DQUOTE,) /* report function key */
+_VTE_REPLY(DECRPKT, CSI, 'v', NONE, COMMA, ) /* report key type */
+_VTE_REPLY(DECRPM_ECMA, CSI, 'y', NONE, CASH, ) /* report ECMA mode */
+_VTE_REPLY(DECRPM_DEC, CSI, 'y', WHAT, CASH, ) /* report private mode */
+_VTE_REPLY(DECRPSS, DCS, 'r', NONE, CASH, ) /* report state or setting */
+_VTE_REPLY(DECRPTUI, DCS, '|', NONE, BANG, _VTE_REPLY_STRING("7E565445") /* "~VTE" */) /* report
terminal unit ID */
+_VTE_REPLY(DECTABSR, DCS, '@', NONE, CASH, ) /* tabulation stop report */
+_VTE_REPLY(DECTSR, DCS, 's', NONE, CASH, _VTE_REPLY_PARAMS({1})) /* terminal state report */
+_VTE_REPLY(DECXCPR, CSI, 'R', NONE, NONE, ) /* extended cursor position report */
+_VTE_REPLY(DSR, CSI, 'n', NONE, NONE, ) /* device status report */
+_VTE_REPLY(OSC, OSC, 0, NONE, NONE, ) /* operating system command */
+_VTE_REPLY(PM, PM, 0, NONE, NONE, ) /* privacy message */
+_VTE_REPLY(SOS, SOS, 0, NONE, NONE, ) /* start of string */
+_VTE_REPLY(URXVT_MOUSE_EXT_REPORT, CSI, 'M', NONE, NONE,) /* URXVT mouse mode report */
+_VTE_REPLY(XTERM_BRACKET, CSI, '~', NONE, NONE,) /* XTERM bracketed paste */
+_VTE_REPLY(XTERM_FOCUS_IN, CSI, 'I', NONE, NONE,) /* XTERM focus in report */
+_VTE_REPLY(XTERM_FOCUS_OUT, CSI, 'O', NONE, NONE,) /* XTERM focus out report */
+_VTE_REPLY(XTERM_MOUSE_EXT_SGR_REPORT_BUTTON_PRESS, CSI, 'M', LT, NONE,) /* XTERM SGR mouse mode button
press report */
+_VTE_REPLY(XTERM_MOUSE_EXT_SGR_REPORT_BUTTON_RELEASE, CSI, 'm', LT, NONE,) /* XTERM SGR mouse mode button
release report */
+_VTE_REPLY(XTERM_WM, CSI, 't', NONE, NONE,) /* XTERM WM report */
diff --git a/src/parser-test.cc b/src/parser-test.cc
index 293995f..b0890b2 100644
--- a/src/parser-test.cc
+++ b/src/parser-test.cc
@@ -48,6 +48,9 @@ seq_to_str(unsigned int type)
case VTE_SEQ_CSI: return "CSI";
case VTE_SEQ_DCS: return "DCS";
case VTE_SEQ_OSC: return "OSC";
+ case VTE_SEQ_APC: return "APC";
+ case VTE_SEQ_PM: return "PM";
+ case VTE_SEQ_SOS: return "SOS";
default:
g_assert_not_reached();
}
@@ -1422,6 +1425,16 @@ test_seq_glue_string_tokeniser(void)
g_assert_true(pit4 == tokeniser4.cend());
}
+static void
+test_seq_glue_sequence_builder(void)
+{
+}
+
+static void
+test_seq_glue_reply_builder(void)
+{
+}
+
int
main(int argc,
char* argv[])
@@ -1436,6 +1449,8 @@ main(int argc,
g_test_add_func("/vte/parser/sequences/glue/arg", test_seq_glue_arg);
g_test_add_func("/vte/parser/sequences/glue/string", test_seq_glue_string);
g_test_add_func("/vte/parser/sequences/glue/string-tokeniser", test_seq_glue_string_tokeniser);
+ g_test_add_func("/vte/parser/sequences/glue/sequence-builder", test_seq_glue_sequence_builder);
+ g_test_add_func("/vte/parser/sequences/glue/reply-builder", test_seq_glue_reply_builder);
g_test_add_func("/vte/parser/sequences/control", test_seq_control);
g_test_add_func("/vte/parser/sequences/escape/invalid", test_seq_esc_invalid);
g_test_add_func("/vte/parser/sequences/escape/charset/94", test_seq_esc_charset_94);
diff --git a/src/parser.hh b/src/parser.hh
index 751ee11..f6a11ee 100644
--- a/src/parser.hh
+++ b/src/parser.hh
@@ -81,10 +81,44 @@ enum {
VTE_SEQ_DCS, /* device control string */
VTE_SEQ_OSC, /* operating system control */
+ VTE_SEQ_APC, /* application program command */
+ VTE_SEQ_PM, /* privacy message */
+ VTE_SEQ_SOS, /* start of string */
+
VTE_SEQ_N,
};
enum {
+ VTE_SEQ_INTERMEDIATE_NONE = 0,
+
+ VTE_SEQ_INTERMEDIATE_SPACE = ' ', /* 02/00 */
+ VTE_SEQ_INTERMEDIATE_BANG = '!', /* 02/01 */
+ VTE_SEQ_INTERMEDIATE_DQUOTE = '"', /* 02/02 */
+ VTE_SEQ_INTERMEDIATE_HASH = '#', /* 02/03 */
+ VTE_SEQ_INTERMEDIATE_CASH = '$', /* 02/04 */
+ VTE_SEQ_INTERMEDIATE_PERCENT= '%', /* 02/05 */
+ VTE_SEQ_INTERMEDIATE_AND = '&', /* 02/06 */
+ VTE_SEQ_INTERMEDIATE_SQUOTE = '\'', /* 02/07 */
+ VTE_SEQ_INTERMEDIATE_POPEN = '(', /* 02/08 */
+ VTE_SEQ_INTERMEDIATE_PCLOSE = ')', /* 02/09 */
+ VTE_SEQ_INTERMEDIATE_MULT = '*', /* 02/10 */
+ VTE_SEQ_INTERMEDIATE_PLUS = '+', /* 02/11 */
+ VTE_SEQ_INTERMEDIATE_COMMA = ',', /* 02/12 */
+ VTE_SEQ_INTERMEDIATE_MINUS = '-', /* 02/13 */
+ VTE_SEQ_INTERMEDIATE_DOT = '.', /* 02/14 */
+ VTE_SEQ_INTERMEDIATE_SLASH = '/', /* 02/15 */
+
+ /* 16-25 is reserved for numbers; unused */
+
+ /* COLON is reserved = ':' * 03/10 */
+ /* SEMICOLON is reserved = ';' * 03/11 */
+ VTE_SEQ_INTERMEDIATE_LT = '<', /* 03/12 */
+ VTE_SEQ_INTERMEDIATE_EQUAL = '=', /* 03/13 */
+ VTE_SEQ_INTERMEDIATE_GT = '>', /* 03/14 */
+ VTE_SEQ_INTERMEDIATE_WHAT = '?' /* 03/15 */
+};
+
+enum {
/* these must be kept compatible to (1U << (ch - 0x20)) */
VTE_SEQ_FLAG_SPACE = (1U << 0), /* char: */
@@ -123,6 +157,14 @@ enum {
};
enum {
+#define _VTE_REPLY(cmd,type,final,pintro,intermediate,code) VTE_REPLY_##cmd,
+#include "parser-reply.hh"
+#undef _VTE_REPLY
+
+ VTE_REPLY_N
+};
+
+enum {
#define _VTE_CHARSET_PASTE(name) VTE_CHARSET_##name,
#define _VTE_CHARSET(name) _VTE_CHARSET_PASTE(name)
#define _VTE_CHARSET_ALIAS_PASTE(name1,name2) VTE_CHARSET_##name1 = VTE_CHARSET_##name2,
diff --git a/src/vte.cc b/src/vte.cc
index e312ae3..fdf7a23 100644
--- a/src/vte.cc
+++ b/src/vte.cc
@@ -4272,6 +4272,70 @@ VteTerminalPrivate::feed_child_using_modes(char const* data,
send_child(data, length, !m_modes_ecma.SRM());
}
+void
+VteTerminalPrivate::send(vte::parser::u8SequenceBuilder const& builder,
+ bool c1,
+ vte::parser::u8SequenceBuilder::ST st) noexcept
+{
+ std::string str;
+ builder.to_string(str, c1, -1, st);
+ feed_child(str.data(), str.size());
+}
+
+void
+VteTerminalPrivate::send(vte::parser::Sequence const& seq,
+ vte::parser::u8SequenceBuilder const& builder) noexcept
+{
+ // FIXMEchpe take c1 & ST from @seq
+ send(builder, false);
+}
+
+void
+VteTerminalPrivate::send(unsigned int type,
+ std::initializer_list<int> params) noexcept
+{
+ // FIXMEchpe take c1 & ST from @seq
+ send(vte::parser::ReplyBuilder{type, params}, false);
+}
+
+void
+VteTerminalPrivate::reply(vte::parser::Sequence const& seq,
+ unsigned int type,
+ std::initializer_list<int> params) noexcept
+{
+ send(seq, vte::parser::ReplyBuilder{type, params});
+}
+
+void
+VteTerminalPrivate::reply(vte::parser::Sequence const& seq,
+ unsigned int type,
+ char const* format,
+ ...) noexcept
+{
+ switch (type) {
+ case VTE_SEQ_OSC:
+ case VTE_SEQ_APC:
+ case VTE_SEQ_PM:
+ case VTE_SEQ_SOS:
+ break;
+ default:
+ assert(false);
+ return;
+ }
+
+ char buf[128];
+ va_list vargs;
+ va_start(vargs, format);
+ auto len = g_vsnprintf(buf, sizeof(buf), format, vargs);
+ va_end(vargs);
+ g_assert_cmpint(len, <, sizeof(buf));
+
+ vte::parser::u8SequenceBuilder builder{type};
+ builder.set_string(std::string{buf});
+
+ send(seq, builder);
+}
+
/* Send text from the input method to the child. */
static void
vte_terminal_im_commit_cb(GtkIMContext *im_context,
@@ -5250,6 +5314,7 @@ VteTerminalPrivate::widget_paste_received(char const* text)
}
bool const bracketed_paste = m_modes_private.XTERM_READLINE_BRACKETED_PASTE();
+ // FIXMEchpe can we not hardcode C0 controls here?
if (bracketed_paste)
feed_child("\e[200~", -1);
// FIXMEchpe add a way to avoid the extra string copy done here
@@ -5324,17 +5389,19 @@ VteTerminalPrivate::feed_mouse_event(vte::grid::coords const& rowcol /* confined
/* Check the extensions in decreasing order of preference. Encoding the release event above assumes
that 1006 comes first. */
if (m_modes_private.XTERM_MOUSE_EXT_SGR()) {
/* xterm's extended mode (1006) */
- len = g_snprintf(buf, sizeof(buf), _VTE_CAP_CSI "<%d;%ld;%ld%c", cb, cx, cy, is_release ? 'm'
: 'M');
+ send(is_release ? VTE_REPLY_XTERM_MOUSE_EXT_SGR_REPORT_BUTTON_RELEASE
+ : VTE_REPLY_XTERM_MOUSE_EXT_SGR_REPORT_BUTTON_PRESS,
+ {cb, (int)cx, (int)cy});
} else if (m_modes_private.URXVT_MOUSE_EXT()) {
/* urxvt's extended mode (1015) */
- len = g_snprintf(buf, sizeof(buf), _VTE_CAP_CSI "%d;%ld;%ldM", 32 + cb, cx, cy);
+ send(VTE_REPLY_URXVT_MOUSE_EXT_REPORT, {32 + cb, (int)cx, (int)cy});
} else if (cx <= 231 && cy <= 231) {
/* legacy mode */
len = g_snprintf(buf, sizeof(buf), _VTE_CAP_CSI "M%c%c%c", 32 + cb, 32 + (guchar)cx, 32 +
(guchar)cy);
- }
- /* Send event direct to the child, this is binary not text data */
- feed_child_binary((guint8*) buf, len);
+ /* Send event direct to the child, this is binary not text data */
+ feed_child_binary((guint8*) buf, len);
+ }
return true;
}
@@ -5342,11 +5409,7 @@ VteTerminalPrivate::feed_mouse_event(vte::grid::coords const& rowcol /* confined
void
VteTerminalPrivate::feed_focus_event(bool in)
{
- char buf[8];
- gsize len;
-
- len = g_snprintf(buf, sizeof(buf), _VTE_CAP_CSI "%c", in ? 'I' : 'O');
- feed_child_binary((guint8 *)buf, len);
+ send(in ? VTE_REPLY_XTERM_FOCUS_IN : VTE_REPLY_XTERM_FOCUS_OUT, {});
}
void
diff --git a/src/vteinternal.hh b/src/vteinternal.hh
index e6b1a1e..b4c0123 100644
--- a/src/vteinternal.hh
+++ b/src/vteinternal.hh
@@ -1223,6 +1223,21 @@ public:
void select_empty(vte::grid::column_t col,
vte::grid::row_t row);
+ void send(vte::parser::u8SequenceBuilder const& builder,
+ bool c1 = true,
+ vte::parser::u8SequenceBuilder::ST st = vte::parser::u8SequenceBuilder::ST::DEFAULT)
noexcept;
+ void send(vte::parser::Sequence const& seq,
+ vte::parser::u8SequenceBuilder const& builder) noexcept;
+ void send(unsigned int type,
+ std::initializer_list<int> params) noexcept;
+ void reply(vte::parser::Sequence const& seq,
+ unsigned int type,
+ std::initializer_list<int> params) noexcept;
+ void reply(vte::parser::Sequence const& seq,
+ unsigned int type,
+ char const* format,
+ ...) noexcept G_GNUC_PRINTF(4, 5);
+
/* OSC handlers */
void set_color(vte::parser::Sequence const& seq,
vte::parser::StringTokeniser::const_iterator& token,
diff --git a/src/vteseq.cc b/src/vteseq.cc
index 46eb62b..69b444a 100644
--- a/src/vteseq.cc
+++ b/src/vteseq.cc
@@ -1358,14 +1358,11 @@ VteTerminalPrivate::set_color(vte::parser::Sequence const& seq,
auto const str = *token;
if (str == "?"s) {
- gchar buf[128];
auto c = get_color(value);
g_assert_nonnull(c);
- g_snprintf (buf, sizeof (buf),
- _VTE_CAP_OSC "4;%u;rgb:%04x/%04x/%04x%s",
- value, c->red, c->green, c->blue,
- seq.terminator() == 0x7 ? BEL_C0 : ST_C0);
- feed_child(buf, -1);
+
+ reply(seq, VTE_SEQ_OSC, "4;%d;rgb:%04x/%04x/%04x",
+ value, c->red, c->green, c->blue);
} else {
vte::color::rgb color;
if (color.parse(str.data())) {
@@ -1396,17 +1393,13 @@ VteTerminalPrivate::set_special_color(vte::parser::Sequence const& seq,
auto const str = *token;
if (str == "?"s) {
- gchar buf[128];
auto c = get_color(index);
if (c == nullptr && index_fallback != -1)
c = get_color(index_fallback);
g_assert_nonnull(c);
- auto len = g_snprintf (buf, sizeof (buf),
- _VTE_CAP_OSC "%d;rgb:%04x/%04x/%04x%s",
- osc,
- c->red, c->green, c->blue,
- ST_C0);//seq.terminator() == 7 ? BEL_C0 : ST_C0);
- feed_child(buf, len);
+
+ reply(seq, VTE_SEQ_OSC, "%d;rgb:%04x/%04x/%04x",
+ osc, c->red, c->green, c->blue);
} else {
vte::color::rgb color;
if (color.parse(str.data())) {
@@ -2087,8 +2080,8 @@ VteTerminalPrivate::DA1(vte::parser::Sequence const& seq)
* enabled features.
*
* The terminal's answer is:
- * ^[ ? 64 ; ARGS c
- * The first argument, 64, is fixed and denotes a VT420, the last
+ * ^[ ? 65 ; ARGS c
+ * The first argument, 65, is fixed and denotes a VT520, the last
* DEC-term that extended this number.
* All following arguments denote supported features. Note
* that at most 15 features can be sent (max CSI args). It is safe to
@@ -2107,7 +2100,7 @@ VteTerminalPrivate::DA1(vte::parser::Sequence const& seq)
* Support for ReGIS graphics is available. The ReGIS routines
* provide the "remote graphics instruction set" and allow basic
* vector-rendering.
- * 4: sixel
+ * 4: Sixel
* Support of Sixel graphics is available. This provides access
* to the sixel bitmap routines.
* 6: selective erase
@@ -2120,7 +2113,7 @@ VteTerminalPrivate::DA1(vte::parser::Sequence const& seq)
* TODO: ?
* 9: national-replacement character sets (NRCS)
* National-replacement character-sets are available.
- * 12: Yugoslavian (SCS)
+ * 12: Serbo-Croatian (SCS)
* TODO: ?
* 15: technical character set
* The DEC technical-character-set is available.
@@ -2128,13 +2121,13 @@ VteTerminalPrivate::DA1(vte::parser::Sequence const& seq)
* TODO: ?
* 21: horizontal scrolling
* TODO: ?
- * 22: ANSII color
+ * 22: ANSI color
* TODO: ?
* 23: Greek
* TODO: ?
* 24: Turkish
* TODO: ?
- * 29: ANSI text locator
+ * 29: DECterm text locator
* TODO: ?
* 42: ISO Latin-2 character set
* TODO: ?
@@ -2149,16 +2142,13 @@ VteTerminalPrivate::DA1(vte::parser::Sequence const& seq)
* args[0]: 0
*
* References: ECMA-48 § 8.3.24
+ * VT525
*/
-#if 0
- SEQ_WRITE(screen, C0_CSI, C1_CSI, "?64;1;6;9;15c");
-#endif
if (seq.collect1(0, 0) != 0)
return;
- /* Claim to be a VT220 with only national character set support. */
- feed_child("\e[?62;c", -1);
+ reply(seq, VTE_REPLY_DECDA1R, {62});
}
void
@@ -2172,7 +2162,7 @@ VteTerminalPrivate::DA2(vte::parser::Sequence const& seq)
* terminal features.
*
* The terminal's response is:
- * ^[ > 61 ; FIRMWARE ; KEYBOARD c
+ * ^[ > 65 ; FIRMWARE ; KEYBOARD c
* whereas 65 is fixed for VT525 terminals, the last terminal-line that
* increased this number. FIRMWARE is the firmware
* version encoded as major/minor (20 == 2.0) and KEYBOARD is 0 for STD
@@ -2183,29 +2173,13 @@ VteTerminalPrivate::DA2(vte::parser::Sequence const& seq)
*
* References: VT525
*/
-#if 0
- return SEQ_WRITE(screen, C0_CSI, C1_CSI,
- ">65;" __stringify(LINUX_VERSION_CODE) ";1c");
-#endif
+ /* Param != 0 means this is a reply, not a request */
if (seq.collect1(0, 0) != 0)
return;
- char **version;
- char buf[128];
- long ver = 0, i;
- /* Claim to be a VT220, more or less. The '>' in the response appears
- * to be undocumented. */
- version = g_strsplit(VERSION, ".", 0);
- if (version != NULL) {
- for (i = 0; version[i] != NULL; i++) {
- ver = ver * 100;
- ver += atol(version[i]);
- }
- g_strfreev(version);
- }
- g_snprintf(buf, sizeof (buf), _VTE_CAP_ESC "[>65;%ld;0c", ver);
- feed_child(buf, -1);
+ int const version = (VTE_MAJOR_VERSION * 100 + VTE_MINOR_VERSION) * 100 + VTE_MICRO_VERSION;
+ reply(seq, VTE_REPLY_DECDA2R, {65, version, 1});
}
void
@@ -2219,12 +2193,14 @@ VteTerminalPrivate::DA3(vte::parser::Sequence const& seq)
* ^P ! | XX AA BB CC ^\
* whereas all four parameters are hexadecimal-encoded pairs. XX
* denotes the manufacturing site, AA BB CC is the terminal's ID.
+ *
+ * We always reply with '~VTE' encoded in hex.
*/
- /* we do not support tertiary DAs */
-
if (seq.collect1(0, 0) != 0)
return;
+
+ reply(seq, VTE_REPLY_DECRPTUI, {});
}
void
@@ -2805,21 +2781,31 @@ VteTerminalPrivate::DECREQTPARM(vte::parser::Sequence const& seq)
* Defaults:
* args[0]: 0
*
- * References: VT525
+ * References: VT100
*/
-#if 0
- if (seq->n_args < 1 || seq->args[0] == 0) {
+
+ switch (seq.collect1(0)) {
+ case -1:
+ case 0:
+ #if 0
screen->flags &= ~VTE_FLAG_INHIBIT_TPARM;
- return SEQ_WRITE(screen, C0_CSI, C1_CSI, "2;1;1;120;120;1;0x");
- } else if (seq->args[0] == 1) {
+ #endif
+ reply(seq, VTE_REPLY_DECREPTPARM,
+ {2, 1, 1, 120, 120, 1, 0});
+ break;
+ case 1:
+ #if 0
screen->flags |= VTE_FLAG_INHIBIT_TPARM;
- return SEQ_WRITE(screen, C0_CSI, C1_CSI, "3;1;1;120;120;1;0x");
- } else {
- return 0;
+ #endif
+ reply(seq, VTE_REPLY_DECREPTPARM,
+ {3, 1, 1, 120, 120, 1, 0});
+ break;
+ case 2:
+ case 3:
+ /* This is a report, not a request */
+ default:
+ break;
}
-#endif
-
- feed_child("\e[?x", -1);
}
void
@@ -3693,9 +3679,7 @@ VteTerminalPrivate::DSR_ECMA(vte::parser::Sequence const& seq)
* References: ECMA-48 § 8.3.35
*/
- auto param = seq.collect1(0);
-
- switch (param) {
+ switch (seq.collect1(0)) {
case -1:
case 0:
case 1:
@@ -3704,14 +3688,23 @@ VteTerminalPrivate::DSR_ECMA(vte::parser::Sequence const& seq)
case 4:
/* This is a status report */
break;
+
case 5:
- /* Requesting a DSR */
- feed_child(_VTE_CAP_CSI "0n", -1);
+ /* Request operating status report.
+ * Reply: DSR
+ * @arg[0]: status
+ * 0 = ok
+ * 3 = malfunction
+ */
+ reply(seq, VTE_REPLY_DSR, {0});
break;
- case 6:
- /* Requesting a CPR */
- /* Send the cursor position. */
+ case 6:
+ /* Request extended cursor position report
+ * Reply: CPR
+ * @arg[0]: line
+ * @arg[1]: column
+ */
vte::grid::row_t rowval, origin, rowmax;
if (m_modes_private.DEC_ORIGIN() &&
m_scrolling_restricted) {
@@ -3724,13 +3717,11 @@ VteTerminalPrivate::DSR_ECMA(vte::parser::Sequence const& seq)
// FIXMEchpe this looks wrong. shouldn't this first clamp to origin,rowmax and *then*
subtract origin?
rowval = m_screen->cursor.row - m_screen->insert_delta - origin;
rowval = CLAMP(rowval, 0, rowmax);
- char buf[128];
- g_snprintf(buf, sizeof(buf),
- _VTE_CAP_CSI "%ld;%ldR",
- rowval + 1,
- CLAMP(m_screen->cursor.col + 1, 1, m_column_count));
- feed_child(buf, -1);
+
+ reply(seq, VTE_REPLY_CPR,
+ {int(rowval + 1), int(CLAMP(m_screen->cursor.col + 1, 1, m_column_count))});
break;
+
default:
break;
}
@@ -3748,13 +3739,19 @@ VteTerminalPrivate::DSR_DEC(vte::parser::Sequence const& seq)
* arg[0]: 0
*
* References: VT525 5–173
+ * VT330
+ * XTERM
*/
- auto param = seq.collect1(0);
-
- switch (param) {
+ switch (seq.collect1(0)) {
case 6:
- /* Send the cursor position. */
+ /* Request extended cursor position report
+ * Reply: DECXCPR
+ * @arg[0]: line
+ * @arg[1]: column
+ * @arg[2]: page
+ * Always report page 1 here (per XTERM source code).
+ */
vte::grid::row_t rowval, origin, rowmax;
if (m_modes_private.DEC_ORIGIN() &&
m_scrolling_restricted) {
@@ -3767,28 +3764,127 @@ VteTerminalPrivate::DSR_DEC(vte::parser::Sequence const& seq)
// FIXMEchpe this looks wrong. shouldn't this first clamp to origin,rowmax and *then*
subtract origin?
rowval = m_screen->cursor.row - m_screen->insert_delta - origin;
rowval = CLAMP(rowval, 0, rowmax);
- char buf[128];
- g_snprintf(buf, sizeof(buf),
- _VTE_CAP_CSI "?%ld;%ldR",
- rowval + 1,
- CLAMP(m_screen->cursor.col + 1, 1, m_column_count));
- feed_child(buf, -1);
+
+ reply(seq, VTE_REPLY_DECXCPR,
+ {int(rowval + 1), int(CLAMP(m_screen->cursor.col + 1, 1, m_column_count)), 1});
break;
+
case 15:
- /* Send printer status -- 10 = ready,
- * 11 = not ready. We don't print. */
- feed_child(_VTE_CAP_CSI "?11n", -1);
+ /* Request printer port report
+ * Reply: DECDSR
+ * @arg[0]: status
+ * 10 = printer ready
+ * 11 = printer not ready
+ * 13 = no printer
+ * 18 = printer busy
+ * 19 = printer assigned to another session
+ */
+ reply(seq, VTE_REPLY_DECDSR, {13});
break;
+
case 25:
- /* Send UDK status -- 20 = locked,
- * 21 = not locked. I don't even know what
- * that means, but punt anyway. */
- feed_child(_VTE_CAP_CSI "?20n", -1);
+ /* Request user-defined keys report
+ * Reply: DECDSR
+ * @arg[0]: locked status
+ * 20 = UDK unlocked
+ * 21 = UDK locked
+ *
+ * Since we don't do UDK, we report them as locked.
+ */
+ reply(seq, VTE_REPLY_DECDSR, {21});
break;
+
case 26:
- /* Send keyboard status. 50 = no locator. */
- feed_child(_VTE_CAP_CSI "?50n", -1);
+ /* Request keyboard report
+ * Reply: DECDSR
+ * @arg[0]: 27
+ * @arg[1]: Keyboard language
+ * 0 = undetermined
+ * 1..40
+ *
+ * @arg[2]: Keyboard status
+ * 0 = ready
+ * 3 = no keyboard
+ * 8 = keyboard busy
+ *
+ * @arg[3]: Keyboard type
+ * 0 = LK201 (XTERM response)
+ * 4 = LK411
+ * 5 = PCXAL
+ */
+ reply(seq, VTE_REPLY_DECDSR, {27, 0, 0, 5});
break;
+
+ case 53:
+ /* XTERM alias for 55 */
+ /* [[fallthrough]]; */
+ case 55:
+ /* Request locator status report
+ * Reply: DECDSR
+ * @arg[0]: status
+ * 50 = locator ready
+ * 53 = no locator
+ *
+ * Since we don't implement the DEC locator mode,
+ * we reply with 53.
+ */
+ reply(seq, VTE_REPLY_DECDSR, {53});
+ break;
+
+ case 56:
+ /* Request locator type report
+ * Reply: DECDSR
+ * @arg[0]: 57
+ * @arg[1]: status
+ * 0 = unknown
+ * 1 = mouse
+ *
+ * Since we don't implement the DEC locator mode,
+ * we reply with 0.
+ */
+ reply(seq, VTE_REPLY_DECDSR, {57, 0});
+ break;
+
+ case 62:
+ /* Request macro space report
+ * Reply: DECMSR
+ * @arg[0]: floor((number of bytes available) / 16); we report 0
+ */
+ reply(seq, VTE_REPLY_DECMSR, {0});
+ break;
+
+ case 63:
+ /* Request memory checksum report
+ * Reply: DECCKSR
+ * @arg[0]: PID
+ * DATA: hex encoded
+ *
+ * Reply with empty DATA.
+ */
+ reply(seq, VTE_REPLY_DECCKSR, {seq.collect1(1)});
+ break;
+
+ case 75:
+ /* Request data integrity report
+ * Reply: DECDSR
+ * @arg[0]: status
+ * 70 = no error, no power loss, no communication errors
+ * 71 = malfunction or communication error
+ * 73 = no data loss since last power-up
+ */
+ reply(seq, VTE_REPLY_DECDSR, {70});
+ break;
+
+ case 85:
+ /* Request multi-session status report
+ * Reply: DECDSR
+ * @arg[0]: status
+ * ...
+ * 83 = not configured
+ */
+ reply(seq, VTE_REPLY_DECDSR, {83});
+ break;
+
default:
break;
}
@@ -5255,94 +5351,101 @@ VteTerminalPrivate::XTERM_WM(vte::parser::Sequence const& seq)
* No parameter default values.
*
* References: XTERM
+ * VT525
*/
- int param, arg1, arg2;
- if (!seq.collect(0, {¶m, &arg1, &arg2}))
- return;
-
- GdkScreen *gscreen;
+ #if 0
char buf[128];
- int width, height;
+ #endif
+ int param = seq.collect1(0);
switch (param) {
case -1:
case 0:
break;
case VTE_XTERM_WM_RESTORE_WINDOW:
- _vte_debug_print(VTE_DEBUG_PARSER,
- "Deiconifying window.\n");
+ _vte_debug_print(VTE_DEBUG_EMULATION, "Deiconifying window.\n");
emit_deiconify_window();
break;
case VTE_XTERM_WM_MINIMIZE_WINDOW:
- _vte_debug_print(VTE_DEBUG_PARSER,
- "Iconifying window.\n");
+ _vte_debug_print(VTE_DEBUG_EMULATION, "Iconifying window.\n");
emit_iconify_window();
break;
- case VTE_XTERM_WM_SET_WINDOW_POSITION:
- if ((arg1 != -1) && (arg2 != -1)) {
- _vte_debug_print(VTE_DEBUG_PARSER,
- "Moving window to "
- "%d,%d.\n", arg1, arg2);
- emit_move_window(arg1, arg2);
- }
+ case VTE_XTERM_WM_SET_WINDOW_POSITION: {
+ int pos_x = seq.collect1(1, 0);
+ int pos_y = seq.collect1(2, 0);
+
+ _vte_debug_print(VTE_DEBUG_EMULATION,
+ "Moving window to %d,%d.\n", pos_x, pos_y);
+ emit_move_window(pos_x, pos_y);
break;
+ }
- case VTE_XTERM_WM_SET_WINDOW_SIZE_PIXELS:
- if ((arg1 != -1) && (arg2 != -1)) {
- _vte_debug_print(VTE_DEBUG_PARSER,
- "Resizing window "
- "(to %dx%d pixels, grid size %ldx%ld).\n",
- arg2, arg1,
- arg2 / m_cell_width,
- arg1 / m_cell_height);
- emit_resize_window(arg2 / m_cell_width,
- arg1 / m_cell_height);
+ case VTE_XTERM_WM_SET_WINDOW_SIZE_PIXELS: {
+ int width, height;
+ seq.collect(1, {&height, &width});
+
+ if (width != -1 && height != -1) {
+ _vte_debug_print(VTE_DEBUG_EMULATION,
+ "Resizing window to %dx%d pixels, grid size %dx%d.\n",
+ width, height,
+ width / int(m_cell_height), height / int(m_cell_width));
+ emit_resize_window(width / int(m_cell_height), height / int(m_cell_width));
}
break;
+ }
case VTE_XTERM_WM_RAISE_WINDOW:
- _vte_debug_print(VTE_DEBUG_PARSER, "Raising window.\n");
+ _vte_debug_print(VTE_DEBUG_EMULATION, "Raising window.\n");
emit_raise_window();
break;
case VTE_XTERM_WM_LOWER_WINDOW:
- _vte_debug_print(VTE_DEBUG_PARSER, "Lowering window.\n");
+ _vte_debug_print(VTE_DEBUG_EMULATION, "Lowering window.\n");
emit_lower_window();
break;
case VTE_XTERM_WM_REFRESH_WINDOW:
- _vte_debug_print(VTE_DEBUG_PARSER,
- "Refreshing window.\n");
+ _vte_debug_print(VTE_DEBUG_EMULATION, "Refreshing window.\n");
invalidate_all();
emit_refresh_window();
break;
- case VTE_XTERM_WM_SET_WINDOW_SIZE_CELLS:
- if ((arg1 != -1) && (arg2 != -1)) {
- _vte_debug_print(VTE_DEBUG_PARSER,
- "Resizing window "
- "(to %d columns, %d rows).\n",
- arg2, arg1);
- emit_resize_window(arg2, arg1);
+ case VTE_XTERM_WM_SET_WINDOW_SIZE_CELLS: {
+ int width, height;
+ seq.collect(1, {&height, &width});
+
+ if (width != -1 && height != -1) {
+ _vte_debug_print(VTE_DEBUG_EMULATION,
+ "Resizing window to %d columns, %d rows.\n",
+ width, height);
+ emit_resize_window(width, height);
}
break;
+ }
case VTE_XTERM_WM_MAXIMIZE_WINDOW:
- switch (arg1) {
+ switch (seq.collect1(1)) {
+ case -1: /* default */
case 0:
- _vte_debug_print(VTE_DEBUG_PARSER,
- "Restoring window.\n");
+ /* Restore */
+ _vte_debug_print(VTE_DEBUG_EMULATION, "Restoring window.\n");
emit_restore_window();
break;
case 1:
- _vte_debug_print(VTE_DEBUG_PARSER,
- "Maximizing window.\n");
+ /* Maximise */
+ _vte_debug_print(VTE_DEBUG_EMULATION, "Maximizing window.\n");
emit_maximize_window();
break;
+ case 2:
+ /* Maximise Vertically */
+ break;
+ case 3:
+ /* Maximise Horizontally */
+ break;
default:
break;
}
@@ -5353,96 +5456,91 @@ VteTerminalPrivate::XTERM_WM(vte::parser::Sequence const& seq)
case VTE_XTERM_WM_GET_WINDOW_STATE:
/* If we're unmapped, then we're iconified. */
- g_snprintf(buf, sizeof(buf),
- _VTE_CAP_CSI "%dt",
- 1 + !gtk_widget_get_mapped(m_widget));
- _vte_debug_print(VTE_DEBUG_PARSER,
- "Reporting window state %s.\n",
- gtk_widget_get_mapped(m_widget) ?
- "non-iconified" : "iconified");
- feed_child(buf, -1);
+ _vte_debug_print(VTE_DEBUG_EMULATION,
+ "Reporting window state %siconified.\n",
+ gtk_widget_get_mapped(m_widget) ? "non-" : "");
+
+ reply(seq, VTE_REPLY_XTERM_WM,
+ {gtk_widget_get_mapped(m_widget) ? 1 : 2});
break;
- case VTE_XTERM_WM_GET_WINDOW_POSITION:
+ case VTE_XTERM_WM_GET_WINDOW_POSITION: {
/* Send window location, in pixels. */
- gdk_window_get_origin(gtk_widget_get_window(m_widget),
- &width, &height);
- g_snprintf(buf, sizeof(buf),
- _VTE_CAP_CSI "3;%d;%dt",
- width + m_padding.left,
- height + m_padding.top);
- _vte_debug_print(VTE_DEBUG_PARSER,
- "Reporting window location"
- "(%d++,%d++).\n",
- width, height);
- feed_child(buf, -1);
+ /* FIXME: this is not supported on wayland; just hardwire
+ * it to a fixed return always.
+ */
+ int x0, y0;
+ gdk_window_get_origin(gtk_widget_get_window(m_widget), &x0, &y0);
+ _vte_debug_print(VTE_DEBUG_EMULATION,
+ "Reporting window location (%d,%d).\n", x0, y0);
+
+ reply(seq, VTE_REPLY_XTERM_WM,
+ {3, x0 + m_padding.left, y0 + m_padding.top});
break;
+ }
- case VTE_XTERM_WM_GET_WINDOW_SIZE_PIXELS:
+ case VTE_XTERM_WM_GET_WINDOW_SIZE_PIXELS: {
/* Send window size, in pixels. */
- g_snprintf(buf, sizeof(buf),
- _VTE_CAP_CSI "4;%d;%dt",
- (int)(m_row_count * m_cell_height),
- (int)(m_column_count * m_cell_width));
- _vte_debug_print(VTE_DEBUG_PARSER,
- "Reporting window size "
- "(%dx%d)\n",
- (int)(m_row_count * m_cell_height),
- (int)(m_column_count * m_cell_width));
-
- feed_child(buf, -1);
+ int width = m_row_count * m_cell_height;
+ int height = m_column_count * m_cell_width;
+ _vte_debug_print(VTE_DEBUG_EMULATION,
+ "Reporting window size (%dx%d)\n",
+ width, height);
+
+ reply(seq, VTE_REPLY_XTERM_WM, {4, height, width});
break;
+ }
case VTE_XTERM_WM_GET_WINDOW_SIZE_CELLS:
/* Send widget size, in cells. */
- _vte_debug_print(VTE_DEBUG_PARSER,
- "Reporting widget size.\n");
- g_snprintf(buf, sizeof(buf),
- _VTE_CAP_CSI "8;%ld;%ldt",
- m_row_count,
- m_column_count);
- feed_child(buf, -1);
+ _vte_debug_print(VTE_DEBUG_EMULATION,
+ "Reporting widget size %ldx%ld\n",
+ m_row_count, m_column_count);
+
+ reply(seq, VTE_REPLY_XTERM_WM,
+ {8, (int)m_row_count, (int)m_column_count});
break;
- case VTE_XTERM_WM_GET_SCREEN_SIZE_CELLS:
- _vte_debug_print(VTE_DEBUG_PARSER,
- "Reporting screen size.\n");
- gscreen = gtk_widget_get_screen(m_widget);
- height = gdk_screen_get_height(gscreen);
- width = gdk_screen_get_width(gscreen);
- g_snprintf(buf, sizeof(buf),
- _VTE_CAP_CSI "9;%ld;%ldt",
- height / m_cell_height,
- width / m_cell_width);
- feed_child(buf, -1);
+ case VTE_XTERM_WM_GET_SCREEN_SIZE_CELLS: {
+ /* FIMXE: this should really report the monitor's workarea,
+ * or even just a fixed value.
+ */
+ auto gdkscreen = gtk_widget_get_screen(m_widget);
+ int height = gdk_screen_get_height(gdkscreen);
+ int width = gdk_screen_get_width(gdkscreen);
+ _vte_debug_print(VTE_DEBUG_EMULATION,
+ "Reporting screen size as %dx%d cells.\n",
+ height / int(m_cell_height), width / int(m_cell_width));
+
+ reply(seq, VTE_REPLY_XTERM_WM,
+ {9, height / int(m_cell_height), width / int(m_cell_width)});
break;
+ }
case VTE_XTERM_WM_GET_ICON_TITLE:
/* Report a static icon title, since the real
- icon title should NEVER be reported, as it
- creates a security vulnerability. See
- http://marc.info/?l=bugtraq&m=104612710031920&w=2
- and CVE-2003-0070. */
- _vte_debug_print(VTE_DEBUG_PARSER,
- "Reporting fake icon title.\n");
- /* never use m_icon_title here! */
- g_snprintf (buf, sizeof (buf),
- _VTE_CAP_OSC "LTerminal" _VTE_CAP_ST);
- feed_child(buf, -1);
+ * icon title should NEVER be reported, as it
+ * creates a security vulnerability. See
+ * http://marc.info/?l=bugtraq&m=104612710031920&w=2
+ * and CVE-2003-0070.
+ */
+ _vte_debug_print(VTE_DEBUG_EMULATION,
+ "Reporting empty icon title.\n");
+
+ send(seq, vte::parser::u8SequenceBuilder{VTE_SEQ_OSC, "L"s});
break;
case VTE_XTERM_WM_GET_WINDOW_TITLE:
/* Report a static window title, since the real
- window title should NEVER be reported, as it
- creates a security vulnerability. See
- http://marc.info/?l=bugtraq&m=104612710031920&w=2
- and CVE-2003-0070. */
- _vte_debug_print(VTE_DEBUG_PARSER,
- "Reporting fake window title.\n");
- /* never use m_window_title here! */
- g_snprintf (buf, sizeof (buf),
- _VTE_CAP_OSC "lTerminal" _VTE_CAP_ST);
- feed_child(buf, -1);
+ * window title should NEVER be reported, as it
+ * creates a security vulnerability. See
+ * http://marc.info/?l=bugtraq&m=104612710031920&w=2
+ * and CVE-2003-0070.
+ */
+ _vte_debug_print(VTE_DEBUG_EMULATION,
+ "Reporting empty window title.\n");
+
+ send(seq, vte::parser::u8SequenceBuilder{VTE_SEQ_OSC, "l"s});
break;
case VTE_XTERM_WM_TITLE_STACK_PUSH:
@@ -5452,13 +5550,16 @@ VteTerminalPrivate::XTERM_WM(vte::parser::Sequence const& seq)
break;
default:
- /* DECSLPP; param is 24, 25, 36, 41, 42, 48, 52, 53, 72, or 144 */
+ /* DECSLPP.
+ *
+ * VTxxx variously supported 24, 25, 36, 41, 42, 48, 52, 53, 72, or 144 rows,
+ * but we support any value >= 24.
+ */
if (param >= 24) {
- _vte_debug_print(VTE_DEBUG_PARSER,
+ _vte_debug_print(VTE_DEBUG_EMULATION,
"Resizing to %d rows.\n",
param);
- /* Resize to the specified number of
- * rows. */
+ /* Resize to the specified number of rows. */
emit_resize_window(m_column_count, param);
}
break;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]