diff --git a/client.c b/client.c index df6cee94..7f712ffb 100644 --- a/client.c +++ b/client.c @@ -284,6 +284,12 @@ client_main(struct event_base *base, int argc, char **argv, uint64_t flags, log_debug("flags are %#llx", (unsigned long long)client_flags); /* Initialize the client socket and start the server. */ +#ifdef HAVE_SYSTEMD + if (systemd_activated()) { + /* socket-based activation, do not even try to be a client. */ + fd = server_start(client_proc, flags, base, 0, NULL); + } else +#endif fd = client_connect(base, socket_path, client_flags); if (fd == -1) { if (errno == ECONNREFUSED) { diff --git a/cmd-capture-pane.c b/cmd-capture-pane.c index 422f87d6..57e9716d 100644 --- a/cmd-capture-pane.c +++ b/cmd-capture-pane.c @@ -40,7 +40,7 @@ const struct cmd_entry cmd_capture_pane_entry = { .alias = "capturep", .args = { "ab:CeE:JNpPqS:t:", 0, 0, NULL }, - .usage = "[-aCeJNpPq] " CMD_BUFFER_USAGE " [-E end-line] " + .usage = "[-aCeJNpPqT] " CMD_BUFFER_USAGE " [-E end-line] " "[-S start-line] " CMD_TARGET_PANE_USAGE, .target = { 't', CMD_FIND_PANE, 0 }, @@ -110,7 +110,7 @@ cmd_capture_pane_history(struct args *args, struct cmdq_item *item, struct grid *gd; const struct grid_line *gl; struct grid_cell *gc = NULL; - int n, with_codes, escape_c0, join_lines, no_trim; + int n, join_lines, flags = 0; u_int i, sx, top, bottom, tmp; char *cause, *buf, *line; const char *Sflag, *Eflag; @@ -169,15 +169,19 @@ cmd_capture_pane_history(struct args *args, struct cmdq_item *item, top = tmp; } - with_codes = args_has(args, 'e'); - escape_c0 = args_has(args, 'C'); join_lines = args_has(args, 'J'); - no_trim = args_has(args, 'N'); + if (args_has(args, 'e')) + flags |= GRID_STRING_WITH_SEQUENCES; + if (args_has(args, 'C')) + flags |= GRID_STRING_ESCAPE_SEQUENCES; + if (!join_lines && !args_has(args, 'T')) + flags |= GRID_STRING_EMPTY_CELLS; + if (!join_lines && !args_has(args, 'N')) + flags |= GRID_STRING_TRIM_SPACES; buf = NULL; for (i = top; i <= bottom; i++) { - line = grid_string_cells(gd, 0, i, sx, &gc, with_codes, - escape_c0, !join_lines && !no_trim, wp->screen); + line = grid_string_cells(gd, 0, i, sx, &gc, flags, wp->screen); linelen = strlen(line); buf = cmd_capture_pane_append(buf, len, line, linelen); diff --git a/cmd-parse.y b/cmd-parse.y index 1d692770..cdf026f3 100644 --- a/cmd-parse.y +++ b/cmd-parse.y @@ -1086,7 +1086,8 @@ cmd_parse_from_arguments(struct args_value *values, u_int count, arg->type = CMD_PARSE_STRING; arg->string = copy; TAILQ_INSERT_TAIL(&cmd->arguments, arg, entry); - } + } else + free(copy); } else if (values[i].type == ARGS_COMMANDS) { arg = xcalloc(1, sizeof *arg); arg->type = CMD_PARSE_PARSED_COMMANDS; diff --git a/compat.h b/compat.h index 6eb97619..aefc0d38 100644 --- a/compat.h +++ b/compat.h @@ -423,6 +423,7 @@ void *recallocarray(void *, size_t, size_t, size_t); #ifdef HAVE_SYSTEMD /* systemd.c */ +int systemd_activated(void); int systemd_create_socket(int, char **); #endif diff --git a/compat/systemd.c b/compat/systemd.c index 7317e43a..cce42ed4 100644 --- a/compat/systemd.c +++ b/compat/systemd.c @@ -21,15 +21,23 @@ #include +#include + #include "tmux.h" +int +systemd_activated(void) +{ + return (sd_listen_fds(0) >= 1); +} + int systemd_create_socket(int flags, char **cause) { int fds; int fd; struct sockaddr_un sa; - int addrlen = sizeof sa; + socklen_t addrlen = sizeof sa; fds = sd_listen_fds(0); if (fds > 1) { /* too many file descriptors */ diff --git a/grid-view.c b/grid-view.c index 689ac4e4..4d687339 100644 --- a/grid-view.c +++ b/grid-view.c @@ -231,5 +231,5 @@ grid_view_string_cells(struct grid *gd, u_int px, u_int py, u_int nx) px = grid_view_x(gd, px); py = grid_view_y(gd, py); - return (grid_string_cells(gd, px, py, nx, NULL, 0, 0, 0, NULL)); + return (grid_string_cells(gd, px, py, nx, NULL, 0, NULL)); } diff --git a/grid.c b/grid.c index b1afd398..58de03a3 100644 --- a/grid.c +++ b/grid.c @@ -861,40 +861,45 @@ grid_string_cells_us(const struct grid_cell *gc, int *values) /* Add on SGR code. */ static void grid_string_cells_add_code(char *buf, size_t len, u_int n, int *s, int *newc, - int *oldc, size_t nnewc, size_t noldc, int escape_c0) + int *oldc, size_t nnewc, size_t noldc, int flags) { u_int i; char tmp[64]; + int reset = (n != 0 && s[0] == 0); - if (nnewc != 0 && - (nnewc != noldc || - memcmp(newc, oldc, nnewc * sizeof newc[0]) != 0 || - (n != 0 && s[0] == 0))) { - if (escape_c0) - strlcat(buf, "\\033[", len); + if (nnewc == 0) + return; /* no code to add */ + if (!reset && + nnewc == noldc && + memcmp(newc, oldc, nnewc * sizeof newc[0]) == 0) + return; /* no reset and colour unchanged */ + if (reset && (newc[0] == 49 || newc[0] == 39)) + return; /* reset and colour default */ + + if (flags & GRID_STRING_ESCAPE_SEQUENCES) + strlcat(buf, "\\033[", len); + else + strlcat(buf, "\033[", len); + for (i = 0; i < nnewc; i++) { + if (i + 1 < nnewc) + xsnprintf(tmp, sizeof tmp, "%d;", newc[i]); else - strlcat(buf, "\033[", len); - for (i = 0; i < nnewc; i++) { - if (i + 1 < nnewc) - xsnprintf(tmp, sizeof tmp, "%d;", newc[i]); - else - xsnprintf(tmp, sizeof tmp, "%d", newc[i]); - strlcat(buf, tmp, len); - } - strlcat(buf, "m", len); + xsnprintf(tmp, sizeof tmp, "%d", newc[i]); + strlcat(buf, tmp, len); } + strlcat(buf, "m", len); } static int grid_string_cells_add_hyperlink(char *buf, size_t len, const char *id, - const char *uri, int escape_c0) + const char *uri, int flags) { char *tmp; if (strlen(uri) + strlen(id) + 17 >= len) return (0); - if (escape_c0) + if (flags & GRID_STRING_ESCAPE_SEQUENCES) strlcat(buf, "\\033]8;", len); else strlcat(buf, "\033]8;", len); @@ -905,7 +910,7 @@ grid_string_cells_add_hyperlink(char *buf, size_t len, const char *id, } else strlcat(buf, ";", len); strlcat(buf, uri, len); - if (escape_c0) + if (flags & GRID_STRING_ESCAPE_SEQUENCES) strlcat(buf, "\\033\\\\", len); else strlcat(buf, "\033\\", len); @@ -918,7 +923,7 @@ grid_string_cells_add_hyperlink(char *buf, size_t len, const char *id, */ static void grid_string_cells_code(const struct grid_cell *lastgc, - const struct grid_cell *gc, char *buf, size_t len, int escape_c0, + const struct grid_cell *gc, char *buf, size_t len, int flags, struct screen *sc, int *has_link) { int oldc[64], newc[64], s[128]; @@ -927,7 +932,7 @@ grid_string_cells_code(const struct grid_cell *lastgc, char tmp[64]; const char *uri, *id; - struct { + static const struct { u_int mask; u_int code; } attrs[] = { @@ -966,7 +971,7 @@ grid_string_cells_code(const struct grid_cell *lastgc, /* Write the attributes. */ *buf = '\0'; if (n > 0) { - if (escape_c0) + if (flags & GRID_STRING_ESCAPE_SEQUENCES) strlcat(buf, "\\033[", len); else strlcat(buf, "\033[", len); @@ -988,29 +993,29 @@ grid_string_cells_code(const struct grid_cell *lastgc, nnewc = grid_string_cells_fg(gc, newc); noldc = grid_string_cells_fg(lastgc, oldc); grid_string_cells_add_code(buf, len, n, s, newc, oldc, nnewc, noldc, - escape_c0); + flags); /* If the background colour changed, append its parameters. */ nnewc = grid_string_cells_bg(gc, newc); noldc = grid_string_cells_bg(lastgc, oldc); grid_string_cells_add_code(buf, len, n, s, newc, oldc, nnewc, noldc, - escape_c0); + flags); /* If the underscore colour changed, append its parameters. */ nnewc = grid_string_cells_us(gc, newc); noldc = grid_string_cells_us(lastgc, oldc); grid_string_cells_add_code(buf, len, n, s, newc, oldc, nnewc, noldc, - escape_c0); + flags); /* Append shift in/shift out if needed. */ if ((attr & GRID_ATTR_CHARSET) && !(lastattr & GRID_ATTR_CHARSET)) { - if (escape_c0) + if (flags & GRID_STRING_ESCAPE_SEQUENCES) strlcat(buf, "\\016", len); /* SO */ else strlcat(buf, "\016", len); /* SO */ } if (!(attr & GRID_ATTR_CHARSET) && (lastattr & GRID_ATTR_CHARSET)) { - if (escape_c0) + if (flags & GRID_STRING_ESCAPE_SEQUENCES) strlcat(buf, "\\017", len); /* SI */ else strlcat(buf, "\017", len); /* SI */ @@ -1020,10 +1025,10 @@ grid_string_cells_code(const struct grid_cell *lastgc, if (sc != NULL && sc->hyperlinks != NULL && lastgc->link != gc->link) { if (hyperlinks_get(sc->hyperlinks, gc->link, &uri, &id, NULL)) { *has_link = grid_string_cells_add_hyperlink(buf, len, - id, uri, escape_c0); + id, uri, flags); } else if (*has_link) { grid_string_cells_add_hyperlink(buf, len, "", "", - escape_c0); + flags); *has_link = 0; } } @@ -1032,15 +1037,14 @@ grid_string_cells_code(const struct grid_cell *lastgc, /* Convert cells into a string. */ char * grid_string_cells(struct grid *gd, u_int px, u_int py, u_int nx, - struct grid_cell **lastgc, int with_codes, int escape_c0, int trim, - struct screen *s) + struct grid_cell **lastgc, int flags, struct screen *s) { struct grid_cell gc; static struct grid_cell lastgc1; const char *data; char *buf, code[8192]; size_t len, off, size, codelen; - u_int xx, has_link = 0; + u_int xx, has_link = 0, end; const struct grid_line *gl; if (lastgc != NULL && *lastgc == NULL) { @@ -1053,16 +1057,20 @@ grid_string_cells(struct grid *gd, u_int px, u_int py, u_int nx, off = 0; gl = grid_peek_line(gd, py); + if (flags & GRID_STRING_EMPTY_CELLS) + end = gl->cellsize; + else + end = gl->cellused; for (xx = px; xx < px + nx; xx++) { - if (gl == NULL || xx >= gl->cellused) + if (gl == NULL || xx >= end) break; grid_get_cell(gd, xx, py, &gc); if (gc.flags & GRID_FLAG_PADDING) continue; - if (with_codes) { + if (flags & GRID_STRING_WITH_SEQUENCES) { grid_string_cells_code(*lastgc, &gc, code, sizeof code, - escape_c0, s, &has_link); + flags, s, &has_link); codelen = strlen(code); memcpy(*lastgc, &gc, sizeof **lastgc); } else @@ -1070,7 +1078,9 @@ grid_string_cells(struct grid *gd, u_int px, u_int py, u_int nx, data = gc.data.data; size = gc.data.size; - if (escape_c0 && size == 1 && *data == '\\') { + if ((flags & GRID_STRING_ESCAPE_SEQUENCES) && + size == 1 && + *data == '\\') { data = "\\\\"; size = 2; } @@ -1090,7 +1100,7 @@ grid_string_cells(struct grid *gd, u_int px, u_int py, u_int nx, if (has_link) { grid_string_cells_add_hyperlink(code, sizeof code, "", "", - escape_c0); + flags); codelen = strlen(code); while (len < off + size + codelen + 1) { buf = xreallocarray(buf, 2, len); @@ -1100,7 +1110,7 @@ grid_string_cells(struct grid *gd, u_int px, u_int py, u_int nx, off += codelen; } - if (trim) { + if (flags & GRID_STRING_TRIM_SPACES) { while (off > 0 && buf[off - 1] == ' ') off--; } diff --git a/input.c b/input.c index 347e57ab..174bf76d 100644 --- a/input.c +++ b/input.c @@ -1899,7 +1899,7 @@ input_csi_dispatch_winops(struct input_ctx *ictx) } break; case 18: - input_reply(ictx, "\033[8;%u;%ut", x, y); + input_reply(ictx, "\033[8;%u;%ut", y, x); break; default: log_debug("%s: unknown '%c'", __func__, ictx->ch); @@ -2242,7 +2242,6 @@ static int input_dcs_dispatch(struct input_ctx *ictx) { struct window_pane *wp = ictx->wp; - struct options *oo = wp->options; struct screen_write_ctx *sctx = &ictx->ctx; struct window *w = wp->window; u_char *buf = ictx->input_buf; @@ -2256,7 +2255,8 @@ input_dcs_dispatch(struct input_ctx *ictx) return (0); if (ictx->flags & INPUT_DISCARD) return (0); - allow_passthrough = options_get_number(oo, "allow-passthrough"); + allow_passthrough = options_get_number(wp->options, + "allow-passthrough"); if (!allow_passthrough) return (0); log_debug("%s: \"%s\"", __func__, buf); diff --git a/options-table.c b/options-table.c index f7e91da1..d4e7b204 100644 --- a/options-table.c +++ b/options-table.c @@ -41,6 +41,9 @@ static const char *options_table_clock_mode_style_list[] = { static const char *options_table_status_list[] = { "off", "on", "2", "3", "4", "5", NULL }; +static const char *options_table_message_line_list[] = { + "0", "1", "2", "3", "4", NULL +}; static const char *options_table_status_keys_list[] = { "emacs", "vi", NULL }; @@ -541,13 +544,21 @@ const struct options_table_entry options_table[] = { "'mode-keys' is set to 'vi'." }, + { .name = "message-line", + .type = OPTIONS_TABLE_CHOICE, + .scope = OPTIONS_TABLE_SESSION, + .choices = options_table_message_line_list, + .default_num = 0, + .text = "Position (line) of messages and the command prompt." + }, + { .name = "message-style", .type = OPTIONS_TABLE_STRING, .scope = OPTIONS_TABLE_SESSION, .default_str = "bg=yellow,fg=black", .flags = OPTIONS_TABLE_IS_STYLE, .separator = ",", - .text = "Style of the command prompt." + .text = "Style of messages and the command prompt." }, { .name = "mouse", diff --git a/regress/conf/2eae5d47049c1f6d0bef3db4e171aed7.conf b/regress/conf/2eae5d47049c1f6d0bef3db4e171aed7.conf index c09adc24..c3a4da4b 100644 --- a/regress/conf/2eae5d47049c1f6d0bef3db4e171aed7.conf +++ b/regress/conf/2eae5d47049c1f6d0bef3db4e171aed7.conf @@ -12,7 +12,7 @@ set-window-option -g pane-base-index 1 unbind ^B bind ^B select-pane -t :.+ -# Reload config wtih a key +# Reload config with a key bind-key r source-file ~/.tmux.conf \; display "Config reloaded!" # Mouse works as expected diff --git a/regress/conf/a46e6e84cd1071105aa807256dbc158d.conf b/regress/conf/a46e6e84cd1071105aa807256dbc158d.conf index bfbb2d3e..d8fd9d20 100644 --- a/regress/conf/a46e6e84cd1071105aa807256dbc158d.conf +++ b/regress/conf/a46e6e84cd1071105aa807256dbc158d.conf @@ -24,7 +24,7 @@ set-option -g default-terminal 'screen-256color' # allow Vim to receive focus events from terminal window set-option -g focus-events on -# allow Vim to recieve modifier keys: Shift, Control, Alt +# allow Vim to receive modifier keys: Shift, Control, Alt set-window-option -g xterm-keys on # prevent tmux from catching modifier keys meant for Vim diff --git a/regress/conf/ad21dbb0893240563ddfdd954b9903a1.conf b/regress/conf/ad21dbb0893240563ddfdd954b9903a1.conf index 27d8f310..0c41caa4 100644 --- a/regress/conf/ad21dbb0893240563ddfdd954b9903a1.conf +++ b/regress/conf/ad21dbb0893240563ddfdd954b9903a1.conf @@ -552,7 +552,7 @@ setw -g status-keys emacs # Changelog: https://github.com/tmux/tmux/blob/master/CHANGES # style colors: default, black, red, green, yellow, blue, magenta, cyan, white, -# colour0-colour255, hexdecimal RGB string '#ffffff' +# colour0-colour255, hexadecimal RGB string '#ffffff' # Use $SCRIPTS/bash/256-colors.sh to figure out the color number you want # style attributes: none, bold/bright, dim, underscore, blink, reverse, hidden, # or italics diff --git a/regress/conf/b9f0ce1976ec62ec60dc5da7dd92c160.conf b/regress/conf/b9f0ce1976ec62ec60dc5da7dd92c160.conf index 0a878369..845002c2 100644 --- a/regress/conf/b9f0ce1976ec62ec60dc5da7dd92c160.conf +++ b/regress/conf/b9f0ce1976ec62ec60dc5da7dd92c160.conf @@ -1,6 +1,6 @@ -# none of these attempts worked, to bind keys, except sometimes during the sesssion. Oh well. +# none of these attempts worked, to bind keys, except sometimes during the session. Oh well. # I thought maybe that was because F1 is handled differently in a console than in X, but -# even just C-1 didnt work. Using just "a" or "x" as the key did, but not yet sure why not "C-". +# even just C-1 didn't work. Using just "a" or "x" as the key did, but not yet sure why not "C-". #bind-key -T root C-1 attach-session -t$0 #But this one works now, only picks the wrong one? Mbe need2understand what "$1" or $0 mean, better, #but with the stub maybe this doesn't matter: @@ -47,7 +47,7 @@ select-window -t :=3 #$3 for email (mutt) new-session sula new-window sula ; send-keys mutt Enter -#nah, probly betr not?: +#nah, probably better not?: #send-keys -l z #send-keys -l "thepassifdecide" #send-keys Enter diff --git a/regress/conf/e2661d67d0d45a8647fb95de76ec8174.conf b/regress/conf/e2661d67d0d45a8647fb95de76ec8174.conf index 79f46df1..3cf1ae9d 100644 --- a/regress/conf/e2661d67d0d45a8647fb95de76ec8174.conf +++ b/regress/conf/e2661d67d0d45a8647fb95de76ec8174.conf @@ -63,7 +63,7 @@ bind N command-prompt -p hosts: 'run-shell -b "bash -c \"~/lbin/nw %% >/dev/null #05:59 < Celti> annihilannic: I believe the #{pane_in_mode} format does what you want #05:59 < Celti> put it in your statusline #05:59 < Celti> annihilannic: No, my mistake, I should have read farther down, you want #{pane_synchronized} -# only works in tmux 2.0?, higher than 1.6.3 anyawy +# only works in tmux 2.0?, higher than 1.6.3 anyway set-option -g window-status-format ' #I:#W#F#{?pane_synchronized,S,}' #set-option -g window-status-current-format ' #I:#W#{?pane_synchronized,[sync],}#F' # to highlight in red when sync is on... not sure why I did this with set-window-option instead of set-option, perhaps diff --git a/screen-write.c b/screen-write.c index 439d0532..458cb348 100644 --- a/screen-write.c +++ b/screen-write.c @@ -1561,7 +1561,8 @@ screen_write_fullredraw(struct screen_write_ctx *ctx) screen_write_collect_flush(ctx, 0, __func__); screen_write_initctx(ctx, &ttyctx, 1); - ttyctx.redraw_cb(&ttyctx); + if (ttyctx.redraw_cb != NULL) + ttyctx.redraw_cb(&ttyctx); } /* Trim collected items. */ @@ -2241,7 +2242,8 @@ screen_write_alternateon(struct screen_write_ctx *ctx, struct grid_cell *gc, screen_alternate_on(ctx->s, gc, cursor); screen_write_initctx(ctx, &ttyctx, 1); - ttyctx.redraw_cb(&ttyctx); + if (ttyctx.redraw_cb != NULL) + ttyctx.redraw_cb(&ttyctx); } /* Turn alternate screen off. */ @@ -2259,5 +2261,6 @@ screen_write_alternateoff(struct screen_write_ctx *ctx, struct grid_cell *gc, screen_alternate_off(ctx->s, gc, cursor); screen_write_initctx(ctx, &ttyctx, 1); - ttyctx.redraw_cb(&ttyctx); + if (ttyctx.redraw_cb != NULL) + ttyctx.redraw_cb(&ttyctx); } diff --git a/session.c b/session.c index 75028882..71435cdf 100644 --- a/session.c +++ b/session.c @@ -708,7 +708,7 @@ session_renumber_windows(struct session *s) struct winlink *wl, *wl1, *wl_new; struct winlinks old_wins; struct winlink_stack old_lastw; - int new_idx, new_curw_idx; + int new_idx, new_curw_idx, marked_idx = -1; /* Save and replace old window list. */ memcpy(&old_wins, &s->windows, sizeof old_wins); @@ -725,6 +725,8 @@ session_renumber_windows(struct session *s) winlink_set_window(wl_new, wl->window); wl_new->flags |= wl->flags & WINLINK_ALERTFLAGS; + if (wl == marked_pane.wl) + marked_idx = wl_new->idx; if (wl == s->curw) new_curw_idx = wl_new->idx; @@ -741,6 +743,11 @@ session_renumber_windows(struct session *s) } /* Set the current window. */ + if (marked_idx != -1) { + marked_pane.wl = winlink_find_by_index(&s->windows, marked_idx); + if (marked_pane.wl == NULL) + server_clear_marked(); + } s->curw = winlink_find_by_index(&s->windows, new_curw_idx); /* Free the old winlinks (reducing window references too). */ diff --git a/status.c b/status.c index 929276d2..b504bbbe 100644 --- a/status.c +++ b/status.c @@ -263,6 +263,17 @@ status_line_size(struct client *c) return (s->statuslines); } +/* Get the prompt line number for client's session. 1 means at the bottom. */ +static u_int +status_prompt_line_at(struct client *c) +{ + struct session *s = c->session; + + if (c->flags & (CLIENT_STATUSOFF|CLIENT_CONTROL)) + return (1); + return (options_get_number(s->options, "message-line")); +} + /* Get window at window list position. */ struct style_range * status_get_range(struct client *c, u_int x, u_int y) @@ -533,7 +544,7 @@ status_message_redraw(struct client *c) struct session *s = c->session; struct screen old_screen; size_t len; - u_int lines, offset; + u_int lines, offset, messageline; struct grid_cell gc; struct format_tree *ft; @@ -546,6 +557,10 @@ status_message_redraw(struct client *c) lines = 1; screen_init(sl->active, c->tty.sx, lines, 0); + messageline = status_prompt_line_at(c); + if (messageline > lines - 1) + messageline = lines - 1; + len = screen_write_strlen("%s", c->message_string); if (len > c->tty.sx) len = c->tty.sx; @@ -555,11 +570,11 @@ status_message_redraw(struct client *c) format_free(ft); screen_write_start(&ctx, sl->active); - screen_write_fast_copy(&ctx, &sl->screen, 0, 0, c->tty.sx, lines - 1); - screen_write_cursormove(&ctx, 0, lines - 1, 0); + screen_write_fast_copy(&ctx, &sl->screen, 0, 0, c->tty.sx, lines); + screen_write_cursormove(&ctx, 0, messageline, 0); for (offset = 0; offset < c->tty.sx; offset++) screen_write_putc(&ctx, &gc, ' '); - screen_write_cursormove(&ctx, 0, lines - 1, 0); + screen_write_cursormove(&ctx, 0, messageline, 0); if (c->message_ignore_styles) screen_write_nputs(&ctx, len, &gc, "%s", c->message_string); else @@ -695,7 +710,7 @@ status_prompt_redraw(struct client *c) struct session *s = c->session; struct screen old_screen; u_int i, lines, offset, left, start, width; - u_int pcursor, pwidth; + u_int pcursor, pwidth, promptline; struct grid_cell gc, cursorgc; struct format_tree *ft; @@ -708,6 +723,10 @@ status_prompt_redraw(struct client *c) lines = 1; screen_init(sl->active, c->tty.sx, lines, 0); + promptline = status_prompt_line_at(c); + if (promptline > lines - 1) + promptline = lines - 1; + ft = format_create_defaults(NULL, c, NULL, NULL, NULL); if (c->prompt_mode == PROMPT_COMMAND) style_apply(&gc, s->options, "message-command-style", ft); @@ -723,13 +742,13 @@ status_prompt_redraw(struct client *c) start = c->tty.sx; screen_write_start(&ctx, sl->active); - screen_write_fast_copy(&ctx, &sl->screen, 0, 0, c->tty.sx, lines - 1); - screen_write_cursormove(&ctx, 0, lines - 1, 0); + screen_write_fast_copy(&ctx, &sl->screen, 0, 0, c->tty.sx, lines); + screen_write_cursormove(&ctx, 0, promptline, 0); for (offset = 0; offset < c->tty.sx; offset++) screen_write_putc(&ctx, &gc, ' '); - screen_write_cursormove(&ctx, 0, lines - 1, 0); + screen_write_cursormove(&ctx, 0, promptline, 0); format_draw(&ctx, &gc, start, c->prompt_string, NULL, 0); - screen_write_cursormove(&ctx, start, lines - 1, 0); + screen_write_cursormove(&ctx, start, promptline, 0); left = c->tty.sx - start; if (left == 0) diff --git a/tmux.1 b/tmux.1 index ed327479..d61324fc 100644 --- a/tmux.1 +++ b/tmux.1 @@ -1811,7 +1811,9 @@ The following commands are supported in copy mode: .It Li "search-forward " Ta "/" Ta "" .It Li "search-forward-incremental " Ta "" Ta "C-s" .It Li "search-forward-text " Ta "" Ta "" +.It Li "scroll-bottom" Ta "" Ta "" .It Li "scroll-middle" Ta "z" Ta "" +.It Li "scroll-top" Ta "" Ta "" .It Li "search-reverse" Ta "N" Ta "N" .It Li "select-line" Ta "V" Ta "" .It Li "select-word" Ta "" Ta "" @@ -2014,7 +2016,7 @@ but a different format may be specified with .Fl F . .Tg capturep .It Xo Ic capture-pane -.Op Fl aepPqCJN +.Op Fl aAepPqCJN .Op Fl b Ar buffer-name .Op Fl E Ar end-line .Op Fl S Ar start-line @@ -2039,10 +2041,15 @@ is given, the output includes escape sequences for text and background attributes. .Fl C also escapes non-printable characters as octal \exxx. +.Fl T +ignores trailing positions that do not contain a character. .Fl N preserves trailing spaces at each line's end and .Fl J -preserves trailing spaces and joins any wrapped lines. +preserves trailing spaces and joins any wrapped lines; +.Fl J +implies +.Fl T . .Fl P captures only any output that the pane has received that is the beginning of an as-yet incomplete escape sequence. @@ -3876,6 +3883,10 @@ For how to specify see the .Sx STYLES section. +.It Xo Ic message-line +.Op Ic 0 | 1 | 2 | 3 | 4 +.Xc +Set line on which status line messages and the command prompt are shown. .It Ic message-style Ar style Set status line message style. This is used for messages and for the command prompt. diff --git a/tmux.h b/tmux.h index 52852817..e205bcfa 100644 --- a/tmux.h +++ b/tmux.h @@ -670,6 +670,14 @@ struct colour_palette { #define GRID_LINE_EXTENDED 0x2 #define GRID_LINE_DEAD 0x4 +/* Grid string flags. */ +#define GRID_STRING_WITH_SEQUENCES 0x1 +#define GRID_STRING_ESCAPE_SEQUENCES 0x2 +#define GRID_STRING_TRIM_SPACES 0x4 +#define GRID_STRING_USED_ONLY 0x8 +#define GRID_STRING_EMPTY_CELLS 0x10 + +/* Cell positions. */ #define CELL_INSIDE 0 #define CELL_TOPBOTTOM 1 #define CELL_LEFTRIGHT 2 @@ -684,6 +692,7 @@ struct colour_palette { #define CELL_JOIN 11 #define CELL_OUTSIDE 12 +/* Cell borders. */ #define CELL_BORDERS " xqlkmjwvtun~" #define SIMPLE_BORDERS " |-+++++++++." #define PADDED_BORDERS " " @@ -2807,7 +2816,7 @@ void grid_clear_lines(struct grid *, u_int, u_int, u_int); void grid_move_lines(struct grid *, u_int, u_int, u_int, u_int); void grid_move_cells(struct grid *, u_int, u_int, u_int, u_int, u_int); char *grid_string_cells(struct grid *, u_int, u_int, u_int, - struct grid_cell **, int, int, int, struct screen *); + struct grid_cell **, int, struct screen *); void grid_duplicate_lines(struct grid *, u_int, struct grid *, u_int, u_int); void grid_reflow(struct grid *, u_int); diff --git a/window-copy.c b/window-copy.c index 743364d6..ed481d70 100644 --- a/window-copy.c +++ b/window-copy.c @@ -1250,20 +1250,23 @@ window_copy_cmd_cursor_right(struct window_copy_cmd_state *cs) return (WINDOW_COPY_CMD_NOTHING); } +/* Scroll line containing the cursor to the given position. */ static enum window_copy_cmd_action -window_copy_cmd_scroll_middle(struct window_copy_cmd_state *cs) +window_copy_cmd_scroll_to(struct window_copy_cmd_state *cs, u_int to) { struct window_mode_entry *wme = cs->wme; struct window_copy_mode_data *data = wme->data; - u_int mid_value, oy, delta; + u_int oy, delta; int scroll_up; /* >0 up, <0 down */ - mid_value = (screen_size_y(&data->screen) - 1) / 2; - scroll_up = data->cy - mid_value; + scroll_up = data->cy - to; delta = abs(scroll_up); - oy = screen_hsize(data->backing) + data->cy - data->oy; + oy = screen_hsize(data->backing) - data->oy; - log_debug ("XXX %u %u %u %d %u", mid_value, oy, delta, scroll_up, data->oy); + /* + * oy is the maximum scroll down amount, while data->oy is the maximum + * scroll up amount. + */ if (scroll_up > 0 && data->oy >= delta) { window_copy_scroll_up(wme, delta); data->cy -= delta; @@ -1276,6 +1279,35 @@ window_copy_cmd_scroll_middle(struct window_copy_cmd_state *cs) return (WINDOW_COPY_CMD_REDRAW); } +/* Scroll line containing the cursor to the bottom. */ +static enum window_copy_cmd_action +window_copy_cmd_scroll_bottom(struct window_copy_cmd_state *cs) +{ + struct window_copy_mode_data *data = cs->wme->data; + u_int bottom; + + bottom = screen_size_y(&data->screen) - 1; + return (window_copy_cmd_scroll_to(cs, bottom)); +} + +/* Scroll line containing the cursor to the middle. */ +static enum window_copy_cmd_action +window_copy_cmd_scroll_middle(struct window_copy_cmd_state *cs) +{ + struct window_copy_mode_data *data = cs->wme->data; + u_int mid_value; + + mid_value = (screen_size_y(&data->screen) - 1) / 2; + return (window_copy_cmd_scroll_to(cs, mid_value)); +} + +/* Scroll line containing the cursor to the top. */ +static enum window_copy_cmd_action +window_copy_cmd_scroll_top(struct window_copy_cmd_state *cs) +{ + return (window_copy_cmd_scroll_to(cs, 0)); +} + static enum window_copy_cmd_action window_copy_cmd_cursor_up(struct window_copy_cmd_state *cs) { @@ -2794,6 +2826,12 @@ static const struct { .clear = WINDOW_COPY_CMD_CLEAR_ALWAYS, .f = window_copy_cmd_refresh_from_pane }, + { .command = "scroll-bottom", + .minargs = 0, + .maxargs = 0, + .clear = WINDOW_COPY_CMD_CLEAR_ALWAYS, + .f = window_copy_cmd_scroll_bottom + }, { .command = "scroll-down", .minargs = 0, .maxargs = 0, @@ -2812,6 +2850,12 @@ static const struct { .clear = WINDOW_COPY_CMD_CLEAR_ALWAYS, .f = window_copy_cmd_scroll_middle }, + { .command = "scroll-top", + .minargs = 0, + .maxargs = 0, + .clear = WINDOW_COPY_CMD_CLEAR_ALWAYS, + .f = window_copy_cmd_scroll_top + }, { .command = "scroll-up", .minargs = 0, .maxargs = 0,