From b41e40e065c60e76b9721747492875c3454440dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Pi=C3=B3rkowski?= Date: Tue, 22 Feb 2022 15:41:49 +0000 Subject: [PATCH] Add support for CSI sequences --- src/libply-splash-core/ply-keyboard.c | 52 +++++++++++++++++++++++++-- src/main.c | 2 ++ src/plugins/renderers/x11/plugin.c | 19 ++++++++++ 3 files changed, 71 insertions(+), 2 deletions(-) diff --git a/src/libply-splash-core/ply-keyboard.c b/src/libply-splash-core/ply-keyboard.c index b174261..b40e961 100644 --- a/src/libply-splash-core/ply-keyboard.c +++ b/src/libply-splash-core/ply-keyboard.c @@ -48,6 +48,12 @@ #define KEY_RETURN '\n' #define KEY_BACKSPACE '\177' +#define CSI_SEQUENCE_PREFIX "\033[" +#define CSI_SEQUENCE_MINIMUM_LENGTH (strlen (CSI_SEQUENCE_PREFIX) + 1) + +#define FUNCTION_KEY_SEQUENCE_PREFIX (CSI_SEQUENCE_PREFIX "[") +#define FUNCTION_KEY_SEQUENCE_MINIMUM_LENGTH (strlen (FUNCTION_KEY_SEQUENCE_PREFIX) + 1) + typedef void (*ply_keyboard_handler_t) (void *); typedef struct @@ -195,7 +201,11 @@ process_keyboard_input (ply_keyboard_t *keyboard, wchar_t key; ply_list_node_t *node; - if ((ssize_t) mbrtowc (&key, keyboard_input, character_size, NULL) > 0) { + if (keyboard_input[0] == KEY_ESCAPE && character_size >= 2){ + /* Escape sequence */ + ply_buffer_append_bytes (keyboard->line_buffer, + keyboard_input, character_size); + } else if ((ssize_t) mbrtowc (&key, keyboard_input, character_size, NULL) > 0) { switch (key) { case KEY_CTRL_U: case KEY_CTRL_W: @@ -270,8 +280,46 @@ on_key_event (ply_keyboard_t *keyboard, while (i < size) { ssize_t character_size; char *keyboard_input; + size_t bytes_left = size - i; + + /* Control Sequence Introducer sequences + */ + if(bytes_left >= FUNCTION_KEY_SEQUENCE_MINIMUM_LENGTH && + strncmp (bytes + i, FUNCTION_KEY_SEQUENCE_PREFIX, + strlen (FUNCTION_KEY_SEQUENCE_PREFIX)) == 0) { + /* Special case - CSI [ after which the next character + * is a function key + */ + process_keyboard_input (keyboard, bytes + i, 4); + i += 4; + continue; + } else if(bytes_left >= CSI_SEQUENCE_MINIMUM_LENGTH && /* At least CSI + final byte */ + strncmp (bytes + i, CSI_SEQUENCE_PREFIX, + strlen (CSI_SEQUENCE_PREFIX)) == 0) { + ssize_t csi_seq_size; + csi_seq_size = 0; + for (size_t j = strlen (CSI_SEQUENCE_PREFIX); j < bytes_left; j++) { + if ((bytes[i + j] >= 0x40) && + (bytes[i + j] <= 0x7E)) { + /* Final byte found */ + csi_seq_size = j + 1; + break; + } + /* We presume if we aren't at the final byte, the intermediate + * bytes will be in the range 0x20-0x2F, but we don't validate + * that, since it's not really clear how invalid sequences should + * be handled, and letting them through to the keyboard input + * handlers seems just as reasonable as alternatives. + */ + } + if (csi_seq_size == 0) /* No final byte found */ + continue; + process_keyboard_input (keyboard, bytes + i, csi_seq_size); + i += csi_seq_size; + continue; + } - character_size = (ssize_t) ply_utf8_character_get_size (bytes + i, size - i); + character_size = (ssize_t) ply_utf8_character_get_size (bytes + i, bytes_left); if (character_size < 0) break; diff --git a/src/main.c b/src/main.c index 1cb8f6c..bedab7d 100644 --- a/src/main.c +++ b/src/main.c @@ -1516,6 +1516,8 @@ on_keyboard_input (state_t *state, ply_buffer_clear (state->entry_buffer); ply_list_remove_node (state->entry_triggers, node); free (entry_trigger); + } else if (character_size >= 2 && keyboard_input[0] == '\033') { + /* Ignore escape sequences */ } else { ply_buffer_append_bytes (state->entry_buffer, keyboard_input, character_size); } diff --git a/src/plugins/renderers/x11/plugin.c b/src/plugins/renderers/x11/plugin.c index bfb039a..e7169f3 100644 --- a/src/plugins/renderers/x11/plugin.c +++ b/src/plugins/renderers/x11/plugin.c @@ -61,6 +61,21 @@ #include "ply-renderer.h" #include "ply-renderer-plugin.h" +static const char *function_key_escape_sequence[] = { + "\033[[A", /* F1 */ + "\033[[B", /* F2 */ + "\033[[C", /* F3 */ + "\033[[D", /* F4 */ + "\033[[E", /* F5 */ + "\033[17~", /* F6 */ + "\033[18~", /* F7 */ + "\033[19~", /* F8 */ + "\033[20~", /* F9 */ + "\033[21~", /* F10 */ + "\033[22~", /* F11 */ + "\033[23~", /* F12 */ +}; + struct _ply_renderer_head { ply_renderer_backend_t *backend; @@ -482,6 +497,10 @@ on_key_event (GtkWidget *widget, ply_buffer_append_bytes (input_source->key_buffer, "\033", 1); } else if (event->keyval == GDK_KEY_BackSpace) { /* Backspace */ ply_buffer_append_bytes (input_source->key_buffer, "\177", 1); + } else if (GDK_KEY_F1 <= event->keyval && + GDK_KEY_F12 >= event->keyval) { /* F1-F12 */ + const char *key = function_key_escape_sequence[event->keyval - GDK_KEY_F1]; + ply_buffer_append_bytes (input_source->key_buffer, key, strlen(key)); } else { gchar bytes[7]; int byte_count; -- 2.35.1