]> git.ipfire.org Git - thirdparty/plymouth.git/commitdiff
Add support for CSI sequences
authorMateusz Piórkowski <mati7337@protonmail.ch>
Tue, 22 Feb 2022 15:41:49 +0000 (15:41 +0000)
committerRay Strode <halfline@gmail.com>
Tue, 22 Feb 2022 15:41:49 +0000 (15:41 +0000)
src/libply-splash-core/ply-keyboard.c
src/main.c
src/plugins/renderers/x11/plugin.c

index b174261881ecb8e89b53f5ca840693130564046e..b40e961e441c9c3bebf571d7bc441a5e0b0fe5b6 100644 (file)
 #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;
index 1cb8f6c0cb79bf3690a96bfadadc782db824bdce..bedab7d39cdf2ced992107fb48f4a2b83ca53287 100644 (file)
@@ -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);
                 }
index bfb039a6a179eb52b9ffc4e432d4da99e7b4b255..e7169f3e3f6daba752246113b0ab0017dde2cc2c 100644 (file)
 #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;