=================================================================== RCS file: /cvsrepo/anoncvs/cvs/src/usr.bin/tmux/input.c,v retrieving revision 1.170 retrieving revision 1.171 diff -u -r1.170 -r1.171 --- src/usr.bin/tmux/input.c 2020/02/03 13:46:27 1.170 +++ src/usr.bin/tmux/input.c 2020/03/19 14:03:48 1.171 @@ -1,4 +1,4 @@ -/* $OpenBSD: input.c,v 1.170 2020/02/03 13:46:27 nicm Exp $ */ +/* $OpenBSD: input.c,v 1.171 2020/03/19 14:03:48 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -128,7 +128,7 @@ 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 *); @@ -731,10 +731,9 @@ 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 +787,13 @@ } /* Initialise input parser. */ -void +struct input_ctx * input_init(struct window_pane *wp) { 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_buf = xmalloc(INPUT_BUF_START); @@ -804,15 +804,15 @@ 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 +825,18 @@ 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 +855,15 @@ /* 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 +871,15 @@ ictx->state->enter(ictx); } -/* Parse input. */ -void -input_parse(struct window_pane *wp) +/* Parse data. */ +static void +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; 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,17 +922,66 @@ /* 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); } +} - /* 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); } +/* 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). */ static int input_split(struct input_ctx *ictx) @@ -1043,14 +1058,18 @@ static void input_reply(struct input_ctx *ictx, const char *fmt, ...) { - va_list ap; - char *reply; + struct window_pane *wp = ictx->wp; + va_list ap; + char *reply; + if (wp == NULL) + return; + va_start(ap, fmt); xvasprintf(&reply, fmt, ap); va_end(ap); - bufferevent_write(ictx->wp->event, reply, strlen(reply)); + bufferevent_write(wp->event, reply, strlen(reply)); free(reply); } @@ -1177,7 +1196,8 @@ 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 +1244,7 @@ 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 +1261,8 @@ 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; @@ -1612,6 +1634,7 @@ { 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 +1646,7 @@ 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 +1678,12 @@ break; case 47: case 1047: - window_pane_alternate_off(wp, &ictx->cell.cell, 0); + if (wp != NULL) + window_pane_alternate_off(wp, gc, 0); break; case 1049: - window_pane_alternate_off(wp, &ictx->cell.cell, 1); + if (wp != NULL) + window_pane_alternate_off(wp, gc, 1); break; case 2004: screen_write_mode_clear(sctx, MODE_BRACKETPASTE); @@ -1700,6 +1725,7 @@ { 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 +1768,8 @@ 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 +1779,12 @@ break; case 47: case 1047: - window_pane_alternate_on(wp, &ictx->cell.cell, 0); + if (wp != NULL) + window_pane_alternate_on(wp, gc, 0); break; case 1049: - window_pane_alternate_on(wp, &ictx->cell.cell, 1); + if (wp != NULL) + window_pane_alternate_on(wp, gc, 1); break; case 2004: screen_write_mode_set(sctx, MODE_BRACKETPASTE); @@ -1823,12 +1852,16 @@ 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); + if (wp != NULL) { + input_reply(ictx, "\033[8;%u;%ut", wp->sy, + wp->sx); + } break; default: log_debug("%s: unknown '%c'", __func__, ictx->ch); @@ -2193,6 +2226,7 @@ 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 +2247,7 @@ 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 +2256,8 @@ 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 +2302,14 @@ 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 +2330,8 @@ 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 +2347,9 @@ 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 +2445,9 @@ 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 +2482,8 @@ u_int r, g, b; char tmp[16]; + if (wp == NULL) + return; if (strcmp(p, "?") == 0) return; @@ -2465,6 +2508,8 @@ u_int r, g, b; char tmp[16]; + if (wp == NULL) + return; if (strcmp(p, "?") == 0) return; @@ -2494,6 +2539,8 @@ 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; @@ -2554,6 +2601,9 @@ struct window_pane *wp = ictx->wp; char *copy, *s; long idx; + + if (wp == NULL) + return; if (*p == '\0') { window_pane_reset_palette(wp);