diff --git a/key-bindings.c b/key-bindings.c index f61d372d..7de1782e 100644 --- a/key-bindings.c +++ b/key-bindings.c @@ -503,7 +503,7 @@ key_bindings_init(void) "bind -Tcopy-mode C-b { send -X cursor-left }", "bind -Tcopy-mode C-g { send -X clear-selection }", "bind -Tcopy-mode C-k { send -X copy-pipe-end-of-line-and-cancel }", - "bind -Tcopy-mode C-l { send -X cursor-centre-vertical }", + "bind -Tcopy-mode C-l { send -X recentre-top-bottom }", "bind -Tcopy-mode M-l { send -X cursor-centre-horizontal }", "bind -Tcopy-mode C-n { send -X cursor-down }", "bind -Tcopy-mode C-p { send -X cursor-up }", diff --git a/layout-custom.c b/layout-custom.c index 22de0bdd..27d5bf82 100644 --- a/layout-custom.c +++ b/layout-custom.c @@ -160,13 +160,14 @@ layout_parse(struct window *w, const char *layout, char **cause) struct window_pane *wp; u_int npanes, ncells, sx = 0, sy = 0; u_short csum; + int n; /* Check validity. */ - if (sscanf(layout, "%hx,", &csum) != 1) { + if (sscanf(layout, "%hx,%n", &csum, &n) != 1 || n != 5) { *cause = xstrdup("invalid layout"); return (-1); } - layout += 5; + layout += n; if (csum != layout_checksum(layout)) { *cause = xstrdup("invalid layout"); return (-1); diff --git a/tmux.1 b/tmux.1 index c112d1b1..fe360159 100644 --- a/tmux.1 +++ b/tmux.1 @@ -2224,6 +2224,11 @@ Turn off rectangle selection mode. .Xc Toggle rectangle selection mode. .It Xo +.Ic recentre\-top\-bottom +(emacs : C-l) +.Xc +Cycles the current line between centre, top, and bottom. +.It Xo .Ic refresh\-from\-pane (vi: r) (emacs: r) diff --git a/window-copy.c b/window-copy.c index def9d8f3..af80b8b4 100644 --- a/window-copy.c +++ b/window-copy.c @@ -286,6 +286,13 @@ struct window_copy_mode_data { SEL_LINE, /* select one line at a time */ } selflag; + enum { + RECENTRE_TOP, + RECENTRE_MIDDLE, + RECENTRE_BOTTOM, + } recentre_state; + u_int recentre_line; + const char *separators; /* word separators */ u_int dx; /* drag start position */ @@ -497,6 +504,9 @@ window_copy_init(struct window_mode_entry *wme, screen_size_x(&data->screen)), data->cy, 0); screen_write_stop(&ctx); + data->recentre_state = RECENTRE_MIDDLE; + data->recentre_line = 0; + return (&data->screen); } @@ -2789,6 +2799,62 @@ window_copy_cmd_refresh_from_pane(struct window_copy_cmd_state *cs) return (WINDOW_COPY_CMD_REDRAW); } +static enum window_copy_cmd_action +window_copy_cmd_recentre_top_bottom(struct window_copy_cmd_state *cs) +{ + struct window_mode_entry *wme = cs->wme; + struct window_copy_mode_data *data = wme->data; + u_int cy = data->cy, oy = data->oy; + u_int sy = screen_size_y(&data->screen) - 1; + u_int sm = sy / 2, backing_row; + enum { MIDDLE, TOP, BOTTOM } target; + + backing_row = screen_hsize(data->backing) + cy - data->oy; + if (data->recentre_line != backing_row) { + data->recentre_state = RECENTRE_MIDDLE; + data->recentre_line = backing_row; + } + + switch (data->recentre_state) { + case RECENTRE_MIDDLE: + data->recentre_state = RECENTRE_TOP; + target = MIDDLE; + break; + case RECENTRE_TOP: + data->recentre_state = RECENTRE_BOTTOM; + target = TOP; + break; + case RECENTRE_BOTTOM: + default: + data->recentre_state = RECENTRE_MIDDLE; + target = BOTTOM; + break; + } + + oy = data->oy; + switch (target) { + case MIDDLE: + if (cy < sm) + window_copy_scroll_down(wme, sm - cy); + else if (cy > sm) + window_copy_scroll_up(wme, cy - sm); + if (data->oy != oy) + data->cy = cy + (data->oy - oy); + break; + case TOP: + window_copy_scroll_up(wme, cy); + data->cy = cy - (oy - data->oy); + break; + case BOTTOM: + window_copy_scroll_down(wme, sy - cy); + data->cy = cy + (data->oy - oy); + break; + } + window_copy_update_selection(wme, 0, 0); + + return (WINDOW_COPY_CMD_REDRAW); +} + static const struct { const char *command; u_int minargs; @@ -3173,6 +3239,12 @@ static const struct { .clear = WINDOW_COPY_CMD_CLEAR_EMACS_ONLY, .f = window_copy_cmd_previous_word }, + { .command = "recentre-top-bottom", + .args = { "", 0, 0, NULL }, + .flags = WINDOW_COPY_CMD_FLAG_READONLY, + .clear = WINDOW_COPY_CMD_CLEAR_ALWAYS, + .f = window_copy_cmd_recentre_top_bottom + }, { .command = "rectangle-on", .args = { "", 0, 0, NULL }, .flags = 0,