aboutsummaryrefslogtreecommitdiff
path: root/input.c
diff options
context:
space:
mode:
Diffstat (limited to 'input.c')
-rw-r--r--input.c230
1 files changed, 142 insertions, 88 deletions
diff --git a/input.c b/input.c
index 82d2b398..1b1be485 100644
--- a/input.c
+++ b/input.c
@@ -75,6 +75,7 @@ struct input_param {
/* Input parser context. */
struct input_ctx {
struct window_pane *wp;
+ struct bufferevent *event;
struct screen_write_ctx ctx;
struct input_cell cell;
@@ -128,7 +129,7 @@ struct input_transition;
static int input_split(struct input_ctx *);
static int input_get(struct input_ctx *, u_int, int, int);
static void printflike(2, 3) input_reply(struct input_ctx *, const char *, ...);
-static void input_set_state(struct window_pane *,
+static void input_set_state(struct input_ctx *,
const struct input_transition *);
static void input_reset_cell(struct input_ctx *);
@@ -253,6 +254,7 @@ enum input_csi_type {
INPUT_CSI_TBC,
INPUT_CSI_VPA,
INPUT_CSI_WINOPS,
+ INPUT_CSI_XDA,
};
/* Control (CSI) command table. */
@@ -289,6 +291,7 @@ static const struct input_table_entry input_csi_table[] = {
{ 'm', "", INPUT_CSI_SGR },
{ 'n', "", INPUT_CSI_DSR },
{ 'q', " ", INPUT_CSI_DECSCUSR },
+ { 'q', ">", INPUT_CSI_XDA },
{ 'r', "", INPUT_CSI_DECSTBM },
{ 's', "", INPUT_CSI_SCP },
{ 't', "", INPUT_CSI_WINOPS },
@@ -731,10 +734,9 @@ static void
input_timer_callback(__unused int fd, __unused short events, void *arg)
{
struct input_ctx *ictx = arg;
- struct window_pane *wp = ictx->wp;
- log_debug("%s: %%%u %s expired" , __func__, wp->id, ictx->state->name);
- input_reset(wp, 0);
+ log_debug("%s: %s expired" , __func__, ictx->state->name);
+ input_reset(ictx, 0);
}
/* Start the timer. */
@@ -788,12 +790,14 @@ input_restore_state(struct input_ctx *ictx)
}
/* Initialise input parser. */
-void
-input_init(struct window_pane *wp)
+struct input_ctx *
+input_init(struct window_pane *wp, struct bufferevent *bev)
{
struct input_ctx *ictx;
- ictx = wp->ictx = xcalloc(1, sizeof *ictx);
+ ictx = xcalloc(1, sizeof *ictx);
+ ictx->wp = wp;
+ ictx->event = bev;
ictx->input_space = INPUT_BUF_START;
ictx->input_buf = xmalloc(INPUT_BUF_START);
@@ -804,15 +808,15 @@ input_init(struct window_pane *wp)
evtimer_set(&ictx->timer, input_timer_callback, ictx);
- input_reset(wp, 0);
+ input_reset(ictx, 0);
+ return (ictx);
}
/* Destroy input parser. */
void
-input_free(struct window_pane *wp)
+input_free(struct input_ctx *ictx)
{
- struct input_ctx *ictx = wp->ictx;
- u_int i;
+ u_int i;
for (i = 0; i < ictx->param_list_len; i++) {
if (ictx->param_list[i].type == INPUT_STRING)
@@ -825,19 +829,18 @@ input_free(struct window_pane *wp)
evbuffer_free(ictx->since_ground);
free(ictx);
- wp->ictx = NULL;
}
/* Reset input state and clear screen. */
void
-input_reset(struct window_pane *wp, int clear)
+input_reset(struct input_ctx *ictx, int clear)
{
- struct input_ctx *ictx = wp->ictx;
struct screen_write_ctx *sctx = &ictx->ctx;
+ struct window_pane *wp = ictx->wp;
input_reset_cell(ictx);
- if (clear) {
+ if (clear && wp != NULL) {
if (TAILQ_EMPTY(&wp->modes))
screen_write_start(sctx, wp, &wp->base);
else
@@ -856,17 +859,15 @@ input_reset(struct window_pane *wp, int clear)
/* Return pending data. */
struct evbuffer *
-input_pending(struct window_pane *wp)
+input_pending(struct input_ctx *ictx)
{
- return (wp->ictx->since_ground);
+ return (ictx->since_ground);
}
/* Change input state. */
static void
-input_set_state(struct window_pane *wp, const struct input_transition *itr)
+input_set_state(struct input_ctx *ictx, const struct input_transition *itr)
{
- struct input_ctx *ictx = wp->ictx;
-
if (ictx->state->exit != NULL)
ictx->state->exit(ictx);
ictx->state = itr->state;
@@ -874,46 +875,15 @@ input_set_state(struct window_pane *wp, const struct input_transition *itr)
ictx->state->enter(ictx);
}
-/* Parse input. */
-void
-input_parse(struct window_pane *wp)
-{
- struct evbuffer *evb = wp->event->input;
-
- input_parse_buffer(wp, EVBUFFER_DATA(evb), EVBUFFER_LENGTH(evb));
- evbuffer_drain(evb, EVBUFFER_LENGTH(evb));
-}
-
-/* Parse given input. */
-void
-input_parse_buffer(struct window_pane *wp, u_char *buf, size_t len)
+/* Parse data. */
+static void
+input_parse(struct input_ctx *ictx, u_char *buf, size_t len)
{
- struct input_ctx *ictx = wp->ictx;
struct screen_write_ctx *sctx = &ictx->ctx;
const struct input_state *state = NULL;
const struct input_transition *itr = NULL;
size_t off = 0;
- if (len == 0)
- return;
-
- window_update_activity(wp->window);
- wp->flags |= PANE_CHANGED;
- notify_input(wp, buf, len);
-
- /*
- * Open the screen. Use NULL wp if there is a mode set as don't want to
- * update the tty.
- */
- if (TAILQ_EMPTY(&wp->modes))
- screen_write_start(sctx, wp, &wp->base);
- else
- screen_write_start(sctx, NULL, &wp->base);
- ictx->wp = wp;
-
- log_debug("%s: %%%u %s, %zu bytes: %.*s", __func__, wp->id,
- ictx->state->name, len, (int)len, buf);
-
/* Parse the input. */
while (off < len) {
ictx->ch = buf[off++];
@@ -956,14 +926,63 @@ input_parse_buffer(struct window_pane *wp, u_char *buf, size_t len)
/* And switch state, if necessary. */
if (itr->state != NULL)
- input_set_state(wp, itr);
+ input_set_state(ictx, itr);
/* If not in ground state, save input. */
if (ictx->state != &input_state_ground)
evbuffer_add(ictx->since_ground, &ictx->ch, 1);
}
+}
+
+/* Parse input from pane. */
+void
+input_parse_pane(struct window_pane *wp)
+{
+ struct evbuffer *evb = wp->event->input;
+
+ input_parse_buffer(wp, EVBUFFER_DATA(evb), EVBUFFER_LENGTH(evb));
+ evbuffer_drain(evb, EVBUFFER_LENGTH(evb));
+}
+
+/* Parse given input. */
+void
+input_parse_buffer(struct window_pane *wp, u_char *buf, size_t len)
+{
+ struct input_ctx *ictx = wp->ictx;
+ struct screen_write_ctx *sctx = &ictx->ctx;
+
+ if (len == 0)
+ return;
+
+ window_update_activity(wp->window);
+ wp->flags |= PANE_CHANGED;
+ notify_input(wp, buf, len);
- /* Close the screen. */
+ /* NULL wp if there is a mode set as don't want to update the tty. */
+ if (TAILQ_EMPTY(&wp->modes))
+ screen_write_start(sctx, wp, &wp->base);
+ else
+ screen_write_start(sctx, NULL, &wp->base);
+
+ log_debug("%s: %%%u %s, %zu bytes: %.*s", __func__, wp->id,
+ ictx->state->name, len, (int)len, buf);
+
+ input_parse(ictx, buf, len);
+ screen_write_stop(sctx);
+}
+
+/* Parse given input for screen. */
+void
+input_parse_screen(struct input_ctx *ictx, struct screen *s, u_char *buf,
+ size_t len)
+{
+ struct screen_write_ctx *sctx = &ictx->ctx;
+
+ if (len == 0)
+ return;
+
+ screen_write_start(sctx, NULL, s);
+ input_parse(ictx, buf, len);
screen_write_stop(sctx);
}
@@ -1043,14 +1062,15 @@ input_get(struct input_ctx *ictx, u_int validx, int minval, int defval)
static void
input_reply(struct input_ctx *ictx, const char *fmt, ...)
{
- va_list ap;
- char *reply;
+ struct bufferevent *bev = ictx->event;
+ va_list ap;
+ char *reply;
va_start(ap, fmt);
xvasprintf(&reply, fmt, ap);
va_end(ap);
- bufferevent_write(ictx->wp->event, reply, strlen(reply));
+ bufferevent_write(bev, reply, strlen(reply));
free(reply);
}
@@ -1177,7 +1197,8 @@ input_c0_dispatch(struct input_ctx *ictx)
case '\000': /* NUL */
break;
case '\007': /* BEL */
- alerts_queue(wp->window, WINDOW_BELL);
+ if (wp != NULL)
+ alerts_queue(wp->window, WINDOW_BELL);
break;
case '\010': /* BS */
screen_write_backspace(sctx);
@@ -1224,6 +1245,7 @@ static int
input_esc_dispatch(struct input_ctx *ictx)
{
struct screen_write_ctx *sctx = &ictx->ctx;
+ struct window_pane *wp = ictx->wp;
struct screen *s = sctx->s;
struct input_table_entry *entry;
@@ -1240,7 +1262,8 @@ input_esc_dispatch(struct input_ctx *ictx)
switch (entry->type) {
case INPUT_ESC_RIS:
- window_pane_reset_palette(ictx->wp);
+ if (wp != NULL)
+ window_pane_reset_palette(wp);
input_reset_cell(ictx);
screen_write_reset(sctx);
break;
@@ -1303,7 +1326,6 @@ input_csi_dispatch(struct input_ctx *ictx)
struct input_table_entry *entry;
int i, n, m;
u_int cx, bg = ictx->cell.cell.bg;
- char *copy, *cp;
if (ictx->flags & INPUT_DISCARD)
return (0);
@@ -1435,13 +1457,6 @@ input_csi_dispatch(struct input_ctx *ictx)
case 6:
input_reply(ictx, "\033[%u;%uR", s->cy + 1, s->cx + 1);
break;
- case 1337: /* Terminal version, from iTerm2. */
- copy = xstrdup(getversion());
- for (cp = copy; *cp != '\0'; cp++)
- *cp = toupper((u_char)*cp);
- input_reply(ictx, "\033[TMUX %sn", copy);
- free(copy);
- break;
default:
log_debug("%s: unknown '%c'", __func__, ictx->ch);
break;
@@ -1576,6 +1591,10 @@ input_csi_dispatch(struct input_ctx *ictx)
if (n != -1)
screen_set_cursor_style(s, n);
break;
+ case INPUT_CSI_XDA:
+ input_reply(ictx, "\033P>|tmux %s\033\\", getversion());
+ break;
+
}
ictx->last = -1;
@@ -1612,6 +1631,7 @@ input_csi_dispatch_rm_private(struct input_ctx *ictx)
{
struct screen_write_ctx *sctx = &ictx->ctx;
struct window_pane *wp = ictx->wp;
+ struct grid_cell *gc = &ictx->cell.cell;
u_int i;
for (i = 0; i < ictx->param_list_len; i++) {
@@ -1623,7 +1643,7 @@ input_csi_dispatch_rm_private(struct input_ctx *ictx)
break;
case 3: /* DECCOLM */
screen_write_cursormove(sctx, 0, 0, 1);
- screen_write_clearscreen(sctx, ictx->cell.cell.bg);
+ screen_write_clearscreen(sctx, gc->bg);
break;
case 6: /* DECOM */
screen_write_mode_clear(sctx, MODE_ORIGIN);
@@ -1655,10 +1675,16 @@ input_csi_dispatch_rm_private(struct input_ctx *ictx)
break;
case 47:
case 1047:
- window_pane_alternate_off(wp, &ictx->cell.cell, 0);
+ if (wp != NULL)
+ window_pane_alternate_off(wp, gc, 0);
+ else
+ screen_alternate_off(sctx->s, gc, 0);
break;
case 1049:
- window_pane_alternate_off(wp, &ictx->cell.cell, 1);
+ if (wp != NULL)
+ window_pane_alternate_off(wp, gc, 1);
+ else
+ screen_alternate_off(sctx->s, gc, 1);
break;
case 2004:
screen_write_mode_clear(sctx, MODE_BRACKETPASTE);
@@ -1700,6 +1726,7 @@ input_csi_dispatch_sm_private(struct input_ctx *ictx)
{
struct screen_write_ctx *sctx = &ictx->ctx;
struct window_pane *wp = ictx->wp;
+ struct grid_cell *gc = &ictx->cell.cell;
u_int i;
for (i = 0; i < ictx->param_list_len; i++) {
@@ -1742,7 +1769,8 @@ input_csi_dispatch_sm_private(struct input_ctx *ictx)
if (sctx->s->mode & MODE_FOCUSON)
break;
screen_write_mode_set(sctx, MODE_FOCUSON);
- wp->flags |= PANE_FOCUSPUSH; /* force update */
+ if (wp != NULL)
+ wp->flags |= PANE_FOCUSPUSH; /* force update */
break;
case 1005:
screen_write_mode_set(sctx, MODE_MOUSE_UTF8);
@@ -1752,10 +1780,16 @@ input_csi_dispatch_sm_private(struct input_ctx *ictx)
break;
case 47:
case 1047:
- window_pane_alternate_on(wp, &ictx->cell.cell, 0);
+ if (wp != NULL)
+ window_pane_alternate_on(wp, gc, 0);
+ else
+ screen_alternate_on(sctx->s, gc, 0);
break;
case 1049:
- window_pane_alternate_on(wp, &ictx->cell.cell, 1);
+ if (wp != NULL)
+ window_pane_alternate_on(wp, gc, 1);
+ else
+ screen_alternate_on(sctx->s, gc, 1);
break;
case 2004:
screen_write_mode_set(sctx, MODE_BRACKETPASTE);
@@ -1772,7 +1806,9 @@ static void
input_csi_dispatch_winops(struct input_ctx *ictx)
{
struct screen_write_ctx *sctx = &ictx->ctx;
+ struct screen *s = sctx->s;
struct window_pane *wp = ictx->wp;
+ u_int x = screen_size_x(s), y = screen_size_y(s);
int n, m;
m = 0;
@@ -1823,12 +1859,13 @@ input_csi_dispatch_winops(struct input_ctx *ictx)
case 0:
case 2:
screen_pop_title(sctx->s);
- server_status_window(ictx->wp->window);
+ if (wp != NULL)
+ server_status_window(wp->window);
break;
}
break;
case 18:
- input_reply(ictx, "\033[8;%u;%ut", wp->sy, wp->sx);
+ input_reply(ictx, "\033[8;%u;%ut", x, y);
break;
default:
log_debug("%s: unknown '%c'", __func__, ictx->ch);
@@ -2193,6 +2230,7 @@ static void
input_exit_osc(struct input_ctx *ictx)
{
struct screen_write_ctx *sctx = &ictx->ctx;
+ struct window_pane *wp = ictx->wp;
u_char *p = ictx->input_buf;
u_int option;
@@ -2213,7 +2251,7 @@ input_exit_osc(struct input_ctx *ictx)
switch (option) {
case 0:
case 2:
- if (screen_set_title(sctx->s, p))
+ if (screen_set_title(sctx->s, p) && wp != NULL)
server_status_window(ictx->wp->window);
break;
case 4:
@@ -2222,7 +2260,8 @@ input_exit_osc(struct input_ctx *ictx)
case 7:
if (utf8_isvalid(p)) {
screen_set_path(sctx->s, p);
- server_status_window(ictx->wp->window);
+ if (wp != NULL)
+ server_status_window(wp->window);
}
break;
case 10:
@@ -2267,13 +2306,14 @@ static void
input_exit_apc(struct input_ctx *ictx)
{
struct screen_write_ctx *sctx = &ictx->ctx;
+ struct window_pane *wp = ictx->wp;
if (ictx->flags & INPUT_DISCARD)
return;
log_debug("%s: \"%s\"", __func__, ictx->input_buf);
- if (screen_set_title(sctx->s, ictx->input_buf))
- server_status_window(ictx->wp->window);
+ if (screen_set_title(sctx->s, ictx->input_buf) && wp != NULL)
+ server_status_window(wp->window);
}
/* Rename string started. */
@@ -2294,6 +2334,8 @@ input_exit_rename(struct input_ctx *ictx)
struct window_pane *wp = ictx->wp;
struct options_entry *oe;
+ if (wp == NULL)
+ return;
if (ictx->flags & INPUT_DISCARD)
return;
if (!options_get_number(ictx->wp->options, "allow-rename"))
@@ -2309,9 +2351,9 @@ input_exit_rename(struct input_ctx *ictx)
options_remove(oe);
return;
}
- window_set_name(ictx->wp->window, ictx->input_buf);
- options_set_number(ictx->wp->window->options, "automatic-rename", 0);
- server_status_window(ictx->wp->window);
+ window_set_name(wp->window, ictx->input_buf);
+ options_set_number(wp->window->options, "automatic-rename", 0);
+ server_status_window(wp->window);
}
/* Open UTF-8 character. */
@@ -2407,6 +2449,9 @@ input_osc_4(struct input_ctx *ictx, const char *p)
long idx;
u_int r, g, b;
+ if (wp == NULL)
+ return;
+
copy = s = xstrdup(p);
while (s != NULL && *s != '\0') {
idx = strtol(s, &next, 10);
@@ -2441,6 +2486,8 @@ input_osc_10(struct input_ctx *ictx, const char *p)
u_int r, g, b;
char tmp[16];
+ if (wp == NULL)
+ return;
if (strcmp(p, "?") == 0)
return;
@@ -2465,6 +2512,8 @@ input_osc_11(struct input_ctx *ictx, const char *p)
u_int r, g, b;
char tmp[16];
+ if (wp == NULL)
+ return;
if (strcmp(p, "?") == 0)
return;
@@ -2494,6 +2543,8 @@ input_osc_52(struct input_ctx *ictx, const char *p)
struct screen_write_ctx ctx;
struct paste_buffer *pb;
+ if (wp == NULL)
+ return;
state = options_get_number(global_options, "set-clipboard");
if (state != 2)
return;
@@ -2518,13 +2569,13 @@ input_osc_52(struct input_ctx *ictx, const char *p)
outlen = 0;
out = NULL;
}
- bufferevent_write(wp->event, "\033]52;;", 6);
+ bufferevent_write(ictx->event, "\033]52;;", 6);
if (outlen != 0)
- bufferevent_write(wp->event, out, outlen);
+ bufferevent_write(ictx->event, out, outlen);
if (ictx->input_end == INPUT_END_BEL)
- bufferevent_write(wp->event, "\007", 1);
+ bufferevent_write(ictx->event, "\007", 1);
else
- bufferevent_write(wp->event, "\033\\", 2);
+ bufferevent_write(ictx->event, "\033\\", 2);
free(out);
return;
}
@@ -2555,6 +2606,9 @@ input_osc_104(struct input_ctx *ictx, const char *p)
char *copy, *s;
long idx;
+ if (wp == NULL)
+ return;
+
if (*p == '\0') {
window_pane_reset_palette(wp);
return;