From 9cc04a0f9a62c5f4d9e643538f0f866115d6b16d Mon Sep 17 00:00:00 2001 From: nicm Date: Fri, 8 Mar 2019 10:29:25 +0000 Subject: [PATCH 1/2] Do not use window mode entry after free. --- window-copy.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/window-copy.c b/window-copy.c index 9efc6a46..94c34980 100644 --- a/window-copy.c +++ b/window-copy.c @@ -997,11 +997,12 @@ window_copy_command(struct window_mode_entry *wme, struct client *c, data->searchx = data->searchy = -1; } + wme->prefix = 1; + if (cancel) window_pane_reset_mode(wp); else if (redraw) window_copy_redraw_screen(wme); - wme->prefix = 1; } static void From de730f68a4bc97e26f8f5dcb404ed27dc489c0fd Mon Sep 17 00:00:00 2001 From: nicm Date: Fri, 8 Mar 2019 10:34:20 +0000 Subject: [PATCH 2/2] Make the mode used to view command output (a variant of copy mode) use its own mode definition struct with a different init function rather than calling special setup functions. --- cfg.c | 5 ++- cmd-copy-mode.c | 3 +- cmd-queue.c | 17 +++++----- cmd-run-shell.c | 5 ++- tmux.h | 3 +- window-copy.c | 84 +++++++++++++++++++++++++++---------------------- 6 files changed, 66 insertions(+), 51 deletions(-) diff --git a/cfg.c b/cfg.c index 0842f638..fc7e345c 100644 --- a/cfg.c +++ b/cfg.c @@ -348,7 +348,10 @@ cfg_show_causes(struct session *s) return; wp = s->curw->window->active; - window_copy_init_for_output(wp); + if (wp->mode == NULL || wp->mode->mode != &window_view_mode) { + window_pane_reset_mode(wp); + window_pane_set_mode(wp, &window_view_mode, NULL, NULL); + } for (i = 0; i < cfg_ncauses; i++) { window_copy_add(wp, "%s", cfg_causes[i]); free(cfg_causes[i]); diff --git a/cmd-copy-mode.c b/cmd-copy-mode.c index 1668029c..d9471aab 100644 --- a/cmd-copy-mode.c +++ b/cmd-copy-mode.c @@ -75,10 +75,9 @@ cmd_copy_mode_exec(struct cmd *self, struct cmdq_item *item) } if (wp->mode == NULL || wp->mode->mode != &window_copy_mode) { - flag = window_pane_set_mode(wp, &window_copy_mode, NULL, NULL); + flag = window_pane_set_mode(wp, &window_copy_mode, NULL, args); if (flag != 0) return (CMD_RETURN_NORMAL); - window_copy_init_from_pane(wp, args_has(self->args, 'e')); } if (args_has(args, 'M')) { if (wp->mode != NULL && wp->mode->mode != &window_copy_mode) diff --git a/cmd-queue.c b/cmd-queue.c index ccb25c9a..2a95a3e5 100644 --- a/cmd-queue.c +++ b/cmd-queue.c @@ -404,10 +404,10 @@ cmdq_guard(struct cmdq_item *item, const char *guard, int flags) void cmdq_print(struct cmdq_item *item, const char *fmt, ...) { - struct client *c = item->client; - struct window *w; - va_list ap; - char *tmp, *msg; + struct client *c = item->client; + struct window_pane *wp; + va_list ap; + char *tmp, *msg; va_start(ap, fmt); @@ -425,9 +425,12 @@ cmdq_print(struct cmdq_item *item, const char *fmt, ...) evbuffer_add(c->stdout_data, "\n", 1); server_client_push_stdout(c); } else { - w = c->session->curw->window; - window_copy_init_for_output(w->active); - window_copy_vadd(w->active, fmt, ap); + wp = c->session->curw->window->active; + if (wp->mode == NULL || wp->mode->mode != &window_view_mode) { + window_pane_reset_mode(wp); + window_pane_set_mode(wp, &window_view_mode, NULL, NULL); + } + window_copy_vadd(wp, fmt, ap); } va_end(ap); diff --git a/cmd-run-shell.c b/cmd-run-shell.c index 998ffcd8..8e99f90b 100644 --- a/cmd-run-shell.c +++ b/cmd-run-shell.c @@ -75,7 +75,10 @@ cmd_run_shell_print(struct job *job, const char *msg) return; } - window_copy_init_for_output(wp); + if (wp->mode == NULL || wp->mode->mode != &window_view_mode) { + window_pane_reset_mode(wp); + window_pane_set_mode(wp, &window_view_mode, NULL, NULL); + } window_copy_add(wp, "%s", msg); } diff --git a/tmux.h b/tmux.h index 69935f17..1053ddcd 100644 --- a/tmux.h +++ b/tmux.h @@ -2310,8 +2310,7 @@ extern const struct window_mode window_client_mode; /* window-copy.c */ extern const struct window_mode window_copy_mode; -void window_copy_init_from_pane(struct window_pane *, int); -void window_copy_init_for_output(struct window_pane *); +extern const struct window_mode window_view_mode; void printflike(2, 3) window_copy_add(struct window_pane *, const char *, ...); void window_copy_vadd(struct window_pane *, const char *, va_list); void window_copy_pageup(struct window_pane *, int); diff --git a/window-copy.c b/window-copy.c index 94c34980..d7ce3e8a 100644 --- a/window-copy.c +++ b/window-copy.c @@ -30,6 +30,8 @@ static void window_copy_command(struct window_mode_entry *, struct client *, struct mouse_event *); static struct screen *window_copy_init(struct window_mode_entry *, struct cmd_find_state *, struct args *); +static struct screen *window_copy_view_init(struct window_mode_entry *, + struct cmd_find_state *, struct args *); static void window_copy_free(struct window_mode_entry *); static void window_copy_resize(struct window_mode_entry *, u_int, u_int); static void window_copy_formats(struct window_mode_entry *, @@ -125,6 +127,17 @@ const struct window_mode window_copy_mode = { .formats = window_copy_formats, }; +const struct window_mode window_view_mode = { + .name = "view-mode", + + .init = window_copy_view_init, + .free = window_copy_free, + .resize = window_copy_resize, + .key_table = window_copy_key_table, + .command = window_copy_command, + .formats = window_copy_formats, +}; + enum { WINDOW_COPY_OFF, WINDOW_COPY_SEARCHUP, @@ -203,13 +216,12 @@ struct window_copy_mode_data { char jumpchar; }; -static struct screen * -window_copy_init(struct window_mode_entry *wme, - __unused struct cmd_find_state *fs, __unused struct args *args) +static struct window_copy_mode_data * +window_copy_common_init(struct window_mode_entry *wme) { struct window_pane *wp = wme->wp; struct window_copy_mode_data *data; - struct screen *s; + struct screen *base = &wp->base; wme->data = data = xcalloc(1, sizeof *data); @@ -226,66 +238,62 @@ window_copy_init(struct window_mode_entry *wme, data->searchmark = NULL; data->searchx = data->searchy = data->searcho = -1; - if (wp->fd != -1) - bufferevent_disable(wp->event, EV_READ|EV_WRITE); - data->jumptype = WINDOW_COPY_OFF; data->jumpchar = '\0'; - s = &data->screen; - screen_init(s, screen_size_x(&wp->base), screen_size_y(&wp->base), 0); + screen_init(&data->screen, screen_size_x(base), screen_size_y(base), 0); data->modekeys = options_get_number(wp->window->options, "mode-keys"); - data->backing = NULL; - - return (s); + return (data); } -void -window_copy_init_from_pane(struct window_pane *wp, int scroll_exit) +static struct screen * +window_copy_init(struct window_mode_entry *wme, + __unused struct cmd_find_state *fs, struct args *args) { - struct window_mode_entry *wme = wp->mode; - struct window_copy_mode_data *data = wme->data; - struct screen *s = &data->screen; - struct screen_write_ctx ctx; + struct window_pane *wp = wme->wp; + struct window_copy_mode_data *data; + struct screen_write_ctx ctx; u_int i; - if (wme == NULL || wme->mode != &window_copy_mode) - fatalx("not in copy mode"); + data = window_copy_common_init(wme); + + if (wp->fd != -1) + bufferevent_disable(wp->event, EV_READ|EV_WRITE); data->backing = &wp->base; data->cx = data->backing->cx; data->cy = data->backing->cy; - data->scroll_exit = scroll_exit; - s->cx = data->cx; - s->cy = data->cy; + data->scroll_exit = args_has(args, 'e'); - screen_write_start(&ctx, NULL, s); - for (i = 0; i < screen_size_y(s); i++) + data->screen.cx = data->cx; + data->screen.cy = data->cy; + + screen_write_start(&ctx, NULL, &data->screen); + for (i = 0; i < screen_size_y(&data->screen); i++) window_copy_write_line(wme, &ctx, i); screen_write_cursormove(&ctx, data->cx, data->cy); screen_write_stop(&ctx); + + return (&data->screen); } -void -window_copy_init_for_output(struct window_pane *wp) +static struct screen * +window_copy_view_init(struct window_mode_entry *wme, + __unused struct cmd_find_state *fs, __unused struct args *args) { + struct window_pane *wp = wme->wp; struct window_copy_mode_data *data; + struct screen *base = &wp->base; + struct screen *s; - if (wp->mode != NULL && wp->mode->mode == &window_copy_mode) { - data = wp->mode->data; - if (data->backing != &wp->base) - return; - } - window_pane_reset_mode(wp); + data = window_copy_common_init(wme); - window_pane_set_mode(wp, &window_copy_mode, NULL, NULL); - data = wp->mode->data; + data->backing = s = xmalloc(sizeof *data->backing); + screen_init(s, screen_size_x(base), screen_size_y(base), UINT_MAX); - data->backing = xmalloc(sizeof *data->backing); - screen_init(data->backing, screen_size_x(&wp->base), - screen_size_y(&wp->base), UINT_MAX); + return (&data->screen); } static void