version 1.170, 2020/02/03 13:46:27 |
version 1.171, 2020/03/19 14:03:48 |
|
|
static int input_split(struct input_ctx *); |
static int input_split(struct input_ctx *); |
static int input_get(struct input_ctx *, u_int, int, int); |
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 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 *); |
const struct input_transition *); |
static void input_reset_cell(struct input_ctx *); |
static void input_reset_cell(struct input_ctx *); |
|
|
|
|
input_timer_callback(__unused int fd, __unused short events, void *arg) |
input_timer_callback(__unused int fd, __unused short events, void *arg) |
{ |
{ |
struct input_ctx *ictx = arg; |
struct input_ctx *ictx = arg; |
struct window_pane *wp = ictx->wp; |
|
|
|
log_debug("%s: %%%u %s expired" , __func__, wp->id, ictx->state->name); |
log_debug("%s: %s expired" , __func__, ictx->state->name); |
input_reset(wp, 0); |
input_reset(ictx, 0); |
} |
} |
|
|
/* Start the timer. */ |
/* Start the timer. */ |
|
|
} |
} |
|
|
/* Initialise input parser. */ |
/* Initialise input parser. */ |
void |
struct input_ctx * |
input_init(struct window_pane *wp) |
input_init(struct window_pane *wp) |
{ |
{ |
struct input_ctx *ictx; |
struct input_ctx *ictx; |
|
|
ictx = wp->ictx = xcalloc(1, sizeof *ictx); |
ictx = xcalloc(1, sizeof *ictx); |
|
ictx->wp = wp; |
|
|
ictx->input_space = INPUT_BUF_START; |
ictx->input_space = INPUT_BUF_START; |
ictx->input_buf = xmalloc(INPUT_BUF_START); |
ictx->input_buf = xmalloc(INPUT_BUF_START); |
|
|
|
|
evtimer_set(&ictx->timer, input_timer_callback, ictx); |
evtimer_set(&ictx->timer, input_timer_callback, ictx); |
|
|
input_reset(wp, 0); |
input_reset(ictx, 0); |
|
return (ictx); |
} |
} |
|
|
/* Destroy input parser. */ |
/* Destroy input parser. */ |
void |
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++) { |
for (i = 0; i < ictx->param_list_len; i++) { |
if (ictx->param_list[i].type == INPUT_STRING) |
if (ictx->param_list[i].type == INPUT_STRING) |
|
|
evbuffer_free(ictx->since_ground); |
evbuffer_free(ictx->since_ground); |
|
|
free(ictx); |
free(ictx); |
wp->ictx = NULL; |
|
} |
} |
|
|
/* Reset input state and clear screen. */ |
/* Reset input state and clear screen. */ |
void |
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 screen_write_ctx *sctx = &ictx->ctx; |
|
struct window_pane *wp = ictx->wp; |
|
|
input_reset_cell(ictx); |
input_reset_cell(ictx); |
|
|
if (clear) { |
if (clear && wp != NULL) { |
if (TAILQ_EMPTY(&wp->modes)) |
if (TAILQ_EMPTY(&wp->modes)) |
screen_write_start(sctx, wp, &wp->base); |
screen_write_start(sctx, wp, &wp->base); |
else |
else |
|
|
|
|
/* Return pending data. */ |
/* Return pending data. */ |
struct evbuffer * |
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. */ |
/* Change input state. */ |
static void |
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) |
if (ictx->state->exit != NULL) |
ictx->state->exit(ictx); |
ictx->state->exit(ictx); |
ictx->state = itr->state; |
ictx->state = itr->state; |
|
|
ictx->state->enter(ictx); |
ictx->state->enter(ictx); |
} |
} |
|
|
/* Parse input. */ |
/* Parse data. */ |
void |
static void |
input_parse(struct window_pane *wp) |
input_parse(struct input_ctx *ictx, u_char *buf, size_t len) |
{ |
{ |
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; |
struct screen_write_ctx *sctx = &ictx->ctx; |
const struct input_state *state = NULL; |
const struct input_state *state = NULL; |
const struct input_transition *itr = NULL; |
const struct input_transition *itr = NULL; |
size_t off = 0; |
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. */ |
/* Parse the input. */ |
while (off < len) { |
while (off < len) { |
ictx->ch = buf[off++]; |
ictx->ch = buf[off++]; |
|
|
|
|
/* And switch state, if necessary. */ |
/* And switch state, if necessary. */ |
if (itr->state != NULL) |
if (itr->state != NULL) |
input_set_state(wp, itr); |
input_set_state(ictx, itr); |
|
|
/* If not in ground state, save input. */ |
/* If not in ground state, save input. */ |
if (ictx->state != &input_state_ground) |
if (ictx->state != &input_state_ground) |
evbuffer_add(ictx->since_ground, &ictx->ch, 1); |
evbuffer_add(ictx->since_ground, &ictx->ch, 1); |
} |
} |
|
} |
|
|
/* Close the screen. */ |
/* 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); |
|
|
|
/* 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); |
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); |
|
} |
|
|
/* Split the parameter list (if any). */ |
/* Split the parameter list (if any). */ |
static int |
static int |
input_split(struct input_ctx *ictx) |
input_split(struct input_ctx *ictx) |
|
|
static void |
static void |
input_reply(struct input_ctx *ictx, const char *fmt, ...) |
input_reply(struct input_ctx *ictx, const char *fmt, ...) |
{ |
{ |
va_list ap; |
struct window_pane *wp = ictx->wp; |
char *reply; |
va_list ap; |
|
char *reply; |
|
|
|
if (wp == NULL) |
|
return; |
|
|
va_start(ap, fmt); |
va_start(ap, fmt); |
xvasprintf(&reply, fmt, ap); |
xvasprintf(&reply, fmt, ap); |
va_end(ap); |
va_end(ap); |
|
|
bufferevent_write(ictx->wp->event, reply, strlen(reply)); |
bufferevent_write(wp->event, reply, strlen(reply)); |
free(reply); |
free(reply); |
} |
} |
|
|
|
|
case '\000': /* NUL */ |
case '\000': /* NUL */ |
break; |
break; |
case '\007': /* BEL */ |
case '\007': /* BEL */ |
alerts_queue(wp->window, WINDOW_BELL); |
if (wp != NULL) |
|
alerts_queue(wp->window, WINDOW_BELL); |
break; |
break; |
case '\010': /* BS */ |
case '\010': /* BS */ |
screen_write_backspace(sctx); |
screen_write_backspace(sctx); |
|
|
input_esc_dispatch(struct input_ctx *ictx) |
input_esc_dispatch(struct input_ctx *ictx) |
{ |
{ |
struct screen_write_ctx *sctx = &ictx->ctx; |
struct screen_write_ctx *sctx = &ictx->ctx; |
|
struct window_pane *wp = ictx->wp; |
struct screen *s = sctx->s; |
struct screen *s = sctx->s; |
struct input_table_entry *entry; |
struct input_table_entry *entry; |
|
|
|
|
|
|
switch (entry->type) { |
switch (entry->type) { |
case INPUT_ESC_RIS: |
case INPUT_ESC_RIS: |
window_pane_reset_palette(ictx->wp); |
if (wp != NULL) |
|
window_pane_reset_palette(wp); |
input_reset_cell(ictx); |
input_reset_cell(ictx); |
screen_write_reset(sctx); |
screen_write_reset(sctx); |
break; |
break; |
|
|
{ |
{ |
struct screen_write_ctx *sctx = &ictx->ctx; |
struct screen_write_ctx *sctx = &ictx->ctx; |
struct window_pane *wp = ictx->wp; |
struct window_pane *wp = ictx->wp; |
|
struct grid_cell *gc = &ictx->cell.cell; |
u_int i; |
u_int i; |
|
|
for (i = 0; i < ictx->param_list_len; i++) { |
for (i = 0; i < ictx->param_list_len; i++) { |
|
|
break; |
break; |
case 3: /* DECCOLM */ |
case 3: /* DECCOLM */ |
screen_write_cursormove(sctx, 0, 0, 1); |
screen_write_cursormove(sctx, 0, 0, 1); |
screen_write_clearscreen(sctx, ictx->cell.cell.bg); |
screen_write_clearscreen(sctx, gc->bg); |
break; |
break; |
case 6: /* DECOM */ |
case 6: /* DECOM */ |
screen_write_mode_clear(sctx, MODE_ORIGIN); |
screen_write_mode_clear(sctx, MODE_ORIGIN); |
|
|
break; |
break; |
case 47: |
case 47: |
case 1047: |
case 1047: |
window_pane_alternate_off(wp, &ictx->cell.cell, 0); |
if (wp != NULL) |
|
window_pane_alternate_off(wp, gc, 0); |
break; |
break; |
case 1049: |
case 1049: |
window_pane_alternate_off(wp, &ictx->cell.cell, 1); |
if (wp != NULL) |
|
window_pane_alternate_off(wp, gc, 1); |
break; |
break; |
case 2004: |
case 2004: |
screen_write_mode_clear(sctx, MODE_BRACKETPASTE); |
screen_write_mode_clear(sctx, MODE_BRACKETPASTE); |
|
|
{ |
{ |
struct screen_write_ctx *sctx = &ictx->ctx; |
struct screen_write_ctx *sctx = &ictx->ctx; |
struct window_pane *wp = ictx->wp; |
struct window_pane *wp = ictx->wp; |
|
struct grid_cell *gc = &ictx->cell.cell; |
u_int i; |
u_int i; |
|
|
for (i = 0; i < ictx->param_list_len; i++) { |
for (i = 0; i < ictx->param_list_len; i++) { |
|
|
if (sctx->s->mode & MODE_FOCUSON) |
if (sctx->s->mode & MODE_FOCUSON) |
break; |
break; |
screen_write_mode_set(sctx, MODE_FOCUSON); |
screen_write_mode_set(sctx, MODE_FOCUSON); |
wp->flags |= PANE_FOCUSPUSH; /* force update */ |
if (wp != NULL) |
|
wp->flags |= PANE_FOCUSPUSH; /* force update */ |
break; |
break; |
case 1005: |
case 1005: |
screen_write_mode_set(sctx, MODE_MOUSE_UTF8); |
screen_write_mode_set(sctx, MODE_MOUSE_UTF8); |
|
|
break; |
break; |
case 47: |
case 47: |
case 1047: |
case 1047: |
window_pane_alternate_on(wp, &ictx->cell.cell, 0); |
if (wp != NULL) |
|
window_pane_alternate_on(wp, gc, 0); |
break; |
break; |
case 1049: |
case 1049: |
window_pane_alternate_on(wp, &ictx->cell.cell, 1); |
if (wp != NULL) |
|
window_pane_alternate_on(wp, gc, 1); |
break; |
break; |
case 2004: |
case 2004: |
screen_write_mode_set(sctx, MODE_BRACKETPASTE); |
screen_write_mode_set(sctx, MODE_BRACKETPASTE); |
|
|
case 0: |
case 0: |
case 2: |
case 2: |
screen_pop_title(sctx->s); |
screen_pop_title(sctx->s); |
server_status_window(ictx->wp->window); |
if (wp != NULL) |
|
server_status_window(wp->window); |
break; |
break; |
} |
} |
break; |
break; |
case 18: |
case 18: |
input_reply(ictx, "\033[8;%u;%ut", wp->sy, wp->sx); |
if (wp != NULL) { |
|
input_reply(ictx, "\033[8;%u;%ut", wp->sy, |
|
wp->sx); |
|
} |
break; |
break; |
default: |
default: |
log_debug("%s: unknown '%c'", __func__, ictx->ch); |
log_debug("%s: unknown '%c'", __func__, ictx->ch); |
|
|
input_exit_osc(struct input_ctx *ictx) |
input_exit_osc(struct input_ctx *ictx) |
{ |
{ |
struct screen_write_ctx *sctx = &ictx->ctx; |
struct screen_write_ctx *sctx = &ictx->ctx; |
|
struct window_pane *wp = ictx->wp; |
u_char *p = ictx->input_buf; |
u_char *p = ictx->input_buf; |
u_int option; |
u_int option; |
|
|
|
|
switch (option) { |
switch (option) { |
case 0: |
case 0: |
case 2: |
case 2: |
if (screen_set_title(sctx->s, p)) |
if (screen_set_title(sctx->s, p) && wp != NULL) |
server_status_window(ictx->wp->window); |
server_status_window(ictx->wp->window); |
break; |
break; |
case 4: |
case 4: |
|
|
case 7: |
case 7: |
if (utf8_isvalid(p)) { |
if (utf8_isvalid(p)) { |
screen_set_path(sctx->s, p); |
screen_set_path(sctx->s, p); |
server_status_window(ictx->wp->window); |
if (wp != NULL) |
|
server_status_window(wp->window); |
} |
} |
break; |
break; |
case 10: |
case 10: |
|
|
input_exit_apc(struct input_ctx *ictx) |
input_exit_apc(struct input_ctx *ictx) |
{ |
{ |
struct screen_write_ctx *sctx = &ictx->ctx; |
struct screen_write_ctx *sctx = &ictx->ctx; |
|
struct window_pane *wp = ictx->wp; |
|
|
if (ictx->flags & INPUT_DISCARD) |
if (ictx->flags & INPUT_DISCARD) |
return; |
return; |
log_debug("%s: \"%s\"", __func__, ictx->input_buf); |
log_debug("%s: \"%s\"", __func__, ictx->input_buf); |
|
|
if (screen_set_title(sctx->s, ictx->input_buf)) |
if (screen_set_title(sctx->s, ictx->input_buf) && wp != NULL) |
server_status_window(ictx->wp->window); |
server_status_window(wp->window); |
} |
} |
|
|
/* Rename string started. */ |
/* Rename string started. */ |
|
|
struct window_pane *wp = ictx->wp; |
struct window_pane *wp = ictx->wp; |
struct options_entry *oe; |
struct options_entry *oe; |
|
|
|
if (wp == NULL) |
|
return; |
if (ictx->flags & INPUT_DISCARD) |
if (ictx->flags & INPUT_DISCARD) |
return; |
return; |
if (!options_get_number(ictx->wp->options, "allow-rename")) |
if (!options_get_number(ictx->wp->options, "allow-rename")) |
|
|
options_remove(oe); |
options_remove(oe); |
return; |
return; |
} |
} |
window_set_name(ictx->wp->window, ictx->input_buf); |
window_set_name(wp->window, ictx->input_buf); |
options_set_number(ictx->wp->window->options, "automatic-rename", 0); |
options_set_number(wp->window->options, "automatic-rename", 0); |
server_status_window(ictx->wp->window); |
server_status_window(wp->window); |
} |
} |
|
|
/* Open UTF-8 character. */ |
/* Open UTF-8 character. */ |
|
|
long idx; |
long idx; |
u_int r, g, b; |
u_int r, g, b; |
|
|
|
if (wp == NULL) |
|
return; |
|
|
copy = s = xstrdup(p); |
copy = s = xstrdup(p); |
while (s != NULL && *s != '\0') { |
while (s != NULL && *s != '\0') { |
idx = strtol(s, &next, 10); |
idx = strtol(s, &next, 10); |
|
|
u_int r, g, b; |
u_int r, g, b; |
char tmp[16]; |
char tmp[16]; |
|
|
|
if (wp == NULL) |
|
return; |
if (strcmp(p, "?") == 0) |
if (strcmp(p, "?") == 0) |
return; |
return; |
|
|
|
|
u_int r, g, b; |
u_int r, g, b; |
char tmp[16]; |
char tmp[16]; |
|
|
|
if (wp == NULL) |
|
return; |
if (strcmp(p, "?") == 0) |
if (strcmp(p, "?") == 0) |
return; |
return; |
|
|
|
|
struct screen_write_ctx ctx; |
struct screen_write_ctx ctx; |
struct paste_buffer *pb; |
struct paste_buffer *pb; |
|
|
|
if (wp == NULL) |
|
return; |
state = options_get_number(global_options, "set-clipboard"); |
state = options_get_number(global_options, "set-clipboard"); |
if (state != 2) |
if (state != 2) |
return; |
return; |
|
|
struct window_pane *wp = ictx->wp; |
struct window_pane *wp = ictx->wp; |
char *copy, *s; |
char *copy, *s; |
long idx; |
long idx; |
|
|
|
if (wp == NULL) |
|
return; |
|
|
if (*p == '\0') { |
if (*p == '\0') { |
window_pane_reset_palette(wp); |
window_pane_reset_palette(wp); |