summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNicholas Marriott <nicm@openbsd.org>2011-03-07 23:46:27 +0000
committerNicholas Marriott <nicm@openbsd.org>2011-03-07 23:46:27 +0000
commit79e30daeae1d49a1cf1dc4618edf1ec82804a80c (patch)
tree60ba3ed616a1c1d247a4af715dc27ef8a2d22e76
parentd5ed5fb08ff83a2cc38292b3eb0addab21ce6282 (diff)
Support passing through escape sequences to the underlying terminal by
using DCS with a "tmux;" prefix. Escape characters in the sequences must be doubled. For example: $ printf '\033Ptmux;\033\033]12;red\007\033\\' Will pass \033]12;red\007 to the terminal (and change the cursor colour in xterm). From Kevin Goodsell.
-rw-r--r--input.c71
-rw-r--r--screen-write.c12
-rw-r--r--tmux.h2
-rw-r--r--tty.c10
4 files changed, 72 insertions, 23 deletions
diff --git a/input.c b/input.c
index f80e7fc1..3da950d5 100644
--- a/input.c
+++ b/input.c
@@ -41,6 +41,9 @@
*
* - 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.
+ *
+ * - Special handling for ESC inside a DCS to allow arbitrary byte sequences to
+ * be passed to the underlying teminal(s).
*/
/* Helper functions. */
@@ -50,8 +53,6 @@ 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 *);
@@ -68,6 +69,7 @@ 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_dcs_dispatch(struct input_ctx *);
int input_utf8_open(struct input_ctx *);
int input_utf8_add(struct input_ctx *);
int input_utf8_close(struct input_ctx *);
@@ -204,6 +206,7 @@ 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_escape_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[];
@@ -286,10 +289,17 @@ const struct input_state input_state_dcs_intermediate = {
/* dcs_handler state definition. */
const struct input_state input_state_dcs_handler = {
"dcs_handler",
- input_enter_dcs, input_exit_dcs,
+ NULL, NULL,
input_state_dcs_handler_table
};
+/* dcs_escape state definition. */
+const struct input_state input_state_dcs_escape = {
+ "dcs_escape",
+ NULL, NULL,
+ input_state_dcs_escape_table
+};
+
/* dcs_ignore state definition. */
const struct input_state input_state_dcs_ignore = {
"dcs_ignore",
@@ -482,7 +492,7 @@ const struct input_transition input_state_dcs_enter_table[] = {
{ 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 },
+ { 0x40, 0x7e, input_input, &input_state_dcs_handler },
{ 0x7f, 0xff, NULL, NULL },
{ -1, -1, NULL, NULL }
@@ -500,7 +510,7 @@ const struct input_transition input_state_dcs_parameter_table[] = {
{ 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 },
+ { 0x40, 0x7e, input_input, &input_state_dcs_handler },
{ 0x7f, 0xff, NULL, NULL },
{ -1, -1, NULL, NULL }
@@ -515,7 +525,7 @@ const struct input_transition input_state_dcs_intermediate_table[] = {
{ 0x1c, 0x1f, NULL, NULL },
{ 0x20, 0x2f, input_intermediate, NULL },
{ 0x30, 0x3f, NULL, &input_state_dcs_ignore },
- { 0x40, 0x7e, NULL, &input_state_dcs_handler },
+ { 0x40, 0x7e, input_input, &input_state_dcs_handler },
{ 0x7f, 0xff, NULL, NULL },
{ -1, -1, NULL, NULL }
@@ -523,13 +533,22 @@ const struct input_transition input_state_dcs_intermediate_table[] = {
/* dcs_handler state table. */
const struct input_transition input_state_dcs_handler_table[] = {
- INPUT_STATE_ANYWHERE,
+ /* No INPUT_STATE_ANYWHERE */
- { 0x00, 0x17, NULL, NULL },
- { 0x19, 0x19, input_input, NULL },
- { 0x1c, 0x1f, input_input, NULL },
- { 0x20, 0x7e, input_input, NULL },
- { 0x7f, 0xff, NULL, NULL },
+ { 0x00, 0x1a, input_input, NULL },
+ { 0x1b, 0x1b, NULL, &input_state_dcs_escape },
+ { 0x1c, 0xff, input_input, NULL },
+
+ { -1, -1, NULL, NULL }
+};
+
+/* dcs_escape state table. */
+const struct input_transition input_state_dcs_escape_table[] = {
+ /* No INPUT_STATE_ANYWHERE */
+
+ { 0x00, 0x5b, input_input, &input_state_dcs_handler },
+ { 0x5c, 0x5c, input_dcs_dispatch, &input_state_ground },
+ { 0x5d, 0xff, input_input, &input_state_dcs_handler },
{ -1, -1, NULL, NULL }
};
@@ -1391,20 +1410,26 @@ input_csi_dispatch_sgr(struct input_ctx *ictx)
}
}
-/* DCS string started. */
-void
-input_enter_dcs(struct input_ctx *ictx)
+/* DCS terminator (ST) received. */
+int
+input_dcs_dispatch(struct input_ctx *ictx)
{
- log_debug("%s", __func__);
+ const char prefix[] = "tmux;";
+ const u_int prefix_len = (sizeof prefix) - 1;
- input_clear(ictx);
-}
+ if (ictx->flags & INPUT_DISCARD)
+ return (0);
-/* DCS terminator (ST) received. */
-void
-input_exit_dcs(unused struct input_ctx *ictx)
-{
- log_debug("%s", __func__);
+ log_debug("%s: \"%s\"", __func__, ictx->input_buf);
+
+ /* Check for tmux prefix. */
+ if (ictx->input_len >= prefix_len &&
+ strncmp(ictx->input_buf, prefix, prefix_len) == 0) {
+ screen_write_rawstring(&ictx->ctx,
+ ictx->input_buf + prefix_len, ictx->input_len - prefix_len);
+ }
+
+ return (0);
}
/* OSC string started. */
diff --git a/screen-write.c b/screen-write.c
index 4c8382de..09f84bfd 100644
--- a/screen-write.c
+++ b/screen-write.c
@@ -1191,3 +1191,15 @@ screen_write_overwrite(struct screen_write_ctx *ctx, u_int width)
grid_view_set_cell(gd, xx, s->cy, &grid_default_cell);
}
}
+
+void
+screen_write_rawstring(struct screen_write_ctx *ctx, u_char *str, u_int len)
+{
+ struct tty_ctx ttyctx;
+
+ screen_write_initctx(ctx, &ttyctx, 0);
+ ttyctx.ptr = str;
+ ttyctx.num = len;
+
+ tty_write(tty_cmd_rawstring, &ttyctx);
+}
diff --git a/tmux.h b/tmux.h
index 61022983..2e53a24a 100644
--- a/tmux.h
+++ b/tmux.h
@@ -1426,6 +1426,7 @@ void tty_cmd_insertline(struct tty *, const struct tty_ctx *);
void tty_cmd_linefeed(struct tty *, const struct tty_ctx *);
void tty_cmd_utf8character(struct tty *, const struct tty_ctx *);
void tty_cmd_reverseindex(struct tty *, const struct tty_ctx *);
+void tty_cmd_rawstring(struct tty *, const struct tty_ctx *);
/* tty-term.c */
extern struct tty_terms tty_terms;
@@ -1804,6 +1805,7 @@ void screen_write_clearstartofscreen(struct screen_write_ctx *);
void screen_write_clearscreen(struct screen_write_ctx *);
void screen_write_cell(struct screen_write_ctx *,
const struct grid_cell *, const struct utf8_data *);
+void screen_write_rawstring(struct screen_write_ctx *, u_char *, u_int);
/* screen-redraw.c */
void screen_redraw_screen(struct client *, int, int);
diff --git a/tty.c b/tty.c
index b44c5974..46b8a475 100644
--- a/tty.c
+++ b/tty.c
@@ -932,6 +932,16 @@ tty_cmd_utf8character(struct tty *tty, const struct tty_ctx *ctx)
}
void
+tty_cmd_rawstring(struct tty *tty, const struct tty_ctx *ctx)
+{
+ u_int i;
+ u_char *str = ctx->ptr;
+
+ for (i = 0; i < ctx->num; i++)
+ tty_putc(tty, str[i]);
+}
+
+void
tty_cell(
struct tty *tty, const struct grid_cell *gc, const struct grid_utf8 *gu)
{