aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNicholas Marriott <nicholas.marriott@gmail.com>2007-09-28 22:47:22 +0000
committerNicholas Marriott <nicholas.marriott@gmail.com>2007-09-28 22:47:22 +0000
commitaafee17de62d21f5cd5ced9a798a89c39bb8a70a (patch)
tree0f883f4683c033ae13e57ac8caf22d024b2d9c40
parentd2e035f892ac8b21889e0124157a9be4f94462d3 (diff)
downloadrtmux-aafee17de62d21f5cd5ced9a798a89c39bb8a70a.tar.gz
rtmux-aafee17de62d21f5cd5ced9a798a89c39bb8a70a.tar.bz2
rtmux-aafee17de62d21f5cd5ced9a798a89c39bb8a70a.zip
New input parser via state machine.
-rw-r--r--CHANGES14
-rw-r--r--Makefile6
-rw-r--r--input-keys.c78
-rw-r--r--input.c1494
-rw-r--r--local.c32
-rw-r--r--screen.c266
-rw-r--r--server-msg.c5
-rw-r--r--tmux.h77
-rw-r--r--window.c10
9 files changed, 1057 insertions, 925 deletions
diff --git a/CHANGES b/CHANGES
index a07d365d..bbfd3d32 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,5 +1,15 @@
28 September 2007
- * (mxey) Added window remaming, like "tmux rename [-s session] [-i index] name"
+
+* (nicm) Major rewrite of input parser:
+ - Lose the old weirdness in favour of a state machine.
+ - Merge in parsing from screen.c.
+ - Split key parsing off into a separate file.
+ This is step one towards hopefully allowing a status line. It requires
+ that we output data as if the terminal had one line less than it really does -
+ a serious problem when it comes to things like scrolling. This change
+ consolidates all the range checking and limiting together which should make
+ it easier.
+* (mxey) Added window remaming, like "tmux rename [-s session] [-i index] name"
27 September 2007
@@ -58,5 +68,5 @@
(including mutt, emacs). No status bar yet and no key remapping or other
customisation.
-$Id: CHANGES,v 1.12 2007-09-28 21:41:51 mxey Exp $
+$Id: CHANGES,v 1.13 2007-09-28 22:47:21 nicm Exp $
diff --git a/Makefile b/Makefile
index e9912ec6..723735c5 100644
--- a/Makefile
+++ b/Makefile
@@ -1,4 +1,4 @@
-# $Id: Makefile,v 1.6 2007-09-26 18:32:16 nicm Exp $
+# $Id: Makefile,v 1.7 2007-09-28 22:47:21 nicm Exp $
.SUFFIXES: .c .o .y .h
.PHONY: clean
@@ -17,8 +17,8 @@ DEBUG=
META?= \002 # C-b
SRCS= tmux.c server.c server-msg.c server-fn.c buffer.c buffer-poll.c \
- xmalloc.c xmalloc-debug.c input.c screen.c window.c session.c local.c \
- log.c client.c client-msg.c client-cmd.c op.c op-list.c
+ xmalloc.c xmalloc-debug.c input.c input-keys.c screen.c window.c \
+ session.c local.c log.c client.c client-msg.c client-cmd.c op.c op-list.c
YACC= yacc -d
diff --git a/input-keys.c b/input-keys.c
new file mode 100644
index 00000000..b0eab60a
--- /dev/null
+++ b/input-keys.c
@@ -0,0 +1,78 @@
+/* $Id: input-keys.c,v 1.1 2007-09-28 22:47:21 nicm Exp $ */
+
+/*
+ * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
+ * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
+ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/types.h>
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "tmux.h"
+
+struct {
+ int key;
+ const char *data;
+} input_keys[] = {
+/* { KEYC_BACKSPACE, "\010" }, */
+ { KEYC_DC, "\e[3~" },
+ { KEYC_DOWN, "\eOB" },
+ { KEYC_F1, "\eOP" },
+ { KEYC_F10, "\e[21~" },
+ { KEYC_F11, "\e[23~" },
+ { KEYC_F12, "\e[24~" },
+ { KEYC_F2, "\eOQ" },
+ { KEYC_F3, "\eOR" },
+ { KEYC_F4, "\eOS" },
+ { KEYC_F5, "\e[15~" },
+ { KEYC_F6, "\e[17~" },
+ { KEYC_F7, "\e[18~" },
+ { KEYC_F8, "\e[19~" },
+ { KEYC_F9, "\e[20~" },
+ { KEYC_HOME, "\e[1~" },
+ { KEYC_IC, "\e[2~" },
+ { KEYC_LEFT, "\eOD" },
+ { KEYC_LL, "\e[4~" },
+ { KEYC_NPAGE, "\e[6~" },
+ { KEYC_PPAGE, "\e[5~" },
+ { KEYC_RIGHT, "\eOC" },
+ { KEYC_UP, "\eOA" }
+};
+#define NINPUTKEYS (sizeof input_keys / sizeof input_keys[0])
+
+/* Translate a key code from client into an output key sequence. */
+void
+input_translate_key(struct buffer *b, int key)
+{
+ u_int i;
+
+ log_debug2("writing key %d", key);
+ if (key != KEYC_NONE && key >= 0) {
+ input_store8(b, key);
+ return;
+ }
+
+ for (i = 0; i < NINPUTKEYS; i++) {
+ if (input_keys[i].key == key) {
+ log_debug2(
+ "found key %d: \"%s\"", key, input_keys[i].data);
+ buffer_write(
+ b, input_keys[i].data, strlen(input_keys[i].data));
+ return;
+ }
+ }
+}
diff --git a/input.c b/input.c
index 6dc44ecc..01fe7f4e 100644
--- a/input.c
+++ b/input.c
@@ -1,4 +1,4 @@
-/* $Id: input.c,v 1.5 2007-09-21 19:24:37 nicm Exp $ */
+/* $Id: input.c,v 1.6 2007-09-28 22:47:21 nicm Exp $ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -19,753 +19,999 @@
#include <sys/types.h>
#include <stdint.h>
-#include <stdlib.h>
#include <string.h>
+#include <stdlib.h>
#include "tmux.h"
-size_t input_sequence(
- u_char *, size_t, u_char *, u_char *, uint16_t **, u_int *);
-int input_control(
- u_char **, size_t *, struct buffer *, struct screen *, u_char);
-int input_pair_private(
- u_char **, size_t *, struct buffer *, struct screen *, u_char);
-int input_pair_standard(
- u_char **, size_t *, struct buffer *, struct screen *, u_char);
-int input_pair_control(
- u_char **, size_t *, struct buffer *, struct screen *, u_char);
-int input_control_sequence(
- u_char **, size_t *, struct buffer *, struct screen *);
-int input_check_one(uint16_t *, u_int, uint16_t *, uint16_t);
-int input_check_one2(
- uint16_t *, u_int, uint16_t *, uint16_t, uint16_t, uint16_t);
-int input_check_two(
- uint16_t *, u_int, uint16_t *, uint16_t, uint16_t *, uint16_t);
-
-struct input_key {
- int key;
- const char *string;
-};
-
-struct input_key input_keys[] = {
-/* { KEYC_BACKSPACE, "\010" }, */
- { KEYC_DC, "\e[3~" },
- { KEYC_DOWN, "\eOB" },
- { KEYC_F1, "\eOP" },
- { KEYC_F10, "\e[21~" },
- { KEYC_F11, "\e[23~" },
- { KEYC_F12, "\e[24~" },
- { KEYC_F2, "\eOQ" },
- { KEYC_F3, "\eOR" },
- { KEYC_F4, "\eOS" },
- { KEYC_F5, "\e[15~" },
- { KEYC_F6, "\e[17~" },
- { KEYC_F7, "\e[18~" },
- { KEYC_F8, "\e[19~" },
- { KEYC_F9, "\e[20~" },
- { KEYC_HOME, "\e[1~" },
- { KEYC_IC, "\e[2~" },
- { KEYC_LEFT, "\eOD" },
- { KEYC_LL, "\e[4~" },
- { KEYC_NPAGE, "\e[6~" },
- { KEYC_PPAGE, "\e[5~" },
- { KEYC_RIGHT, "\eOC" },
- { KEYC_UP, "\eOA" }
+struct {
+ u_char first;
+ u_char last;
+ enum input_class class;
+} input_table[] = {
+ { 0x00, 0x1f, INPUT_C0CONTROL },
+ { 0x20, 0x20, INPUT_SPACE },
+ { 0x21, 0x2F, INPUT_INTERMEDIATE }, /* also INPUT_SPACE */
+ { 0x30, 0x3F, INPUT_PARAMETER },
+ { 0x40, 0x5F, INPUT_UPPERCASE },
+ { 0x60, 0x7E, INPUT_LOWERCASE },
+ { 0x7F, 0x7F, INPUT_DELETE },
+ { 0x80, 0x9F, INPUT_C1CONTROL },
+ { 0xA0, 0xA0, INPUT_SPACE },
+ { 0xA1, 0xFE, INPUT_G1DISPLAYABLE },
+ { 0xFF, 0xFF, INPUT_SPECIAL },
};
-
-/*
- * This parses CSI escape sequences into a code and a block of uint16_t
- * arguments. buf must be the next byte after the \e[ and len the remaining
- * data.
- */
-size_t
-input_sequence(u_char *buf, size_t len,
- u_char *code, u_char *private, uint16_t **argv, u_int *argc)
+#define NINPUTCLASS (sizeof input_table / sizeof input_table[0])
+
+enum input_class input_lookup_class(u_char);
+int input_get_argument(struct input_ctx *, u_int, uint16_t *, uint16_t);
+
+void *input_state_first(u_char, enum input_class, struct input_ctx *);
+void *input_state_escape(u_char, enum input_class, struct input_ctx *);
+void *input_state_intermediate(u_char, enum input_class, struct input_ctx *);
+void *input_state_sequence_first(
+ u_char, enum input_class, struct input_ctx *);
+void *input_state_sequence_next(
+ u_char, enum input_class, struct input_ctx *);
+void *input_state_sequence_intermediate(
+ u_char, enum input_class, 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_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_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 *);
+
+enum input_class
+input_lookup_class(u_char ch)
{
- char ch;
- u_char *ptr, *saved;
- const char *errstr;
-
- *code = 0;
+ enum input_class iclass;
+ u_int i;
- *argc = 0;
- *argv = NULL;
-
- if (len == 0)
- return (0);
- saved = buf;
-
- /*
- * 0x3c (<) to 0x3f (?) mark private sequences when appear as the first
- * character.
- */
- *private = '\0';
- if (*buf >= '<' && *buf <= '?') {
- *private = *buf;
- buf++; len--;
- } else if (*buf < '0' || *buf > ';')
- goto complete;
-
- while (len > 0) {
- /*
- * Every parameter substring is bytes from 0x30 (0) to 0x3a (:),
- * terminated by 0x3b (;). 0x3a is an internal seperator.
- */
-
- /* Find the end of the substring. */
- ptr = buf;
- while (len != 0 && *ptr >= '0' && *ptr <= '9') {
- ptr++;
- len--;
- }
- if (len == 0)
+ iclass = INPUT_SPACE;
+ for (i = 0; i < NINPUTCLASS; i++) {
+ if (ch >= input_table[i].first && ch <= input_table[i].last) {
+ iclass = input_table[i].class;
break;
-
- /* An 0x3a is unsupported. */
- if (*ptr == ':')
- goto invalid;
-
- /* Create a new argument. */
- (*argc)++;
- *argv = xrealloc(*argv, *argc, sizeof **argv);
-
- /* Fill in argument value. */
- errstr = NULL;
- if (ptr == buf)
- (*argv)[*argc - 1] = UINT16_MAX;
- else {
- ch = *ptr; *ptr = '\0';
- (*argv)[*argc - 1] =
- strtonum(buf, 0, UINT16_MAX - 1, &errstr);
- *ptr = ch;
}
- buf = ptr;
-
- /* If the conversion had errors, abort now. */
- if (errstr != NULL)
- goto invalid;
-
- /* Break for any non-terminator. */
- if (*buf != ';')
- goto complete;
- buf++; len--;
}
- if (len == 0)
- goto incomplete;
-
-complete:
- /* Valid final characters are 0x40 (@) to 0x7e (~). */
- if (*buf < '@' || *buf > '~')
- goto invalid;
+ if (i == NINPUTCLASS)
+ fatalx("character without class");
- *code = *buf;
- return (buf - saved + 1);
+ return (iclass);
+}
-invalid:
- if (*argv != NULL) {
- xfree(*argv);
- *argv = NULL;
- }
- *argc = 0;
+int
+input_get_argument(struct input_ctx *ictx, u_int i, uint16_t *n, uint16_t d)
+{
+ struct input_arg *arg;
+ char tmp[64];
+ const char *errstr;
- /* Invalid. Consume until a valid terminator. */
- while (len > 0) {
- if (*buf >= '@' && *buf <= '~')
- break;
- buf++; len--;
- }
- if (len == 0)
- goto incomplete;
+ *n = d;
+ if (i >= ARRAY_LENGTH(&ictx->args))
+ return (0);
- *code = '\0';
- return (buf - saved + 1);
+ arg = &ARRAY_ITEM(&ictx->args, i);
+ if (arg->len == 0)
+ return (0);
-incomplete:
- if (*argv != NULL) {
- xfree(*argv);
- *argv = NULL;
- }
- *argc = 0;
+ if (arg->len > sizeof tmp - 1)
+ return (-1);
+ memcpy(tmp, ictx->buf + arg->off, arg->len);
+ tmp[arg->len] = '\0';
- *code = '\0';
+ *n = strtonum(tmp, 0, UINT16_MAX, &errstr);
+ if (errstr != NULL)
+ return (-1);
return (0);
}
-/* Translate a key code into an output key sequence. */
void
-input_key(struct buffer *b, int key)
+input_init(struct input_ctx *ictx, struct screen *s)
{
- struct input_key *ak;
- u_int i;
+ ictx->s = s;
- log_debug("writing key %d", key);
- if (key != KEYC_NONE && key >= 0) {
- input_store8(b, key);
- return;
- }
+ ictx->intoff = 0;
+ ictx->intlen = 0;
- for (i = 0; i < (sizeof input_keys / sizeof input_keys[0]); i++) {
- ak = input_keys + i;
- if (ak->key == key) {
- log_debug("found key %d: \"%s\"", key, ak->string);
- buffer_write(b, ak->string, strlen(ak->string));
- return;
- }
- }
+ ARRAY_INIT(&ictx->args);
+
+ ictx->state = input_state_first;
+}
+
+void
+input_free(struct input_ctx *ictx)
+{
+ ARRAY_FREE(&ictx->args);
}
-/*
- * Parse a block of data and normalise escape sequences into a \e, a single
- * character code and the correct number of arguments. This includes adding
- * missing arguments and default values, and enforcing limits. Returns the
- * number of bytes consumed. The screen is updated with the data and used
- * to fill in current cursor positions and sizes.
- */
size_t
-input_parse(u_char *buf, size_t len, struct buffer *b, struct screen *s)
+input_parse(struct input_ctx *ictx, u_char *buf, size_t len, struct buffer *b)
{
- u_char *saved, ch;
- size_t size;
- FILE *f;
+ enum input_class iclass;
+ u_char ch;
- saved = buf;
+ ictx->buf = buf;
+ ictx->len = len;
+ ictx->off = 0;
- if (debug_level > 1) {
- f = fopen("tmux-in.log", "a+");
- fwrite(buf, len, 1, f);
- fclose(f);
+ ictx->b = b;
+
+ log_debug2("entry; buffer=%zu", ictx->len);
+
+ while (ictx->off < ictx->len) {
+ ch = ictx->buf[ictx->off++];
+ iclass = input_lookup_class(ch);
+ ictx->state = ictx->state(ch, iclass, ictx);
}
- while (len > 0) {
- ch = *buf++; len--;
-
- /* Handle control characters. */
- if (ch != '\e') {
- if (ch < ' ') {
- if (input_control(&buf, &len, b, s, ch) == 1) {
- *--buf = ch;
- break;
- }
- } else {
- log_debug("character: %c (%hhu)", ch, ch);
- screen_character(s, ch);
- input_store8(b, ch);
- }
- continue;
- }
- if (len == 0) {
- *--buf = '\e';
- break;
- }
+ return (ictx->len);
+}
- /* Read the first character. */
- ch = *buf++; len--;
+void *
+input_state_first(u_char ch, enum input_class iclass, struct input_ctx *ictx)
+{
+ log_debug2("first (%hhu); sx=%u, sy=%u, cx=%u, cy=%u",
+ ch, ictx->s->sx, ictx->s->sy, ictx->s->cx, ictx->s->cy);
+
+ switch (iclass) {
+ case INPUT_C0CONTROL:
+ if (ch == 0x1b)
+ return (input_state_escape);
+ input_handle_c0_control(ch, ictx);
+ break;
+ case INPUT_C1CONTROL:
+ ch -= 0x40;
+ if (ch == '[')
+ return (input_state_sequence_first);
+ input_handle_c1_control(ch, ictx);
+ break;
+ case INPUT_SPACE:
+ case INPUT_INTERMEDIATE:
+ case INPUT_PARAMETER:
+ case INPUT_UPPERCASE:
+ case INPUT_LOWERCASE:
+ case INPUT_DELETE:
+ case INPUT_G1DISPLAYABLE:
+ case INPUT_SPECIAL:
+ input_handle_character(ch, ictx);
+ break;
+ }
+ return (input_state_first);
+}
- /* Ignore delete. */
- if (ch == '\177') {
- if (len == 0) {
- *--buf = '\e';
- break;
- }
- ch = *buf++; len--;
- }
+void *
+input_state_escape(u_char ch, enum input_class iclass, struct input_ctx *ictx)
+{
+ if (iclass == INPUT_C1CONTROL || iclass == INPUT_G1DISPLAYABLE) {
+ /* Treat as 7-bit equivalent. */
+ ch &= 0x7f;
+ iclass = input_lookup_class(ch);
+ }
- /* Interpret C0 immediately. */
- if (ch < ' ') {
- if (input_control(&buf, &len, b, s, ch) == 1) {
- *--buf = ch;
- break;
- }
+ switch (iclass) {
+ case INPUT_C0CONTROL:
+ input_handle_c0_control(ch, ictx);
+ return (input_state_escape);
+ case INPUT_SPACE:
+ case INPUT_INTERMEDIATE:
+ ictx->intoff = ictx->off;
+ ictx->intlen = 1;
+ return (input_state_intermediate);
+ case INPUT_PARAMETER:
+ input_handle_private_two(ch, ictx);
+ break;
+ case INPUT_UPPERCASE:
+ if (ch == '[')
+ return (input_state_sequence_first);
+ input_handle_c1_control(ch, ictx);
+ break;
+ case INPUT_LOWERCASE:
+ input_handle_standard_two(ch, ictx);
+ break;
+ case INPUT_DELETE:
+ case INPUT_SPECIAL:
+ case INPUT_C1CONTROL:
+ case INPUT_G1DISPLAYABLE:
+ break;
+ }
+ return (input_state_first);
+}
- if (len == 0) {
- *--buf = '\e';
- break;
- }
- ch = *buf++; len--;
- }
+void *
+input_state_intermediate(
+ u_char ch, enum input_class iclass, struct input_ctx *ictx)
+{
+ switch (iclass) {
+ case INPUT_SPACE:
+ case INPUT_INTERMEDIATE:
+ ictx->intlen++;
+ return (input_state_intermediate);
+ case INPUT_PARAMETER:
+ input_handle_private_two(ch, ictx);
+ break;
+ case INPUT_UPPERCASE:
+ case INPUT_LOWERCASE:
+ input_handle_standard_two(ch, ictx);
+ break;
+ case INPUT_C0CONTROL:
+ case INPUT_DELETE:
+ case INPUT_SPECIAL:
+ case INPUT_C1CONTROL:
+ case INPUT_G1DISPLAYABLE:
+ break;
+ }
+ return (input_state_first);
+}
- /*
- * Save used size to work out how much to pass to
- * screen_sequence later.
- */
- size = BUFFER_USED(b);
-
- /* Skip until the end of intermediate strings. */
- if (ch >= ' ' && ch <= '/') {
- while (len != 0) {
- if (ch >= 0x30 && ch <= 0x3f)
- break;
- if (ch >= 0x40 && ch <= 0x5f)
- break;
- ch = *buf++; len--;
- }
- continue;
+void *
+input_state_sequence_first(
+ u_char ch, enum input_class iclass, struct input_ctx *ictx)
+{
+ ictx->private = '\0';
+
+ switch (iclass) {
+ case INPUT_PARAMETER:
+ if (ch >= 0x3c && ch <= 0x3f) {
+ /* Private control sequence. */
+ ictx->private = ch;
+
+ ictx->saved = ictx->off;
+ return (input_state_sequence_next);
}
+ break;
+ case INPUT_C0CONTROL:
+ case INPUT_C1CONTROL:
+ case INPUT_SPACE:
+ case INPUT_INTERMEDIATE:
+ case INPUT_UPPERCASE:
+ case INPUT_LOWERCASE:
+ case INPUT_DELETE:
+ case INPUT_G1DISPLAYABLE:
+ case INPUT_SPECIAL:
+ break;
+ }
- /* Handle two-character sequences. */
- if (ch >= '0' && ch <= '?') {
- if (input_pair_private(&buf, &len, b, s, ch) == 1)
- goto incomplete;
- goto next;
+ /* Pass this character to next state directly. */
+ ictx->saved = ictx->off - 1;
+ return (input_state_sequence_next(ch, iclass, ictx));
+}
+
+void *
+input_state_sequence_next(
+ u_char ch, enum input_class iclass, struct input_ctx *ictx)
+{
+ struct input_arg *iarg;
+
+ switch (iclass) {
+ case INPUT_SPACE:
+ case INPUT_INTERMEDIATE:
+ if (ictx->saved != ictx->off) {
+ ARRAY_EXPAND(&ictx->args, 1);
+ iarg = &ARRAY_LAST(&ictx->args);
+ iarg->off = ictx->saved;
+ iarg->len = ictx->off - ictx->saved - 1;
}
- if (ch >= '`' && ch <= '~') {
- if (input_pair_standard(&buf, &len, b, s, ch) == 1)
- goto incomplete;
- goto next;
+ ictx->intoff = ictx->off;
+ ictx->intlen = 1;
+ return (input_state_sequence_intermediate);
+ case INPUT_PARAMETER:
+ if (ch == ';') {
+ ARRAY_EXPAND(&ictx->args, 1);
+ iarg = &ARRAY_LAST(&ictx->args);
+ iarg->off = ictx->saved;
+ iarg->len = ictx->off - ictx->saved - 1;
+
+ ictx->saved = ictx->off;
+ return (input_state_sequence_next);
}
- if (ch >= '@' && ch <= '_' && ch != '[') {
- if (input_pair_control(&buf, &len, b, s, ch) == 1)
- goto incomplete;
- goto next;
+ return (input_state_sequence_next);
+ case INPUT_UPPERCASE:
+ case INPUT_LOWERCASE:
+ if (ictx->saved != ictx->off) {
+ ARRAY_EXPAND(&ictx->args, 1);
+ iarg = &ARRAY_LAST(&ictx->args);
+ iarg->off = ictx->saved;
+ iarg->len = ictx->off - ictx->saved - 1;
}
+ input_handle_sequence(ch, ictx);
+ break;
+ case INPUT_C0CONTROL:
+ case INPUT_C1CONTROL:
+ case INPUT_DELETE:
+ case INPUT_SPECIAL:
+ case INPUT_G1DISPLAYABLE:
+ break;
+ }
+ return (input_state_first);
+}
- /* If not CSI at this point, invalid. */
- if (ch != '[')
- continue;
-
- if (input_control_sequence(&buf, &len, b, s) == 1)
- goto incomplete;
-
- next:
- size = BUFFER_USED(b) - size;
- log_debug("output is %zu bytes", size);
- if (size > 0) /* XXX only one command? */
- screen_sequence(s, BUFFER_IN(b) - size);
- log_debug("remaining data %zu bytes", len);
- }
+void *
+input_state_sequence_intermediate(
+ u_char ch, enum input_class iclass, struct input_ctx *ictx)
+{
+ switch (iclass) {
+ case INPUT_SPACE:
+ case INPUT_INTERMEDIATE:
+ ictx->intlen++;
+ return (input_state_sequence_intermediate);
+ case INPUT_UPPERCASE:
+ case INPUT_LOWERCASE:
+ input_handle_sequence(ch, ictx);
+ break;
+ case INPUT_PARAMETER:
+ case INPUT_C0CONTROL:
+ case INPUT_DELETE:
+ case INPUT_SPECIAL:
+ case INPUT_C1CONTROL:
+ case INPUT_G1DISPLAYABLE:
+ break;
+ }
+ return (input_state_first);
+}
- return (buf - saved);
+void
+input_handle_character(u_char ch, struct input_ctx *ictx)
+{
+ log_debug2("-- ch %zu: %hhu (%c)", ictx->off, ch, ch);
-incomplete:
- *--buf = ch;
- *--buf = '\e';
- return (buf - saved);
+ screen_write_character(ictx->s, ch);
+ input_store8(ictx->b, ch);
}
-/* Handle single control characters. */
-int
-input_control(unused u_char **buf, unused size_t *len,
- struct buffer *b, struct screen *s, u_char ch)
+void
+input_handle_c0_control(u_char ch, struct input_ctx *ictx)
{
+ log_debug2("-- c0 %zu: %hhu", ictx->off, ch);
+
switch (ch) {
case '\0': /* NUL */
break;
case '\n': /* LF */
+ screen_cursor_down_scroll(ictx->s);
+ break;
case '\r': /* CR */
+ ictx->s->cx = 0;
+ break;
case '\010': /* BS */
- log_debug("control: %hhu", ch);
- screen_character(s, ch);
- input_store8(b, ch);
+ if (ictx->s->cx > 0)
+ ictx->s->cx--;
break;
default:
- log_debug("unknown control: %c (%hhu)", ch, ch);
- break;
+ log_debug("unknown c0: %hhu", ch);
+ return;
}
+ input_store8(ictx->b, ch);
+}
- return (0);
+void
+input_handle_c1_control(u_char ch, struct input_ctx *ictx)
+{
+ log_debug2("-- c1 %zu: %hhu (%c)", ictx->off, ch, ch);
+
+ /* XXX window title */
+ switch (ch) {
+ case 'M': /* RI */
+ screen_cursor_up_scroll(ictx->s);
+ input_store_zero(ictx->b, CODE_REVERSEINDEX);
+ break;
+ default:
+ log_debug("unknown c1: %hhu", ch);
+ break;
+ }
}
-/* Translate a private two-character sequence. */
-int
-input_pair_private(unused u_char **buf, unused size_t *len,
- unused struct buffer *b, unused struct screen *s, unused u_char ch)
+void
+input_handle_private_two(u_char ch, struct input_ctx *ictx)
{
- log_debug("private2: %c (%hhu)", ch, ch);
+ log_debug2("-- p2 %zu: %hhu (%c) (%zu, %zu)",
+ ictx->off, ch, ch, ictx->intoff, ictx->intlen);
switch (ch) {
case '=': /* DECKPAM */
- input_store_zero(b, CODE_KKEYPADON);
+ input_store_zero(ictx->b, CODE_KKEYPADON);
break;
case '>': /* DECKPNM*/
- input_store_zero(b, CODE_KKEYPADOFF);
+ input_store_zero(ictx->b, CODE_KKEYPADOFF);
break;
default:
- log_debug("unknown private2: %c (%hhu)", ch, ch);
+ log_debug("unknown p2: %hhu", ch);
break;
}
+}
- return (0);
+void
+input_handle_standard_two(u_char ch, struct input_ctx *ictx)
+{
+ log_debug2("-- s2 %zu: %hhu (%c) (%zu,%zu)",
+ ictx->off, ch, ch, ictx->intoff, ictx->intlen);
+
+ log_debug("unknown s2: %hhu", ch);
}
-/* Translate a standard two-character sequence. */
-int
-input_pair_standard(unused u_char **buf, unused size_t *len,
- unused struct buffer *b, unused struct screen *s, u_char ch)
+void
+input_handle_sequence(u_char ch, struct input_ctx *ictx)
{
- log_debug("unknown standard2: %c (%hhu)", ch, ch);
+ static const struct {
+ u_char ch;
+ void (*fn)(struct input_ctx *);
+ } table[] = {
+ { 'A', input_handle_sequence_cuu },
+ { 'B', input_handle_sequence_cud },
+ { 'C', input_handle_sequence_cuf },
+ { 'D', input_handle_sequence_cub },
+ { 'P', input_handle_sequence_dch },
+ { 'M', input_handle_sequence_dl },
+ { '@', input_handle_sequence_ich },
+ { 'L', input_handle_sequence_il },
+ { 'd', input_handle_sequence_vpa },
+ { 'G', input_handle_sequence_hpa },
+ { 'H', input_handle_sequence_cup },
+ { 'f', input_handle_sequence_cup },
+ { 'J', input_handle_sequence_ed },
+ { 'K', input_handle_sequence_el },
+ { 'h', input_handle_sequence_sm },
+ { 'l', input_handle_sequence_rm },
+ { 'r', input_handle_sequence_decstbm },
+ { 'm', input_handle_sequence_sgr },
+ };
+ u_int i;
+ struct input_arg *iarg;
+
+ log_debug2("-- sq %zu: %hhu (%c) (%zu,%zu): %u",
+ ictx->off, ch, ch, ictx->intoff, ictx->intlen,
+ ARRAY_LENGTH(&ictx->args));
+ for (i = 0; i < ARRAY_LENGTH(&ictx->args); i++) {
+ iarg = &ARRAY_ITEM(&ictx->args, i);
+ if (iarg->len > 0) {
+ log_debug(" ++ %u: (%zu) %.*s", i,
+ iarg->len, (int) iarg->len, ictx->buf + iarg->off);
+ }
+ }
- return (0);
+ /* XXX bsearch? */
+ for (i = 0; i < (sizeof table / sizeof table[0]); i++) {
+ if (table[i].ch == ch) {
+ table[i].fn(ictx);
+ ARRAY_CLEAR(&ictx->args);
+ return;
+ }
+ }
+ ARRAY_CLEAR(&ictx->args);
+
+ log_debug("unknown sq: %c (%hhu %hhu)", ch, ch, ictx->private);
}
-/* Translate a control two-character sequence. */
-int
-input_pair_control(u_char **buf, size_t *len,
- struct buffer *b, unused struct screen *s, u_char ch)
+void
+input_handle_sequence_cuu(struct input_ctx *ictx)
{
- u_char *ptr;
- size_t size;
+ uint16_t n;
- log_debug("control2: %c (%hhu)", ch, ch);
+ if (ictx->private != '\0')
+ return;
- switch (ch) {
- case ']': /* window title */
- if (*len < 3)
- return (1);
- ch = *(*buf)++; (*len)--;
-
- /*
- * Search MAXTITLELEN + 1 to allow space for the ;. The
- * \007 is also included, but space is needed for a \0 so
- * it doesn't need to be compensated for.
- */
- size = *len > MAXTITLELEN + 1 ? MAXTITLELEN + 1 : *len;
- if ((ptr = memchr(*buf, '\007', size)) == NULL) {
- log_debug("title not found in %zu bytes", size);
- if (*len >= MAXTITLELEN + 1)
- break;
- (*buf)--; (*len)++;
- return (1);
- }
- size = ptr - *buf;
+ if (ARRAY_LENGTH(&ictx->args) > 1)
+ return;
+ if (input_get_argument(ictx, 0, &n, 1) != 0)
+ return;
- /* A zero size means no ;, just skip the \007 and return. */
- if (size == 0) {
- (*buf)++; (*len)--;
- break;
- }
+ if (n == 0 || n > ictx->s->cy) {
+ log_debug3("cuu: out of range: %hu", n);
+ return;
+ }
- /* Set the title if appropriate. */
- if (**buf == ';' && (ch == '0' || ch == '1')) {
- log_debug("title found, length %zu bytes: %.*s",
- size - 1, (int) size - 1, *buf + 1);
- if (size > 1) {
- input_store_one(b, CODE_TITLE, size - 1);
- buffer_write(b, *buf + 1, size - 1);
- }
- }
+ ictx->s->cy -= n;
+ input_store_one(ictx->b, CODE_CURSORUP, n);
+}
- /* Skip the title; add one for the \007. */
- (*buf) += size + 1;
- (*len) -= size + 1;
- break;
- case 'M': /* RI */
- input_store_zero(b, CODE_REVERSEINDEX);
- break;
- default:
- log_debug("unknown control2: %c (%hhu)", ch, ch);
- break;
+void
+input_handle_sequence_cud(struct input_ctx *ictx)
+{
+ uint16_t n;
+
+ if (ictx->private != '\0')
+ return;
+
+ if (ARRAY_LENGTH(&ictx->args) > 1)
+ return;
+ if (input_get_argument(ictx, 0, &n, 1) != 0)
+ return;
+
+ if (n == 0 || n > ictx->s->sy - ictx->s->cy - 1) {
+ log_debug3("cud: out of range: %hu", n);
+ return;
}
- return (0);
+ ictx->s->cy += n;
+ input_store_one(ictx->b, CODE_CURSORDOWN, n);
}
-/* Translate a control sequence. */
-int
-input_control_sequence(
- u_char **buf, size_t *len, struct buffer *b, struct screen *s)
+void
+input_handle_sequence_cuf(struct input_ctx *ictx)
+{
+ uint16_t n;
+
+ if (ictx->private != '\0')
+ return;
+
+ if (ARRAY_LENGTH(&ictx->args) > 1)
+ return;
+ if (input_get_argument(ictx, 0, &n, 1) != 0)
+ return;
+
+ if (n == 0 || n > ictx->s->sx - ictx->s->cx - 1) {
+ log_debug3("cuf: out of range: %hu", n);
+ return;
+ }
+
+ ictx->s->cx += n;
+ input_store_one(ictx->b, CODE_CURSORRIGHT, n);
+}
+
+void
+input_handle_sequence_cub(struct input_ctx *ictx)
{
- u_char code, private;
- size_t used;
- uint16_t *argv, ua, ub;
- u_int argc, i;
+ uint16_t n;
- used = input_sequence(*buf, *len, &code, &private, &argv, &argc);
- if (used == 0) /* incomplete */
- return (1);
+ if (ictx->private != '\0')
+ return;
- (*buf) += used;
- (*len) -= used;
+ if (ARRAY_LENGTH(&ictx->args) > 1)
+ return;
+ if (input_get_argument(ictx, 0, &n, 1) != 0)
+ return;
- if (code == '\0') /* invalid */
- return (-1);
+ if (n == 0 || n > ictx->s->cx) {
+ log_debug3("cub: out of range: %hu", n);
+ return;
+ }
- log_debug(
- "sequence: %c (%hhu) [%c] [cx %u, cy %u, sx %u, sy %u]: %u", code,
- code, private, s->cx, s->cy, s->sx, s->sy, argc);
- for (i = 0; i < argc; i++)
- log_debug("\targument %u: %u", i, argv[i]);
+ ictx->s->cx -= n;
+ input_store_one(ictx->b, CODE_CURSORLEFT, n);
+}
- switch (code) {
- case 'A': /* CUU */
- if (private != '\0')
- break;
- if (input_check_one(argv, argc, &ua, 1) != 0)
- break;
- if (ua == 0)
- break;
- input_store_one(b, CODE_CURSORUP, ua);
- break;
- case 'B': /* CUD */
- if (private != '\0')
- break;
- if (input_check_one(argv, argc, &ua, 1) != 0)
- break;
- if (ua == 0)
- break;
- input_store_one(b, CODE_CURSORDOWN, ua);
- break;
- case 'C': /* CUF */
- if (private != '\0')
- break;
- if (input_check_one(argv, argc, &ua, 1) != 0)
- break;
- if (ua == 0)
- break;
- input_store_one(b, CODE_CURSORRIGHT, ua);
- break;
- case 'D': /* CUB */
- if (private != '\0')
- break;
- if (input_check_one(argv, argc, &ua, 1) != 0)
- break;
- if (ua == 0)
- break;
- input_store_one(b, CODE_CURSORLEFT, ua);
- break;
- case 'P': /* DCH */
- if (private != '\0')
- break;
- if (input_check_one(argv, argc, &ua, 1) != 0)
- break;
- if (ua == 0)
- break;
- input_store_one(b, CODE_DELETECHARACTER, ua);
+void
+input_handle_sequence_dch(struct input_ctx *ictx)
+{
+ uint16_t n;
+
+ if (ictx->private != '\0')
+ return;
+
+ if (ARRAY_LENGTH(&ictx->args) > 1)
+ return;
+ if (input_get_argument(ictx, 0, &n, 1) != 0)
+ return;
+
+ if (n == 0 || n > ictx->s->sx - ictx->s->cx - 1) {
+ log_debug3("dch: out of range: %hu", n);
+ return;
+ }
+
+ screen_delete_characters(ictx->s, ictx->s->cx, ictx->s->cy, n);
+ input_store_one(ictx->b, CODE_DELETECHARACTER, n);
+}
+
+void
+input_handle_sequence_dl(struct input_ctx *ictx)
+{
+ uint16_t n;
+
+ if (ictx->private != '\0')
+ return;
+
+ if (ARRAY_LENGTH(&ictx->args) > 1)
+ return;
+ if (input_get_argument(ictx, 0, &n, 1) != 0)
+ return;
+
+ if (n == 0 || n > ictx->s->sy - ictx->s->cy - 1) {
+ log_debug3("dl: out of range: %hu", n);
+ return;
+ }
+
+ screen_delete_lines(ictx->s, ictx->s->cy, n);
+ input_store_one(ictx->b, CODE_DELETELINE, n);
+}
+
+void
+input_handle_sequence_ich(struct input_ctx *ictx)
+{
+ uint16_t n;
+
+ if (ictx->private != '\0')
+ return;
+
+ if (ARRAY_LENGTH(&ictx->args) > 1)
+ return;
+ if (input_get_argument(ictx, 0, &n, 1) != 0)
+ return;
+
+ if (n == 0 || n > ictx->s->sx - ictx->s->cx - 1) {
+ log_debug3("ich: out of range: %hu", n);
+ return;
+ }
+
+ screen_insert_characters(ictx->s, ictx->s->cx, ictx->s->cy, n);
+ input_store_one(ictx->b, CODE_INSERTCHARACTER, n);
+}
+
+void
+input_handle_sequence_il(struct input_ctx *ictx)
+{
+ uint16_t n;
+
+ if (ictx->private != '\0')
+ return;
+
+ if (ARRAY_LENGTH(&ictx->args) > 1)
+ return;
+ if (input_get_argument(ictx, 0, &n, 1) != 0)
+ return;
+
+ if (n == 0 || n > ictx->s->sy - ictx->s->cy - 1) {
+ log_debug3("il: out of range: %hu", n);
+ return;
+ }
+
+ screen_insert_lines(ictx->s, ictx->s->cy, n);
+ input_store_one(ictx->b, CODE_INSERTLINE, n);
+}
+
+void
+input_handle_sequence_vpa(struct input_ctx *ictx)
+{
+ uint16_t n;
+
+ if (ictx->private != '\0')
+ return;
+
+ if (ARRAY_LENGTH(&ictx->args) > 1)
+ return;
+ if (input_get_argument(ictx, 0, &n, 1) != 0)
+ return;
+
+ if (n == 0 || n > ictx->s->sy) {
+ log_debug3("vpa: out of range: %hu", n);
+ return;
+ }
+
+ ictx->s->cy = n - 1;
+ input_store_two(ictx->b, CODE_CURSORMOVE, n, ictx->s->cx + 1);
+}
+
+void
+input_handle_sequence_hpa(struct input_ctx *ictx)
+{
+ uint16_t n;
+
+ if (ictx->private != '\0')
+ return;
+
+ if (ARRAY_LENGTH(&ictx->args) > 1)
+ return;
+ if (input_get_argument(ictx, 0, &n, 1) != 0)
+ return;
+
+ if (n == 0 || n > ictx->s->sx) {
+ log_debug3("hpa: out of range: %hu", n);
+ return;
+ }
+
+ ictx->s->cx = n - 1;
+ input_store_two(ictx->b, CODE_CURSORMOVE, ictx->s->cy + 1, n);
+}
+
+void
+input_handle_sequence_cup(struct input_ctx *ictx)
+{
+ uint16_t n, m;
+
+ if (ictx->private != '\0')
+ return;
+
+ if (ARRAY_LENGTH(&ictx->args) > 2)
+ return;
+ if (input_get_argument(ictx, 0, &n, 1) != 0)
+ return;
+ if (input_get_argument(ictx, 1, &m, 1) != 0)
+ return;
+
+ if (n == 0 || n > ictx->s->sy || m == 0 || m > ictx->s->sx) {
+ log_debug3("cup: out of range: %hu", n);
+ return;
+ }
+
+ ictx->s->cx = m - 1;
+ ictx->s->cy = n - 1;
+ input_store_two(ictx->b, CODE_CURSORMOVE, n, m);
+}
+
+void
+input_handle_sequence_ed(struct input_ctx *ictx)
+{
+ uint16_t n;
+
+ if (ictx->private != '\0')
+ return;
+
+ if (ARRAY_LENGTH(&ictx->args) > 1)
+ return;
+ if (input_get_argument(ictx, 0, &n, 0) != 0)
+ return;
+
+ if (n > 2)
+ return;
+
+ switch (n) {
+ case 0:
+ screen_fill_end_of_screen(ictx->s, ictx->s->cx, ictx->s->cy,
+ SCREEN_DEFDATA, ictx->s->attr, ictx->s->colr);
+ input_store_zero(ictx->b, CODE_CLEARENDOFSCREEN);
break;
- case 'M': /* DL */
- if (private != '\0')
- break;
- if (input_check_one(argv, argc, &ua, 1) != 0)
- break;
- if (ua == 0)
- break;
- input_store_one(b, CODE_DELETELINE, ua);
+ case 2:
+ screen_fill_screen(
+ ictx->s, SCREEN_DEFDATA, ictx->s->attr, ictx->s->colr);
+ input_store_zero(ictx->b, CODE_CLEARSCREEN);
break;
- case '@': /* ICH */
- if (private != '\0')
- break;
- if (input_check_one(argv, argc, &ua, 1) != 0)
- break;
- if (ua == 0)
- break;
- input_store_one(b, CODE_INSERTCHARACTER, ua);
+ }
+}
+
+void
+input_handle_sequence_el(struct input_ctx *ictx)
+{
+ uint16_t n;
+
+ if (ictx->private != '\0')
+ return;
+
+ if (ARRAY_LENGTH(&ictx->args) > 1)
+ return;
+ if (input_get_argument(ictx, 0, &n, 0) != 0)
+ return;
+
+ if (n > 2)
+ return;
+
+ switch (n) {
+ case 0:
+ screen_fill_end_of_line(ictx->s, ictx->s->cx, ictx->s->cy,
+ SCREEN_DEFDATA, ictx->s->attr, ictx->s->colr);
+ input_store_zero(ictx->b, CODE_CLEARENDOFLINE);
break;
- case 'L': /* IL */
- if (private != '\0')
- break;
- if (input_check_one(argv, argc, &ua, 1) != 0)
- break;
- if (ua == 0)
- break;
- input_store_one(b, CODE_INSERTLINE, ua);
+ case 1:
+ screen_fill_start_of_line(ictx->s, ictx->s->cx, ictx->s->cy,
+ SCREEN_DEFDATA, ictx->s->attr, ictx->s->colr);
+ input_store_zero(ictx->b, CODE_CLEARSTARTOFLINE);
break;
- case 'd': /* VPA */
- if (private != '\0')
- break;
- if (input_check_one(argv, argc, &ua, 1) != 0)
- break;
- if (ua == 0)
- break;
- input_store_two(b, CODE_CURSORMOVE, ua, s->cx + 1);
+ case 2:
+ screen_fill_line(ictx->s, ictx->s->cy,
+ SCREEN_DEFDATA, ictx->s->attr, ictx->s->colr);
+ input_store_zero(ictx->b, CODE_CLEARLINE);
break;
- case 'G': /* HPA */
- if (private != '\0')
- break;
- if (input_check_one(argv, argc, &ua, 1) != 0)
+ }
+}
+
+void
+input_handle_sequence_sm(struct input_ctx *ictx)
+{
+ uint16_t n;
+
+ if (ARRAY_LENGTH(&ictx->args) > 1)
+ return;
+ if (input_get_argument(ictx, 0, &n, 0) != 0)
+ return;
+
+ if (ictx->private == '?') {
+ switch (n) {
+ case 1: /* GATM */
+ ictx->s->mode |= MODE_KCURSOR;
+ input_store_zero(ictx->b, CODE_KCURSORON);
break;
- if (ua == 0)
+ case 25: /* TCEM */
+ ictx->s->mode |= MODE_CURSOR;
+ input_store_zero(ictx->b, CODE_CURSORON);
break;
- input_store_two(b, CODE_CURSORMOVE, s->cy + 1, ua);
- break;
- case 'H': /* CUP */
- case 'f': /* HVP */
- if (private != '\0')
+ default:
+ log_debug("unknown SM [%hhu]: %u", ictx->private, n);
break;
- if (input_check_two(argv, argc, &ua, 1, &ub, 1) != 0)
+ }
+ } else {
+ switch (n) {
+ case 4: /* IRM */
+ ictx->s->mode |= MODE_INSERT;
+ input_store_zero(ictx->b, CODE_INSERTON);
break;
- if (ua == 0 || ub == 0)
+ case 34:
+ /* Cursor high visibility not supported. */
break;
- input_store_two(b, CODE_CURSORMOVE, ua, ub);
- break;
- case 'J': /* ED */
- if (private != '\0')
+ default:
+ log_debug("unknown SM [%hhu]: %u", ictx->private, n);
break;
- if (input_check_one2(argv, argc, &ua, 0, 0, 2) != 0)
+ }
+ }
+}
+
+void
+input_handle_sequence_rm(struct input_ctx *ictx)
+{
+ uint16_t n;
+
+ if (ARRAY_LENGTH(&ictx->args) > 1)
+ return;
+ if (input_get_argument(ictx, 0, &n, 0) != 0)
+ return;
+
+ if (ictx->private == '?') {
+ switch (n) {
+ case 1: /* GATM */
+ ictx->s->mode &= ~MODE_KCURSOR;
+ input_store_zero(ictx->b, CODE_KCURSOROFF);
break;
- switch (ua) {
- case 0:
- input_store_zero(b, CODE_CLEARENDOFSCREEN);
+ case 25: /* TCEM */
+ ictx->s->mode &= ~MODE_CURSOR;
+ input_store_zero(ictx->b, CODE_CURSOROFF);
break;
- case 2:
- input_store_zero(b, CODE_CLEARSCREEN);
+ default:
+ log_debug("unknown RM [%hhu]: %u", ictx->private, n);
break;
}
- break;
- case 'K': /* EL */
- if (private != '\0')
- break;
- if (input_check_one2(argv, argc, &ua, 0, 0, 2) != 0)
- break;
- switch (ua) {
- case 0:
- input_store_zero(b, CODE_CLEARENDOFLINE);
+ } else if (ictx->private == '\0') {
+ switch (n) {
+ case 4: /* IRM */
+ ictx->s->mode &= ~MODE_INSERT;
+ input_store_zero(ictx->b, CODE_INSERTOFF);
break;
- case 1:
- input_store_zero(b, CODE_CLEARSTARTOFLINE);
+ case 34:
+ /* Cursor high visibility not supported. */
break;
- case 2:
- input_store_zero(b, CODE_CLEARLINE);
+ default:
+ log_debug("unknown RM [%hhu]: %u", ictx->private, n);
break;
}
- break;
- case 'h': /* SM */
- if (input_check_one(argv, argc, &ua, 0) != 0)
- break;
- switch (private) {
- case '?':
- switch (ua) {
- case 1: /* GATM */
- input_store_zero(b, CODE_KCURSORON);
+ }
+}
+
+void
+input_handle_sequence_decstbm(struct input_ctx *ictx)
+{
+ uint16_t n, m;
+
+ if (ictx->private != '\0')
+ return;
+
+ if (ARRAY_LENGTH(&ictx->args) > 2)
+ return;
+ if (input_get_argument(ictx, 0, &n, 1) != 0)
+ return;
+ if (input_get_argument(ictx, 1, &m, 1) != 0)
+ return;
+
+ if (n == 0 || n > ictx->s->sy - 1 || m == 0 || m > ictx->s->sx - 1) {
+ log_debug3("decstbm: out of range: %hu,%hu", m, n);
+ return;
+ }
+ if (m > n) {
+ log_debug3("decstbm: out of range: %hu,%hu", m, n);
+ return;
+ }
+
+ ictx->s->ry_upper = n - 1;
+ ictx->s->ry_lower = m - 1;
+ input_store_two(ictx->b, CODE_SCROLLREGION, n, m);
+}
+
+void
+input_handle_sequence_sgr(struct input_ctx *ictx)
+{
+ u_int i, n;
+ uint16_t m;
+
+ n = ARRAY_LENGTH(&ictx->args);
+
+ input_store_zero(ictx->b, CODE_ATTRIBUTES);
+ if (n == 0) {
+ ictx->s->attr = 0;
+ ictx->s->colr = SCREEN_DEFCOLR;
+ input_store16(ictx->b, 1);
+ input_store16(ictx->b, 0);
+ } else {
+ input_store16(ictx->b, n);
+ for (i = 0; i < n; i++) {
+ if (input_get_argument(ictx, i, &m, 0) != 0) {
+ /* XXX XXX partial write to client */
+ return;
+ }
+ switch (m) {
+ case 0:
+ case 10:
+ ictx->s->attr = 0;
+ ictx->s->colr = SCREEN_DEFCOLR;
break;
- case 25: /* TCEM */
- input_store_zero(b, CODE_CURSORON);
+ case 1:
+ ictx->s->attr |= ATTR_BRIGHT;
break;
- default:
- log_debug("unknown SM [%d]: %u", private, ua);
- }
- break;
- case '\0':
- switch (ua) {
- case 4: /* IRM */
- input_store_zero(b, CODE_INSERTON);
+ case 2:
+ ictx->s->attr |= ATTR_DIM;
break;
- case 34:
- /* Cursor high visibility not supported. */
+ case 3:
+ ictx->s->attr |= ATTR_ITALICS;
break;
- default:
- log_debug("unknown SM [%d]: %u", private, ua);
+ case 4:
+ ictx->s->attr |= ATTR_UNDERSCORE;
break;
- }
- break;
- }
- break;
- case 'l': /* RM */
- if (input_check_one(argv, argc, &ua, 0) != 0)
- break;
- switch (private) {
- case '?':
- switch (ua) {
- case 1: /* GATM */
- input_store_zero(b, CODE_KCURSOROFF);
+ case 5:
+ ictx->s->attr |= ATTR_BLINK;
break;
- case 25: /* TCEM */
- input_store_zero(b, CODE_CURSOROFF);
+ case 7:
+ ictx->s->attr |= ATTR_REVERSE;
break;
- default:
- log_debug("unknown RM [%d]: %u", private, ua);
- }
- break;
- case '\0':
- switch (ua) {
- case 4: /* IRM */
- input_store_zero(b, CODE_INSERTOFF);
+ case 8:
+ ictx->s->attr |= ATTR_HIDDEN;
break;
+ case 23:
+ ictx->s->attr &= ~ATTR_ITALICS;
+ break;
+ case 24:
+ ictx->s->attr &= ~ATTR_UNDERSCORE;
+ break;
+ case 30:
+ case 31:
+ case 32:
+ case 33:
case 34:
- /* Cursor high visibility not supported. */
+ case 35:
+ case 36:
+ case 37:
+ ictx->s->colr &= 0x0f;
+ ictx->s->colr |= (m - 30) << 4;
break;
- default:
- log_debug("unknown RM [%d]: %u", private, ua);
+ case 39:
+ ictx->s->colr &= 0x0f;
+ ictx->s->colr |= 0x80;
+ break;
+ case 40:
+ case 41:
+ case 42:
+ case 43:
+ case 44:
+ case 45:
+ case 46:
+ case 47:
+ ictx->s->colr &= 0xf0;
+ ictx->s->colr |= m - 40;
+ break;
+ case 49:
+ ictx->s->colr &= 0xf0;
+ ictx->s->colr |= 0x08;
break;
}
- break;
- }
- break;
- case 'r': /* DECSTBM */
- if (private != '\0')
- break;
- if (input_check_two(argv, argc,
- &ua, s->ry_upper + 1, &ub, s->ry_lower + 1) != 0)
- break;
- if (ua == 0 || ub == 0 || ub < ua)
- break;
- input_store_two(b, CODE_SCROLLREGION, ua, ub);
- break;
- case 'm': /* SGR */
- input_store_zero(b, CODE_ATTRIBUTES);
- if (argc == 0) {
- input_store16(b, 1);
- input_store16(b, 0);
- } else {
- input_store16(b, argc);
- for (i = 0; i < argc; i++) {
- if (argv[i] == UINT16_MAX)
- argv[i] = 0;
- input_store16(b, argv[i]);
- }
+ input_store16(ictx->b, m);
}
- break;
- default:
- log_debug("unknown sequence: %c (%hhu)", code, code);
- break;
- }
-
- if (argv != NULL) {
- xfree(argv);
- argv = NULL;
}
-
- return (0);
-}
-
-/* Check for one argument. */
-int
-input_check_one(uint16_t *argv, u_int argc, uint16_t *a, uint16_t ad)
-{
- *a = ad;
- if (argc == 1) {
- if (argv[0] != UINT16_MAX)
- *a = argv[0];
- } else if (argc != 0)
- return (-1);
- return (0);
-}
-
-/* Check for one argument with limits. */
-int
-input_check_one2(uint16_t *argv, u_int argc,
- uint16_t *a, uint16_t ad, uint16_t al, uint16_t au)
-{
- *a = ad;
- if (argc == 1) {
- if (argv[0] != UINT16_MAX)
- *a = argv[0];
- } else if (argc != 0)
- return (-1);
- if (*a < al || *a > au)
- return (-1);
- return (0);
-}
-
-/* Check for two arguments. */
-int
-input_check_two(uint16_t *argv, u_int argc,
- uint16_t *a, uint16_t ad, uint16_t *b, uint16_t bd)
-{
- *a = ad;
- *b = bd;
- if (argc == 1) {
- if (argv[0] != UINT16_MAX)
- *a = argv[0];
- } else if (argc == 2) {
- if (argv[0] != UINT16_MAX)
- *a = argv[0];
- if (argv[1] != UINT16_MAX)
- *b = argv[1];
- } else if (argc != 0)
- return (-1);
- return (0);
}
-/* Store a code without arguments. */
void
input_store_zero(struct buffer *b, u_char code)
{
@@ -773,7 +1019,6 @@ input_store_zero(struct buffer *b, u_char code)
input_store8(b, code);
}
-/* Store a code with a single argument. */
void
input_store_one(struct buffer *b, u_char code, uint16_t ua)
{
@@ -782,7 +1027,6 @@ input_store_one(struct buffer *b, u_char code, uint16_t ua)
input_store16(b, ua);
}
-/* Store a code with two arguments. */
void
input_store_two(struct buffer *b, u_char code, uint16_t ua, uint16_t ub)
{
@@ -792,21 +1036,18 @@ input_store_two(struct buffer *b, u_char code, uint16_t ua, uint16_t ub)
input_store16(b, ub);
}
-/* Write an 8-bit quantity to a buffer. */
void
input_store8(struct buffer *b, uint8_t n)
{
buffer_write(b, &n, sizeof n);
}
-/* Write a 16-bit argument to a buffer. */
void
input_store16(struct buffer *b, uint16_t n)
{
buffer_write(b, &n, sizeof n);
}
-/* Extract an 8-bit quantity from a buffer. */
uint8_t
input_extract8(struct buffer *b)
{
@@ -816,7 +1057,6 @@ input_extract8(struct buffer *b)
return (n);
}
-/* Extract a 16-bit argument from a pointer. */
uint16_t
input_extract16(struct buffer *b)
{
diff --git a/local.c b/local.c
index 648e70bc..2c58bbb7 100644
--- a/local.c
+++ b/local.c
@@ -1,4 +1,4 @@
-/* $Id: local.c,v 1.7 2007-09-21 19:24:37 nicm Exp $ */
+/* $Id: local.c,v 1.8 2007-09-28 22:47:21 nicm Exp $ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -310,7 +310,7 @@ local_putc(int c)
if (c < 0 || c > (int) UCHAR_MAX)
fatalx("invalid character");
- if (debug_level > 1) {
+ if (debug_level > 2) {
f = fopen("tmux-out.log", "a+");
fprintf(f, "%c", ch);
fclose(f);
@@ -416,7 +416,7 @@ local_output(struct buffer *b, size_t size)
switch (ch) {
case CODE_CURSORUP:
if (size < 2)
- fatalx("underflow");
+ fatalx("CODE_CURSORUP underflow");
size -= 2;
ua = input_extract16(b);
if (parm_up_cursor == NULL) {
@@ -427,7 +427,7 @@ local_output(struct buffer *b, size_t size)
break;
case CODE_CURSORDOWN:
if (size < 2)
- fatalx("underflow");
+ fatalx("CODE_CURSORDOWN underflow");
size -= 2;
ua = input_extract16(b);
if (parm_down_cursor == NULL) {
@@ -438,7 +438,7 @@ local_output(struct buffer *b, size_t size)
break;
case CODE_CURSORRIGHT:
if (size < 2)
- fatalx("underflow");
+ fatalx("CODE_CURSORRIGHT underflow");
size -= 2;
ua = input_extract16(b);
if (parm_right_cursor == NULL) {
@@ -449,7 +449,7 @@ local_output(struct buffer *b, size_t size)
break;
case CODE_CURSORLEFT:
if (size < 2)
- fatalx("underflow");
+ fatalx("CODE_CURSORLEFT underflow");
size -= 2;
ua = input_extract16(b);
if (parm_left_cursor == NULL) {
@@ -460,7 +460,7 @@ local_output(struct buffer *b, size_t size)
break;
case CODE_CURSORMOVE:
if (size < 4)
- fatalx("underflow");
+ fatalx("CODE_CURSORMOVE underflow");
size -= 4;
ua = input_extract16(b);
ub = input_extract16(b);
@@ -507,7 +507,7 @@ local_output(struct buffer *b, size_t size)
break;
case CODE_INSERTLINE:
if (size < 2)
- fatalx("underflow");
+ fatalx("CODE_INSERTLINE underflow");
size -= 2;
ua = input_extract16(b);
if (parm_insert_line == NULL) {
@@ -518,7 +518,7 @@ local_output(struct buffer *b, size_t size)
break;
case CODE_DELETELINE:
if (size < 2)
- fatalx("underflow");
+ fatalx("CODE_DELETELINE underflow");
size -= 2;
ua = input_extract16(b);
if (parm_delete_line == NULL) {
@@ -529,7 +529,7 @@ local_output(struct buffer *b, size_t size)
break;
case CODE_INSERTCHARACTER:
if (size < 2)
- fatalx("underflow");
+ fatalx("CODE_INSERTCHARACTER underflow");
size -= 2;
ua = input_extract16(b);
if (parm_ich == NULL) {
@@ -540,7 +540,7 @@ local_output(struct buffer *b, size_t size)
break;
case CODE_DELETECHARACTER:
if (size < 2)
- fatalx("underflow");
+ fatalx("CODE_DELETECHARACTER underflow");
size -= 2;
ua = input_extract16(b);
if (parm_dch == NULL) {
@@ -572,7 +572,7 @@ local_output(struct buffer *b, size_t size)
break;
case CODE_SCROLLREGION:
if (size < 4)
- fatalx("underflow");
+ fatalx("CODE_SCROLLREGION underflow");
size -= 4;
ua = input_extract16(b);
ub = input_extract16(b);
@@ -630,18 +630,18 @@ local_output(struct buffer *b, size_t size)
break;
case CODE_TITLE:
if (size < 2)
- fatalx("underflow");
+ fatalx("CODE_TITLE underflow");
size -= 2;
ua = input_extract16(b);
if (size < ua)
- fatalx("underflow");
+ fatalx("CODE_TITLE underflow");
size -= ua;
buffer_remove(b, ua);
break;
case CODE_ATTRIBUTES:
if (size < 2)
- fatalx("underflow");
+ fatalx("CODE_ATTRIBUTES underflow");
size -= 2;
ua = input_extract16(b);
@@ -656,7 +656,7 @@ local_output(struct buffer *b, size_t size)
while (ua-- != 0) {
if (size < 2)
- fatalx("underflow");
+ fatalx("CODE_ATTRIBUTES underflow");
size -= 2;
ub = input_extract16(b);
diff --git a/screen.c b/screen.c
index 1d968e4f..63619e61 100644
--- a/screen.c
+++ b/screen.c
@@ -1,4 +1,4 @@
-/* $Id: screen.c,v 1.11 2007-09-21 19:24:37 nicm Exp $ */
+/* $Id: screen.c,v 1.12 2007-09-28 22:47:21 nicm Exp $ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -35,30 +35,6 @@ void screen_make_lines(struct screen *, u_int, u_int);
void screen_move_lines(struct screen *, u_int, u_int, u_int);
void screen_fill_lines(
struct screen *, u_int, u_int, u_char, u_char, u_char);
-uint16_t screen_extract(u_char *);
-void screen_write_character(struct screen *, u_char);
-void screen_cursor_up_scroll(struct screen *);
-void screen_cursor_down_scroll(struct screen *);
-void screen_scroll_region_up(struct screen *);
-void screen_scroll_region_down(struct screen *);
-void screen_scroll_up(struct screen *, u_int);
-void screen_scroll_down(struct screen *, u_int);
-void screen_fill_screen(struct screen *, u_char, u_char, u_char);
-void screen_fill_line(struct screen *, u_int, u_char, u_char, u_char);
-void screen_fill_end_of_screen(
- struct screen *, u_int, u_int, u_char, u_char, u_char);
-void screen_fill_end_of_line(
- struct screen *, u_int, u_int, u_char, u_char, u_char);
-void screen_fill_start_of_line(
- struct screen *, u_int, u_int, u_char, u_char, u_char);
-void screen_insert_lines(struct screen *, u_int, u_int);
-void screen_delete_lines(struct screen *, u_int, u_int);
-void screen_insert_characters(struct screen *, u_int, u_int, u_int);
-void screen_delete_characters(struct screen *, u_int, u_int, u_int);
-
-#define SCREEN_DEFDATA ' '
-#define SCREEN_DEFATTR 0
-#define SCREEN_DEFCOLR 0x88
#define screen_last_y(s) ((s)->sy - 1)
#define screen_last_x(s) ((s)->sx - 1)
@@ -380,246 +356,6 @@ screen_fill_lines(
screen_fill_line(s, i, data, attr, colr);
}
-/* Update screen with character. */
-void
-screen_character(struct screen *s, u_char ch)
-{
- switch (ch) {
- case '\n': /* LF */
- screen_cursor_down_scroll(s);
- break;
- case '\r': /* CR */
- s->cx = 0;
- break;
- case '\010': /* BS */
- if (s->cx > 0)
- s->cx--;
- break;
- case '\177': /* DC */
- /* XXX */
- break;
- default:
- if (ch < ' ')
- fatalx("bad control");
- screen_write_character(s, ch);
- break;
- }
-}
-
-/* Extract 16-bit value from pointer. */
-uint16_t
-screen_extract(u_char *ptr)
-{
- uint16_t n;
-
- memcpy(&n, ptr, sizeof n);
- return (n);
-}
-
-/* Update screen with escape sequence. */
-void
-screen_sequence(struct screen *s, u_char *ptr)
-{
- uint16_t ua, ub;
-
- ptr++;
- log_debug("processing code %hhu", *ptr);
- switch (*ptr++) {
- case CODE_CURSORUP:
- ua = screen_extract(ptr);
- if (ua > s->cy)
- ua = s->cy;
- s->cy -= ua;
- break;
- case CODE_CURSORDOWN:
- ua = screen_extract(ptr);
- if (s->cy + ua > screen_last_y(s))
- ua = screen_last_y(s) - s->cy;
- s->cy += ua;
- break;
- case CODE_CURSORLEFT:
- ua = screen_extract(ptr);
- if (ua > s->cx)
- ua = s->cx;
- s->cx -= ua;
- break;
- case CODE_CURSORRIGHT:
- ua = screen_extract(ptr);
- if (s->cx + ua > screen_last_x(s))
- ua = screen_last_x(s) - s->cx;
- s->cx += ua;
- break;
- case CODE_CURSORMOVE:
- ua = screen_extract(ptr);
- ptr += 2;
- ub = screen_extract(ptr);
- if (ub > s->sx)
- ub = s->sx;
- s->cx = ub - 1;
- if (ua > s->sy)
- ua = s->sy;
- s->cy = ua - 1;
- break;
- case CODE_CLEARENDOFSCREEN:
- screen_fill_end_of_screen(
- s, s->cx, s->cy, SCREEN_DEFDATA, s->attr, s->colr);
- break;
- case CODE_CLEARSCREEN:
- screen_fill_screen(s, SCREEN_DEFDATA, s->attr, s->colr);
- break;
- case CODE_CLEARENDOFLINE:
- screen_fill_end_of_line(
- s, s->cx, s->cy, SCREEN_DEFDATA, s->attr, s->colr);
- break;
- case CODE_CLEARSTARTOFLINE:
- screen_fill_start_of_line(
- s, s->cx, s->cy, SCREEN_DEFDATA, s->attr, s->colr);
- break;
- case CODE_CLEARLINE:
- screen_fill_line(s, s->cy, SCREEN_DEFDATA, s->attr, s->colr);
- break;
- case CODE_INSERTLINE:
- ua = screen_extract(ptr);
- screen_insert_lines(s, s->cy, ua);
- break;
- case CODE_DELETELINE:
- ua = screen_extract(ptr);
- screen_delete_lines(s, s->cy, ua);
- break;
- case CODE_INSERTCHARACTER:
- ua = screen_extract(ptr);
- screen_insert_characters(s, s->cx, s->cy, ua);
- break;
- case CODE_DELETECHARACTER:
- ua = screen_extract(ptr);
- screen_delete_characters(s, s->cx, s->cy, ua);
- break;
- case CODE_CURSORON:
- s->mode |= MODE_CURSOR;
- break;
- case CODE_CURSOROFF:
- s->mode &= ~MODE_CURSOR;
- break;
- case CODE_REVERSEINDEX:
- screen_cursor_up_scroll(s);
- break;
- case CODE_SCROLLREGION:
- ua = screen_extract(ptr);
- ptr += 2;
- ub = screen_extract(ptr);
- if (ua > s->sy)
- ua = s->sy;
- s->ry_upper = ua - 1;
- if (ub > s->sy)
- ub = s->sy;
- s->ry_lower = ub - 1;
- break;
- case CODE_INSERTOFF:
- s->mode &= ~MODE_INSERT;
- break;
- case CODE_INSERTON:
- s->mode |= MODE_INSERT;
- break;
- case CODE_KCURSOROFF:
- s->mode &= ~MODE_KCURSOR;
- break;
- case CODE_KCURSORON:
- s->mode |= MODE_KCURSOR;
- break;
- case CODE_KKEYPADOFF:
- s->mode &= ~MODE_KKEYPAD;
- break;
- case CODE_KKEYPADON:
- s->mode |= MODE_KKEYPAD;
- break;
- case CODE_TITLE:
- ua = screen_extract(ptr);
- ptr += 2;
- log_debug("new title: %u:%.*s", ua, (int) ua, ptr);
- if (ua > (sizeof s->title) - 1)
- ua = (sizeof s->title) - 1;
- memcpy(s->title, ptr, ua);
- s->title[ua] = '\0';
- break;
- case CODE_ATTRIBUTES:
- ua = screen_extract(ptr);
- if (ua == 0) {
- s->attr = 0;
- s->colr = SCREEN_DEFCOLR;
- break;
- }
-
- while (ua-- > 0) {
- ptr += 2;
- ub = screen_extract(ptr);
- switch (ub) {
- case 0:
- case 10:
- s->attr = 0;
- s->colr = SCREEN_DEFCOLR;
- break;
- case 1:
- s->attr |= ATTR_BRIGHT;
- break;
- case 2:
- s->attr |= ATTR_DIM;
- break;
- case 3:
- s->attr |= ATTR_ITALICS;
- break;
- case 4:
- s->attr |= ATTR_UNDERSCORE;
- break;
- case 5:
- s->attr |= ATTR_BLINK;
- break;
- case 7:
- s->attr |= ATTR_REVERSE;
- break;
- case 8:
- s->attr |= ATTR_HIDDEN;
- break;
- case 23:
- s->attr &= ~ATTR_ITALICS;
- break;
- case 24:
- s->attr &= ~ATTR_UNDERSCORE;
- break;
- case 30:
- case 31:
- case 32:
- case 33:
- case 34:
- case 35:
- case 36:
- case 37:
- s->colr &= 0x0f;
- s->colr |= (ub - 30) << 4;
- break;
- case 39:
- s->colr &= 0x0f;
- s->colr |= 0x80;
- break;
- case 40:
- case 41:
- case 42:
- case 43:
- case 44:
- case 45:
- case 46:
- case 47:
- s->colr &= 0xf0;
- s->colr |= ub - 40;
- break;
- case 49:
- s->colr &= 0xf0;
- s->colr |= 0x08;
- break;
- }
- }
- }
-}
-
/* Write a single character to the screen at the cursor and move forward. */
void
screen_write_character(struct screen *s, u_char ch)
diff --git a/server-msg.c b/server-msg.c
index 9ec5ecbb..6ec36e8e 100644
--- a/server-msg.c
+++ b/server-msg.c
@@ -1,4 +1,4 @@
-/* $Id: server-msg.c,v 1.7 2007-09-28 21:41:52 mxey Exp $ */
+/* $Id: server-msg.c,v 1.8 2007-09-28 22:47:21 nicm Exp $ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -389,14 +389,13 @@ server_msg_fn_rename(struct hdr *hdr, struct client *c)
char *cause;
struct window *w;
struct session *s;
-
if (hdr->size != sizeof data)
fatalx("bad MSG_RENAME size");
buffer_read(c->in, &data, hdr->size);
- data.newname[sizeof data.newname] = '\0';
+ data.newname[(sizeof data.newname) - 1] = '\0';
if ((s = server_find_sessid(&data.sid, &cause)) == NULL) {
/* XXX: Send message to client */
diff --git a/tmux.h b/tmux.h
index 9f01ae5c..a4173985 100644
--- a/tmux.h
+++ b/tmux.h
@@ -1,4 +1,4 @@
-/* $Id: tmux.h,v 1.20 2007-09-28 21:41:52 mxey Exp $ */
+/* $Id: tmux.h,v 1.21 2007-09-28 22:47:21 nicm Exp $ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -391,6 +391,50 @@ struct screen {
int mode;
};
+/* Screen default contents. */
+#define SCREEN_DEFDATA ' '
+#define SCREEN_DEFATTR 0
+#define SCREEN_DEFCOLR 0x88
+
+/* Input parser sequence argument. */
+struct input_arg {
+ size_t off;
+ size_t len;
+};
+
+/* Input character classes. */
+enum input_class {
+ INPUT_C0CONTROL,
+ INPUT_SPACE,
+ INPUT_INTERMEDIATE,
+ INPUT_PARAMETER,
+ INPUT_UPPERCASE,
+ INPUT_LOWERCASE,
+ INPUT_DELETE,
+ INPUT_C1CONTROL,
+ INPUT_G1DISPLAYABLE,
+ INPUT_SPECIAL
+};
+
+/* Input parser context. */
+struct input_ctx {
+ u_char *buf;
+ size_t len;
+ size_t off;
+
+ struct buffer *b;
+ struct screen *s;
+
+ void *(*state)(u_char, enum input_class, struct input_ctx *);
+
+ size_t intoff;
+ size_t intlen;
+
+ size_t saved;
+ u_char private;
+ ARRAY_DECL(, struct input_arg) args;
+};
+
/* Window structure. */
struct window {
char name[MAXNAMELEN];
@@ -401,6 +445,8 @@ struct window {
u_int references;
+ struct input_ctx ictx;
+
struct screen screen;
};
ARRAY_DECL(windows, struct window *);
@@ -492,8 +538,9 @@ void server_window_changed(struct client *);
void server_draw_client(struct client *, u_int, u_int);
/* input.c */
-void input_key(struct buffer *, int);
-size_t input_parse(u_char *, size_t, struct buffer *, struct screen *);
+void input_init(struct input_ctx *, struct screen *);
+void input_free(struct input_ctx *);
+size_t input_parse(struct input_ctx *, u_char *, size_t, struct buffer *);
uint8_t input_extract8(struct buffer *);
uint16_t input_extract16(struct buffer *);
void input_store8(struct buffer *, uint8_t);
@@ -502,12 +549,32 @@ void input_store_zero(struct buffer *, u_char);
void input_store_one(struct buffer *, u_char, uint16_t);
void input_store_two(struct buffer *, u_char, uint16_t, uint16_t);
+/* input-key.c */
+void input_translate_key(struct buffer *, int);
+
/* screen.c */
void screen_create(struct screen *, u_int, u_int);
void screen_resize(struct screen *, u_int, u_int);
void screen_draw(struct screen *, struct buffer *, u_int, u_int);
-void screen_character(struct screen *, u_char);
-void screen_sequence(struct screen *, u_char *);
+void screen_write_character(struct screen *, u_char);
+void screen_insert_lines(struct screen *, u_int, u_int);
+void screen_delete_lines(struct screen *, u_int, u_int);
+void screen_insert_characters(struct screen *, u_int, u_int, u_int);
+void screen_delete_characters(struct screen *, u_int, u_int, u_int);
+void screen_cursor_up_scroll(struct screen *);
+void screen_cursor_down_scroll(struct screen *);
+void screen_scroll_region_up(struct screen *);
+void screen_scroll_region_down(struct screen *);
+void screen_scroll_up(struct screen *, u_int);
+void screen_scroll_down(struct screen *, u_int);
+void screen_fill_screen(struct screen *, u_char, u_char, u_char);
+void screen_fill_line(struct screen *, u_int, u_char, u_char, u_char);
+void screen_fill_end_of_screen(
+ struct screen *, u_int, u_int, u_char, u_char, u_char);
+void screen_fill_end_of_line(
+ struct screen *, u_int, u_int, u_char, u_char, u_char);
+void screen_fill_start_of_line(
+ struct screen *, u_int, u_int, u_char, u_char, u_char);
/* local.c */
int local_init(struct buffer **, struct buffer **);
diff --git a/window.c b/window.c
index 37ae9593..ec22399b 100644
--- a/window.c
+++ b/window.c
@@ -1,4 +1,4 @@
-/* $Id: window.c,v 1.11 2007-09-27 09:15:58 nicm Exp $ */
+/* $Id: window.c,v 1.12 2007-09-28 22:47:22 nicm Exp $ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -102,6 +102,7 @@ window_create(const char *cmd, const char **environ, u_int sx, u_int sy)
w->in = buffer_create(BUFSIZ);
w->out = buffer_create(BUFSIZ);
screen_create(&w->screen, sx, sy);
+ input_init(&w->ictx, &w->screen);
name = xstrdup(cmd);
if ((ptr = strchr(name, ' ')) != NULL) {
@@ -175,6 +176,8 @@ window_destroy(struct window *w)
{
close(w->fd);
+ input_free(&w->ictx);
+
buffer_destroy(w->in);
buffer_destroy(w->out);
xfree(w);
@@ -300,7 +303,7 @@ window_input(struct window *w, struct buffer *b, size_t size)
size -= 2;
key = (int16_t) input_extract16(b);
}
- input_key(w->out, key);
+ input_translate_key(w->out, key);
}
}
@@ -313,8 +316,7 @@ window_output(struct window *w, struct buffer *b)
{
size_t used;
- used = input_parse(
- BUFFER_OUT(w->in), BUFFER_USED(w->in), b, &w->screen);
+ used = input_parse(&w->ictx, BUFFER_OUT(w->in), BUFFER_USED(w->in), b);
if (used != 0)
buffer_remove(w->in, used);
}