From 5a6cbb8c3e4d23f8ab16552a02c6cc13207f8961 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Sun, 12 Jan 2020 11:55:22 +0100 Subject: [PATCH] dcs: initial handling of DCS in general Add data structure to term->vt. This structure tracks the free-form data that is passed-through, and the handler to call at the end. Intermediates and parameters are collected by the normal VT parser. Then, when we enter the passthrough state, we call dcs_hook(). This function checks the intermediate(s) and parameters, and selects the appropriate unhook handler (and optionally does some execution already). In passthrough mode, we simply append strings to an internal buffer. This might have to be changed in the future, if we need to support a DCS that needs to execute as we go. In unhook (i.e. when the DCS is terminated), we execute the unhook handler. As a proof-of-concept, handlers for BSU/ESU (Begin/End Synchronized Update) has been added (but are left unimplemented). --- dcs.c | 87 +++++++++++++++++++++++++++++++++++++++++++++++++++++ dcs.h | 8 +++++ meson.build | 1 + terminal.h | 6 ++++ vt.c | 4 +++ 5 files changed, 106 insertions(+) create mode 100644 dcs.c create mode 100644 dcs.h diff --git a/dcs.c b/dcs.c new file mode 100644 index 00000000..b6a0b4fa --- /dev/null +++ b/dcs.c @@ -0,0 +1,87 @@ +#include "dcs.h" + +#define LOG_MODULE "dcs" +#define LOG_ENABLE_DBG 0 +#include "log.h" +#include "vt.h" + +static void +bsu(struct terminal *term) +{ + LOG_WARN("unimplemented: BSU - Begin Synchronized Update (params: %.*s)", + (int)term->vt.dcs.idx, term->vt.dcs.data); +} + +static void +esu(struct terminal *term) +{ + LOG_WARN("unimplemented: ESU - Begin Synchronized Update (params: %.*s)", + (int)term->vt.dcs.idx, term->vt.dcs.data); +} + +void +dcs_hook(struct terminal *term, uint8_t final) +{ + LOG_DBG("hook: %c (intermediate(s): %.2s, param=%d)", final, term->vt.private, + vt_param_get(term, 0, 127)); + + assert(term->vt.dcs.data == NULL); + assert(term->vt.dcs.size == 0); + assert(term->vt.dcs.unhook_handler == NULL); + + switch (term->vt.private[0]) { + case '=': + switch (final) { + case 's': + switch (vt_param_get(term, 0, 0)) { + case 1: term->vt.dcs.unhook_handler = &bsu; return; + case 2: term->vt.dcs.unhook_handler = &esu; return; + } + break; + } + break; + } +} + +static bool +ensure_size(struct terminal *term, size_t required_size) +{ + if (required_size <= term->vt.dcs.size) + return true; + + size_t new_size = (required_size + 127) / 128 * 128; + assert(new_size > 0); + + uint8_t *new_data = realloc(term->vt.dcs.data, new_size); + if (new_data == NULL) { + LOG_ERRNO("failed to increase size of DCS buffer"); + return false; + } + + term->vt.dcs.data = new_data; + term->vt.dcs.size = new_size; + return true; +} + +void +dcs_put(struct terminal *term, uint8_t c) +{ + LOG_DBG("PUT: %c", c); + ensure_size(term, term->vt.dcs.idx + 1); + term->vt.dcs.data[term->vt.dcs.idx++] = c; +} + +void +dcs_unhook(struct terminal *term) +{ + assert(term->vt.dcs.unhook_handler != NULL); + if (term->vt.dcs.unhook_handler != NULL) + term->vt.dcs.unhook_handler(term); + + term->vt.dcs.unhook_handler = NULL; + + free(term->vt.dcs.data); + term->vt.dcs.data = NULL; + term->vt.dcs.size = 0; + term->vt.dcs.idx = 0; +} diff --git a/dcs.h b/dcs.h new file mode 100644 index 00000000..f89de38a --- /dev/null +++ b/dcs.h @@ -0,0 +1,8 @@ +#pragma once + +#include +#include "terminal.h" + +void dcs_hook(struct terminal *term, uint8_t final); +void dcs_put(struct terminal *term, uint8_t c); +void dcs_unhook(struct terminal *term); diff --git a/meson.build b/meson.build index 786ab7c9..5e5060fc 100644 --- a/meson.build +++ b/meson.build @@ -70,6 +70,7 @@ executable( 'config.c', 'config.h', 'commands.c', 'commands.h', 'csi.c', 'csi.h', + 'dcs.c', 'dcs.h', 'fdm.c', 'fdm.h', 'grid.c', 'grid.h', 'input.c', 'input.h', diff --git a/terminal.h b/terminal.h index 1595f902..8e47826b 100644 --- a/terminal.h +++ b/terminal.h @@ -125,6 +125,12 @@ struct vt { size_t idx; size_t left; } utf8; + struct { + uint8_t *data; + size_t size; + size_t idx; + void (*unhook_handler)(struct terminal *term); + } dcs; struct attributes attrs; struct attributes saved_attrs; }; diff --git a/vt.c b/vt.c index 114aba02..19044339 100644 --- a/vt.c +++ b/vt.c @@ -9,6 +9,7 @@ #define LOG_ENABLE_DBG 0 #include "log.h" #include "csi.h" +#include "dcs.h" #include "grid.h" #include "osc.h" @@ -482,16 +483,19 @@ action_osc_put(struct terminal *term, uint8_t c) static void action_hook(struct terminal *term, uint8_t c) { + dcs_hook(term, c); } static void action_unhook(struct terminal *term, uint8_t c) { + dcs_unhook(term); } static void action_put(struct terminal *term, uint8_t c) { + dcs_put(term, c); } static void