summaryrefslogtreecommitdiffstats
path: root/input.c
diff options
context:
space:
mode:
authorNicholas Marriott <nicm@openbsd.org>2010-03-22 19:02:54 +0000
committerNicholas Marriott <nicm@openbsd.org>2010-03-22 19:02:54 +0000
commit4baafd81262a2b1961e9b710b6f9c9cff9b2b828 (patch)
tree00bd93a3847fb471c468f59f08ba735c49034e8f /input.c
parent48dd72005e879336ea2439fb3422296be664cc76 (diff)
New input parser based on http://vt100.net/emu/dec_ansi_parser.
Diffstat (limited to 'input.c')
-rw-r--r--input.c2281
1 files changed, 1136 insertions, 1145 deletions
diff --git a/input.c b/input.c
index bf31413c..e709b366 100644
--- a/input.c
+++ b/input.c
@@ -18,1395 +18,1259 @@
#include <sys/types.h>
-#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include "tmux.h"
-#define INPUT_C0CONTROL(ch) (ch <= 0x1f)
-#define INPUT_INTERMEDIATE(ch) (ch == 0xa0 || (ch >= 0x20 && ch <= 0x2f))
-#define INPUT_PARAMETER(ch) (ch >= 0x30 && ch <= 0x3f)
-#define INPUT_UPPERCASE(ch) (ch >= 0x40 && ch <= 0x5f)
-#define INPUT_LOWERCASE(ch) (ch >= 0x60 && ch <= 0x7e)
-#define INPUT_DELETE(ch) (ch == 0x7f)
-#define INPUT_C1CONTROL(ch) (ch >= 0x80 && ch <= 0x9f)
-#define INPUT_G1DISPLAYABLE(ch) (ch >= 0xa1 && ch <= 0xfe)
-#define INPUT_SPECIAL(ch) (ch == 0xff)
-
-int input_get_argument(struct input_ctx *, u_int, uint16_t *, uint16_t);
-void input_new_argument(struct input_ctx *);
-int input_add_argument(struct input_ctx *, u_char);
-
-void input_start_string(struct input_ctx *, int);
-void input_abort_string(struct input_ctx *);
-int input_add_string(struct input_ctx *, u_char);
-char *input_get_string(struct input_ctx *);
-
-void input_state(struct input_ctx *, void *);
-
-void input_state_first(u_char, struct input_ctx *);
-void input_state_escape(u_char, struct input_ctx *);
-void input_state_intermediate(u_char, struct input_ctx *);
-void input_state_sequence_first(u_char, struct input_ctx *);
-void input_state_sequence_next(u_char, struct input_ctx *);
-void input_state_sequence_intermediate(u_char, struct input_ctx *);
-void input_state_string_next(u_char, struct input_ctx *);
-void input_state_string_escape(u_char, struct input_ctx *);
-void input_state_utf8(u_char, struct input_ctx *);
-
-void input_handle_character(u_char, struct input_ctx *);
-void input_handle_c0_control(u_char, struct input_ctx *);
-void input_handle_c1_control(u_char, struct input_ctx *);
-void input_handle_private_two(u_char, struct input_ctx *);
-void input_handle_standard_two(u_char, struct input_ctx *);
-void input_handle_sequence(u_char, struct input_ctx *);
-
-void input_handle_sequence_cuu(struct input_ctx *);
-void input_handle_sequence_cud(struct input_ctx *);
-void input_handle_sequence_cuf(struct input_ctx *);
-void input_handle_sequence_cub(struct input_ctx *);
-void input_handle_sequence_dch(struct input_ctx *);
-void input_handle_sequence_cbt(struct input_ctx *);
-void input_handle_sequence_da(struct input_ctx *);
-void input_handle_sequence_dl(struct input_ctx *);
-void input_handle_sequence_ich(struct input_ctx *);
-void input_handle_sequence_il(struct input_ctx *);
-void input_handle_sequence_vpa(struct input_ctx *);
-void input_handle_sequence_hpa(struct input_ctx *);
-void input_handle_sequence_cup(struct input_ctx *);
-void input_handle_sequence_cup(struct input_ctx *);
-void input_handle_sequence_tbc(struct input_ctx *);
-void input_handle_sequence_ed(struct input_ctx *);
-void input_handle_sequence_el(struct input_ctx *);
-void input_handle_sequence_sm(struct input_ctx *);
-void input_handle_sequence_rm(struct input_ctx *);
-void input_handle_sequence_decstbm(struct input_ctx *);
-void input_handle_sequence_sgr(struct input_ctx *);
-void input_handle_sequence_dsr(struct input_ctx *);
-
-int input_sequence_cmp(const void *, const void *);
-
-struct input_sequence_entry {
- u_char ch;
- void (*fn)(struct input_ctx *);
-};
-const struct input_sequence_entry input_sequence_table[] = {
- { '@', input_handle_sequence_ich },
- { 'A', input_handle_sequence_cuu },
- { 'B', input_handle_sequence_cud },
- { 'C', input_handle_sequence_cuf },
- { 'D', input_handle_sequence_cub },
- { 'G', input_handle_sequence_hpa },
- { 'H', input_handle_sequence_cup },
- { 'J', input_handle_sequence_ed },
- { 'K', input_handle_sequence_el },
- { 'L', input_handle_sequence_il },
- { 'M', input_handle_sequence_dl },
- { 'P', input_handle_sequence_dch },
- { 'Z', input_handle_sequence_cbt },
- { 'c', input_handle_sequence_da },
- { 'd', input_handle_sequence_vpa },
- { 'f', input_handle_sequence_cup },
- { 'g', input_handle_sequence_tbc },
- { 'h', input_handle_sequence_sm },
- { 'l', input_handle_sequence_rm },
- { 'm', input_handle_sequence_sgr },
- { 'n', input_handle_sequence_dsr },
- { 'r', input_handle_sequence_decstbm },
+/*
+ * Based on the description by Paul Williams at:
+ *
+ * http://vt100.net/emu/dec_ansi_parser
+ *
+ * With the following changes:
+ *
+ * - 7-bit only.
+ *
+ * - Support for UTF-8.
+ *
+ * - OSC (but not APC) may be terminated by \007 as well as ST.
+ *
+ * - A state for APC similar to OSC. Some terminals appear to use this to set
+ * the title.
+ *
+ * - A state for the screen \033k...\033\\ sequence to rename a window. This is
+ * pretty stupid but not supporting it is more trouble than it is worth.
+ */
+
+/* Helper functions. */
+int input_split(struct input_ctx *);
+int input_get(struct input_ctx *, u_int, int, int);
+void input_reply(struct input_ctx *, const char *, ...);
+
+/* Transition entry/exit handlers. */
+void input_clear(struct input_ctx *);
+void input_enter_dcs(struct input_ctx *);
+void input_exit_dcs(struct input_ctx *);
+void input_enter_osc(struct input_ctx *);
+void input_exit_osc(struct input_ctx *);
+void input_enter_apc(struct input_ctx *);
+void input_exit_apc(struct input_ctx *);
+void input_enter_rename(struct input_ctx *);
+void input_exit_rename(struct input_ctx *);
+
+/* Input state handlers. */
+int input_print(struct input_ctx *);
+int input_intermediate(struct input_ctx *);
+int input_parameter(struct input_ctx *);
+int input_input(struct input_ctx *);
+int input_c0_dispatch(struct input_ctx *);
+int input_esc_dispatch(struct input_ctx *);
+int input_csi_dispatch(struct input_ctx *);
+void input_csi_dispatch_sgr(struct input_ctx *);
+int input_utf8_open(struct input_ctx *);
+int input_utf8_add(struct input_ctx *);
+int input_utf8_close(struct input_ctx *);
+
+/* Command table comparison function. */
+int input_table_compare(const void *, const void *);
+
+/* Command table entry. */
+struct input_table_entry {
+ int ch;
+ const char *interm;
+ int type;
};
-int
-input_sequence_cmp(const void *a, const void *b)
-{
- int ai = ((const struct input_sequence_entry *) a)->ch;
- int bi = ((const struct input_sequence_entry *) b)->ch;
+/* Escape commands. */
+enum input_esc_type {
+ INPUT_ESC_DECALN,
+ INPUT_ESC_DECKPAM,
+ INPUT_ESC_DECKPNM,
+ INPUT_ESC_DECRC,
+ INPUT_ESC_DECSC,
+ INPUT_ESC_HTS,
+ INPUT_ESC_IND,
+ INPUT_ESC_NEL,
+ INPUT_ESC_RI,
+ INPUT_ESC_RIS,
+ INPUT_ESC_SCSOFF_G0,
+ INPUT_ESC_SCSON_G0,
+};
- return (ai - bi);
-}
+/* Escape command table. */
+const struct input_table_entry input_esc_table[] = {
+ { '0', "(", INPUT_ESC_SCSOFF_G0 },
+ { '7', "", INPUT_ESC_DECSC },
+ { '8', "", INPUT_ESC_DECRC },
+ { '8', "#", INPUT_ESC_DECALN },
+ { '=', "", INPUT_ESC_DECKPAM },
+ { '>', "", INPUT_ESC_DECKPNM },
+ { 'B', "(", INPUT_ESC_SCSON_G0 },
+ { 'D', "", INPUT_ESC_IND },
+ { 'E', "", INPUT_ESC_NEL },
+ { 'H', "", INPUT_ESC_HTS },
+ { 'M', "", INPUT_ESC_RI },
+ { 'c', "", INPUT_ESC_RIS },
+};
-void
-input_new_argument(struct input_ctx *ictx)
-{
- struct input_arg *arg;
+/* Control (CSI) commands. */
+enum input_csi_type {
+ INPUT_CSI_CBT,
+ INPUT_CSI_CUB,
+ INPUT_CSI_CUD,
+ INPUT_CSI_CUF,
+ INPUT_CSI_CUP,
+ INPUT_CSI_CUU,
+ INPUT_CSI_DA,
+ INPUT_CSI_DCH,
+ INPUT_CSI_DECSTBM,
+ INPUT_CSI_DL,
+ INPUT_CSI_DSR,
+ INPUT_CSI_ED,
+ INPUT_CSI_EL,
+ INPUT_CSI_HPA,
+ INPUT_CSI_ICH,
+ INPUT_CSI_IL,
+ INPUT_CSI_RM,
+ INPUT_CSI_RM_PRIVATE,
+ INPUT_CSI_SGR,
+ INPUT_CSI_SM,
+ INPUT_CSI_SM_PRIVATE,
+ INPUT_CSI_TBC,
+ INPUT_CSI_VPA,
+};
- ARRAY_EXPAND(&ictx->args, 1);
+/* Control (CSI) command table. */
+const struct input_table_entry input_csi_table[] = {
+ { '@', "", INPUT_CSI_ICH },
+ { 'A', "", INPUT_CSI_CUU },
+ { 'B', "", INPUT_CSI_CUD },
+ { 'C', "", INPUT_CSI_CUF },
+ { 'D', "", INPUT_CSI_CUB },
+ { 'G', "", INPUT_CSI_HPA },
+ { 'H', "", INPUT_CSI_CUP },
+ { 'J', "", INPUT_CSI_ED },
+ { 'K', "", INPUT_CSI_EL },
+ { 'L', "", INPUT_CSI_IL },
+ { 'M', "", INPUT_CSI_DL },
+ { 'P', "", INPUT_CSI_DCH },
+ { 'Z', "", INPUT_CSI_CBT },
+ { 'c', "", INPUT_CSI_DA },
+ { 'd', "", INPUT_CSI_VPA },
+ { 'f', "", INPUT_CSI_CUP },
+ { 'g', "", INPUT_CSI_TBC },
+ { 'h', "", INPUT_CSI_SM },
+ { 'h', "?", INPUT_CSI_SM_PRIVATE },
+ { 'l', "", INPUT_CSI_RM },
+ { 'l', "?", INPUT_CSI_RM_PRIVATE },
+ { 'm', "", INPUT_CSI_SGR },
+ { 'n', "", INPUT_CSI_DSR },
+ { 'r', "", INPUT_CSI_DECSTBM },
+};
- arg = &ARRAY_LAST(&ictx->args);
- arg->used = 0;
-}
+/* Input transition. */
+struct input_transition {
+ int first;
+ int last;
-int
-input_add_argument(struct input_ctx *ictx, u_char ch)
-{
- struct input_arg *arg;
-
- if (ARRAY_LENGTH(&ictx->args) == 0)
- return (0);
+ int (*handler)(struct input_ctx *);
+ const struct input_state *state;
+};
- arg = &ARRAY_LAST(&ictx->args);
- if (arg->used > (sizeof arg->data) - 1)
- return (-1);
- arg->data[arg->used++] = ch;
+/* Input state. */
+struct input_state {
+ const char *name;
+ void (*enter)(struct input_ctx *);
+ void (*exit)(struct input_ctx *);
+ const struct input_transition *transitions;
+};
- return (0);
-}
+/* State transitions available from all states. */
+#define INPUT_STATE_ANYWHERE \
+ { 0x18, 0x18, input_c0_dispatch, &input_state_ground }, \
+ { 0x1a, 0x1a, input_c0_dispatch, &input_state_ground }, \
+ { 0x1b, 0x1b, NULL, &input_state_esc_enter }
+
+/* Forward declarations of state tables. */
+const struct input_transition input_state_ground_table[];
+const struct input_transition input_state_esc_enter_table[];
+const struct input_transition input_state_esc_intermediate_table[];
+const struct input_transition input_state_csi_enter_table[];
+const struct input_transition input_state_csi_parameter_table[];
+const struct input_transition input_state_csi_intermediate_table[];
+const struct input_transition input_state_csi_ignore_table[];
+const struct input_transition input_state_dcs_enter_table[];
+const struct input_transition input_state_dcs_parameter_table[];
+const struct input_transition input_state_dcs_intermediate_table[];
+const struct input_transition input_state_dcs_handler_table[];
+const struct input_transition input_state_dcs_ignore_table[];
+const struct input_transition input_state_osc_string_table[];
+const struct input_transition input_state_apc_string_table[];
+const struct input_transition input_state_rename_string_table[];
+const struct input_transition input_state_consume_st_table[];
+const struct input_transition input_state_utf8_three_table[];
+const struct input_transition input_state_utf8_two_table[];
+const struct input_transition input_state_utf8_one_table[];
+
+/* ground state definition. */
+const struct input_state input_state_ground = {
+ "ground",
+ NULL, NULL,
+ input_state_ground_table
+};
-int
-input_get_argument(struct input_ctx *ictx, u_int i, uint16_t *n, uint16_t d)
-{
- struct input_arg *arg;
- const char *errstr;
+/* esc_enter state definition. */
+const struct input_state input_state_esc_enter = {
+ "esc_enter",
+ input_clear, NULL,
+ input_state_esc_enter_table
+};
- *n = d;
- if (i >= ARRAY_LENGTH(&ictx->args))
- return (0);
+/* esc_intermediate state definition. */
+const struct input_state input_state_esc_intermediate = {
+ "esc_intermediate",
+ NULL, NULL,
+ input_state_esc_intermediate_table
+};
- arg = &ARRAY_ITEM(&ictx->args, i);
- if (*arg->data == '\0')
- return (0);
+/* csi_enter state definition. */
+const struct input_state input_state_csi_enter = {
+ "csi_enter",
+ input_clear, NULL,
+ input_state_csi_enter_table
+};
- *n = strtonum(arg->data, 0, UINT16_MAX, &errstr);
- if (errstr != NULL)
- return (-1);
- return (0);
-}
+/* csi_parameter state definition. */
+const struct input_state input_state_csi_parameter = {
+ "csi_parameter",
+ NULL, NULL,
+ input_state_csi_parameter_table
+};
-void
-input_start_string(struct input_ctx *ictx, int type)
-{
- ictx->string_type = type;
- ictx->string_len = 0;
-}
+/* csi_intermediate state definition. */
+const struct input_state input_state_csi_intermediate = {
+ "csi_intermediate",
+ NULL, NULL,
+ input_state_csi_intermediate_table
+};
-void
-input_abort_string(struct input_ctx *ictx)
-{
- if (ictx->string_buf != NULL)
- xfree(ictx->string_buf);
- ictx->string_buf = NULL;
-}
+/* csi_ignore state definition. */
+const struct input_state input_state_csi_ignore = {
+ "csi_ignore",
+ NULL, NULL,
+ input_state_csi_ignore_table
+};
-int
-input_add_string(struct input_ctx *ictx, u_char ch)
-{
- ictx->string_buf = xrealloc(ictx->string_buf, 1, ictx->string_len + 1);
- ictx->string_buf[ictx->string_len++] = ch;
+/* dcs_enter state definition. */
+const struct input_state input_state_dcs_enter = {
+ "dcs_enter",
+ input_clear, NULL,
+ input_state_dcs_enter_table
+};
- if (ictx->string_len >= MAXSTRINGLEN) {
- input_abort_string(ictx);
- return (1);
- }
+/* dcs_parameter state definition. */
+const struct input_state input_state_dcs_parameter = {
+ "dcs_parameter",
+ NULL, NULL,
+ input_state_dcs_parameter_table
+};
- return (0);
-}
+/* dcs_intermediate state definition. */
+const struct input_state input_state_dcs_intermediate = {
+ "dcs_intermediate",
+ NULL, NULL,
+ input_state_dcs_intermediate_table
+};
-char *
-input_get_string(struct input_ctx *ictx)
-{
- char *s;
+/* dcs_handler state definition. */
+const struct input_state input_state_dcs_handler = {
+ "dcs_handler",
+ input_enter_dcs, input_exit_dcs,
+ input_state_dcs_handler_table
+};
- if (ictx->string_buf == NULL || input_add_string(ictx, '\0') != 0)
- return (xstrdup(""));
+/* dcs_ignore state definition. */
+const struct input_state input_state_dcs_ignore = {
+ "dcs_ignore",
+ NULL, NULL,
+ input_state_dcs_ignore_table
+};
- s = ictx->string_buf;
- ictx->string_buf = NULL;
- return (s);
-}
+/* osc_string state definition. */
+const struct input_state input_state_osc_string = {
+ "osc_string",
+ input_enter_osc, input_exit_osc,
+ input_state_osc_string_table
+};
-void
-input_state(struct input_ctx *ictx, void *state)
-{
- ictx->state = state;
-}
+/* apc_string state definition. */
+const struct input_state input_state_apc_string = {
+ "apc_string",
+ input_enter_apc, input_exit_apc,
+ input_state_apc_string_table
+};
-void
-input_init(struct window_pane *wp)
-{
- struct input_ctx *ictx = &wp->ictx;
+/* rename_string state definition. */
+const struct input_state input_state_rename_string = {
+ "rename_string",
+ input_enter_rename, input_exit_rename,
+ input_state_rename_string_table
+};
- ARRAY_INIT(&ictx->args);
+/* consume_st state definition. */
+const struct input_state input_state_consume_st = {
+ "consume_st",
+ NULL, NULL,
+ input_state_consume_st_table
+};
- ictx->string_len = 0;
- ictx->string_buf = NULL;
+/* utf8_three state definition. */
+const struct input_state input_state_utf8_three = {
+ "utf8_three",
+ NULL, NULL,
+ input_state_utf8_three_table
+};
- memcpy(&ictx->cell, &grid_default_cell, sizeof ictx->cell);
+/* utf8_two state definition. */
+const struct input_state input_state_utf8_two = {
+ "utf8_two",
+ NULL, NULL,
+ input_state_utf8_two_table
+};
- memcpy(&ictx->saved_cell, &grid_default_cell, sizeof ictx->saved_cell);
- ictx->saved_cx = 0;
- ictx->saved_cy = 0;
+/* utf8_one state definition. */
+const struct input_state input_state_utf8_one = {
+ "utf8_one",
+ NULL, NULL,
+ input_state_utf8_one_table
+};
- input_state(ictx, input_state_first);
+/* ground state table. */
+const struct input_transition input_state_ground_table[] = {
+ INPUT_STATE_ANYWHERE,
+
+ { 0x00, 0x17, input_c0_dispatch, NULL },
+ { 0x19, 0x19, input_c0_dispatch, NULL },
+ { 0x1c, 0x1f, input_c0_dispatch, NULL },
+ { 0x20, 0x7e, input_print, NULL },
+ { 0x7f, 0x7f, NULL, NULL },
+ { 0x80, 0xc1, input_print, NULL },
+ { 0xc2, 0xdf, input_utf8_open, &input_state_utf8_one },
+ { 0xe0, 0xef, input_utf8_open, &input_state_utf8_two },
+ { 0xf0, 0xf4, input_utf8_open, &input_state_utf8_three },
+ { 0xf5, 0xff, input_print, NULL },
+
+ { -1, -1, NULL, NULL }
+};
- ictx->was = 0;
-}
+/* esc_enter state table. */
+const struct input_transition input_state_esc_enter_table[] = {
+ INPUT_STATE_ANYWHERE,
+
+ { 0x00, 0x17, input_c0_dispatch, NULL },
+ { 0x19, 0x19, input_c0_dispatch, NULL },
+ { 0x1c, 0x1f, input_c0_dispatch, NULL },
+ { 0x20, 0x2f, input_intermediate, &input_state_esc_intermediate },
+ { 0x30, 0x4f, input_esc_dispatch, &input_state_ground },
+ { 0x50, 0x50, NULL, &input_state_dcs_enter },
+ { 0x51, 0x57, input_esc_dispatch, &input_state_ground },
+ { 0x58, 0x58, NULL, &input_state_consume_st },
+ { 0x59, 0x59, input_esc_dispatch, &input_state_ground },
+ { 0x5a, 0x5a, input_esc_dispatch, &input_state_ground },
+ { 0x5b, 0x5b, NULL, &input_state_csi_enter },
+ { 0x5c, 0x5c, input_esc_dispatch, &input_state_ground },
+ { 0x5d, 0x5d, NULL, &input_state_osc_string },
+ { 0x5e, 0x5e, NULL, &input_state_consume_st },
+ { 0x5f, 0x5f, NULL, &input_state_apc_string },
+ { 0x60, 0x6a, input_esc_dispatch, &input_state_ground },
+ { 0x6b, 0x6b, NULL, &input_state_rename_string },
+ { 0x6c, 0x7c, input_esc_dispatch, &input_state_ground },
+ { 0x7f, 0xff, NULL, NULL },
+
+ { -1, -1, NULL, NULL }
+};
-void
-input_free(struct window_pane *wp)
-{
- if (wp->ictx.string_buf != NULL)
- xfree(wp->ictx.string_buf);
+/* esc_interm state table. */
+const struct input_transition input_state_esc_intermediate_table[] = {
+ INPUT_STATE_ANYWHERE,
- ARRAY_FREE(&wp->ictx.args);
-}
+ { 0x00, 0x17, input_c0_dispatch, NULL },
+ { 0x19, 0x19, input_c0_dispatch, NULL },
+ { 0x1c, 0x1f, input_c0_dispatch, NULL },
+ { 0x20, 0x2f, input_intermediate, NULL },
+ { 0x30, 0x7e, input_esc_dispatch, &input_state_ground },
+ { 0x7f, 0xff, NULL, NULL },
-void
-input_parse(struct window_pane *wp)
-{
- struct input_ctx *ictx = &wp->ictx;
- u_char ch;
+ { -1, -1, NULL, NULL }
+};
- if (EVBUFFER_LENGTH(wp->event->input) == ictx->was)
- return;
- wp->window->flags |= WINDOW_ACTIVITY;
+/* csi_enter state table. */
+const struct input_transition input_state_csi_enter_table[] = {
+ INPUT_STATE_ANYWHERE,
+
+ { 0x00, 0x17, input_c0_dispatch, NULL },
+ { 0x19, 0x19, input_c0_dispatch, NULL },
+ { 0x1c, 0x1f, input_c0_dispatch, NULL },
+ { 0x20, 0x2f, input_intermediate, &input_state_csi_intermediate },
+ { 0x30, 0x39, input_parameter, &input_state_csi_parameter },
+ { 0x3a, 0x3a, NULL, &input_state_csi_ignore },
+ { 0x3b, 0x3b, input_parameter, &input_state_csi_parameter },
+ { 0x3c, 0x3f, input_intermediate, &input_state_csi_parameter },
+ { 0x40, 0x7e, input_csi_dispatch, &input_state_ground },
+ { 0x7f, 0xff, NULL, NULL },
+
+ { -1, -1, NULL, NULL }
+};
- ictx->buf = EVBUFFER_DATA(wp->event->input);
- ictx->len = EVBUFFER_LENGTH(wp->event->input);
- ictx->off = 0;
+/* csi_parameter state table. */
+const struct input_transition input_state_csi_parameter_table[] = {
+ INPUT_STATE_ANYWHERE,
+
+ { 0x00, 0x17, input_c0_dispatch, NULL },
+ { 0x19, 0x19, input_c0_dispatch, NULL },
+ { 0x1c, 0x1f, input_c0_dispatch, NULL },
+ { 0x20, 0x2f, input_intermediate, &input_state_csi_intermediate },
+ { 0x30, 0x39, input_parameter, NULL },
+ { 0x3a, 0x3a, NULL, &input_state_csi_ignore },
+ { 0x3b, 0x3b, input_parameter, NULL },
+ { 0x3c, 0x3f, NULL, &input_state_csi_ignore },
+ { 0x40, 0x7e, input_csi_dispatch, &input_state_ground },
+ { 0x7f, 0xff, NULL, NULL },
+
+ { -1, -1, NULL, NULL }
+};
- ictx->wp = wp;
+/* csi_intermediate state table. */
+const struct input_transition input_state_csi_intermediate_table[] = {
+ INPUT_STATE_ANYWHERE,
- /* If there is a mode set, don't want to update the screen. */
- if (wp->mode == NULL)
- screen_write_start(&ictx->ctx, wp, &wp->base);
- else
- screen_write_start(&ictx->ctx, NULL, &wp->base);
+ { 0x00, 0x17, input_c0_dispatch, NULL },
+ { 0x19, 0x19, input_c0_dispatch, NULL },
+ { 0x1c, 0x1f, input_c0_dispatch, NULL },
+ { 0x20, 0x2f, input_intermediate, NULL },
+ { 0x30, 0x3f, NULL, &input_state_csi_ignore },
+ { 0x40, 0x7e, input_csi_dispatch, &input_state_ground },
+ { 0x7f, 0xff, NULL, NULL },
- while (ictx->off < ictx->len) {
- ch = ictx->buf[ictx->off++];
- ictx->state(ch, ictx);
- }
+ { -1, -1, NULL, NULL }
+};
- screen_write_stop(&ictx->ctx);
+/* csi_ignore state table. */
+const struct input_transition input_state_csi_ignore_table[] = {
+ INPUT_STATE_ANYWHERE,
- evbuffer_drain(wp->event->input, ictx->len);
- ictx->was = EVBUFFER_LENGTH(wp->event->input);
-}
+ { 0x00, 0x17, input_c0_dispatch, NULL },
+ { 0x19, 0x19, input_c0_dispatch, NULL },
+ { 0x1c, 0x1f, input_c0_dispatch, NULL },
+ { 0x20, 0x3f, NULL, NULL },
+ { 0x40, 0x7e, NULL, &input_state_ground },
+ { 0x7f, 0xff, NULL, NULL },
-void
-input_state_first(u_char ch, struct input_ctx *ictx)
-{
- ictx->intermediate = '\0';
+ { -1, -1, NULL, NULL }
+};
- if (INPUT_C0CONTROL(ch)) {
- if (ch == 0x1b)
- input_state(ictx, input_state_escape);
- else
- input_handle_c0_control(ch, ictx);
- return;
- }
+/* dcs_enter state table. */
+const struct input_transition input_state_dcs_enter_table[] = {
+ INPUT_STATE_ANYWHERE,
+
+ { 0x00, 0x17, NULL, NULL },
+ { 0x19, 0x19, NULL, NULL },
+ { 0x1c, 0x1f, NULL, NULL },
+ { 0x20, 0x2f, input_intermediate, &input_state_dcs_intermediate },
+ { 0x30, 0x39, input_parameter, &input_state_dcs_parameter },
+ { 0x3a, 0x3a, NULL, &input_state_dcs_ignore },
+ { 0x3b, 0x3b, input_parameter, &input_state_dcs_parameter },
+ { 0x3c, 0x3f, input_intermediate, &input_state_dcs_parameter },
+ { 0x40, 0x7e, NULL, &input_state_dcs_handler },
+ { 0x7f, 0xff, NULL, NULL },
+
+ { -1, -1, NULL, NULL }
+};
-#if 0
- if (INPUT_C1CONTROL(ch)) {
- ch -= 0x40;
- if (ch == '[')
- input_state(ictx, input_state_sequence_first);
- else if (ch == ']') {
- input_start_string(ictx, STRING_SYSTEM);
- input_state(ictx, input_state_string_next);
- } else if (ch == '_') {
- input_start_string(ictx, STRING_APPLICATION);
- input_state(ictx, input_state_string_next);
- } else
- input_handle_c1_control(ch, ictx);
- return;
- }
-#endif
+/* dcs_parameter state table. */
+const struct input_transition input_state_dcs_parameter_table[] = {
+ INPUT_STATE_ANYWHERE,
+
+ { 0x00, 0x17, NULL, NULL },
+ { 0x19, 0x19, NULL, NULL },
+ { 0x1c, 0x1f, NULL, NULL },
+ { 0x20, 0x2f, input_intermediate, &input_state_dcs_intermediate },
+ { 0x30, 0x39, input_parameter, NULL },
+ { 0x3a, 0x3a, NULL, &input_state_dcs_ignore },
+ { 0x3b, 0x3b, input_parameter, NULL },
+ { 0x3c, 0x3f, NULL, &input_state_dcs_ignore },
+ { 0x40, 0x7e, NULL, &input_state_dcs_handler },
+ { 0x7f, 0xff, NULL, NULL },
+
+ { -1, -1, NULL, NULL }
+};
- if (INPUT_DELETE(ch))
- return;
+/* dcs_interm state table. */
+const struct input_transition input_state_dcs_intermediate_table[] = {
+ INPUT_STATE_ANYWHERE,
- input_handle_character(ch, ictx);
-}
+ { 0x00, 0x17, NULL, NULL },
+ { 0x19, 0x19, NULL, NULL },
+ { 0x1c, 0x1f, NULL, NULL },
+ { 0x20, 0x2f, input_intermediate, NULL },
+ { 0x30, 0x3f, NULL, &input_state_dcs_ignore },
+ { 0x40, 0x7e, NULL, &input_state_dcs_handler },
+ { 0x7f, 0xff, NULL, NULL },
-void
-input_state_escape(u_char ch, struct input_ctx *ictx)
-{
- /* Treat C1 control and G1 displayable as 7-bit equivalent. */
- if (INPUT_C1CONTROL(ch) || INPUT_G1DISPLAYABLE(ch))
- ch &= 0x7f;
+ { -1, -1, NULL, NULL }
+};
- if (INPUT_C0CONTROL(ch)) {
- input_handle_c0_control(ch, ictx);
- return;
- }
+/* dcs_handler state table. */
+const struct input_transition input_state_dcs_handler_table[] = {
+ INPUT_STATE_ANYWHERE,
- if (INPUT_INTERMEDIATE(ch)) {
- log_debug2(":: in1 %zu: %hhu (%c)", ictx->off, ch, ch);
- ictx->intermediate = ch;
- input_state(ictx, input_state_intermediate);
- return;
- }
+ { 0x00, 0x17, NULL, NULL },
+ { 0x19, 0x19, input_input, NULL },
+ { 0x1c, 0x1f, input_input, NULL },
+ { 0x20, 0x7e, input_input, NULL },
+ { 0x7f, 0xff, NULL, NULL },
- if (INPUT_PARAMETER(ch)) {
- input_state(ictx, input_state_first);
- input_handle_private_two(ch, ictx);
- return;
- }
+ { -1, -1, NULL, NULL }
+};
- if (INPUT_UPPERCASE(ch)) {
- if (ch == '[')
- input_state(ictx, input_state_sequence_first);
- else if (ch == ']') {
- input_start_string(ictx, STRING_SYSTEM);
- input_state(ictx, input_state_string_next);
- } else if (ch == '_') {
- input_start_string(ictx, STRING_APPLICATION);
- input_state(ictx, input_state_string_next);
- } else {
- input_state(ictx, input_state_first);
- input_handle_c1_control(ch, ictx);
- }
- return;
- }
+/* device_ignore state table. */
+const struct input_transition input_state_dcs_ignore_table[] = {
+ INPUT_STATE_ANYWHERE,
- if (INPUT_LOWERCASE(ch)) {
- input_state(ictx, input_state_first);
- input_handle_standard_two(ch, ictx);
- return;
- }
+ { 0x00, 0x17, NULL, NULL },
+ { 0x19, 0x19, NULL, NULL },
+ { 0x1c, 0x1f, NULL, NULL },
+ { 0x20, 0xff, NULL, NULL },
- input_state(ictx, input_state_first);
-}
+ { -1, -1, NULL, NULL }
+};
-void
-input_state_intermediate(u_char ch, struct input_ctx *ictx)
-{
- if (INPUT_INTERMEDIATE(ch)) {
- /* Multiple intermediates currently ignored. */
- log_debug2(":: in2 %zu: %hhu (%c)", ictx->off, ch, ch);
- return;
- }
+/* osc_string state table. */
+const struct input_transition input_state_osc_string_table[] = {
+ INPUT_STATE_ANYWHERE,
- if (INPUT_PARAMETER(ch)) {
- input_state(ictx, input_state_first);
- input_handle_private_two(ch, ictx);
- return;
- }
+ { 0x00, 0x06, NULL, NULL },
+ { 0x07, 0x07, NULL, &input_state_ground },
+ { 0x08, 0x17, NULL, NULL },
+ { 0x19, 0x19, NULL, NULL },
+ { 0x1c, 0x1f, NULL, NULL },
+ { 0x20, 0xff, input_input, NULL },
- if (INPUT_UPPERCASE(ch) || INPUT_LOWERCASE(ch)) {
- input_state(ictx, input_state_first);
- input_handle_standard_two(ch, ictx);
- return;
- }
+ { -1, -1, NULL, NULL }
+};
- input_state(ictx, input_state_first);
-}
+/* apc_string state table. */
+const struct input_transition input_state_apc_string_table[] = {
+ INPUT_STATE_ANYWHERE,
-void
-input_state_sequence_first(u_char ch, struct input_ctx *ictx)
-{
- ictx->private = '\0';
- ARRAY_CLEAR(&ictx->args);
-
- /* Most C0 control are accepted within CSI. */
- if (INPUT_C0CONTROL(ch)) {
- if (ch == 0x1b) { /* ESC */
- /* Abort sequence and begin with new. */
- input_state(ictx, input_state_escape);
- return;
- } else if (ch == 0x18 || ch == 0x1a) { /* CAN and SUB */
- /* Abort sequence. */
- input_state(ictx, input_state_first);
- return;
- }
+ { 0x00, 0x17, NULL, NULL },
+ { 0x19, 0x19, NULL, NULL },
+ { 0x1c, 0x1f, NULL, NULL },
+ { 0x20, 0xff, input_input, NULL },
- /* Handle C0 immediately. */
- input_handle_c0_control(ch, ictx);
+ { -1, -1, NULL, NULL }
+};
- /*
- * Just come back to this state, in case the next character
- * is the start of a private sequence.
- */
- return;
- }
+/* rename_string state table. */
+const struct input_transition input_state_rename_string_table[] = {
+ INPUT_STATE_ANYWHERE,
- input_state(ictx, input_state_sequence_next);
+ { 0x00, 0x17, NULL, NULL },
+ { 0x19, 0x19, NULL, NULL },
+ { 0x1c, 0x1f, NULL, NULL },
+ { 0x20, 0xff, input_input, NULL },
- /* Private sequence: always the first character. */
- if (ch >= 0x3c && ch <= 0x3f) {
- ictx->private = ch;
- return;
- }
+ { -1, -1, NULL, NULL }
+};
- /* Pass character on directly. */
- input_state_sequence_next(ch, ictx);
-}
+/* consume_st state table. */
+const struct input_transition input_state_consume_st_table[] = {
+ INPUT_STATE_ANYWHERE,
-void
-input_state_sequence_next(u_char ch, struct input_ctx *ictx)
-{
- if (INPUT_INTERMEDIATE(ch)) {
- if (input_add_argument(ictx, '\0') != 0)
- input_state(ictx, input_state_first);
- else {
- log_debug2(":: si1 %zu: %hhu (%c)", ictx->off, ch, ch);
- input_state(ictx, input_state_sequence_intermediate);
- }
- return;
- }
+ { 0x00, 0x17, NULL, NULL },
+ { 0x19, 0x19, NULL, NULL },
+ { 0x1c, 0x1f, NULL, NULL },
+ { 0x20, 0xff, NULL, NULL },
- if (INPUT_PARAMETER(ch)) {
- if (ARRAY_EMPTY(&ictx->args))
- input_new_argument(ictx);
-
- if (ch == ';') {
- if (input_add_argument(ictx, '\0') != 0)
- input_state(ictx, input_state_first);
- else
- input_new_argument(ictx);
- } else if (input_add_argument(ictx, ch) != 0)
- input_state(ictx, input_state_first);
- return;
- }
+ { -1, -1, NULL, NULL }
+};
- if (INPUT_UPPERCASE(ch) || INPUT_LOWERCASE(ch)) {
- if (input_add_argument(ictx, '\0') != 0)
- input_state(ictx, input_state_first);
- else {
- input_state(ictx, input_state_first);
- input_handle_sequence(ch, ictx);
- }
- return;
- }
+/* utf8_three state table. */
+const struct input_transition input_state_utf8_three_table[] = {
+ /* No INPUT_STATE_ANYWHERE */
- /* Most C0 control are accepted within CSI. */
- if (INPUT_C0CONTROL(ch)) {
- if (ch == 0x1b) { /* ESC */
- /* Abort sequence and begin with new. */
- input_state(ictx, input_state_escape);
- return;
- } else if (ch == 0x18 || ch == 0x1a) { /* CAN and SUB */
- /* Abort sequence. */
- input_state(ictx, input_state_first);
- return;
- }
+ { 0x00, 0x7f, NULL, &input_state_ground },
+ { 0x80, 0xbf, input_utf8_add, &input_state_utf8_two },
+ { 0xc0, 0xff, NULL, &input_state_ground },
- /* Handle C0 immediately. */
- input_handle_c0_control(ch, ictx);
+ { -1, -1, NULL, NULL }
+};
- return;
- }
+/* utf8_two state table. */
+const struct input_transition input_state_utf8_two_table[] = {
+ /* No INPUT_STATE_ANYWHERE */
- input_state(ictx, input_state_first);
-}
+ { 0x00, 0x7f, NULL, &input_state_ground },
+ { 0x80, 0xbf, input_utf8_add, &input_state_utf8_one },
+ { 0xc0, 0xff, NULL, &input_state_ground },
-void
-input_state_sequence_intermediate(u_char ch, struct input_ctx *ictx)
-{
- if (INPUT_INTERMEDIATE(ch)) {
- log_debug2(":: si2 %zu: %hhu (%c)", ictx->off, ch, ch);
- return;
- }
-
- if (INPUT_UPPERCASE(ch) || INPUT_LOWERCASE(ch)) {
- input_state(ictx, input_state_first);
- input_handle_sequence(ch, ictx);
- return;
- }
+ { -1, -1, NULL, NULL }
+};
- input_state(ictx, input_state_first);
-}
+/* utf8_one state table. */
+const struct input_transition input_state_utf8_one_table[] = {
+ /* No INPUT_STATE_ANYWHERE */
-void
-input_state_string_next(u_char ch, struct input_ctx *ictx)
-{
- if (ch == 0x1b) {
- input_state(ictx, input_state_string_escape);
- return;
- }
- if (ch == 0x07) {
- input_state_string_escape(ch, ictx);
- return;
- }
+ { 0x00, 0x7f, NULL, &input_state_ground },
+ { 0x80, 0xbf, input_utf8_close, &input_state_ground },
+ { 0xc0, 0xff, NULL, &input_state_ground },
- if (ch >= 0x20) {
- if (input_add_string(ictx, ch) != 0)
- input_state(ictx, input_state_first);
- return;
- }
-}
+ { -1, -1, NULL, NULL }
+};
-void
-input_state_string_escape(u_char ch, struct input_ctx *ictx)
+/* Input table compare. */
+int
+input_table_compare(const void *key, const void *value)
{
- char *s;
-
- if (ch == '\007' || ch == '\\') {
- input_state(ictx, input_state_first);
- switch (ictx->string_type) {
- case STRING_SYSTEM:
- if (ch != '\007')
- return;
- s = input_get_string(ictx);
- if ((s[0] != '0' && s[0] != '2') || s[1] != ';') {
- xfree(s);
- return;
- }
- screen_set_title(ictx->ctx.s, s + 2);
- server_status_window(ictx->wp->window);
- xfree(s);
- break;
- case STRING_APPLICATION:
- if (ch != '\\')
- return;
- s = input_get_string(ictx);
- screen_set_title(ictx->ctx.s, s);
- server_status_window(ictx->wp->window);
- xfree(s);
- break;
- case STRING_NAME:
- if (ch != '\\')
- return;
- xfree(ictx->wp->window->name);
- ictx->wp->window->name = input_get_string(ictx);
- server_status_window(ictx->wp->window);
- break;
- }
- return;
- }
+ const struct input_ctx *ictx = key;
+ const struct input_table_entry *entry = value;
- input_state(ictx, input_state_string_next);
- input_state_string_next(ch, ictx);
+ if (ictx->ch != entry->ch)
+ return (ictx->ch - entry->ch);
+ return (strcmp(ictx->interm_buf, entry->interm));
}
+/* Initialise input parser. */
void
-input_state_utf8(u_char ch, struct input_ctx *ictx)
+input_init(struct window_pane *wp)
{
- log_debug2("-- utf8 next: %zu: %hhu (%c)", ictx->off, ch, ch);
+ struct input_ctx *ictx = &wp->ictx;
- if (utf8_append(&ictx->utf8data, ch))
- return; /* more to come */
- input_state(ictx, input_state_first);
+ memcpy(&ictx->cell, &grid_default_cell, sizeof ictx->cell);
- ictx->cell.flags |= GRID_FLAG_UTF8;
- screen_write_cell(&ictx->ctx, &ictx->cell, &ictx->utf8data);
- ictx->cell.flags &= ~GRID_FLAG_UTF8;
-}
+ memcpy(&ictx->old_cell, &grid_default_cell, sizeof ictx->old_cell);
+ ictx->old_cx = 0;
+ ictx->old_cy = 0;
-void
-input_handle_character(u_char ch, struct input_ctx *ictx)
-{
- struct window_pane *wp = ictx->wp;
+ *ictx->interm_buf = '\0';
+ ictx->interm_len = 0;
- if (ch > 0x7f && options_get_number(&wp->window->options, "utf8")) {
- if (utf8_open(&ictx->utf8data, ch)) {
- log_debug2("-- utf8 size %zu: %zu: %hhu (%c)",
- ictx->utf8data.size, ictx->off, ch, ch);
- input_state(ictx, input_state_utf8);
- return;
- }
- }
- log_debug2("-- ch %zu: %hhu (%c)", ictx->off, ch, ch);