From 22a8afee9e8dcbe45a371ca72af0169b7c94eac5 Mon Sep 17 00:00:00 2001 From: nicm Date: Wed, 12 Oct 2016 09:07:58 +0000 Subject: [PATCH 1/7] Unused variable and missing time.h. --- paste.c | 2 +- window-copy.c | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/paste.c b/paste.c index 672927f4..d3a90a78 100644 --- a/paste.c +++ b/paste.c @@ -17,10 +17,10 @@ */ #include -#include #include #include +#include #include #include "tmux.h" diff --git a/window-copy.c b/window-copy.c index d282e25e..86c90134 100644 --- a/window-copy.c +++ b/window-copy.c @@ -1069,11 +1069,10 @@ window_copy_write_line(struct window_pane *wp, struct screen_write_ctx *ctx, struct options *oo = wp->window->options; struct grid_cell gc; char hdr[512]; - size_t last, xoff = 0, size = 0; + size_t xoff = 0, size = 0; style_apply(&gc, oo, "mode-style"); - last = screen_size_y(s) - 1; if (py == 0) { size = xsnprintf(hdr, sizeof hdr, "[%u/%u]", data->oy, screen_hsize(data->backing)); From 68bebe1fb7dfe5d152a2734c5bd572b1db641a4c Mon Sep 17 00:00:00 2001 From: nicm Date: Wed, 12 Oct 2016 13:03:27 +0000 Subject: [PATCH 2/7] The repeat prompt in both emacs and vi (and the old one in tmux) doesn't support line editing and instead executes a command as soon as a non-number key is pressed. Add a -N flag to command-prompt for the same in copy mode. Reported by Theo Buehler. --- cmd-command-prompt.c | 6 ++-- key-bindings.c | 38 ++++++++++----------- server-client.c | 7 ++-- status.c | 80 ++++++++++++++++++++++++++------------------ tmux.1 | 4 ++- tmux.h | 3 +- 6 files changed, 79 insertions(+), 59 deletions(-) diff --git a/cmd-command-prompt.c b/cmd-command-prompt.c index 09ab9813..12ecb493 100644 --- a/cmd-command-prompt.c +++ b/cmd-command-prompt.c @@ -38,8 +38,8 @@ const struct cmd_entry cmd_command_prompt_entry = { .name = "command-prompt", .alias = NULL, - .args = { "1I:p:t:", 0, 1 }, - .usage = "[-1] [-I inputs] [-p prompts] " CMD_TARGET_CLIENT_USAGE " " + .args = { "1I:Np:t:", 0, 1 }, + .usage = "[-1N] [-I inputs] [-p prompts] " CMD_TARGET_CLIENT_USAGE " " "[template]", .tflag = CMD_CLIENT, @@ -112,6 +112,8 @@ cmd_command_prompt_exec(struct cmd *self, struct cmd_q *cmdq) flags = 0; if (args_has(args, '1')) flags |= PROMPT_SINGLE; + else if (args_has(args, 'N')) + flags |= PROMPT_NUMERIC; status_prompt_set(c, prompt, input, cmd_command_prompt_callback, cmd_command_prompt_free, cdata, flags); free(prompt); diff --git a/key-bindings.c b/key-bindings.c index f6b17c3c..b464c199 100644 --- a/key-bindings.c +++ b/key-bindings.c @@ -271,15 +271,15 @@ key_bindings_init(void) "bind -Tcopy-mode Down send -X cursor-down", "bind -Tcopy-mode Left send -X cursor-left", "bind -Tcopy-mode Right send -X cursor-right", - "bind -Tcopy-mode M-1 command-prompt -p'repeat' -I1 \"send -N '%%'\"", - "bind -Tcopy-mode M-2 command-prompt -p'repeat' -I2 \"send -N '%%'\"", - "bind -Tcopy-mode M-3 command-prompt -p'repeat' -I3 \"send -N '%%'\"", - "bind -Tcopy-mode M-4 command-prompt -p'repeat' -I4 \"send -N '%%'\"", - "bind -Tcopy-mode M-5 command-prompt -p'repeat' -I5 \"send -N '%%'\"", - "bind -Tcopy-mode M-6 command-prompt -p'repeat' -I6 \"send -N '%%'\"", - "bind -Tcopy-mode M-7 command-prompt -p'repeat' -I7 \"send -N '%%'\"", - "bind -Tcopy-mode M-8 command-prompt -p'repeat' -I8 \"send -N '%%'\"", - "bind -Tcopy-mode M-9 command-prompt -p'repeat' -I9 \"send -N '%%'\"", + "bind -Tcopy-mode M-1 command-prompt -Np'repeat' -I1 \"send -N '%%'\"", + "bind -Tcopy-mode M-2 command-prompt -Np'repeat' -I2 \"send -N '%%'\"", + "bind -Tcopy-mode M-3 command-prompt -Np'repeat' -I3 \"send -N '%%'\"", + "bind -Tcopy-mode M-4 command-prompt -Np'repeat' -I4 \"send -N '%%'\"", + "bind -Tcopy-mode M-5 command-prompt -Np'repeat' -I5 \"send -N '%%'\"", + "bind -Tcopy-mode M-6 command-prompt -Np'repeat' -I6 \"send -N '%%'\"", + "bind -Tcopy-mode M-7 command-prompt -Np'repeat' -I7 \"send -N '%%'\"", + "bind -Tcopy-mode M-8 command-prompt -Np'repeat' -I8 \"send -N '%%'\"", + "bind -Tcopy-mode M-9 command-prompt -Np'repeat' -I9 \"send -N '%%'\"", "bind -Tcopy-mode M-< send -X history-top", "bind -Tcopy-mode M-> send -X history-bottom", "bind -Tcopy-mode M-R send -X top-line", @@ -313,17 +313,17 @@ key_bindings_init(void) "bind -Tcopy-mode-vi , send -X jump-reverse", "bind -Tcopy-mode-vi / command-prompt -p'search down' \"send -X search-forward '%%'\"", "bind -Tcopy-mode-vi 0 send -X start-of-line", - "bind -Tcopy-mode-vi 1 command-prompt -p'repeat' -I1 \"send -N '%%'\"", - "bind -Tcopy-mode-vi 2 command-prompt -p'repeat' -I2 \"send -N '%%'\"", - "bind -Tcopy-mode-vi 3 command-prompt -p'repeat' -I3 \"send -N '%%'\"", - "bind -Tcopy-mode-vi 4 command-prompt -p'repeat' -I4 \"send -N '%%'\"", - "bind -Tcopy-mode-vi 5 command-prompt -p'repeat' -I5 \"send -N '%%'\"", - "bind -Tcopy-mode-vi 6 command-prompt -p'repeat' -I6 \"send -N '%%'\"", - "bind -Tcopy-mode-vi 7 command-prompt -p'repeat' -I7 \"send -N '%%'\"", - "bind -Tcopy-mode-vi 8 command-prompt -p'repeat' -I8 \"send -N '%%'\"", - "bind -Tcopy-mode-vi 9 command-prompt -p'repeat' -I9 \"send -N '%%'\"", + "bind -Tcopy-mode-vi 1 command-prompt -Np'repeat' -I1 \"send -N '%%'\"", + "bind -Tcopy-mode-vi 2 command-prompt -Np'repeat' -I2 \"send -N '%%'\"", + "bind -Tcopy-mode-vi 3 command-prompt -Np'repeat' -I3 \"send -N '%%'\"", + "bind -Tcopy-mode-vi 4 command-prompt -Np'repeat' -I4 \"send -N '%%'\"", + "bind -Tcopy-mode-vi 5 command-prompt -Np'repeat' -I5 \"send -N '%%'\"", + "bind -Tcopy-mode-vi 6 command-prompt -Np'repeat' -I6 \"send -N '%%'\"", + "bind -Tcopy-mode-vi 7 command-prompt -Np'repeat' -I7 \"send -N '%%'\"", + "bind -Tcopy-mode-vi 8 command-prompt -Np'repeat' -I8 \"send -N '%%'\"", + "bind -Tcopy-mode-vi 9 command-prompt -Np'repeat' -I9 \"send -N '%%'\"", "bind -Tcopy-mode-vi : command-prompt -p'goto line' \"send -X goto-line '%%'\"", - "bind -Tcopy-mode-vi \\; send -X jump-again" + "bind -Tcopy-mode-vi \\; send -X jump-again", "bind -Tcopy-mode-vi ? command-prompt -p'search up' \"send -X search-backward '%%'\"", "bind -Tcopy-mode-vi A send -X append-selection-and-cancel", "bind -Tcopy-mode-vi B send -X previous-space", diff --git a/server-client.c b/server-client.c index d5c0cf23..7e4d1ee4 100644 --- a/server-client.c +++ b/server-client.c @@ -727,9 +727,10 @@ server_client_handle_key(struct client *c, key_code key) server_clear_identify(c, NULL); } if (c->prompt_string != NULL) { - if (!(c->flags & CLIENT_READONLY)) - status_prompt_key(c, key); - return; + if (c->flags & CLIENT_READONLY) + return; + if (status_prompt_key(c, key) == 0) + return; } /* Check for mouse keys. */ diff --git a/status.c b/status.c index 6ea8c6c3..dc88efe5 100644 --- a/status.c +++ b/status.c @@ -855,7 +855,7 @@ status_prompt_space(const struct utf8_data *ud) } /* Handle keys in prompt. */ -void +int status_prompt_key(struct client *c, key_code key) { struct options *oo = c->session->options; @@ -867,6 +867,17 @@ status_prompt_key(struct client *c, key_code key) struct utf8_data tmp, *first, *last, *ud; size = utf8_strlen(c->prompt_buffer); + + if (c->prompt_flags & PROMPT_NUMERIC) { + if (key >= '0' && key <= '9') + goto append_key; + s = utf8_tocstr(c->prompt_buffer); + c->prompt_callbackfn(c->prompt_data, s); + status_prompt_clear(c); + free(s); + return (1); + } + switch (mode_key_lookup(&c->prompt_mdata, key)) { case MODEKEYEDIT_CURSORLEFT: if (c->prompt_index > 0) { @@ -1185,41 +1196,44 @@ status_prompt_key(struct client *c, key_code key) status_prompt_clear(c); break; case MODEKEY_OTHER: - if (key <= 0x1f || key >= KEYC_BASE) - break; - if (utf8_split(key, &tmp) != UTF8_DONE) - break; - - c->prompt_buffer = xreallocarray(c->prompt_buffer, size + 2, - sizeof *c->prompt_buffer); - - if (c->prompt_index == size) { - utf8_copy(&c->prompt_buffer[c->prompt_index], &tmp); - c->prompt_index++; - c->prompt_buffer[c->prompt_index].size = 0; - } else { - memmove(c->prompt_buffer + c->prompt_index + 1, - c->prompt_buffer + c->prompt_index, - (size + 1 - c->prompt_index) * - sizeof *c->prompt_buffer); - utf8_copy(&c->prompt_buffer[c->prompt_index], &tmp); - c->prompt_index++; - } - - if (c->prompt_flags & PROMPT_SINGLE) { - s = utf8_tocstr(c->prompt_buffer); - if (strlen(s) != 1) - status_prompt_clear(c); - else if (c->prompt_callbackfn(c->prompt_data, s) == 0) - status_prompt_clear(c); - free(s); - } - - c->flags |= CLIENT_STATUS; break; default: - break; + return (0); } + +append_key: + if (key <= 0x1f || key >= KEYC_BASE) + return (0); + if (utf8_split(key, &tmp) != UTF8_DONE) + return (0); + + c->prompt_buffer = xreallocarray(c->prompt_buffer, size + 2, + sizeof *c->prompt_buffer); + + if (c->prompt_index == size) { + utf8_copy(&c->prompt_buffer[c->prompt_index], &tmp); + c->prompt_index++; + c->prompt_buffer[c->prompt_index].size = 0; + } else { + memmove(c->prompt_buffer + c->prompt_index + 1, + c->prompt_buffer + c->prompt_index, + (size + 1 - c->prompt_index) * + sizeof *c->prompt_buffer); + utf8_copy(&c->prompt_buffer[c->prompt_index], &tmp); + c->prompt_index++; + } + + if (c->prompt_flags & PROMPT_SINGLE) { + s = utf8_tocstr(c->prompt_buffer); + if (strlen(s) != 1) + status_prompt_clear(c); + else if (c->prompt_callbackfn(c->prompt_data, s) == 0) + status_prompt_clear(c); + free(s); + } + + c->flags |= CLIENT_STATUS; + return (0); } /* Get previous line from the history. */ diff --git a/tmux.1 b/tmux.1 index f375a215..4cf403e7 100644 --- a/tmux.1 +++ b/tmux.1 @@ -3748,7 +3748,7 @@ session option. Commands related to the status line are as follows: .Bl -tag -width Ds .It Xo Ic command-prompt -.Op Fl 1 +.Op Fl 1N .Op Fl I Ar inputs .Op Fl p Ar prompts .Op Fl t Ar target-client @@ -3802,6 +3802,8 @@ to .Fl 1 makes the prompt only accept one key press, in this case the resulting input is a single character. +.Fl N +accepts only numbers and exit the prompt on any other key press. .It Xo Ic confirm-before .Op Fl p Ar prompt .Op Fl t Ar target-client diff --git a/tmux.h b/tmux.h index b5fd8714..64393edd 100644 --- a/tmux.h +++ b/tmux.h @@ -1269,6 +1269,7 @@ struct client { u_int prompt_hindex; #define PROMPT_SINGLE 0x1 +#define PROMPT_NUMERIC 0x2 int prompt_flags; struct mode_key_data prompt_mdata; @@ -1920,7 +1921,7 @@ void status_prompt_set(struct client *, const char *, const char *, int (*)(void *, const char *), void (*)(void *), void *, int); void status_prompt_clear(struct client *); int status_prompt_redraw(struct client *); -void status_prompt_key(struct client *, key_code); +int status_prompt_key(struct client *, key_code); void status_prompt_update(struct client *, const char *, const char *); void status_prompt_load_history(void); void status_prompt_save_history(void); From 4160df4ca4035c8caafce7650d0fcbcccc391f80 Mon Sep 17 00:00:00 2001 From: nicm Date: Wed, 12 Oct 2016 13:24:07 +0000 Subject: [PATCH 3/7] Redraw selection in tty_draw_line, so it appears when redrawing whole pane. Reported by Theo Buehler. --- screen-write.c | 6 +----- screen.c | 16 ++++++++++++++++ tmux.h | 2 ++ tty.c | 8 ++++++-- 4 files changed, 25 insertions(+), 7 deletions(-) diff --git a/screen-write.c b/screen-write.c index 3a1fc8c8..1767d9bb 100644 --- a/screen-write.c +++ b/screen-write.c @@ -1141,12 +1141,8 @@ screen_write_cell(struct screen_write_ctx *ctx, const struct grid_cell *gc) /* Write to the screen. */ if (selected) { - memcpy(&tmp_gc, &s->sel.cell, sizeof tmp_gc); - utf8_copy(&tmp_gc.data, &gc->data); - tmp_gc.attr = tmp_gc.attr & ~GRID_ATTR_CHARSET; - tmp_gc.attr |= gc->attr & GRID_ATTR_CHARSET; - tmp_gc.flags = gc->flags; screen_write_flush(ctx); + screen_select_cell(s, &tmp_gc, gc); ttyctx.cell = &tmp_gc; tty_write(tty_cmd_cell, &ttyctx); ctx->written++; diff --git a/screen.c b/screen.c index 7bde6f9b..3d6b8cdc 100644 --- a/screen.c +++ b/screen.c @@ -371,6 +371,22 @@ screen_check_selection(struct screen *s, u_int px, u_int py) return (1); } +/* Get selected grid cell. */ +void +screen_select_cell(struct screen *s, struct grid_cell *dst, + const struct grid_cell *src) +{ + if (!s->sel.flag) + return; + + memcpy(dst, &s->sel.cell, sizeof *dst); + + utf8_copy(&dst->data, &src->data); + dst->attr = dst->attr & ~GRID_ATTR_CHARSET; + dst->attr |= src->attr & GRID_ATTR_CHARSET; + dst->flags = src->flags; +} + /* Reflow wrapped lines. */ static void screen_reflow(struct screen *s, u_int new_x) diff --git a/tmux.h b/tmux.h index 64393edd..dc5e8712 100644 --- a/tmux.h +++ b/tmux.h @@ -2060,6 +2060,8 @@ void screen_set_selection(struct screen *, u_int, u_int, u_int, u_int, u_int, struct grid_cell *); void screen_clear_selection(struct screen *); int screen_check_selection(struct screen *, u_int, u_int); +void screen_select_cell(struct screen *, struct grid_cell *, + const struct grid_cell *); /* window.c */ extern struct windows windows; diff --git a/tty.c b/tty.c index d8702a2f..c4adfe82 100644 --- a/tty.c +++ b/tty.c @@ -658,7 +658,7 @@ void tty_draw_line(struct tty *tty, const struct window_pane *wp, struct screen *s, u_int py, u_int ox, u_int oy) { - struct grid_cell gc; + struct grid_cell gc, tmp_gc; struct grid_line *gl; u_int i, sx; int flags; @@ -687,7 +687,11 @@ tty_draw_line(struct tty *tty, const struct window_pane *wp, for (i = 0; i < sx; i++) { grid_view_get_cell(s->grid, i, py, &gc); - tty_cell(tty, &gc, wp); + if (gc.flags & GRID_FLAG_SELECTED) { + screen_select_cell(s, &tmp_gc, &gc); + tty_cell(tty, &tmp_gc, wp); + } else + tty_cell(tty, &gc, wp); } if (sx < tty->sx) { From c484c5a2a1b6c8261564b2959866e2cfa061ca99 Mon Sep 17 00:00:00 2001 From: nicm Date: Wed, 12 Oct 2016 14:50:14 +0000 Subject: [PATCH 4/7] Drop the edit mode key tables and just use fixed key bindings for the command prompt. --- cmd-bind-key.c | 2 - cmd-list-keys.c | 24 +--- cmd-unbind-key.c | 5 +- mode-key.c | 339 ++++++++++++----------------------------------- status.c | 247 +++++++++++++++++++++++----------- tmux.1 | 47 ++++--- tmux.h | 37 +----- 7 files changed, 292 insertions(+), 409 deletions(-) diff --git a/cmd-bind-key.c b/cmd-bind-key.c index 69314788..b87d5245 100644 --- a/cmd-bind-key.c +++ b/cmd-bind-key.c @@ -120,11 +120,9 @@ cmd_bind_key_mode_table(struct cmd *self, struct cmd_q *cmdq, key_code key) } mtmp.key = key; - mtmp.mode = !!args_has(args, 'c'); if ((mbind = RB_FIND(mode_key_tree, mtab->tree, &mtmp)) == NULL) { mbind = xmalloc(sizeof *mbind); mbind->key = mtmp.key; - mbind->mode = mtmp.mode; RB_INSERT(mode_key_tree, mtab->tree, mbind); } mbind->cmd = cmd; diff --git a/cmd-list-keys.c b/cmd-list-keys.c index 85cb4744..e58a90f2 100644 --- a/cmd-list-keys.c +++ b/cmd-list-keys.c @@ -135,10 +135,10 @@ static enum cmd_retval cmd_list_keys_table(struct cmd *self, struct cmd_q *cmdq) { struct args *args = self->args; - const char *tablename, *key, *cmdstr, *mode; + const char *tablename, *cmdstr; const struct mode_key_table *mtab; struct mode_key_binding *mbind; - int width, keywidth, any_mode; + int width, keywidth; tablename = args_get(args, 't'); if ((mtab = mode_key_findtable(tablename)) == NULL) { @@ -147,30 +147,18 @@ cmd_list_keys_table(struct cmd *self, struct cmd_q *cmdq) } keywidth = 0; - any_mode = 0; RB_FOREACH(mbind, mode_key_tree, mtab->tree) { - key = key_string_lookup_key(mbind->key); - - if (mbind->mode != 0) - any_mode = 1; - - width = strlen(key); + width = strlen(key_string_lookup_key(mbind->key)); if (width > keywidth) keywidth = width; } RB_FOREACH(mbind, mode_key_tree, mtab->tree) { - key = key_string_lookup_key(mbind->key); - - mode = ""; - if (mbind->mode != 0) - mode = "c"; cmdstr = mode_key_tostring(mtab->cmdstr, mbind->cmd); if (cmdstr != NULL) { - cmdq_print(cmdq, "bind-key -%st %s%s %*s %s", - mode, any_mode && *mode == '\0' ? " " : "", - mtab->name, - (int)keywidth, key, cmdstr); + cmdq_print(cmdq, "bind-key -t %s %*s %s", + mtab->name, (int)keywidth, + key_string_lookup_key(mbind->key), cmdstr); } } diff --git a/cmd-unbind-key.c b/cmd-unbind-key.c index 00c7779b..644a4c3a 100644 --- a/cmd-unbind-key.c +++ b/cmd-unbind-key.c @@ -34,8 +34,8 @@ const struct cmd_entry cmd_unbind_key_entry = { .name = "unbind-key", .alias = "unbind", - .args = { "acnt:T:", 0, 1 }, - .usage = "[-acn] [-t mode-table] [-T key-table] key", + .args = { "ant:T:", 0, 1 }, + .usage = "[-an] [-t mode-table] [-T key-table] key", .flags = 0, .exec = cmd_unbind_key_exec @@ -122,7 +122,6 @@ cmd_unbind_key_mode_table(struct cmd *self, struct cmd_q *cmdq, key_code key) } mtmp.key = key; - mtmp.mode = !!args_has(args, 'c'); if ((mbind = RB_FIND(mode_key_tree, mtab->tree, &mtmp)) != NULL) { RB_REMOVE(mode_key_tree, mtab->tree, mbind); free(mbind); diff --git a/mode-key.c b/mode-key.c index 32333957..4245d173 100644 --- a/mode-key.c +++ b/mode-key.c @@ -47,52 +47,9 @@ struct mode_key_cmdstr { /* Entry in the default mode key tables. */ struct mode_key_entry { key_code key; - - /* - * Editing mode for vi: 0 is edit mode, keys not in the table are - * returned as MODEKEY_OTHER; 1 is command mode, keys not in the table - * are returned as MODEKEY_NONE. This is also matched on, allowing some - * keys to be bound in edit mode. - */ - int mode; enum mode_key_cmd cmd; }; -/* Edit keys command strings. */ -static const struct mode_key_cmdstr mode_key_cmdstr_edit[] = { - { MODEKEYEDIT_BACKSPACE, "backspace" }, - { MODEKEYEDIT_CANCEL, "cancel" }, - { MODEKEYEDIT_COMPLETE, "complete" }, - { MODEKEYEDIT_CURSORLEFT, "cursor-left" }, - { MODEKEYEDIT_CURSORRIGHT, "cursor-right" }, - { MODEKEYEDIT_DELETE, "delete" }, - { MODEKEYEDIT_DELETELINE, "delete-line" }, - { MODEKEYEDIT_DELETETOENDOFLINE, "delete-end-of-line" }, - { MODEKEYEDIT_DELETEWORD, "delete-word" }, - { MODEKEYEDIT_ENDOFLINE, "end-of-line" }, - { MODEKEYEDIT_ENTER, "enter" }, - { MODEKEYEDIT_HISTORYDOWN, "history-down" }, - { MODEKEYEDIT_HISTORYUP, "history-up" }, - { MODEKEYEDIT_NEXTSPACE, "next-space" }, - { MODEKEYEDIT_NEXTSPACEEND, "next-space-end" }, - { MODEKEYEDIT_NEXTWORD, "next-word" }, - { MODEKEYEDIT_NEXTWORDEND, "next-word-end" }, - { MODEKEYEDIT_PASTE, "paste" }, - { MODEKEYEDIT_PREVIOUSSPACE, "previous-space" }, - { MODEKEYEDIT_PREVIOUSWORD, "previous-word" }, - { MODEKEYEDIT_STARTOFLINE, "start-of-line" }, - { MODEKEYEDIT_SWITCHMODE, "switch-mode" }, - { MODEKEYEDIT_SWITCHMODEAPPEND, "switch-mode-append" }, - { MODEKEYEDIT_SWITCHMODEAPPENDLINE, "switch-mode-append-line" }, - { MODEKEYEDIT_SWITCHMODEBEGINLINE, "switch-mode-begin-line" }, - { MODEKEYEDIT_SWITCHMODECHANGELINE, "switch-mode-change-line" }, - { MODEKEYEDIT_SWITCHMODESUBSTITUTE, "switch-mode-substitute" }, - { MODEKEYEDIT_SWITCHMODESUBSTITUTELINE, "switch-mode-substitute-line" }, - { MODEKEYEDIT_TRANSPOSECHARS, "transpose-chars" }, - - { 0, NULL } -}; - /* Choice keys command strings. */ static const struct mode_key_cmdstr mode_key_cmdstr_choice[] = { { MODEKEYCHOICE_BACKSPACE, "backspace" }, @@ -118,205 +75,106 @@ static const struct mode_key_cmdstr mode_key_cmdstr_choice[] = { { 0, NULL } }; -/* vi editing keys. */ -static const struct mode_key_entry mode_key_vi_edit[] = { - { '\003' /* C-c */, 0, MODEKEYEDIT_CANCEL }, - { '\010' /* C-h */, 0, MODEKEYEDIT_BACKSPACE }, - { '\011' /* Tab */, 0, MODEKEYEDIT_COMPLETE }, - { '\025' /* C-u */, 0, MODEKEYEDIT_DELETELINE }, - { '\027' /* C-w */, 0, MODEKEYEDIT_DELETEWORD }, - { '\033' /* Escape */, 0, MODEKEYEDIT_SWITCHMODE }, - { '\n', 0, MODEKEYEDIT_ENTER }, - { '\r', 0, MODEKEYEDIT_ENTER }, - { KEYC_BSPACE, 0, MODEKEYEDIT_BACKSPACE }, - { KEYC_DC, 0, MODEKEYEDIT_DELETE }, - { KEYC_DOWN, 0, MODEKEYEDIT_HISTORYDOWN }, - { KEYC_LEFT, 0, MODEKEYEDIT_CURSORLEFT }, - { KEYC_RIGHT, 0, MODEKEYEDIT_CURSORRIGHT }, - { KEYC_UP, 0, MODEKEYEDIT_HISTORYUP }, - { KEYC_HOME, 0, MODEKEYEDIT_STARTOFLINE }, - { KEYC_END, 0, MODEKEYEDIT_ENDOFLINE }, - - { '$', 1, MODEKEYEDIT_ENDOFLINE }, - { '0', 1, MODEKEYEDIT_STARTOFLINE }, - { 'A', 1, MODEKEYEDIT_SWITCHMODEAPPENDLINE }, - { 'B', 1, MODEKEYEDIT_PREVIOUSSPACE }, - { 'C', 1, MODEKEYEDIT_SWITCHMODECHANGELINE }, - { 'D', 1, MODEKEYEDIT_DELETETOENDOFLINE }, - { 'E', 1, MODEKEYEDIT_NEXTSPACEEND }, - { 'I', 1, MODEKEYEDIT_SWITCHMODEBEGINLINE }, - { 'S', 1, MODEKEYEDIT_SWITCHMODESUBSTITUTELINE }, - { 'W', 1, MODEKEYEDIT_NEXTSPACE }, - { 'X', 1, MODEKEYEDIT_BACKSPACE }, - { '\003' /* C-c */, 1, MODEKEYEDIT_CANCEL }, - { '\010' /* C-h */, 1, MODEKEYEDIT_BACKSPACE }, - { '\n', 1, MODEKEYEDIT_ENTER }, - { '\r', 1, MODEKEYEDIT_ENTER }, - { '^', 1, MODEKEYEDIT_STARTOFLINE }, - { 'a', 1, MODEKEYEDIT_SWITCHMODEAPPEND }, - { 'b', 1, MODEKEYEDIT_PREVIOUSWORD }, - { 'd', 1, MODEKEYEDIT_DELETELINE }, - { 'e', 1, MODEKEYEDIT_NEXTWORDEND }, - { 'h', 1, MODEKEYEDIT_CURSORLEFT }, - { 'i', 1, MODEKEYEDIT_SWITCHMODE }, - { 'j', 1, MODEKEYEDIT_HISTORYDOWN }, - { 'k', 1, MODEKEYEDIT_HISTORYUP }, - { 'l', 1, MODEKEYEDIT_CURSORRIGHT }, - { 'p', 1, MODEKEYEDIT_PASTE }, - { 's', 1, MODEKEYEDIT_SWITCHMODESUBSTITUTE }, - { 'w', 1, MODEKEYEDIT_NEXTWORD }, - { 'x', 1, MODEKEYEDIT_DELETE }, - { KEYC_BSPACE, 1, MODEKEYEDIT_BACKSPACE }, - { KEYC_DC, 1, MODEKEYEDIT_DELETE }, - { KEYC_DOWN, 1, MODEKEYEDIT_HISTORYDOWN }, - { KEYC_LEFT, 1, MODEKEYEDIT_CURSORLEFT }, - { KEYC_RIGHT, 1, MODEKEYEDIT_CURSORRIGHT }, - { KEYC_UP, 1, MODEKEYEDIT_HISTORYUP }, - - { 0, -1, 0 } -}; -struct mode_key_tree mode_key_tree_vi_edit; - /* vi choice selection keys. */ static const struct mode_key_entry mode_key_vi_choice[] = { - { '0' | KEYC_ESCAPE, 0, MODEKEYCHOICE_STARTNUMBERPREFIX }, - { '1' | KEYC_ESCAPE, 0, MODEKEYCHOICE_STARTNUMBERPREFIX }, - { '2' | KEYC_ESCAPE, 0, MODEKEYCHOICE_STARTNUMBERPREFIX }, - { '3' | KEYC_ESCAPE, 0, MODEKEYCHOICE_STARTNUMBERPREFIX }, - { '4' | KEYC_ESCAPE, 0, MODEKEYCHOICE_STARTNUMBERPREFIX }, - { '5' | KEYC_ESCAPE, 0, MODEKEYCHOICE_STARTNUMBERPREFIX }, - { '6' | KEYC_ESCAPE, 0, MODEKEYCHOICE_STARTNUMBERPREFIX }, - { '7' | KEYC_ESCAPE, 0, MODEKEYCHOICE_STARTNUMBERPREFIX }, - { '8' | KEYC_ESCAPE, 0, MODEKEYCHOICE_STARTNUMBERPREFIX }, - { '9' | KEYC_ESCAPE, 0, MODEKEYCHOICE_STARTNUMBERPREFIX }, - { '\002' /* C-b */, 0, MODEKEYCHOICE_PAGEUP }, - { '\003' /* C-c */, 0, MODEKEYCHOICE_CANCEL }, - { '\005' /* C-e */, 0, MODEKEYCHOICE_SCROLLDOWN }, - { '\006' /* C-f */, 0, MODEKEYCHOICE_PAGEDOWN }, - { '\031' /* C-y */, 0, MODEKEYCHOICE_SCROLLUP }, - { '\n', 0, MODEKEYCHOICE_CHOOSE }, - { '\r', 0, MODEKEYCHOICE_CHOOSE }, - { 'j', 0, MODEKEYCHOICE_DOWN }, - { 'k', 0, MODEKEYCHOICE_UP }, - { 'q', 0, MODEKEYCHOICE_CANCEL }, - { KEYC_HOME, 0, MODEKEYCHOICE_STARTOFLIST }, - { 'g', 0, MODEKEYCHOICE_STARTOFLIST }, - { 'H', 0, MODEKEYCHOICE_TOPLINE }, - { 'L', 0, MODEKEYCHOICE_BOTTOMLINE }, - { 'G', 0, MODEKEYCHOICE_ENDOFLIST }, - { KEYC_END, 0, MODEKEYCHOICE_ENDOFLIST }, - { KEYC_BSPACE, 0, MODEKEYCHOICE_BACKSPACE }, - { KEYC_DOWN | KEYC_CTRL, 0, MODEKEYCHOICE_SCROLLDOWN }, - { KEYC_DOWN, 0, MODEKEYCHOICE_DOWN }, - { KEYC_NPAGE, 0, MODEKEYCHOICE_PAGEDOWN }, - { KEYC_PPAGE, 0, MODEKEYCHOICE_PAGEUP }, - { KEYC_UP | KEYC_CTRL, 0, MODEKEYCHOICE_SCROLLUP }, - { KEYC_UP, 0, MODEKEYCHOICE_UP }, - { ' ', 0, MODEKEYCHOICE_TREE_TOGGLE }, - { KEYC_LEFT, 0, MODEKEYCHOICE_TREE_COLLAPSE }, - { KEYC_RIGHT, 0, MODEKEYCHOICE_TREE_EXPAND }, - { KEYC_LEFT | KEYC_CTRL, 0, MODEKEYCHOICE_TREE_COLLAPSE_ALL }, - { KEYC_RIGHT | KEYC_CTRL, 0, MODEKEYCHOICE_TREE_EXPAND_ALL }, - { KEYC_MOUSEDOWN1_PANE, 0, MODEKEYCHOICE_CHOOSE }, - { KEYC_MOUSEDOWN3_PANE, 0, MODEKEYCHOICE_TREE_TOGGLE }, - { KEYC_WHEELUP_PANE, 0, MODEKEYCHOICE_UP }, - { KEYC_WHEELDOWN_PANE, 0, MODEKEYCHOICE_DOWN }, + { '0' | KEYC_ESCAPE, MODEKEYCHOICE_STARTNUMBERPREFIX }, + { '1' | KEYC_ESCAPE, MODEKEYCHOICE_STARTNUMBERPREFIX }, + { '2' | KEYC_ESCAPE, MODEKEYCHOICE_STARTNUMBERPREFIX }, + { '3' | KEYC_ESCAPE, MODEKEYCHOICE_STARTNUMBERPREFIX }, + { '4' | KEYC_ESCAPE, MODEKEYCHOICE_STARTNUMBERPREFIX }, + { '5' | KEYC_ESCAPE, MODEKEYCHOICE_STARTNUMBERPREFIX }, + { '6' | KEYC_ESCAPE, MODEKEYCHOICE_STARTNUMBERPREFIX }, + { '7' | KEYC_ESCAPE, MODEKEYCHOICE_STARTNUMBERPREFIX }, + { '8' | KEYC_ESCAPE, MODEKEYCHOICE_STARTNUMBERPREFIX }, + { '9' | KEYC_ESCAPE, MODEKEYCHOICE_STARTNUMBERPREFIX }, + { '\002' /* C-b */, MODEKEYCHOICE_PAGEUP }, + { '\003' /* C-c */, MODEKEYCHOICE_CANCEL }, + { '\005' /* C-e */, MODEKEYCHOICE_SCROLLDOWN }, + { '\006' /* C-f */, MODEKEYCHOICE_PAGEDOWN }, + { '\031' /* C-y */, MODEKEYCHOICE_SCROLLUP }, + { '\n', MODEKEYCHOICE_CHOOSE }, + { '\r', MODEKEYCHOICE_CHOOSE }, + { 'j', MODEKEYCHOICE_DOWN }, + { 'k', MODEKEYCHOICE_UP }, + { 'q', MODEKEYCHOICE_CANCEL }, + { KEYC_HOME, MODEKEYCHOICE_STARTOFLIST }, + { 'g', MODEKEYCHOICE_STARTOFLIST }, + { 'H', MODEKEYCHOICE_TOPLINE }, + { 'L', MODEKEYCHOICE_BOTTOMLINE }, + { 'G', MODEKEYCHOICE_ENDOFLIST }, + { KEYC_END, MODEKEYCHOICE_ENDOFLIST }, + { KEYC_BSPACE, MODEKEYCHOICE_BACKSPACE }, + { KEYC_DOWN | KEYC_CTRL, MODEKEYCHOICE_SCROLLDOWN }, + { KEYC_DOWN, MODEKEYCHOICE_DOWN }, + { KEYC_NPAGE, MODEKEYCHOICE_PAGEDOWN }, + { KEYC_PPAGE, MODEKEYCHOICE_PAGEUP }, + { KEYC_UP | KEYC_CTRL, MODEKEYCHOICE_SCROLLUP }, + { KEYC_UP, MODEKEYCHOICE_UP }, + { ' ', MODEKEYCHOICE_TREE_TOGGLE }, + { KEYC_LEFT, MODEKEYCHOICE_TREE_COLLAPSE }, + { KEYC_RIGHT, MODEKEYCHOICE_TREE_EXPAND }, + { KEYC_LEFT | KEYC_CTRL, MODEKEYCHOICE_TREE_COLLAPSE_ALL }, + { KEYC_RIGHT | KEYC_CTRL, MODEKEYCHOICE_TREE_EXPAND_ALL }, + { KEYC_MOUSEDOWN1_PANE, MODEKEYCHOICE_CHOOSE }, + { KEYC_MOUSEDOWN3_PANE, MODEKEYCHOICE_TREE_TOGGLE }, + { KEYC_WHEELUP_PANE, MODEKEYCHOICE_UP }, + { KEYC_WHEELDOWN_PANE, MODEKEYCHOICE_DOWN }, - { 0, -1, 0 } + { KEYC_NONE, -1 } }; struct mode_key_tree mode_key_tree_vi_choice; -/* emacs editing keys. */ -static const struct mode_key_entry mode_key_emacs_edit[] = { - { '\001' /* C-a */, 0, MODEKEYEDIT_STARTOFLINE }, - { '\002' /* C-b */, 0, MODEKEYEDIT_CURSORLEFT }, - { '\003' /* C-c */, 0, MODEKEYEDIT_CANCEL }, - { '\004' /* C-d */, 0, MODEKEYEDIT_DELETE }, - { '\005' /* C-e */, 0, MODEKEYEDIT_ENDOFLINE }, - { '\006' /* C-f */, 0, MODEKEYEDIT_CURSORRIGHT }, - { '\010' /* C-H */, 0, MODEKEYEDIT_BACKSPACE }, - { '\011' /* Tab */, 0, MODEKEYEDIT_COMPLETE }, - { '\013' /* C-k */, 0, MODEKEYEDIT_DELETETOENDOFLINE }, - { '\016' /* C-n */, 0, MODEKEYEDIT_HISTORYDOWN }, - { '\020' /* C-p */, 0, MODEKEYEDIT_HISTORYUP }, - { '\024' /* C-t */, 0, MODEKEYEDIT_TRANSPOSECHARS }, - { '\025' /* C-u */, 0, MODEKEYEDIT_DELETELINE }, - { '\027' /* C-w */, 0, MODEKEYEDIT_DELETEWORD }, - { '\031' /* C-y */, 0, MODEKEYEDIT_PASTE }, - { '\033' /* Escape */, 0, MODEKEYEDIT_CANCEL }, - { '\n', 0, MODEKEYEDIT_ENTER }, - { '\r', 0, MODEKEYEDIT_ENTER }, - { 'b' | KEYC_ESCAPE, 0, MODEKEYEDIT_PREVIOUSWORD }, - { 'f' | KEYC_ESCAPE, 0, MODEKEYEDIT_NEXTWORDEND }, - { 'm' | KEYC_ESCAPE, 0, MODEKEYEDIT_STARTOFLINE }, - { KEYC_BSPACE, 0, MODEKEYEDIT_BACKSPACE }, - { KEYC_DC, 0, MODEKEYEDIT_DELETE }, - { KEYC_DOWN, 0, MODEKEYEDIT_HISTORYDOWN }, - { KEYC_LEFT, 0, MODEKEYEDIT_CURSORLEFT }, - { KEYC_RIGHT, 0, MODEKEYEDIT_CURSORRIGHT }, - { KEYC_UP, 0, MODEKEYEDIT_HISTORYUP }, - { KEYC_HOME, 0, MODEKEYEDIT_STARTOFLINE }, - { KEYC_END, 0, MODEKEYEDIT_ENDOFLINE }, - - { 0, -1, 0 } -}; -struct mode_key_tree mode_key_tree_emacs_edit; - /* emacs choice selection keys. */ static const struct mode_key_entry mode_key_emacs_choice[] = { - { '0' | KEYC_ESCAPE, 0, MODEKEYCHOICE_STARTNUMBERPREFIX }, - { '1' | KEYC_ESCAPE, 0, MODEKEYCHOICE_STARTNUMBERPREFIX }, - { '2' | KEYC_ESCAPE, 0, MODEKEYCHOICE_STARTNUMBERPREFIX }, - { '3' | KEYC_ESCAPE, 0, MODEKEYCHOICE_STARTNUMBERPREFIX }, - { '4' | KEYC_ESCAPE, 0, MODEKEYCHOICE_STARTNUMBERPREFIX }, - { '5' | KEYC_ESCAPE, 0, MODEKEYCHOICE_STARTNUMBERPREFIX }, - { '6' | KEYC_ESCAPE, 0, MODEKEYCHOICE_STARTNUMBERPREFIX }, - { '7' | KEYC_ESCAPE, 0, MODEKEYCHOICE_STARTNUMBERPREFIX }, - { '8' | KEYC_ESCAPE, 0, MODEKEYCHOICE_STARTNUMBERPREFIX }, - { '9' | KEYC_ESCAPE, 0, MODEKEYCHOICE_STARTNUMBERPREFIX }, - { '\003' /* C-c */, 0, MODEKEYCHOICE_CANCEL }, - { '\016' /* C-n */, 0, MODEKEYCHOICE_DOWN }, - { '\020' /* C-p */, 0, MODEKEYCHOICE_UP }, - { '\026' /* C-v */, 0, MODEKEYCHOICE_PAGEDOWN }, - { '\033' /* Escape */, 0, MODEKEYCHOICE_CANCEL }, - { '\n', 0, MODEKEYCHOICE_CHOOSE }, - { '\r', 0, MODEKEYCHOICE_CHOOSE }, - { 'q', 0, MODEKEYCHOICE_CANCEL }, - { 'v' | KEYC_ESCAPE, 0, MODEKEYCHOICE_PAGEUP }, - { KEYC_HOME, 0, MODEKEYCHOICE_STARTOFLIST }, - { '<' | KEYC_ESCAPE, 0, MODEKEYCHOICE_STARTOFLIST }, - { 'R' | KEYC_ESCAPE, 0, MODEKEYCHOICE_TOPLINE }, - { '>' | KEYC_ESCAPE, 0, MODEKEYCHOICE_ENDOFLIST }, - { KEYC_END, 0, MODEKEYCHOICE_ENDOFLIST }, - { KEYC_BSPACE, 0, MODEKEYCHOICE_BACKSPACE }, - { KEYC_DOWN | KEYC_CTRL, 0, MODEKEYCHOICE_SCROLLDOWN }, - { KEYC_DOWN, 0, MODEKEYCHOICE_DOWN }, - { KEYC_NPAGE, 0, MODEKEYCHOICE_PAGEDOWN }, - { KEYC_PPAGE, 0, MODEKEYCHOICE_PAGEUP }, - { KEYC_UP | KEYC_CTRL, 0, MODEKEYCHOICE_SCROLLUP }, - { KEYC_UP, 0, MODEKEYCHOICE_UP }, - { ' ', 0, MODEKEYCHOICE_TREE_TOGGLE }, - { KEYC_LEFT, 0, MODEKEYCHOICE_TREE_COLLAPSE }, - { KEYC_RIGHT, 0, MODEKEYCHOICE_TREE_EXPAND }, - { KEYC_LEFT | KEYC_CTRL, 0, MODEKEYCHOICE_TREE_COLLAPSE_ALL }, - { KEYC_RIGHT | KEYC_CTRL, 0, MODEKEYCHOICE_TREE_EXPAND_ALL }, - { KEYC_MOUSEDOWN1_PANE, 0, MODEKEYCHOICE_CHOOSE }, - { KEYC_MOUSEDOWN3_PANE, 0, MODEKEYCHOICE_TREE_TOGGLE }, - { KEYC_WHEELUP_PANE, 0, MODEKEYCHOICE_UP }, - { KEYC_WHEELDOWN_PANE, 0, MODEKEYCHOICE_DOWN }, + { '0' | KEYC_ESCAPE, MODEKEYCHOICE_STARTNUMBERPREFIX }, + { '1' | KEYC_ESCAPE, MODEKEYCHOICE_STARTNUMBERPREFIX }, + { '2' | KEYC_ESCAPE, MODEKEYCHOICE_STARTNUMBERPREFIX }, + { '3' | KEYC_ESCAPE, MODEKEYCHOICE_STARTNUMBERPREFIX }, + { '4' | KEYC_ESCAPE, MODEKEYCHOICE_STARTNUMBERPREFIX }, + { '5' | KEYC_ESCAPE, MODEKEYCHOICE_STARTNUMBERPREFIX }, + { '6' | KEYC_ESCAPE, MODEKEYCHOICE_STARTNUMBERPREFIX }, + { '7' | KEYC_ESCAPE, MODEKEYCHOICE_STARTNUMBERPREFIX }, + { '8' | KEYC_ESCAPE, MODEKEYCHOICE_STARTNUMBERPREFIX }, + { '9' | KEYC_ESCAPE, MODEKEYCHOICE_STARTNUMBERPREFIX }, + { '\003' /* C-c */, MODEKEYCHOICE_CANCEL }, + { '\016' /* C-n */, MODEKEYCHOICE_DOWN }, + { '\020' /* C-p */, MODEKEYCHOICE_UP }, + { '\026' /* C-v */, MODEKEYCHOICE_PAGEDOWN }, + { '\033' /* Escape */, MODEKEYCHOICE_CANCEL }, + { '\n', MODEKEYCHOICE_CHOOSE }, + { '\r', MODEKEYCHOICE_CHOOSE }, + { 'q', MODEKEYCHOICE_CANCEL }, + { 'v' | KEYC_ESCAPE, MODEKEYCHOICE_PAGEUP }, + { KEYC_HOME, MODEKEYCHOICE_STARTOFLIST }, + { '<' | KEYC_ESCAPE, MODEKEYCHOICE_STARTOFLIST }, + { 'R' | KEYC_ESCAPE, MODEKEYCHOICE_TOPLINE }, + { '>' | KEYC_ESCAPE, MODEKEYCHOICE_ENDOFLIST }, + { KEYC_END, MODEKEYCHOICE_ENDOFLIST }, + { KEYC_BSPACE, MODEKEYCHOICE_BACKSPACE }, + { KEYC_DOWN | KEYC_CTRL, MODEKEYCHOICE_SCROLLDOWN }, + { KEYC_DOWN, MODEKEYCHOICE_DOWN }, + { KEYC_NPAGE, MODEKEYCHOICE_PAGEDOWN }, + { KEYC_PPAGE, MODEKEYCHOICE_PAGEUP }, + { KEYC_UP | KEYC_CTRL, MODEKEYCHOICE_SCROLLUP }, + { KEYC_UP, MODEKEYCHOICE_UP }, + { ' ', MODEKEYCHOICE_TREE_TOGGLE }, + { KEYC_LEFT, MODEKEYCHOICE_TREE_COLLAPSE }, + { KEYC_RIGHT, MODEKEYCHOICE_TREE_EXPAND }, + { KEYC_LEFT | KEYC_CTRL, MODEKEYCHOICE_TREE_COLLAPSE_ALL }, + { KEYC_RIGHT | KEYC_CTRL, MODEKEYCHOICE_TREE_EXPAND_ALL }, + { KEYC_MOUSEDOWN1_PANE, MODEKEYCHOICE_CHOOSE }, + { KEYC_MOUSEDOWN3_PANE, MODEKEYCHOICE_TREE_TOGGLE }, + { KEYC_WHEELUP_PANE, MODEKEYCHOICE_UP }, + { KEYC_WHEELDOWN_PANE, MODEKEYCHOICE_DOWN }, - { 0, -1, 0 } + { KEYC_NONE, -1 } }; struct mode_key_tree mode_key_tree_emacs_choice; /* Table mapping key table names to default settings and trees. */ static const struct mode_key_table mode_key_tables[] = { - { "vi-edit", mode_key_cmdstr_edit, - &mode_key_tree_vi_edit, mode_key_vi_edit }, { "vi-choice", mode_key_cmdstr_choice, &mode_key_tree_vi_choice, mode_key_vi_choice }, - { "emacs-edit", mode_key_cmdstr_edit, - &mode_key_tree_emacs_edit, mode_key_emacs_edit }, { "emacs-choice", mode_key_cmdstr_choice, &mode_key_tree_emacs_choice, mode_key_emacs_choice }, @@ -328,10 +186,6 @@ RB_GENERATE(mode_key_tree, mode_key_binding, entry, mode_key_cmp); int mode_key_cmp(struct mode_key_binding *mbind1, struct mode_key_binding *mbind2) { - if (mbind1->mode < mbind2->mode) - return (-1); - if (mbind1->mode > mbind2->mode) - return (1); if (mbind1->key < mbind2->key) return (-1); if (mbind1->key > mbind2->key) @@ -380,10 +234,9 @@ mode_key_init_trees(void) for (mtab = mode_key_tables; mtab->name != NULL; mtab++) { RB_INIT(mtab->tree); - for (ment = mtab->table; ment->mode != -1; ment++) { + for (ment = mtab->table; ment->key != KEYC_NONE; ment++) { mbind = xmalloc(sizeof *mbind); mbind->key = ment->key; - mbind->mode = ment->mode; mbind->cmd = ment->cmd; RB_INSERT(mode_key_tree, mtab->tree, mbind); } @@ -394,7 +247,6 @@ void mode_key_init(struct mode_key_data *mdata, struct mode_key_tree *mtree) { mdata->tree = mtree; - mdata->mode = 0; } enum mode_key_cmd @@ -403,24 +255,7 @@ mode_key_lookup(struct mode_key_data *mdata, key_code key) struct mode_key_binding *mbind, mtmp; mtmp.key = key; - mtmp.mode = mdata->mode; - if ((mbind = RB_FIND(mode_key_tree, mdata->tree, &mtmp)) == NULL) { - if (mdata->mode != 0) - return (MODEKEY_NONE); + if ((mbind = RB_FIND(mode_key_tree, mdata->tree, &mtmp)) == NULL) return (MODEKEY_OTHER); - } - - switch (mbind->cmd) { - case MODEKEYEDIT_SWITCHMODE: - case MODEKEYEDIT_SWITCHMODEAPPEND: - case MODEKEYEDIT_SWITCHMODEAPPENDLINE: - case MODEKEYEDIT_SWITCHMODEBEGINLINE: - case MODEKEYEDIT_SWITCHMODECHANGELINE: - case MODEKEYEDIT_SWITCHMODESUBSTITUTE: - case MODEKEYEDIT_SWITCHMODESUBSTITUTELINE: - mdata->mode = 1 - mdata->mode; - /* FALLTHROUGH */ - default: - return (mbind->cmd); - } + return (mbind->cmd); } diff --git a/status.c b/status.c index dc88efe5..4cdd4932 100644 --- a/status.c +++ b/status.c @@ -660,7 +660,6 @@ status_prompt_set(struct client *c, const char *msg, const char *input, void *data, int flags) { struct format_tree *ft; - int keys; time_t t; char *tmp; @@ -685,12 +684,7 @@ status_prompt_set(struct client *c, const char *msg, const char *input, c->prompt_hindex = 0; c->prompt_flags = flags; - - keys = options_get_number(c->session->options, "status-keys"); - if (keys == MODEKEY_EMACS) - mode_key_init(&c->prompt_mdata, &mode_key_tree_emacs_edit); - else - mode_key_init(&c->prompt_mdata, &mode_key_tree_vi_edit); + c->prompt_mode = PROMPT_ENTRY; c->tty.flags |= (TTY_NOCURSOR|TTY_FREEZE); c->flags |= CLIENT_STATUS; @@ -765,7 +759,7 @@ status_prompt_redraw(struct client *c) memcpy(&old_status, &c->status, sizeof old_status); screen_init(&c->status, c->tty.sx, 1, 0); - if (c->prompt_mdata.mode == 1) + if (c->prompt_mode == PROMPT_COMMAND) style_apply(&gc, s->options, "message-command-style"); else style_apply(&gc, s->options, "message-style"); @@ -854,6 +848,127 @@ status_prompt_space(const struct utf8_data *ud) return (*ud->data == ' '); } +/* + * Translate key from emacs to vi. Return 0 to drop key, 1 to process the key + * as an emacs key; return 2 to append to the buffer. + */ +static int +status_prompt_translate_key(struct client *c, key_code key, key_code *new_key) +{ + if (c->prompt_mode == PROMPT_ENTRY) { + switch (key) { + case '\003': /* C-c */ + case '\010': /* C-h */ + case '\011': /* Tab */ + case '\025': /* C-u */ + case '\027': /* C-w */ + case '\n': + case '\r': + case KEYC_BSPACE: + case KEYC_DC: + case KEYC_DOWN: + case KEYC_END: + case KEYC_HOME: + case KEYC_LEFT: + case KEYC_RIGHT: + case KEYC_UP: + *new_key = key; + return (1); + case '\033': /* Escape */ + c->prompt_mode = PROMPT_COMMAND; + c->flags |= CLIENT_STATUS; + return (0); + } + *new_key = key; + return (2); + } + + switch (key) { + case 'A': + case 'I': + case 'C': + case 's': + case 'a': + c->prompt_mode = PROMPT_ENTRY; + c->flags |= CLIENT_STATUS; + break; /* switch mode and... */ + case 'S': + c->prompt_mode = PROMPT_ENTRY; + c->flags |= CLIENT_STATUS; + *new_key = '\025'; /* C-u */ + return (1); + case 'i': + case '\033': /* Escape */ + c->prompt_mode = PROMPT_ENTRY; + c->flags |= CLIENT_STATUS; + return (0); + } + + switch (key) { + case 'A': + case '$': + *new_key = KEYC_END; + return (1); + case 'I': + case '0': + case '^': + *new_key = KEYC_HOME; + return (1); + case 'C': + case 'D': + *new_key = '\013'; /* C-k */ + return (1); + case KEYC_BSPACE: + case 'X': + *new_key = KEYC_BSPACE; + return (1); + case 'b': + case 'B': + *new_key = 'b'|KEYC_ESCAPE; + return (1); + case 'd': + *new_key = '\025'; + return (1); + case 'e': + case 'E': + case 'w': + case 'W': + *new_key = 'f'|KEYC_ESCAPE; + return (1); + case 'p': + *new_key = '\031'; /* C-y */ + return (1); + case 's': + case KEYC_DC: + case 'x': + *new_key = KEYC_DC; + return (1); + case KEYC_DOWN: + case 'j': + *new_key = KEYC_DOWN; + return (1); + case KEYC_LEFT: + case 'h': + *new_key = KEYC_LEFT; + return (1); + case 'a': + case KEYC_RIGHT: + case 'l': + *new_key = KEYC_RIGHT; + return (1); + case KEYC_UP: + case 'k': + *new_key = KEYC_UP; + return (1); + case '\010' /* C-h */: + case '\003' /* C-c */: + case '\n': + case '\r': + return (1); + } + return (0); +} + /* Handle keys in prompt. */ int status_prompt_key(struct client *c, key_code key) @@ -865,6 +980,7 @@ status_prompt_key(struct client *c, key_code key) u_char ch; size_t size, n, off, idx, bufsize, used; struct utf8_data tmp, *first, *last, *ud; + int keys; size = utf8_strlen(c->prompt_buffer); @@ -878,44 +994,49 @@ status_prompt_key(struct client *c, key_code key) return (1); } - switch (mode_key_lookup(&c->prompt_mdata, key)) { - case MODEKEYEDIT_CURSORLEFT: + keys = options_get_number(c->session->options, "status-keys"); + if (keys == MODEKEY_VI) { + switch (status_prompt_translate_key(c, key, &key)) { + case 1: + goto process_key; + case 2: + goto append_key; + default: + return (0); + } + } + +process_key: + switch (key) { + case KEYC_LEFT: + case '\002': /* C-b */ if (c->prompt_index > 0) { c->prompt_index--; c->flags |= CLIENT_STATUS; } break; - case MODEKEYEDIT_SWITCHMODE: - c->flags |= CLIENT_STATUS; - break; - case MODEKEYEDIT_SWITCHMODEAPPEND: - c->flags |= CLIENT_STATUS; - /* FALLTHROUGH */ - case MODEKEYEDIT_CURSORRIGHT: + case KEYC_RIGHT: + case '\006': /* C-f */ if (c->prompt_index < size) { c->prompt_index++; c->flags |= CLIENT_STATUS; } break; - case MODEKEYEDIT_SWITCHMODEBEGINLINE: - c->flags |= CLIENT_STATUS; - /* FALLTHROUGH */ - case MODEKEYEDIT_STARTOFLINE: + case KEYC_HOME: + case '\001': /* C-a */ if (c->prompt_index != 0) { c->prompt_index = 0; c->flags |= CLIENT_STATUS; } break; - case MODEKEYEDIT_SWITCHMODEAPPENDLINE: - c->flags |= CLIENT_STATUS; - /* FALLTHROUGH */ - case MODEKEYEDIT_ENDOFLINE: + case KEYC_END: + case '\005': /* C-e */ if (c->prompt_index != size) { c->prompt_index = size; c->flags |= CLIENT_STATUS; } break; - case MODEKEYEDIT_COMPLETE: + case '\011': /* Tab */ if (c->prompt_buffer[0].size == 0) break; @@ -974,7 +1095,8 @@ status_prompt_key(struct client *c, key_code key) c->flags |= CLIENT_STATUS; break; - case MODEKEYEDIT_BACKSPACE: + case KEYC_BSPACE: + case '\010': /* C-h */ if (c->prompt_index != 0) { if (c->prompt_index == size) c->prompt_buffer[--c->prompt_index].size = 0; @@ -988,8 +1110,8 @@ status_prompt_key(struct client *c, key_code key) c->flags |= CLIENT_STATUS; } break; - case MODEKEYEDIT_DELETE: - case MODEKEYEDIT_SWITCHMODESUBSTITUTE: + case KEYC_DC: + case '\004': /* C-d */ if (c->prompt_index != size) { memmove(c->prompt_buffer + c->prompt_index, c->prompt_buffer + c->prompt_index + 1, @@ -998,20 +1120,18 @@ status_prompt_key(struct client *c, key_code key) c->flags |= CLIENT_STATUS; } break; - case MODEKEYEDIT_DELETELINE: - case MODEKEYEDIT_SWITCHMODESUBSTITUTELINE: + case '\025': /* C-u */ c->prompt_buffer[0].size = 0; c->prompt_index = 0; c->flags |= CLIENT_STATUS; break; - case MODEKEYEDIT_DELETETOENDOFLINE: - case MODEKEYEDIT_SWITCHMODECHANGELINE: + case '\013': /* C-k */ if (c->prompt_index < size) { c->prompt_buffer[c->prompt_index].size = 0; c->flags |= CLIENT_STATUS; } break; - case MODEKEYEDIT_DELETEWORD: + case '\027': /* C-w */ ws = options_get_string(oo, "word-separators"); idx = c->prompt_index; @@ -1042,35 +1162,8 @@ status_prompt_key(struct client *c, key_code key) c->flags |= CLIENT_STATUS; break; - case MODEKEYEDIT_NEXTSPACE: - ws = " "; - /* FALLTHROUGH */ - case MODEKEYEDIT_NEXTWORD: - if (ws == NULL) - ws = options_get_string(oo, "word-separators"); - - /* Find a separator. */ - while (c->prompt_index != size) { - idx = ++c->prompt_index; - if (status_prompt_in_list(ws, &c->prompt_buffer[idx])) - break; - } - - /* Find the word right after the separator. */ - while (c->prompt_index != size) { - idx = ++c->prompt_index; - if (!status_prompt_in_list(ws, &c->prompt_buffer[idx])) - break; - } - - c->flags |= CLIENT_STATUS; - break; - case MODEKEYEDIT_NEXTSPACEEND: - ws = " "; - /* FALLTHROUGH */ - case MODEKEYEDIT_NEXTWORDEND: - if (ws == NULL) - ws = options_get_string(oo, "word-separators"); + case 'f'|KEYC_ESCAPE: + ws = options_get_string(oo, "word-separators"); /* Find a word. */ while (c->prompt_index != size) { @@ -1093,12 +1186,8 @@ status_prompt_key(struct client *c, key_code key) c->flags |= CLIENT_STATUS; break; - case MODEKEYEDIT_PREVIOUSSPACE: - ws = " "; - /* FALLTHROUGH */ - case MODEKEYEDIT_PREVIOUSWORD: - if (ws == NULL) - ws = options_get_string(oo, "word-separators"); + case 'b'|KEYC_ESCAPE: + ws = options_get_string(oo, "word-separators"); /* Find a non-separator. */ while (c->prompt_index != 0) { @@ -1119,7 +1208,8 @@ status_prompt_key(struct client *c, key_code key) c->flags |= CLIENT_STATUS; break; - case MODEKEYEDIT_HISTORYUP: + case KEYC_UP: + case '\020': /* C-p */ histstr = status_prompt_up_history(&c->prompt_hindex); if (histstr == NULL) break; @@ -1128,7 +1218,8 @@ status_prompt_key(struct client *c, key_code key) c->prompt_index = utf8_strlen(c->prompt_buffer); c->flags |= CLIENT_STATUS; break; - case MODEKEYEDIT_HISTORYDOWN: + case KEYC_DOWN: + case '\016': /* C-n */ histstr = status_prompt_down_history(&c->prompt_hindex); if (histstr == NULL) break; @@ -1137,7 +1228,7 @@ status_prompt_key(struct client *c, key_code key) c->prompt_index = utf8_strlen(c->prompt_buffer); c->flags |= CLIENT_STATUS; break; - case MODEKEYEDIT_PASTE: + case '\031': /* C-y */ if ((pb = paste_get_top(NULL)) == NULL) break; bufdata = paste_buffer_data(pb, &bufsize); @@ -1170,7 +1261,7 @@ status_prompt_key(struct client *c, key_code key) c->flags |= CLIENT_STATUS; break; - case MODEKEYEDIT_TRANSPOSECHARS: + case '\024': /* C-t */ idx = c->prompt_index; if (idx < size) idx++; @@ -1183,7 +1274,8 @@ status_prompt_key(struct client *c, key_code key) c->flags |= CLIENT_STATUS; } break; - case MODEKEYEDIT_ENTER: + case '\r': + case '\n': s = utf8_tocstr(c->prompt_buffer); if (*s != '\0') status_prompt_add_history(s); @@ -1191,14 +1283,11 @@ status_prompt_key(struct client *c, key_code key) status_prompt_clear(c); free(s); break; - case MODEKEYEDIT_CANCEL: + case '\033': /* Escape */ + case '\003': /* C-c */ if (c->prompt_callbackfn(c->prompt_data, NULL) == 0) status_prompt_clear(c); break; - case MODEKEY_OTHER: - break; - default: - return (0); } append_key: diff --git a/tmux.1 b/tmux.1 index 4cf403e7..03a4ba2f 100644 --- a/tmux.1 +++ b/tmux.1 @@ -1104,11 +1104,7 @@ Commands in copy mode may be prefaced by an optional repeat count. With vi key bindings, a prefix is entered using the number keys; with emacs, the Alt (meta) key and a number begins prefix entry. .Pp -Mode key bindings are defined in a set of named tables: -.Em vi-edit -and -.Em emacs-edit -for keys used when line editing at the command prompt; and +Mode key bindings are defined in two tables: .Em vi-choice and .Em emacs-choice @@ -3000,10 +2996,8 @@ layouts. .It Xo Ic mode-keys .Op Ic vi | emacs .Xc -Use vi or emacs-style key bindings in copy and choice modes. -As with the -.Ic status-keys -option, the default is emacs, unless +Use vi or emacs-style key bindings in copy mode. +The default is emacs, unless .Ev VISUAL or .Ev EDITOR @@ -3748,7 +3742,7 @@ session option. Commands related to the status line are as follows: .Bl -tag -width Ds .It Xo Ic command-prompt -.Op Fl 1N +.Op Fl 1 .Op Fl I Ar inputs .Op Fl p Ar prompts .Op Fl t Ar target-client @@ -3776,13 +3770,6 @@ if it is present, or .Ql \&: if not. .Pp -Both -.Ar inputs -and -.Ar prompts -may contain the special character sequences supported by the -.Ic status-left -option. .Pp Before the command is executed, the first occurrence of the string .Ql %% @@ -3802,8 +3789,30 @@ to .Fl 1 makes the prompt only accept one key press, in this case the resulting input is a single character. -.Fl N -accepts only numbers and exit the prompt on any other key press. +.Pp +The following keys have a special meaning in the command prompt, depending +on the value of the +.Ic status-keys +option: +.Bl -column "FunctionXXXXXXXXXXXXXXXXXXXXXXXXX" "viXXXX" "emacsX" -offset indent +.It Sy "Function" Ta Sy "vi" Ta Sy "emacs" +.It Li "Cancel command prompt" Ta "Escape" Ta "Escape" +.It Li "Delete current word" Ta "" Ta "C-w" +.It Li "Delete entire command" Ta "d" Ta "C-u" +.It Li "Delete from cursor to end" Ta "D" Ta "C-k" +.It Li "Execute command" Ta "Enter" Ta "Enter" +.It Li "Get next command from history" Ta "" Ta "Down" +.It Li "Get previous command from history" Ta "" Ta "Up" +.It Li "Insert top paste buffer" Ta "p" Ta "C-y" +.It Li "Look for completions" Ta "Tab" Ta "Tab" +.It Li "Move cursor left" Ta "h" Ta "Left" +.It Li "Move cursor right" Ta "l" Ta "Right" +.It Li "Move cursor to end" Ta "$" Ta "C-e" +.It Li "Move cursor to next word" Ta "w" Ta "M-f" +.It Li "Move cursor to previous word" Ta "b" Ta "M-b" +.It Li "Move cursor to start" Ta "0" Ta "C-a" +.It Li "Transpose characters" Ta "" Ta "C-t" +.El .It Xo Ic confirm-before .Op Fl p Ar prompt .Op Fl t Ar target-client diff --git a/tmux.h b/tmux.h index dc5e8712..c4c33622 100644 --- a/tmux.h +++ b/tmux.h @@ -471,37 +471,6 @@ enum mode_key_cmd { MODEKEY_NONE, MODEKEY_OTHER, - /* Editing keys. */ - MODEKEYEDIT_BACKSPACE, - MODEKEYEDIT_CANCEL, - MODEKEYEDIT_COMPLETE, - MODEKEYEDIT_CURSORLEFT, - MODEKEYEDIT_CURSORRIGHT, - MODEKEYEDIT_DELETE, - MODEKEYEDIT_DELETELINE, - MODEKEYEDIT_DELETETOENDOFLINE, - MODEKEYEDIT_DELETEWORD, - MODEKEYEDIT_ENDOFLINE, - MODEKEYEDIT_ENTER, - MODEKEYEDIT_HISTORYDOWN, - MODEKEYEDIT_HISTORYUP, - MODEKEYEDIT_NEXTSPACE, - MODEKEYEDIT_NEXTSPACEEND, - MODEKEYEDIT_NEXTWORD, - MODEKEYEDIT_NEXTWORDEND, - MODEKEYEDIT_PASTE, - MODEKEYEDIT_PREVIOUSSPACE, - MODEKEYEDIT_PREVIOUSWORD, - MODEKEYEDIT_STARTOFLINE, - MODEKEYEDIT_SWITCHMODE, - MODEKEYEDIT_SWITCHMODEAPPEND, - MODEKEYEDIT_SWITCHMODEAPPENDLINE, - MODEKEYEDIT_SWITCHMODEBEGINLINE, - MODEKEYEDIT_SWITCHMODECHANGELINE, - MODEKEYEDIT_SWITCHMODESUBSTITUTE, - MODEKEYEDIT_SWITCHMODESUBSTITUTELINE, - MODEKEYEDIT_TRANSPOSECHARS, - /* Menu (choice) keys. */ MODEKEYCHOICE_BACKSPACE, MODEKEYCHOICE_BOTTOMLINE, @@ -527,7 +496,6 @@ enum mode_key_cmd { /* Data required while mode keys are in use. */ struct mode_key_data { struct mode_key_tree *tree; - int mode; }; #define MODEKEY_EMACS 0 #define MODEKEY_VI 1 @@ -535,8 +503,6 @@ struct mode_key_data { /* Binding between a key and a command. */ struct mode_key_binding { key_code key; - - int mode; enum mode_key_cmd cmd; RB_ENTRY(mode_key_binding) entry; @@ -1267,13 +1233,12 @@ struct client { void (*prompt_freefn)(void *); void *prompt_data; u_int prompt_hindex; + enum { PROMPT_ENTRY, PROMPT_COMMAND } prompt_mode; #define PROMPT_SINGLE 0x1 #define PROMPT_NUMERIC 0x2 int prompt_flags; - struct mode_key_data prompt_mdata; - struct session *session; struct session *last_session; From 40253048ca6d6ecf45be24a76220d6012aca9818 Mon Sep 17 00:00:00 2001 From: nicm Date: Wed, 12 Oct 2016 15:26:37 +0000 Subject: [PATCH 5/7] bind-key -c has gone, remove from man page, and unused table declarations. --- tmux.1 | 10 +++------- tmux.h | 2 -- 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/tmux.1 b/tmux.1 index 03a4ba2f..73daac3f 100644 --- a/tmux.1 +++ b/tmux.1 @@ -2100,7 +2100,7 @@ bind-key "'" new-window Commands related to key bindings are as follows: .Bl -tag -width Ds .It Xo Ic bind-key -.Op Fl cnr +.Op Fl nr .Op Fl t Ar mode-table .Op Fl T Ar key-table .Ar key Ar command Op Ar arguments @@ -2155,10 +2155,7 @@ If is present, .Ar key is bound in -.Ar mode-table : -the binding for command mode with -.Fl c -or for normal mode without. +.Ar mode-table . .Pp To view the default bindings and possible commands, see the .Ic list-keys @@ -2232,7 +2229,7 @@ Send the prefix key, or with .Fl 2 the secondary prefix key, to a window as if it was pressed. .It Xo Ic unbind-key -.Op Fl acn +.Op Fl an .Op Fl t Ar mode-table .Op Fl T Ar key-table .Ar key @@ -2240,7 +2237,6 @@ the secondary prefix key, to a window as if it was pressed. .D1 (alias: Ic unbind ) Unbind the command bound to .Ar key . -.Fl c , .Fl n , .Fl T and diff --git a/tmux.h b/tmux.h index c4c33622..4097052e 100644 --- a/tmux.h +++ b/tmux.h @@ -1559,9 +1559,7 @@ int printflike(4, 5) hooks_wait(struct hooks *, struct cmd_q *, struct cmd_find_state *, const char *, ...); /* mode-key.c */ -extern struct mode_key_tree mode_key_tree_vi_edit; extern struct mode_key_tree mode_key_tree_vi_choice; -extern struct mode_key_tree mode_key_tree_emacs_edit; extern struct mode_key_tree mode_key_tree_emacs_choice; int mode_key_cmp(struct mode_key_binding *, struct mode_key_binding *); RB_PROTOTYPE(mode_key_tree, mode_key_binding, entry, mode_key_cmp); From e83ebf50de7503b96203df9a4b2badf2c649b031 Mon Sep 17 00:00:00 2001 From: nicm Date: Wed, 12 Oct 2016 15:43:51 +0000 Subject: [PATCH 6/7] Fix a couple of problems with insert mode: flush dirty cells before we modify the screen, not after; and use grid_view_insert_cells to make space not grid_move_cells. --- screen-write.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/screen-write.c b/screen-write.c index 1767d9bb..8156a1d0 100644 --- a/screen-write.c +++ b/screen-write.c @@ -103,6 +103,7 @@ screen_write_flush(struct screen_write_ctx *ctx) if (ctx->dirty == 0) return; dirty = 0; + log_debug("%s: dirty %u", __func__, ctx->dirty); cx = s->cx; cy = s->cy; @@ -1044,9 +1045,12 @@ screen_write_cell(struct screen_write_ctx *ctx, const struct grid_cell *gc) screen_write_initctx(ctx, &ttyctx); /* If in insert mode, make space for the cells. */ - if ((s->mode & MODE_INSERT) && s->cx <= sx - width) { - xx = sx - s->cx - width; - grid_move_cells(s->grid, s->cx + width, s->cx, s->cy, xx); + if (s->mode & MODE_INSERT) { + if (s->cx <= sx - width) { + screen_write_flush(ctx); + xx = sx - s->cx - width; + grid_view_insert_cells(s->grid, s->cx, s->cy, xx); + } insert = 1; } else insert = 0; @@ -1133,8 +1137,6 @@ screen_write_cell(struct screen_write_ctx *ctx, const struct grid_cell *gc) /* Create space for character in insert mode. */ if (insert) { - if (!wrapped) - screen_write_flush(ctx); ttyctx.num = width; tty_write(tty_cmd_insertcharacter, &ttyctx); } From e0add119ea4a6c8d40905a7ad1f7bc3553d20ccc Mon Sep 17 00:00:00 2001 From: nicm Date: Wed, 12 Oct 2016 17:36:52 +0000 Subject: [PATCH 7/7] Compare to see if pane status line has actually changed, not just size, and do not draw if pane is not visible. --- screen-redraw.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/screen-redraw.c b/screen-redraw.c index 00e94d61..05d094d5 100644 --- a/screen-redraw.c +++ b/screen-redraw.c @@ -269,8 +269,9 @@ screen_redraw_make_pane_status(struct client *c, struct window *w, const char *fmt; struct format_tree *ft; char *out; - size_t outlen, old_size = wp->status_size; + size_t outlen; struct screen_write_ctx ctx; + struct screen old; if (wp == w->active) style_apply(&gc, w->options, "pane-active-border-style"); @@ -282,7 +283,7 @@ screen_redraw_make_pane_status(struct client *c, struct window *w, ft = format_create(NULL, 0); format_defaults(ft, c, NULL, NULL, wp); - screen_free(&wp->status_screen); + memcpy(&old, &wp->status_screen, sizeof old); screen_init(&wp->status_screen, wp->sx, 1, 0); wp->status_screen.mode = 0; @@ -301,7 +302,13 @@ screen_redraw_make_pane_status(struct client *c, struct window *w, format_free(ft); wp->status_size = outlen; - return (wp->status_size != old_size); + + if (grid_compare(wp->status_screen.grid, old.grid) == 0) { + screen_free(&old); + return (0); + } + screen_free(&old); + return (1); } /* Draw pane status. */ @@ -317,6 +324,8 @@ screen_redraw_draw_pane_status(struct client *c, int pane_status) spos = options_get_number(oo, "status-position"); TAILQ_FOREACH(wp, &w->panes, entry) { + if (!window_pane_visible(wp)) + continue; if (pane_status == CELL_STATUS_TOP) yoff = wp->yoff - 1; else