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