diff options
| author | wiz <wiz@NetBSD.org> | 2023-06-28 22:21:26 +0000 |
|---|---|---|
| committer | wiz <wiz@NetBSD.org> | 2023-06-28 22:21:26 +0000 |
| commit | ae2d633ddc09491a8082bd3d121f9fa1d3479559 (patch) | |
| tree | e3d3a92345c233344a82a358bce8696aff793a12 /external | |
| parent | e0fe29fb58e10db52f0ee6ad9ccbab2b2cb89886 (diff) | |
merge tmux 3.3a
Diffstat (limited to 'external')
58 files changed, 5944 insertions, 2485 deletions
diff --git a/external/bsd/tmux/dist/client.c b/external/bsd/tmux/dist/client.c index fc0e1dde166..df6cee941fa 100644 --- a/external/bsd/tmux/dist/client.c +++ b/external/bsd/tmux/dist/client.c @@ -243,6 +243,7 @@ client_main(struct event_base *base, int argc, char **argv, uint64_t flags, ssize_t linelen; char *line = NULL, **caps = NULL, *cause; u_int ncaps = 0; + struct args_value *values; /* Ignore SIGCHLD now or daemon() in the server will leave a zombie. */ signal(SIGCHLD, SIG_IGN); @@ -258,17 +259,20 @@ client_main(struct event_base *base, int argc, char **argv, uint64_t flags, msg = MSG_COMMAND; /* - * It sucks parsing the command string twice (in client and - * later in server) but it is necessary to get the start server - * flag. + * It's annoying parsing the command string twice (in client + * and later in server) but it is necessary to get the start + * server flag. */ - pr = cmd_parse_from_arguments(argc, argv, NULL); + values = args_from_vector(argc, argv); + pr = cmd_parse_from_arguments(values, argc, NULL); if (pr->status == CMD_PARSE_SUCCESS) { if (cmd_list_any_have(pr->cmdlist, CMD_STARTSERVER)) flags |= CLIENT_STARTSERVER; cmd_list_free(pr->cmdlist); } else free(pr->error); + args_free_values(values, argc); + free(values); } /* Create client process structure (starts logging). */ @@ -357,6 +361,7 @@ client_main(struct event_base *base, int argc, char **argv, uint64_t flags, /* Send identify messages. */ client_send_identify(ttynam, termname, caps, ncaps, cwd, feat); tty_term_free_list(caps, ncaps); + proc_flush_peer(client_peer); /* Send first command. */ if (msg == MSG_COMMAND) { @@ -527,7 +532,7 @@ client_signal(int sig) if (sig == SIGCHLD) waitpid(WAIT_ANY, &status, WNOHANG); else if (!client_attached) { - if (sig == SIGTERM) + if (sig == SIGTERM || sig == SIGHUP) proc_exit(client_proc); } else { switch (sig) { diff --git a/external/bsd/tmux/dist/cmd-attach-session.c b/external/bsd/tmux/dist/cmd-attach-session.c index e7b8b261a15..022d0d3cb5a 100644 --- a/external/bsd/tmux/dist/cmd-attach-session.c +++ b/external/bsd/tmux/dist/cmd-attach-session.c @@ -37,13 +37,13 @@ const struct cmd_entry cmd_attach_session_entry = { .name = "attach-session", .alias = "attach", - .args = { "c:dEf:rt:x", 0, 0 }, + .args = { "c:dEf:rt:x", 0, 0, NULL }, .usage = "[-dErx] [-c working-directory] [-f flags] " CMD_TARGET_SESSION_USAGE, /* -t is special */ - .flags = CMD_STARTSERVER, + .flags = CMD_STARTSERVER|CMD_READONLY, .exec = cmd_attach_session_exec }; @@ -69,6 +69,7 @@ cmd_attach_session(struct cmdq_item *item, const char *tflag, int dflag, if (c == NULL) return (CMD_RETURN_NORMAL); + if (server_client_check_nested(c)) { cmdq_error(item, "sessions should be nested with care, " "unset $TMUX to force"); @@ -124,17 +125,9 @@ cmd_attach_session(struct cmdq_item *item, const char *tflag, int dflag, if (!Eflag) environ_update(s->options, c->environ, s->environ); - c->session = s; + server_client_set_session(c, s); if (~cmdq_get_flags(item) & CMDQ_STATE_REPEAT) server_client_set_key_table(c, NULL); - tty_update_client_offset(c); - status_timer_start(c); - notify_client("client-session-changed", c); - session_update_activity(s, NULL); - gettimeofday(&s->last_attached_time, NULL); - server_redraw_client(c); - s->curw->flags &= ~WINLINK_ALERTFLAGS; - s->curw->window->latest = c; } else { if (server_client_open(c, &cause) != 0) { cmdq_error(item, "open terminal failed: %s", cause); @@ -156,25 +149,14 @@ cmd_attach_session(struct cmdq_item *item, const char *tflag, int dflag, if (!Eflag) environ_update(s->options, c->environ, s->environ); - c->session = s; + server_client_set_session(c, s); server_client_set_key_table(c, NULL); - tty_update_client_offset(c); - status_timer_start(c); - notify_client("client-session-changed", c); - session_update_activity(s, NULL); - gettimeofday(&s->last_attached_time, NULL); - server_redraw_client(c); - s->curw->flags &= ~WINLINK_ALERTFLAGS; - s->curw->window->latest = c; if (~c->flags & CLIENT_CONTROL) proc_send(c->peer, MSG_READY, -1, NULL, 0); notify_client("client-attached", c); c->flags |= CLIENT_ATTACHED; } - recalculate_sizes(); - alerts_check_session(s); - server_update_socket(); return (CMD_RETURN_NORMAL); } diff --git a/external/bsd/tmux/dist/cmd-capture-pane.c b/external/bsd/tmux/dist/cmd-capture-pane.c index d919b0cd147..57ec9043af0 100644 --- a/external/bsd/tmux/dist/cmd-capture-pane.c +++ b/external/bsd/tmux/dist/cmd-capture-pane.c @@ -39,7 +39,7 @@ const struct cmd_entry cmd_capture_pane_entry = { .name = "capture-pane", .alias = "capturep", - .args = { "ab:CeE:JNpPqS:t:", 0, 0 }, + .args = { "ab:CeE:JNpPqS:t:", 0, 0, NULL }, .usage = "[-aCeJNpPq] " CMD_BUFFER_USAGE " [-E end-line] " "[-S start-line] " CMD_TARGET_PANE_USAGE, @@ -53,7 +53,7 @@ const struct cmd_entry cmd_clear_history_entry = { .name = "clear-history", .alias = "clearhist", - .args = { "t:", 0, 0 }, + .args = { "t:", 0, 0, NULL }, .usage = CMD_TARGET_PANE_USAGE, .target = { 't', CMD_FIND_PANE, 0 }, diff --git a/external/bsd/tmux/dist/cmd-display-menu.c b/external/bsd/tmux/dist/cmd-display-menu.c index ff6e4fe422d..543511f9d04 100644 --- a/external/bsd/tmux/dist/cmd-display-menu.c +++ b/external/bsd/tmux/dist/cmd-display-menu.c @@ -27,16 +27,18 @@ * Display a menu on a client. */ -static enum cmd_retval cmd_display_menu_exec(struct cmd *, - struct cmdq_item *); -static enum cmd_retval cmd_display_popup_exec(struct cmd *, - struct cmdq_item *); +static enum args_parse_type cmd_display_menu_args_parse(struct args *, + u_int, char **); +static enum cmd_retval cmd_display_menu_exec(struct cmd *, + struct cmdq_item *); +static enum cmd_retval cmd_display_popup_exec(struct cmd *, + struct cmdq_item *); const struct cmd_entry cmd_display_menu_entry = { .name = "display-menu", .alias = "menu", - .args = { "c:t:OT:x:y:", 1, -1 }, + .args = { "c:t:OT:x:y:", 1, -1, cmd_display_menu_args_parse }, .usage = "[-O] [-c target-client] " CMD_TARGET_PANE_USAGE " [-T title] " "[-x position] [-y position] name key command ...", @@ -50,10 +52,12 @@ const struct cmd_entry cmd_display_popup_entry = { .name = "display-popup", .alias = "popup", - .args = { "Cc:d:Eh:t:w:x:y:", 0, -1 }, - .usage = "[-CE] [-c target-client] [-d start-directory] [-h height] " - CMD_TARGET_PANE_USAGE " [-w width] " - "[-x position] [-y position] [command]", + .args = { "Bb:Cc:d:e:Eh:s:S:t:T:w:x:y:", 0, -1, NULL }, + .usage = "[-BCE] [-b border-lines] [-c target-client] " + "[-d start-directory] [-e environment] [-h height] " + "[-s style] [-S border-style] " CMD_TARGET_PANE_USAGE + "[-T title] [-w width] [-x position] [-y position] " + "[shell-command]", .target = { 't', CMD_FIND_PANE, 0 }, @@ -61,6 +65,30 @@ const struct cmd_entry cmd_display_popup_entry = { .exec = cmd_display_popup_exec }; +static enum args_parse_type +cmd_display_menu_args_parse(struct args *args, u_int idx, __unused char **cause) +{ + u_int i = 0; + enum args_parse_type type = ARGS_PARSE_STRING; + + for (;;) { + type = ARGS_PARSE_STRING; + if (i == idx) + break; + if (*args_string(args, i++) == '\0') + continue; + + type = ARGS_PARSE_STRING; + if (i++ == idx) + break; + + type = ARGS_PARSE_COMMANDS_OR_STRING; + if (i++ == idx) + break; + } + return (type); +} + static int cmd_display_menu_get_position(struct client *tc, struct cmdq_item *item, struct args *args, u_int *px, u_int *py, u_int w, u_int h) @@ -120,8 +148,6 @@ cmd_display_menu_get_position(struct client *tc, struct cmdq_item *item, if (sr != NULL) break; } - if (line == lines) - ranges = &tc->status.entries[0].ranges; if (sr != NULL) { format_add(ft, "popup_window_status_line_x", "%u", @@ -174,8 +200,8 @@ cmd_display_menu_get_position(struct client *tc, struct cmdq_item *item, } else format_add(ft, "popup_mouse_centre_y", "%ld", n); n = (long)event->m.y + h; - if (n + h >= tty->sy) - format_add(ft, "popup_mouse_top", "%u", tty->sy - h); + if (n >= tty->sy) + format_add(ft, "popup_mouse_top", "%u", tty->sy - 1); else format_add(ft, "popup_mouse_top", "%ld", n); n = event->m.y - h; @@ -219,7 +245,7 @@ cmd_display_menu_get_position(struct client *tc, struct cmdq_item *item, else if (n < 0) n = 0; *px = n; - log_debug("%s: -x: %s = %s = %u", __func__, xp, p, *px); + log_debug("%s: -x: %s = %s = %u (-w %u)", __func__, xp, p, *px, w); free(p); /* Expand vertical position */ @@ -245,7 +271,7 @@ cmd_display_menu_get_position(struct client *tc, struct cmdq_item *item, else if (n < 0) n = 0; *py = n; - log_debug("%s: -y: %s = %s = %u", __func__, yp, p, *py); + log_debug("%s: -y: %s = %s = %u (-h %u)", __func__, yp, p, *py, h); free(p); return (1); @@ -260,10 +286,10 @@ cmd_display_menu_exec(struct cmd *self, struct cmdq_item *item) struct client *tc = cmdq_get_target_client(item); struct menu *menu = NULL; struct menu_item menu_item; - const char *key; - char *title, *name; - int flags = 0, i; - u_int px, py; + const char *key, *name; + char *title; + int flags = 0; + u_int px, py, i, count = args_count(args); if (tc->overlay_draw != NULL) return (CMD_RETURN_NORMAL); @@ -274,24 +300,24 @@ cmd_display_menu_exec(struct cmd *self, struct cmdq_item *item) title = xstrdup(""); menu = menu_create(title); - for (i = 0; i != args->argc; /* nothing */) { - name = args->argv[i++]; + for (i = 0; i != count; /* nothing */) { + name = args_string(args, i++); if (*name == '\0') { menu_add_item(menu, NULL, item, tc, target); continue; } - if (args->argc - i < 2) { + if (count - i < 2) { cmdq_error(item, "not enough arguments"); free(title); menu_free(menu); return (CMD_RETURN_ERROR); } - key = args->argv[i++]; + key = args_string(args, i++); menu_item.name = name; menu_item.key = key_string_lookup_string(key); - menu_item.command = args->argv[i++]; + menu_item.command = args_string(args, i++); menu_add_item(menu, &menu_item, item, tc, target); } @@ -328,11 +354,17 @@ cmd_display_popup_exec(struct cmd *self, struct cmdq_item *item) struct session *s = target->s; struct client *tc = cmdq_get_target_client(item); struct tty *tty = &tc->tty; - const char *value, *shell[] = { NULL, NULL }; - const char *shellcmd = NULL; - char *cwd, *cause, **argv = args->argv; - int flags = 0, argc = args->argc; - u_int px, py, w, h; + const char *value, *shell, *shellcmd = NULL; + const char *style = args_get(args, 's'); + const char *border_style = args_get(args, 'S'); + char *cwd, *cause = NULL, **argv = NULL, *title; + int flags = 0, argc = 0; + enum box_lines lines = BOX_LINES_DEFAULT; + u_int px, py, w, h, count = args_count(args); + struct args_value *av; + struct environ *env = NULL; + struct options *o = s->curw->window->options; + struct options_entry *oe; if (args_has(args, 'C')) { server_client_clear_overlay(tc); @@ -361,37 +393,73 @@ cmd_display_popup_exec(struct cmd *self, struct cmdq_item *item) } } - if (w > tty->sx - 1) - w = tty->sx - 1; - if (h > tty->sy - 1) - h = tty->sy - 1; + if (w > tty->sx) + w = tty->sx; + if (h > tty->sy) + h = tty->sy; if (!cmd_display_menu_get_position(tc, item, args, &px, &py, w, h)) return (CMD_RETURN_NORMAL); + value = args_get(args, 'b'); + if (args_has(args, 'B')) + lines = BOX_LINES_NONE; + else if (value != NULL) { + oe = options_get(o, "popup-border-lines"); + lines = options_find_choice(options_table_entry(oe), value, + &cause); + if (cause != NULL) { + cmdq_error(item, "popup-border-lines %s", cause); + free(cause); + return (CMD_RETURN_ERROR); + } + } + value = args_get(args, 'd'); if (value != NULL) cwd = format_single_from_target(item, value); else cwd = xstrdup(server_client_get_cwd(tc, s)); - if (argc == 0) + if (count == 0) shellcmd = options_get_string(s->options, "default-command"); - else if (argc == 1) - shellcmd = argv[0]; - if (argc <= 1 && (shellcmd == NULL || *shellcmd == '\0')) { + else if (count == 1) + shellcmd = args_string(args, 0); + if (count <= 1 && (shellcmd == NULL || *shellcmd == '\0')) { shellcmd = NULL; - shell[0] = options_get_string(s->options, "default-shell"); - if (!checkshell(shell[0])) - shell[0] = _PATH_BSHELL; - argc = 1; - argv = __UNCONST(shell); + shell = options_get_string(s->options, "default-shell"); + if (!checkshell(shell)) + shell = _PATH_BSHELL; + cmd_append_argv(&argc, &argv, shell); + } else + args_to_vector(args, &argc, &argv); + + if (args_has(args, 'e') >= 1) { + env = environ_create(); + av = args_first_value(args, 'e'); + while (av != NULL) { + environ_put(env, av->string, 0); + av = args_next_value(av); + } } + if (args_has(args, 'T')) + title = format_single_from_target(item, args_get(args, 'T')); + else + title = xstrdup(""); if (args_has(args, 'E') > 1) flags |= POPUP_CLOSEEXITZERO; else if (args_has(args, 'E')) flags |= POPUP_CLOSEEXIT; - if (popup_display(flags, item, px, py, w, h, shellcmd, argc, argv, cwd, - tc, s, NULL, NULL) != 0) + if (popup_display(flags, lines, item, px, py, w, h, env, shellcmd, argc, + argv, cwd, title, tc, s, style, border_style, NULL, NULL) != 0) { + cmd_free_argv(argc, argv); + if (env != NULL) + environ_free(env); + free(title); return (CMD_RETURN_NORMAL); + } + if (env != NULL) + environ_free(env); + free(title); + cmd_free_argv(argc, argv); return (CMD_RETURN_WAIT); } diff --git a/external/bsd/tmux/dist/cmd-display-message.c b/external/bsd/tmux/dist/cmd-display-message.c index 0522d37f6e4..7828f694040 100644 --- a/external/bsd/tmux/dist/cmd-display-message.c +++ b/external/bsd/tmux/dist/cmd-display-message.c @@ -39,7 +39,7 @@ const struct cmd_entry cmd_display_message_entry = { .name = "display-message", .alias = "display", - .args = { "acd:INpt:F:v", 0, 1 }, + .args = { "ac:d:INpt:F:v", 0, 1, NULL }, .usage = "[-aINpv] [-c target-client] [-d delay] [-F format] " CMD_TARGET_PANE_USAGE " [message]", @@ -68,22 +68,26 @@ cmd_display_message_exec(struct cmd *self, struct cmdq_item *item) struct window_pane *wp = target->wp; const char *template; char *msg, *cause; - int delay = -1; + int delay = -1, flags; struct format_tree *ft; - int flags; + u_int count = args_count(args); if (args_has(args, 'I')) { if (wp == NULL) return (CMD_RETURN_NORMAL); - if (window_pane_start_input(wp, item, &cause) != 0) { + switch (window_pane_start_input(wp, item, &cause)) { + case -1: cmdq_error(item, "%s", cause); free(cause); return (CMD_RETURN_ERROR); + case 1: + return (CMD_RETURN_NORMAL); + case 0: + return (CMD_RETURN_WAIT); } - return (CMD_RETURN_WAIT); } - if (args_has(args, 'F') && args->argc != 0) { + if (args_has(args, 'F') && count != 0) { cmdq_error(item, "only one of -F or argument must be given"); return (CMD_RETURN_ERROR); } @@ -97,9 +101,10 @@ cmd_display_message_exec(struct cmd *self, struct cmdq_item *item) } } - template = args_get(args, 'F'); - if (args->argc != 0) - template = args->argv[0]; + if (count != 0) + template = args_string(args, 0); + else + template = args_get(args, 'F'); if (template == NULL) template = DISPLAY_MESSAGE_TEMPLATE; diff --git a/external/bsd/tmux/dist/cmd-if-shell.c b/external/bsd/tmux/dist/cmd-if-shell.c index c7a2943b32e..205a8ce1088 100644 --- a/external/bsd/tmux/dist/cmd-if-shell.c +++ b/external/bsd/tmux/dist/cmd-if-shell.c @@ -20,6 +20,7 @@ #include <sys/types.h> #include <sys/wait.h> +#include <ctype.h> #include <stdlib.h> #include <string.h> @@ -29,16 +30,19 @@ * Executes a tmux command if a shell command returns true or false. */ -static enum cmd_retval cmd_if_shell_exec(struct cmd *, struct cmdq_item *); +static enum args_parse_type cmd_if_shell_args_parse(struct args *, u_int, + char **); +static enum cmd_retval cmd_if_shell_exec(struct cmd *, + struct cmdq_item *); -static void cmd_if_shell_callback(struct job *); -static void cmd_if_shell_free(void *); +static void cmd_if_shell_callback(struct job *); +static void cmd_if_shell_free(void *); const struct cmd_entry cmd_if_shell_entry = { .name = "if-shell", .alias = "if", - .args = { "bFt:", 2, 3 }, + .args = { "bFt:", 2, 3, cmd_if_shell_args_parse }, .usage = "[-bF] " CMD_TARGET_PANE_USAGE " shell-command command " "[command]", @@ -49,86 +53,72 @@ const struct cmd_entry cmd_if_shell_entry = { }; struct cmd_if_shell_data { - struct cmd_parse_input input; + struct args_command_state *cmd_if; + struct args_command_state *cmd_else; - char *cmd_if; - char *cmd_else; - - struct client *client; - struct cmdq_item *item; + struct client *client; + struct cmdq_item *item; }; +static enum args_parse_type +cmd_if_shell_args_parse(__unused struct args *args, u_int idx, + __unused char **cause) +{ + if (idx == 1 || idx == 2) + return (ARGS_PARSE_COMMANDS_OR_STRING); + return (ARGS_PARSE_STRING); +} + static enum cmd_retval cmd_if_shell_exec(struct cmd *self, struct cmdq_item *item) { struct args *args = cmd_get_args(self); struct cmd_find_state *target = cmdq_get_target(item); - struct cmdq_state *state = cmdq_get_state(item); struct cmd_if_shell_data *cdata; - char *shellcmd, *cmd, *error; - const char *file; + struct cmdq_item *new_item; + char *shellcmd; struct client *tc = cmdq_get_target_client(item); struct session *s = target->s; - struct cmd_parse_input pi; - enum cmd_parse_status status; + struct cmd_list *cmdlist; + u_int count = args_count(args); + int wait = !args_has(args, 'b'); - shellcmd = format_single_from_target(item, args->argv[0]); + shellcmd = format_single_from_target(item, args_string(args, 0)); if (args_has(args, 'F')) { if (*shellcmd != '0' && *shellcmd != '\0') - cmd = args->argv[1]; - else if (args->argc == 3) - cmd = args->argv[2]; - else - cmd = NULL; - free(shellcmd); - if (cmd == NULL) + cmdlist = args_make_commands_now(self, item, 1, 0); + else if (count == 3) + cmdlist = args_make_commands_now(self, item, 2, 0); + else { + free(shellcmd); return (CMD_RETURN_NORMAL); - - memset(&pi, 0, sizeof pi); - cmd_get_source(self, &pi.file, &pi.line); - pi.item = item; - pi.c = tc; - cmd_find_copy_state(&pi.fs, target); - - status = cmd_parse_and_insert(cmd, &pi, item, state, &error); - if (status == CMD_PARSE_ERROR) { - cmdq_error(item, "%s", error); - free(error); - return (CMD_RETURN_ERROR); } + free(shellcmd); + if (cmdlist == NULL) + return (CMD_RETURN_ERROR); + new_item = cmdq_get_command(cmdlist, cmdq_get_state(item)); + cmdq_insert_after(item, new_item); return (CMD_RETURN_NORMAL); } cdata = xcalloc(1, sizeof *cdata); - cdata->cmd_if = xstrdup(args->argv[1]); - if (args->argc == 3) - cdata->cmd_else = xstrdup(args->argv[2]); - else - cdata->cmd_else = NULL; + cdata->cmd_if = args_make_commands_prepare(self, item, 1, NULL, wait, + 0); + if (count == 3) { + cdata->cmd_else = args_make_commands_prepare(self, item, 2, + NULL, wait, 0); + } - if (!args_has(args, 'b')) + if (wait) { cdata->client = cmdq_get_client(item); - else + cdata->item = item; + } else cdata->client = tc; if (cdata->client != NULL) cdata->client->references++; - if (!args_has(args, 'b')) - cdata->item = item; - else - cdata->item = NULL; - - memset(&cdata->input, 0, sizeof cdata->input); - cmd_get_source(self, &file, &cdata->input.line); - if (file != NULL) - cdata->input.file = xstrdup(file); - cdata->input.c = tc; - if (cdata->input.c != NULL) - cdata->input.c->references++; - cmd_find_copy_state(&cdata->input.fs, target); - - if (job_run(shellcmd, 0, NULL, s, + if (job_run(shellcmd, 0, NULL, NULL, s, server_client_get_cwd(cmdq_get_client(item), s), NULL, cmd_if_shell_callback, cmd_if_shell_free, cdata, 0, -1, -1) == NULL) { @@ -139,7 +129,7 @@ cmd_if_shell_exec(struct cmd *self, struct cmdq_item *item) } free(shellcmd); - if (args_has(args, 'b')) + if (!wait) return (CMD_RETURN_NORMAL); return (CMD_RETURN_WAIT); } @@ -149,45 +139,34 @@ cmd_if_shell_callback(struct job *job) { struct cmd_if_shell_data *cdata = job_get_data(job); struct client *c = cdata->client; - struct cmdq_item *new_item = NULL; - struct cmdq_state *new_state = NULL; - char *cmd; + struct cmdq_item *item = cdata->item, *new_item; + struct args_command_state *state; + struct cmd_list *cmdlist; + char *error; int status; - struct cmd_parse_result *pr; status = job_get_status(job); if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) - cmd = cdata->cmd_else; + state = cdata->cmd_else; else - cmd = cdata->cmd_if; - if (cmd == NULL) + state = cdata->cmd_if; + if (state == NULL) goto out; - pr = cmd_parse_from_string(cmd, &cdata->input); - switch (pr->status) { - case CMD_PARSE_EMPTY: - break; - case CMD_PARSE_ERROR: - if (cdata->item != NULL) - cmdq_error(cdata->item, "%s", pr->error); - free(pr->error); - break; - case CMD_PARSE_SUCCESS: - if (cdata->item == NULL) - new_state = cmdq_new_state(NULL, NULL, 0); - else - new_state = cmdq_get_state(cdata->item); - new_item = cmdq_get_command(pr->cmdlist, new_state); - if (cdata->item == NULL) - cmdq_free_state(new_state); - cmd_list_free(pr->cmdlist); - break; - } - if (new_item != NULL) { - if (cdata->item == NULL) - cmdq_append(c, new_item); - else - cmdq_insert_after(cdata->item, new_item); + cmdlist = args_make_commands(state, 0, NULL, &error); + if (cmdlist == NULL) { + if (cdata->item == NULL) { + *error = toupper((u_char)*error); + status_message_set(c, -1, 1, 0, "%s", error); + } else + cmdq_error(cdata->item, "%s", error); + free(error); + } else if (item == NULL) { + new_item = cmdq_get_command(cmdlist, NULL); + cmdq_append(c, new_item); + } else { + new_item = cmdq_get_command(cmdlist, cmdq_get_state(item)); + cmdq_insert_after(item, new_item); } out: @@ -203,12 +182,9 @@ cmd_if_shell_free(void *data) if (cdata->client != NULL) server_client_unref(cdata->client); - free(cdata->cmd_else); - free(cdata->cmd_if); - - if (cdata->input.c != NULL) - server_client_unref(cdata->input.c); - free(__UNCONST(cdata->input.file)); + if (cdata->cmd_else != NULL) + args_make_commands_free(cdata->cmd_else); + args_make_commands_free(cdata->cmd_if); free(cdata); } diff --git a/external/bsd/tmux/dist/cmd-load-buffer.c b/external/bsd/tmux/dist/cmd-load-buffer.c index bca9a8604e3..59810dea24a 100644 --- a/external/bsd/tmux/dist/cmd-load-buffer.c +++ b/external/bsd/tmux/dist/cmd-load-buffer.c @@ -37,7 +37,7 @@ const struct cmd_entry cmd_load_buffer_entry = { .name = "load-buffer", .alias = "loadb", - .args = { "b:t:w", 1, 1 }, + .args = { "b:t:w", 1, 1, NULL }, .usage = CMD_BUFFER_USAGE " " CMD_TARGET_CLIENT_USAGE " path", .flags = CMD_AFTERHOOK|CMD_CLIENT_TFLAG|CMD_CLIENT_CANFAIL, @@ -105,7 +105,7 @@ cmd_load_buffer_exec(struct cmd *self, struct cmdq_item *item) cdata->client->references++; } - path = format_single_from_target(item, args->argv[0]); + path = format_single_from_target(item, args_string(args, 0)); file_read(cmdq_get_client(item), path, cmd_load_buffer_done, cdata); free(path); diff --git a/external/bsd/tmux/dist/cmd-new-session.c b/external/bsd/tmux/dist/cmd-new-session.c index 6aeb26c2d3e..458e9ff115d 100644 --- a/external/bsd/tmux/dist/cmd-new-session.c +++ b/external/bsd/tmux/dist/cmd-new-session.c @@ -39,10 +39,11 @@ const struct cmd_entry cmd_new_session_entry = { .name = "new-session", .alias = "new", - .args = { "Ac:dDe:EF:f:n:Ps:t:x:Xy:", 0, -1 }, + .args = { "Ac:dDe:EF:f:n:Ps:t:x:Xy:", 0, -1, NULL }, .usage = "[-AdDEPX] [-c start-directory] [-e environment] [-F format] " "[-f flags] [-n window-name] [-s session-name] " - CMD_TARGET_SESSION_USAGE " [-x width] [-y height] [command]", + CMD_TARGET_SESSION_USAGE " [-x width] [-y height] " + "[shell-command]", .target = { 't', CMD_FIND_SESSION, CMD_FIND_CANFAIL }, @@ -54,7 +55,7 @@ const struct cmd_entry cmd_has_session_entry = { .name = "has-session", .alias = "has", - .args = { "t:", 0, 0 }, + .args = { "t:", 0, 0, NULL }, .usage = CMD_TARGET_SESSION_USAGE, .target = { 't', CMD_FIND_SESSION, 0 }, @@ -75,15 +76,15 @@ cmd_new_session_exec(struct cmd *self, struct cmdq_item *item) struct options *oo; struct termios tio, *tiop; struct session_group *sg = NULL; - const char *errstr, *template, *group, *tmp, *add; + const char *errstr, *template, *group, *tmp; char *cause, *cwd = NULL, *cp, *newname = NULL; char *name, *prefix = NULL; int detached, already_attached, is_control = 0; - u_int sx, sy, dsx = 80, dsy = 24; - struct spawn_context sc; + u_int sx, sy, dsx = 80, dsy = 24, count = args_count(args); + struct spawn_context sc = { 0 }; enum cmd_retval retval; struct cmd_find_state fs; - struct args_value *value; + struct args_value *av; if (cmd_get_entry(self) == &cmd_has_session_entry) { /* @@ -93,7 +94,7 @@ cmd_new_session_exec(struct cmd *self, struct cmdq_item *item) return (CMD_RETURN_NORMAL); } - if (args_has(args, 't') && (args->argc != 0 || args_has(args, 'n'))) { + if (args_has(args, 't') && (count != 0 || args_has(args, 'n'))) { cmdq_error(item, "command or window name given with target"); return (CMD_RETURN_ERROR); } @@ -102,6 +103,11 @@ cmd_new_session_exec(struct cmd *self, struct cmdq_item *item) if (tmp != NULL) { name = format_single(item, tmp, c, NULL, NULL, NULL); newname = session_check_name(name); + if (newname == NULL) { + cmdq_error(item, "invalid session: %s", name); + free(name); + return (CMD_RETURN_ERROR); + } free(name); } if (args_has(args, 'A')) { @@ -134,8 +140,14 @@ cmd_new_session_exec(struct cmd *self, struct cmdq_item *item) prefix = xstrdup(sg->name); else if (groupwith != NULL) prefix = xstrdup(groupwith->name); - else + else { prefix = session_check_name(group); + if (prefix == NULL) { + cmdq_error(item, "invalid session group: %s", + group); + goto fail; + } + } } /* Set -d if no client. */ @@ -258,22 +270,21 @@ cmd_new_session_exec(struct cmd *self, struct cmdq_item *item) env = environ_create(); if (c != NULL && !args_has(args, 'E')) environ_update(global_s_options, c->environ, env); - add = args_first_value(args, 'e', &value); - while (add != NULL) { - environ_put(env, add, 0); - add = args_next_value(&value); + av = args_first_value(args, 'e'); + while (av != NULL) { + environ_put(env, av->string, 0); + av = args_next_value(av); } s = session_create(prefix, newname, cwd, env, oo, tiop); /* Spawn the initial window. */ - memset(&sc, 0, sizeof sc); sc.item = item; sc.s = s; - sc.tc = c; + if (!detached) + sc.tc = c; sc.name = args_get(args, 'n'); - sc.argc = args->argc; - sc.argv = args->argv; + args_to_vector(args, &sc.argc, &sc.argv); sc.idx = -1; sc.cwd = args_get(args, 'c'); @@ -317,18 +328,10 @@ cmd_new_session_exec(struct cmd *self, struct cmdq_item *item) proc_send(c->peer, MSG_READY, -1, NULL, 0); } else if (c->session != NULL) c->last_session = c->session; - c->session = s; + server_client_set_session(c, s); if (~cmdq_get_flags(item) & CMDQ_STATE_REPEAT) server_client_set_key_table(c, NULL); - tty_update_client_offset(c); - status_timer_start(c); - notify_client("client-session-changed", c); - session_update_activity(s, NULL); - gettimeofday(&s->last_attached_time, NULL); - server_redraw_client(c); } - recalculate_sizes(); - server_update_socket(); /* * If there are still configuration file errors to display, put the new @@ -354,12 +357,16 @@ cmd_new_session_exec(struct cmd *self, struct cmdq_item *item) cmd_find_from_session(&fs, s, 0); cmdq_insert_hook(s, item, &fs, "after-new-session"); + if (sc.argv != NULL) + cmd_free_argv(sc.argc, sc.argv); free(cwd); free(newname); free(prefix); return (CMD_RETURN_NORMAL); fail: + if (sc.argv != NULL) + cmd_free_argv(sc.argc, sc.argv); free(cwd); free(newname); free(prefix); diff --git a/external/bsd/tmux/dist/cmd-new-window.c b/external/bsd/tmux/dist/cmd-new-window.c index 712e2a797a4..e7f0868f4e5 100644 --- a/external/bsd/tmux/dist/cmd-new-window.c +++ b/external/bsd/tmux/dist/cmd-new-window.c @@ -38,9 +38,9 @@ const struct cmd_entry cmd_new_window_entry = { .name = "new-window", .alias = "neww", - .args = { "abc:de:F:kn:PSt:", 0, -1 }, + .args = { "abc:de:F:kn:PSt:", 0, -1, NULL }, .usage = "[-abdkPS] [-c start-directory] [-e environment] [-F format] " - "[-n window-name] " CMD_TARGET_WINDOW_USAGE " [command]", + "[-n window-name] " CMD_TARGET_WINDOW_USAGE " [shell-command]", .target = { 't', CMD_FIND_WINDOW, CMD_FIND_WINDOW_INDEX }, @@ -55,16 +55,15 @@ cmd_new_window_exec(struct cmd *self, struct cmdq_item *item) struct client *c = cmdq_get_client(item); struct cmd_find_state *current = cmdq_get_current(item); struct cmd_find_state *target = cmdq_get_target(item); - struct spawn_context sc; + struct spawn_context sc = { 0 }; struct client *tc = cmdq_get_target_client(item); struct session *s = target->s; - struct winlink *wl = target->wl; + struct winlink *wl = target->wl, *new_wl = NULL; int idx = target->idx, before; - struct winlink *new_wl = NULL; char *cause = NULL, *cp; - const char *template, *add, *name; + const char *template, *name; struct cmd_find_state fs; - struct args_value *value; + struct args_value *av; /* * If -S and -n are given and -t is not and a single window with this @@ -94,7 +93,6 @@ cmd_new_window_exec(struct cmd *self, struct cmdq_item *item) } } - before = args_has(args, 'b'); if (args_has(args, 'a') || before) { idx = winlink_shuffle_up(s, wl, before); @@ -102,20 +100,18 @@ cmd_new_window_exec(struct cmd *self, struct cmdq_item *item) idx = target->idx; } - memset(&sc, 0, sizeof sc); sc.item = item; sc.s = s; sc.tc = tc; sc.name = args_get(args, 'n'); - sc.argc = args->argc; - sc.argv = args->argv; + args_to_vector(args, &sc.argc, &sc.argv); sc.environ = environ_create(); - add = args_first_value(args, 'e', &value); - while (add != NULL) { - environ_put(sc.environ, add, 0); - add = args_next_value(&value); + av = args_first_value(args, 'e'); + while (av != NULL) { + environ_put(sc.environ, av->string, 0); + av = args_next_value(av); } sc.idx = idx; @@ -130,6 +126,9 @@ cmd_new_window_exec(struct cmd *self, struct cmdq_item *item) if ((new_wl = spawn_window(&sc, &cause)) == NULL) { cmdq_error(item, "create window failed: %s", cause); free(cause); + if (sc.argv != NULL) + cmd_free_argv(sc.argc, sc.argv); + environ_free(sc.environ); return (CMD_RETURN_ERROR); } if (!args_has(args, 'd') || new_wl == s->curw) { @@ -150,6 +149,8 @@ cmd_new_window_exec(struct cmd *self, struct cmdq_item *item) cmd_find_from_winlink(&fs, new_wl, 0); cmdq_insert_hook(s, item, &fs, "after-new-window"); + if (sc.argv != NULL) + cmd_free_argv(sc.argc, sc.argv); environ_free(sc.environ); return (CMD_RETURN_NORMAL); } diff --git a/external/bsd/tmux/dist/cmd-parse.y b/external/bsd/tmux/dist/cmd-parse.y index 7b42c62133a..1d692770834 100644 --- a/external/bsd/tmux/dist/cmd-parse.y +++ b/external/bsd/tmux/dist/cmd-parse.y @@ -42,13 +42,27 @@ struct cmd_parse_scope { TAILQ_ENTRY (cmd_parse_scope) entry; }; -struct cmd_parse_command { - u_int line; +enum cmd_parse_argument_type { + CMD_PARSE_STRING, + CMD_PARSE_COMMANDS, + CMD_PARSE_PARSED_COMMANDS +}; + +struct cmd_parse_argument { + enum cmd_parse_argument_type type; + char *string; + struct cmd_parse_commands *commands; + struct cmd_list *cmdlist; + + TAILQ_ENTRY(cmd_parse_argument) entry; +}; +TAILQ_HEAD(cmd_parse_arguments, cmd_parse_argument); - int argc; - char **argv; +struct cmd_parse_command { + u_int line; + struct cmd_parse_arguments arguments; - TAILQ_ENTRY(cmd_parse_command) entry; + TAILQ_ENTRY(cmd_parse_command) entry; }; TAILQ_HEAD(cmd_parse_commands, cmd_parse_command); @@ -77,8 +91,9 @@ static char *cmd_parse_get_error(const char *, u_int, const char *); static void cmd_parse_free_command(struct cmd_parse_command *); static struct cmd_parse_commands *cmd_parse_new_commands(void); static void cmd_parse_free_commands(struct cmd_parse_commands *); -static char *cmd_parse_commands_to_string(struct cmd_parse_commands *); -static void cmd_parse_print_commands(struct cmd_parse_input *, u_int, +static void cmd_parse_build_commands(struct cmd_parse_commands *, + struct cmd_parse_input *, struct cmd_parse_result *); +static void cmd_parse_print_commands(struct cmd_parse_input *, struct cmd_list *); %} @@ -86,10 +101,8 @@ static void cmd_parse_print_commands(struct cmd_parse_input *, u_int, %union { char *token; - struct { - int argc; - char **argv; - } arguments; + struct cmd_parse_arguments *arguments; + struct cmd_parse_argument *argument; int flag; struct { int flag; @@ -107,8 +120,9 @@ static void cmd_parse_print_commands(struct cmd_parse_input *, u_int, %token ENDIF %token <token> FORMAT TOKEN EQUALS -%type <token> argument expanded format +%type <token> expanded format %type <arguments> arguments +%type <argument> argument %type <flag> if_open if_elif %type <elif> elif elif1 %type <commands> argument_statements statements statement @@ -360,7 +374,7 @@ commands : command struct cmd_parse_state *ps = &parse_state; $$ = cmd_parse_new_commands(); - if ($1->argc != 0 && + if (!TAILQ_EMPTY(&$1->arguments) && (ps->scope == NULL || ps->scope->flag)) TAILQ_INSERT_TAIL($$, $1, entry); else @@ -380,7 +394,7 @@ commands : command { struct cmd_parse_state *ps = &parse_state; - if ($3->argc != 0 && + if (!TAILQ_EMPTY(&$3->arguments) && (ps->scope == NULL || ps->scope->flag)) { $$ = $1; TAILQ_INSERT_TAIL($$, $3, entry); @@ -401,27 +415,38 @@ command : assignment $$ = xcalloc(1, sizeof *$$); $$->line = ps->input->line; + TAILQ_INIT(&$$->arguments); } | optional_assignment TOKEN { - struct cmd_parse_state *ps = &parse_state; + struct cmd_parse_state *ps = &parse_state; + struct cmd_parse_argument *arg; $$ = xcalloc(1, sizeof *$$); $$->line = ps->input->line; + TAILQ_INIT(&$$->arguments); - cmd_prepend_argv(&$$->argc, &$$->argv, $2); - + arg = xcalloc(1, sizeof *arg); + arg->type = CMD_PARSE_STRING; + arg->string = $2; + TAILQ_INSERT_HEAD(&$$->arguments, arg, entry); } | optional_assignment TOKEN arguments { - struct cmd_parse_state *ps = &parse_state; + struct cmd_parse_state *ps = &parse_state; + struct cmd_parse_argument *arg; $$ = xcalloc(1, sizeof *$$); $$->line = ps->input->line; + TAILQ_INIT(&$$->arguments); + + TAILQ_CONCAT(&$$->arguments, $3, entry); + free($3); - $$->argc = $3.argc; - $$->argv = $3.argv; - cmd_prepend_argv(&$$->argc, &$$->argv, $2); + arg = xcalloc(1, sizeof *arg); + arg->type = CMD_PARSE_STRING; + arg->string = $2; + TAILQ_INSERT_HEAD(&$$->arguments, arg, entry); } condition1 : if_open commands if_close @@ -505,30 +530,34 @@ elif1 : if_elif commands arguments : argument { - $$.argc = 1; - $$.argv = xreallocarray(NULL, 1, sizeof *$$.argv); + $$ = xcalloc(1, sizeof *$$); + TAILQ_INIT($$); - $$.argv[0] = $1; + TAILQ_INSERT_HEAD($$, $1, entry); } | argument arguments { - cmd_prepend_argv(&$2.argc, &$2.argv, $1); - free($1); + TAILQ_INSERT_HEAD($2, $1, entry); $$ = $2; } argument : TOKEN { - $$ = $1; + $$ = xcalloc(1, sizeof *$$); + $$->type = CMD_PARSE_STRING; + $$->string = $1; } | EQUALS { - $$ = $1; + $$ = xcalloc(1, sizeof *$$); + $$->type = CMD_PARSE_STRING; + $$->string = $1; } | '{' argument_statements { - $$ = cmd_parse_commands_to_string($2); - cmd_parse_free_commands($2); + $$ = xcalloc(1, sizeof *$$); + $$->type = CMD_PARSE_COMMANDS; + $$->commands = $2; } argument_statements : statement '}' @@ -552,30 +581,57 @@ cmd_parse_get_error(const char *file, u_int line, const char *error) if (file == NULL) s = xstrdup(error); else - xasprintf (&s, "%s:%u: %s", file, line, error); + xasprintf(&s, "%s:%u: %s", file, line, error); return (s); } static void -cmd_parse_print_commands(struct cmd_parse_input *pi, u_int line, - struct cmd_list *cmdlist) +cmd_parse_print_commands(struct cmd_parse_input *pi, struct cmd_list *cmdlist) { char *s; - if (pi->item != NULL && (pi->flags & CMD_PARSE_VERBOSE)) { - s = cmd_list_print(cmdlist, 0); - if (pi->file != NULL) - cmdq_print(pi->item, "%s:%u: %s", pi->file, line, s); - else - cmdq_print(pi->item, "%u: %s", line, s); - free(s); + if (pi->item == NULL || (~pi->flags & CMD_PARSE_VERBOSE)) + return; + s = cmd_list_print(cmdlist, 0); + if (pi->file != NULL) + cmdq_print(pi->item, "%s:%u: %s", pi->file, pi->line, s); + else + cmdq_print(pi->item, "%u: %s", pi->line, s); + free(s); +} + +static void +cmd_parse_free_argument(struct cmd_parse_argument *arg) +{ + switch (arg->type) { + case CMD_PARSE_STRING: + free(arg->string); + break; + case CMD_PARSE_COMMANDS: + cmd_parse_free_commands(arg->commands); + break; + case CMD_PARSE_PARSED_COMMANDS: + cmd_list_free(arg->cmdlist); + break; + } + free(arg); +} + +static void +cmd_parse_free_arguments(struct cmd_parse_arguments *args) +{ + struct cmd_parse_argument *arg, *arg1; + + TAILQ_FOREACH_SAFE(arg, args, entry, arg1) { + TAILQ_REMOVE(args, arg, entry); + cmd_parse_free_argument(arg); } } static void cmd_parse_free_command(struct cmd_parse_command *cmd) { - cmd_free_argv(cmd->argc, cmd->argv); + cmd_parse_free_arguments(&cmd->arguments); free(cmd); } @@ -585,7 +641,7 @@ cmd_parse_new_commands(void) struct cmd_parse_commands *cmds; cmds = xmalloc(sizeof *cmds); - TAILQ_INIT (cmds); + TAILQ_INIT(cmds); return (cmds); } @@ -601,30 +657,6 @@ cmd_parse_free_commands(struct cmd_parse_commands *cmds) free(cmds); } -static char * -cmd_parse_commands_to_string(struct cmd_parse_commands *cmds) -{ - struct cmd_parse_command *cmd; - char *string = NULL, *s, *line; - - TAILQ_FOREACH(cmd, cmds, entry) { - line = cmd_stringify_argv(cmd->argc, cmd->argv); - if (string == NULL) - s = line; - else { - xasprintf(&s, "%s ; %s", s, line); - free(line); - } - - free(string); - string = s; - } - if (string == NULL) - string = xstrdup(""); - log_debug("%s: %s", __func__, string); - return (string); -} - static struct cmd_parse_commands * cmd_parse_run_parser(char **cause) { @@ -674,72 +706,170 @@ cmd_parse_do_buffer(const char *buf, size_t len, struct cmd_parse_input *pi, return (cmd_parse_run_parser(cause)); } -static struct cmd_parse_result * -cmd_parse_build_commands(struct cmd_parse_commands *cmds, - struct cmd_parse_input *pi) +static void +cmd_parse_log_commands(struct cmd_parse_commands *cmds, const char *prefix) { - static struct cmd_parse_result pr; - struct cmd_parse_commands *cmds2; - struct cmd_parse_command *cmd, *cmd2, *next, *next2, *after; - u_int line = UINT_MAX; - int i; - struct cmd_list *cmdlist = NULL, *result; - struct cmd *add; - char *name, *alias, *cause, *s; + struct cmd_parse_command *cmd; + struct cmd_parse_argument *arg; + u_int i, j; + char *s; - /* Check for an empty list. */ - if (TAILQ_EMPTY(cmds)) { - cmd_parse_free_commands(cmds); - pr.status = CMD_PARSE_EMPTY; - return (&pr); + i = 0; + TAILQ_FOREACH(cmd, cmds, entry) { + j = 0; + TAILQ_FOREACH(arg, &cmd->arguments, entry) { + switch (arg->type) { + case CMD_PARSE_STRING: + log_debug("%s %u:%u: %s", prefix, i, j, + arg->string); + break; + case CMD_PARSE_COMMANDS: + xasprintf(&s, "%s %u:%u", prefix, i, j); + cmd_parse_log_commands(arg->commands, s); + free(s); + break; + case CMD_PARSE_PARSED_COMMANDS: + s = cmd_list_print(arg->cmdlist, 0); + log_debug("%s %u:%u: %s", prefix, i, j, s); + free(s); + break; + } + j++; + } + i++; } +} - /* - * Walk the commands and expand any aliases. Each alias is parsed - * individually to a new command list, any trailing arguments appended - * to the last command, and all commands inserted into the original - * command list. - */ - TAILQ_FOREACH_SAFE(cmd, cmds, entry, next) { - name = cmd->argv[0]; +static int +cmd_parse_expand_alias(struct cmd_parse_command *cmd, + struct cmd_parse_input *pi, struct cmd_parse_result *pr) +{ + struct cmd_parse_argument *arg, *arg1, *first; + struct cmd_parse_commands *cmds; + struct cmd_parse_command *last; + char *alias, *name, *cause; - alias = cmd_get_alias(name); - if (alias == NULL) - continue; + if (pi->flags & CMD_PARSE_NOALIAS) + return (0); + memset(pr, 0, sizeof *pr); - line = cmd->line; - log_debug("%s: %u %s = %s", __func__, line, name, alias); + first = TAILQ_FIRST(&cmd->arguments); + if (first == NULL || first->type != CMD_PARSE_STRING) { + pr->status = CMD_PARSE_SUCCESS; + pr->cmdlist = cmd_list_new(); + return (1); + } + name = first->string; - pi->line = line; - cmds2 = cmd_parse_do_buffer(alias, strlen(alias), pi, &cause); - free(alias); - if (cmds2 == NULL) { - pr.status = CMD_PARSE_ERROR; - pr.error = cause; - goto out; - } + alias = cmd_get_alias(name); + if (alias == NULL) + return (0); + log_debug("%s: %u alias %s = %s", __func__, pi->line, name, alias); - cmd2 = TAILQ_LAST(cmds2, cmd_parse_commands); - if (cmd2 == NULL) { - TAILQ_REMOVE(cmds, cmd, entry); - cmd_parse_free_command(cmd); - continue; - } - for (i = 1; i < cmd->argc; i++) - cmd_append_argv(&cmd2->argc, &cmd2->argv, cmd->argv[i]); + cmds = cmd_parse_do_buffer(alias, strlen(alias), pi, &cause); + free(alias); + if (cmds == NULL) { + pr->status = CMD_PARSE_ERROR; + pr->error = cause; + return (1); + } - after = cmd; - TAILQ_FOREACH_SAFE(cmd2, cmds2, entry, next2) { - cmd2->line = line; - TAILQ_REMOVE(cmds2, cmd2, entry); - TAILQ_INSERT_AFTER(cmds, after, cmd2, entry); - after = cmd2; + last = TAILQ_LAST(cmds, cmd_parse_commands); + if (last == NULL) { + pr->status = CMD_PARSE_SUCCESS; + pr->cmdlist = cmd_list_new(); + return (1); + } + + TAILQ_REMOVE(&cmd->arguments, first, entry); + cmd_parse_free_argument(first); + + TAILQ_FOREACH_SAFE(arg, &cmd->arguments, entry, arg1) { + TAILQ_REMOVE(&cmd->arguments, arg, entry); + TAILQ_INSERT_TAIL(&last->arguments, arg, entry); + } + cmd_parse_log_commands(cmds, __func__); + + pi->flags |= CMD_PARSE_NOALIAS; + cmd_parse_build_commands(cmds, pi, pr); + pi->flags &= ~CMD_PARSE_NOALIAS; + return (1); +} + +static void +cmd_parse_build_command(struct cmd_parse_command *cmd, + struct cmd_parse_input *pi, struct cmd_parse_result *pr) +{ + struct cmd_parse_argument *arg; + struct cmd *add; + char *cause; + struct args_value *values = NULL; + u_int count = 0, idx; + + memset(pr, 0, sizeof *pr); + + if (cmd_parse_expand_alias(cmd, pi, pr)) + return; + + TAILQ_FOREACH(arg, &cmd->arguments, entry) { + values = xrecallocarray(values, count, count + 1, + sizeof *values); + switch (arg->type) { + case CMD_PARSE_STRING: + values[count].type = ARGS_STRING; + values[count].string = xstrdup(arg->string); + break; + case CMD_PARSE_COMMANDS: + cmd_parse_build_commands(arg->commands, pi, pr); + if (pr->status != CMD_PARSE_SUCCESS) + goto out; + values[count].type = ARGS_COMMANDS; + values[count].cmdlist = pr->cmdlist; + break; + case CMD_PARSE_PARSED_COMMANDS: + values[count].type = ARGS_COMMANDS; + values[count].cmdlist = arg->cmdlist; + values[count].cmdlist->references++; + break; } - cmd_parse_free_commands(cmds2); + count++; + } - TAILQ_REMOVE(cmds, cmd, entry); - cmd_parse_free_command(cmd); + add = cmd_parse(values, count, pi->file, pi->line, &cause); + if (add == NULL) { + pr->status = CMD_PARSE_ERROR; + pr->error = cmd_parse_get_error(pi->file, pi->line, cause); + free(cause); + goto out; } + pr->status = CMD_PARSE_SUCCESS; + pr->cmdlist = cmd_list_new(); + cmd_list_append(pr->cmdlist, add); + +out: + for (idx = 0; idx < count; idx++) + args_free_value(&values[idx]); + free(values); +} + +static void +cmd_parse_build_commands(struct cmd_parse_commands *cmds, + struct cmd_parse_input *pi, struct cmd_parse_result *pr) +{ + struct cmd_parse_command *cmd; + u_int line = UINT_MAX; + struct cmd_list *current = NULL, *result; + char *s; + + memset(pr, 0, sizeof *pr); + + /* Check for an empty list. */ + if (TAILQ_EMPTY(cmds)) { + pr->status = CMD_PARSE_SUCCESS; + pr->cmdlist = cmd_list_new(); + return; + } + cmd_parse_log_commands(cmds, __func__); /* * Parse each command into a command list. Create a new command list @@ -749,49 +879,39 @@ cmd_parse_build_commands(struct cmd_parse_commands *cmds, */ result = cmd_list_new(); TAILQ_FOREACH(cmd, cmds, entry) { - name = cmd->argv[0]; - log_debug("%s: %u %s", __func__, cmd->line, name); - cmd_log_argv(cmd->argc, cmd->argv, __func__); - - if (cmdlist == NULL || - ((~pi->flags & CMD_PARSE_ONEGROUP) && cmd->line != line)) { - if (cmdlist != NULL) { - cmd_parse_print_commands(pi, line, cmdlist); - cmd_list_move(result, cmdlist); - cmd_list_free(cmdlist); + if (((~pi->flags & CMD_PARSE_ONEGROUP) && cmd->line != line)) { + if (current != NULL) { + cmd_parse_print_commands(pi, current); + cmd_list_move(result, current); + cmd_list_free(current); } - cmdlist = cmd_list_new(); + current = cmd_list_new(); } - line = cmd->line; + if (current == NULL) + current = cmd_list_new(); + line = pi->line = cmd->line; - add = cmd_parse(cmd->argc, cmd->argv, pi->file, line, &cause); - if (add == NULL) { + cmd_parse_build_command(cmd, pi, pr); + if (pr->status != CMD_PARSE_SUCCESS) { cmd_list_free(result); - pr.status = CMD_PARSE_ERROR; - pr.error = cmd_parse_get_error(pi->file, line, cause); - free(cause); - cmd_list_free(cmdlist); - goto out; + cmd_list_free(current); + return; } - cmd_list_append(cmdlist, add); + cmd_list_append_all(current, pr->cmdlist); + cmd_list_free(pr->cmdlist); } - if (cmdlist != NULL) { - cmd_parse_print_commands(pi, line, cmdlist); - cmd_list_move(result, cmdlist); - cmd_list_free(cmdlist); + if (current != NULL) { + cmd_parse_print_commands(pi, current); + cmd_list_move(result, current); + cmd_list_free(current); } s = cmd_list_print(result, 0); log_debug("%s: %s", __func__, s); free(s); - pr.status = CMD_PARSE_SUCCESS; - pr.cmdlist = result; - -out: - cmd_parse_free_commands(cmds); - - return (&pr); + pr->status = CMD_PARSE_SUCCESS; + pr->cmdlist = result; } struct cmd_parse_result * @@ -814,7 +934,10 @@ cmd_parse_from_file(FILE *f, struct cmd_parse_input *pi) pr.error = cause; return (&pr); } - return (cmd_parse_build_commands(cmds, pi)); + cmd_parse_build_commands(cmds, pi, &pr); + cmd_parse_free_commands(cmds); + return (&pr); + } struct cmd_parse_result * @@ -845,8 +968,6 @@ cmd_parse_and_insert(const char *s, struct cmd_parse_input *pi, pr = cmd_parse_from_string(s, pi); switch (pr->status) { - case CMD_PARSE_EMPTY: - break; case CMD_PARSE_ERROR: if (error != NULL) *error = pr->error; @@ -871,8 +992,6 @@ cmd_parse_and_append(const char *s, struct cmd_parse_input *pi, pr = cmd_parse_from_string(s, pi); switch (pr->status) { - case CMD_PARSE_EMPTY: - break; case CMD_PARSE_ERROR: if (error != NULL) *error = pr->error; @@ -903,9 +1022,8 @@ cmd_parse_from_buffer(const void *buf, size_t len, struct cmd_parse_input *pi) memset(&pr, 0, sizeof pr); if (len == 0) { - pr.status = CMD_PARSE_EMPTY; - pr.cmdlist = NULL; - pr.error = NULL; + pr.status = CMD_PARSE_SUCCESS; + pr.cmdlist = cmd_list_new(); return (&pr); } @@ -915,18 +1033,24 @@ cmd_parse_from_buffer(const void *buf, size_t len, struct cmd_parse_input *pi) pr.error = cause; return (&pr); } - return (cmd_parse_build_commands(cmds, pi)); + cmd_parse_build_commands(cmds, pi, &pr); + cmd_parse_free_commands(cmds); + return (&pr); } struct cmd_parse_result * -cmd_parse_from_arguments(int argc, char **argv, struct cmd_parse_input *pi) +cmd_parse_from_arguments(struct args_value *values, u_int count, + struct cmd_parse_input *pi) { - struct cmd_parse_input input; - struct cmd_parse_commands *cmds; - struct cmd_parse_command *cmd; - char **copy, **new_argv; - size_t size; - int i, last, new_argc; + static struct cmd_parse_result pr; + struct cmd_parse_input input; + struct cmd_parse_commands *cmds; + struct cmd_parse_command *cmd; + struct cmd_parse_argument *arg; + u_int i; + char *copy; + size_t size; + int end; /* * The commands are already split up into arguments, so just separate @@ -937,62 +1061,55 @@ cmd_parse_from_arguments(int argc, char **argv, struct cmd_parse_input *pi) memset(&input, 0, sizeof input); pi = &input; } - cmd_log_argv(argc, argv, "%s", __func__); + memset(&pr, 0, sizeof pr); cmds = cmd_parse_new_commands(); - copy = cmd_copy_argv(argc, argv); - - last = 0; - for (i = 0; i < argc; i++) { - size = strlen(copy[i]); - if (size == 0 || copy[i][size - 1] != ';') - continue; - copy[i][--size] = '\0'; - if (size > 0 && copy[i][size - 1] == '\\') { - copy[i][size - 1] = ';'; - continue; - } - - new_argc = i - last; - new_argv = copy + last; - if (size != 0) - new_argc++; - - if (new_argc != 0) { - cmd_log_argv(new_argc, new_argv, "%s: at %u", __func__, - i); - - cmd = xcalloc(1, sizeof *cmd); - cmd->line = pi->line; - - cmd->argc = new_argc; - cmd->argv = cmd_copy_argv(new_argc, new_argv); + cmd = xcalloc(1, sizeof *cmd); + cmd->line = pi->line; + TAILQ_INIT(&cmd->arguments); + + for (i = 0; i < count; i++) { + end = 0; + if (values[i].type == ARGS_STRING) { + copy = xstrdup(values[i].string); + size = strlen(copy); + if (size != 0 && copy[size - 1] == ';') { + copy[--size] = '\0'; + if (size > 0 && copy[size - 1] == '\\') + copy[size - 1] = ';'; + else + end = 1; + } + if (!end || size != 0) { + arg = xcalloc(1, sizeof *arg); + arg->type = CMD_PARSE_STRING; + arg->string = copy; + TAILQ_INSERT_TAIL(&cmd->arguments, arg, entry); + } + } else if (values[i].type == ARGS_COMMANDS) { + arg = xcalloc(1, sizeof *arg); + arg->type = CMD_PARSE_PARSED_COMMANDS; + arg->cmdlist = values[i].cmdlist; + arg->cmdlist->references++; + TAILQ_INSERT_TAIL(&cmd->arguments, arg, entry); + } else + fatalx("unknown argument type"); + if (end) { TAILQ_INSERT_TAIL(cmds, cmd, entry); - } - - last = i + 1; - } - if (last != argc) { - new_argv = copy + last; - new_argc = argc - last; - - if (new_argc != 0) { - cmd_log_argv(new_argc, new_argv, "%s: at %u", __func__, - last); - cmd = xcalloc(1, sizeof *cmd); cmd->line = pi->line; - - cmd->argc = new_argc; - cmd->argv = cmd_copy_argv(new_argc, new_argv); - - TAILQ_INSERT_TAIL(cmds, cmd, entry); + TAILQ_INIT(&cmd->arguments); } } + if (!TAILQ_EMPTY(&cmd->arguments)) + TAILQ_INSERT_TAIL(cmds, cmd, entry); + else + free(cmd); - cmd_free_argv(argc, copy); - return (cmd_parse_build_commands(cmds, pi)); + cmd_parse_build_commands(cmds, pi, &pr); + cmd_parse_free_commands(cmds); + return (&pr); } static int printflike(1, 2) @@ -1309,7 +1426,7 @@ yylex_token_escape(char **buf, size_t *len) if (o3 >= '0' && o3 <= '7') { ch = 64 * (ch - '0') + 8 * (o2 - '0') + - (o3 - '0'); + (o3 - '0'); yylex_append1(buf, len, ch); return (1); } diff --git a/external/bsd/tmux/dist/cmd-paste-buffer.c b/external/bsd/tmux/dist/cmd-paste-buffer.c index c8447426995..36326e18419 100644 --- a/external/bsd/tmux/dist/cmd-paste-buffer.c +++ b/external/bsd/tmux/dist/cmd-paste-buffer.c @@ -33,7 +33,7 @@ const struct cmd_entry cmd_paste_buffer_entry = { .name = "paste-buffer", .alias = "pasteb", - .args = { "db:prs:t:", 0, 0 }, + .args = { "db:prs:t:", 0, 0, NULL }, .usage = "[-dpr] [-s separator] " CMD_BUFFER_USAGE " " CMD_TARGET_PANE_USAGE, diff --git a/external/bsd/tmux/dist/cmd-queue.c b/external/bsd/tmux/dist/cmd-queue.c index 7409d23def9..ba148121742 100644 --- a/external/bsd/tmux/dist/cmd-queue.c +++ b/external/bsd/tmux/dist/cmd-queue.c @@ -19,9 +19,11 @@ #include <sys/types.h> #include <ctype.h> +#include <pwd.h> #include <stdlib.h> #include <string.h> #include <time.h> +#include <unistd.h> #include "tmux.h" @@ -124,7 +126,7 @@ cmdq_new(void) { struct cmdq_list *queue; - queue = xcalloc (1, sizeof *queue); + queue = xcalloc(1, sizeof *queue); TAILQ_INIT (&queue->list); return (queue); } @@ -269,6 +271,15 @@ cmdq_add_format(struct cmdq_state *state, const char *key, const char *fmt, ...) free(value); } +/* Add formats to command queue. */ +void +cmdq_add_formats(struct cmdq_state *state, struct format_tree *ft) +{ + if (state->formats == NULL) + state->formats = format_create(NULL, NULL, FORMAT_NONE, 0); + format_merge(state->formats, ft); +} + /* Merge formats from item. */ void cmdq_merge_formats(struct cmdq_item *item, struct format_tree *ft) @@ -343,12 +354,12 @@ cmdq_insert_hook(struct session *s, struct cmdq_item *item, struct cmdq_state *state = item->state; struct cmd *cmd = item->cmd; struct args *args = cmd_get_args(cmd); - struct args_entry *entryp; - struct args_value *valuep; + struct args_entry *ae; + struct args_value *av; struct options *oo; va_list ap; char *name, tmp[32], flag, *arguments; - int i; + u_int i; const char *value; struct cmdq_item *new_item; struct cmdq_state *new_state; @@ -385,11 +396,11 @@ cmdq_insert_hook(struct session *s, struct cmdq_item *item, cmdq_add_format(new_state, "hook_arguments", "%s", arguments); free(arguments); - for (i = 0; i < args->argc; i++) { + for (i = 0; i < args_count(args); i++) { xsnprintf(tmp, sizeof tmp, "hook_argument_%d", i); - cmdq_add_format(new_state, tmp, "%s", args->argv[i]); + cmdq_add_format(new_state, tmp, "%s", args_string(args, i)); } - flag = args_first(args, &entryp); + flag = args_first(args, &ae); while (flag != 0) { value = args_get(args, flag); if (value == NULL) { @@ -401,15 +412,15 @@ cmdq_insert_hook(struct session *s, struct cmdq_item *item, } i = 0; - value = args_first_value(args, flag, &valuep); - while (value != NULL) { + av = args_first_value(args, flag); + while (av != NULL) { xsnprintf(tmp, sizeof tmp, "hook_flag_%c_%d", flag, i); - cmdq_add_format(new_state, tmp, "%s", value); + cmdq_add_format(new_state, tmp, "%s", av->string); i++; - value = args_next_value(&valuep); + av = args_next_value(av); } - flag = args_next(&entryp); + flag = args_next(&ae); } a = options_array_first(o); @@ -469,6 +480,13 @@ cmdq_remove_group(struct cmdq_item *item) } } +/* Empty command callback. */ +static enum cmd_retval +cmdq_empty_command(__unused struct cmdq_item *item, __unused void *data) +{ + return (CMD_RETURN_NORMAL); +} + /* Get a command for the command queue. */ struct cmdq_item * cmdq_get_command(struct cmd_list *cmdlist, struct cmdq_state *state) @@ -478,12 +496,14 @@ cmdq_get_command(struct cmd_list *cmdlist, struct cmdq_state *state) const struct cmd_entry *entry; int created = 0; + if ((cmd = cmd_list_first(cmdlist)) == NULL) + return (cmdq_get_callback(cmdq_empty_command, NULL)); + if (state == NULL) { state = cmdq_new_state(NULL, NULL, 0); created = 1; } - cmd = cmd_list_first(cmdlist); while (cmd != NULL) { entry = cmd_get_entry(cmd); @@ -540,17 +560,31 @@ cmdq_add_message(struct cmdq_item *item) { struct client *c = item->client; struct cmdq_state *state = item->state; - const char *name, *key; + const char *key; char *tmp; + uid_t uid; + struct passwd *pw; + char *user = NULL; tmp = cmd_print(item->cmd); if (c != NULL) { - name = c->name; + uid = proc_get_peer_uid(c->peer); + if (uid != (uid_t)-1 && uid != getuid()) { + if ((pw = getpwuid(uid)) != NULL) + xasprintf(&user, "[%s]", pw->pw_name); + else + user = xstrdup("[unknown]"); + } else + user = xstrdup(""); if (c->session != NULL && state->event.key != KEYC_NONE) { key = key_string_lookup_key(state->event.key, 0); - server_add_message("%s key %s: %s", name, key, tmp); - } else - server_add_message("%s command: %s", name, tmp); + server_add_message("%s%s key %s: %s", c->name, user, + key, tmp); + } else { + server_add_message("%s%s command: %s", c->name, user, + tmp); + } + free(user); } else server_add_message("command: %s", tmp); free(tmp); @@ -822,7 +856,7 @@ cmdq_print(struct cmdq_item *item, const char *fmt, ...) window_pane_set_mode(wp, NULL, &window_view_mode, NULL, NULL); } - window_copy_add(wp, "%s", msg); + window_copy_add(wp, 0, "%s", msg); } free(msg); diff --git a/external/bsd/tmux/dist/cmd-resize-window.c b/external/bsd/tmux/dist/cmd-resize-window.c index 5feec50afe1..b60188e6ef6 100644 --- a/external/bsd/tmux/dist/cmd-resize-window.c +++ b/external/bsd/tmux/dist/cmd-resize-window.c @@ -33,7 +33,7 @@ const struct cmd_entry cmd_resize_window_entry = { .name = "resize-window", .alias = "resizew", - .args = { "aADLRt:Ux:y:", 0, 1 }, + .args = { "aADLRt:Ux:y:", 0, 1, NULL }, .usage = "[-aADLRU] [-x width] [-y height] " CMD_TARGET_WINDOW_USAGE " " "[adjustment]", @@ -56,10 +56,10 @@ cmd_resize_window_exec(struct cmd *self, struct cmdq_item *item) u_int adjust, sx, sy; u_int xpixel = ~0, ypixel = ~0; - if (args->argc == 0) + if (args_count(args) == 0) adjust = 1; else { - adjust = strtonum(args->argv[0], 1, INT_MAX, &errstr); + adjust = strtonum(args_string(args, 0), 1, INT_MAX, &errstr); if (errstr != NULL) { cmdq_error(item, "adjustment %s", errstr); return (CMD_RETURN_ERROR); @@ -108,7 +108,9 @@ cmd_resize_window_exec(struct cmd *self, struct cmdq_item *item) } options_set_number(w->options, "window-size", WINDOW_SIZE_MANUAL); - resize_window(w, sx, sy, xpixel, ypixel); + w->manual_sx = sx; + w->manual_sy = sy; + recalculate_size(w, 1); return (CMD_RETURN_NORMAL); } diff --git a/external/bsd/tmux/dist/cmd-send-keys.c b/external/bsd/tmux/dist/cmd-send-keys.c index b362fab50b4..d6a95434ad7 100644 --- a/external/bsd/tmux/dist/cmd-send-keys.c +++ b/external/bsd/tmux/dist/cmd-send-keys.c @@ -33,7 +33,7 @@ const struct cmd_entry cmd_send_keys_entry = { .name = "send-keys", .alias = "send", - .args = { "FHlMN:Rt:X", 0, -1 }, + .args = { "FHlMN:Rt:X", 0, -1, NULL }, .usage = "[-FHlMRX] [-N repeat-count] " CMD_TARGET_PANE_USAGE " key ...", @@ -47,7 +47,7 @@ const struct cmd_entry cmd_send_prefix_entry = { .name = "send-prefix", .alias = NULL, - .args = { "2t:", 0, 0 }, + .args = { "2t:", 0, 0, NULL }, .usage = "[-2] " CMD_TARGET_PANE_USAGE, .target = { 't', CMD_FIND_PANE, 0 }, @@ -90,7 +90,7 @@ static struct cmdq_item * cmd_send_keys_inject_string(struct cmdq_item *item, struct cmdq_item *after, struct args *args, int i) { - const char *s = args->argv[i]; + const char *s = args_string(args, i); struct utf8_data *ud, *loop; utf8_char uc; key_code key; @@ -145,9 +145,9 @@ cmd_send_keys_exec(struct cmd *self, struct cmdq_item *item) struct mouse_event *m = &event->m; struct window_mode_entry *wme = TAILQ_FIRST(&wp->modes); struct cmdq_item *after = item; - int i; key_code key; - u_int np = 1; + u_int i, np = 1; + u_int count = args_count(args); char *cause = NULL; if (args_has(args, 'N')) { @@ -157,7 +157,7 @@ cmd_send_keys_exec(struct cmd *self, struct cmdq_item *item) free(cause); return (CMD_RETURN_ERROR); } - if (wme != NULL && (args_has(args, 'X') || args->argc == 0)) { + if (wme != NULL && (args_has(args, 'X') || count == 0)) { if (wme->mode->command == NULL) { cmdq_error(item, "not in a mode"); return (CMD_RETURN_ERROR); @@ -197,12 +197,21 @@ cmd_send_keys_exec(struct cmd *self, struct cmdq_item *item) } if (args_has(args, 'R')) { - window_pane_reset_palette(wp); + colour_palette_clear(&wp->palette); input_reset(wp->ictx, 1); + wp->flags |= (PANE_STYLECHANGED|PANE_REDRAW); + } + + if (count == 0) { + if (args_has(args, 'N') || args_has(args, 'R')) + return (CMD_RETURN_NORMAL); + for (; np != 0; np--) + cmd_send_keys_inject_key(item, NULL, event->key); + return (CMD_RETURN_NORMAL); } for (; np != 0; np--) { - for (i = 0; i < args->argc; i++) { + for (i = 0; i < count; i++) { after = cmd_send_keys_inject_string(item, after, args, i); } diff --git a/external/bsd/tmux/dist/cmd-show-messages.c b/external/bsd/tmux/dist/cmd-show-messages.c index d2f8289ff50..dca3ab31347 100644 --- a/external/bsd/tmux/dist/cmd-show-messages.c +++ b/external/bsd/tmux/dist/cmd-show-messages.c @@ -38,7 +38,7 @@ const struct cmd_entry cmd_show_messages_entry = { .name = "show-messages", .alias = "showmsgs", - .args = { "JTt:", 0, 0 }, + .args = { "JTt:", 0, 0, NULL }, .usage = "[-JT] " CMD_TARGET_CLIENT_USAGE, .flags = CMD_AFTERHOOK|CMD_CLIENT_TFLAG, diff --git a/external/bsd/tmux/dist/cmd-show-options.c b/external/bsd/tmux/dist/cmd-show-options.c index e3ba821db74..252a33c6117 100644 --- a/external/bsd/tmux/dist/cmd-show-options.c +++ b/external/bsd/tmux/dist/cmd-show-options.c @@ -38,7 +38,7 @@ const struct cmd_entry cmd_show_options_entry = { .name = "show-options", .alias = "show", - .args = { "AgHpqst:vw", 0, 1 }, + .args = { "AgHpqst:vw", 0, 1, NULL }, .usage = "[-AgHpqsvw] " CMD_TARGET_PANE_USAGE " [option]", .target = { 't', CMD_FIND_PANE, CMD_FIND_CANFAIL }, @@ -51,7 +51,7 @@ const struct cmd_entry cmd_show_window_options_entry = { .name = "show-window-options", .alias = "showw", - .args = { "gvt:", 0, 1 }, + .args = { "gvt:", 0, 1, NULL }, .usage = "[-gv] " CMD_TARGET_WINDOW_USAGE " [option]", .target = { 't', CMD_FIND_WINDOW, CMD_FIND_CANFAIL }, @@ -64,7 +64,7 @@ const struct cmd_entry cmd_show_hooks_entry = { .name = "show-hooks", .alias = NULL, - .args = { "gpt:w", 0, 1 }, + .args = { "gpt:w", 0, 1, NULL }, .usage = "[-gpw] " CMD_TARGET_PANE_USAGE, .target = { 't', CMD_FIND_PANE, CMD_FIND_CANFAIL }, @@ -85,7 +85,7 @@ cmd_show_options_exec(struct cmd *self, struct cmdq_item *item) window = (cmd_get_entry(self) == &cmd_show_window_options_entry); - if (args->argc == 0) { + if (args_count(args) == 0) { scope = options_scope_from_flags(args, window, target, &oo, &cause); if (scope == OPTIONS_TABLE_NONE) { @@ -97,12 +97,12 @@ cmd_show_options_exec(struct cmd *self, struct cmdq_item *item) } return (cmd_show_options_all(self, item, scope, oo)); } - argument = format_single_from_target(item, args->argv[0]); + argument = format_single_from_target(item, args_string(args, 0)); name = options_match(argument, &idx, &ambiguous); if (name == NULL) { if (args_has(args, 'q')) - goto fail; + goto out; if (ambiguous) cmdq_error(item, "ambiguous option: %s", argument); else @@ -113,7 +113,7 @@ cmd_show_options_exec(struct cmd *self, struct cmdq_item *item) &cause); if (scope == OPTIONS_TABLE_NONE) { if (args_has(args, 'q')) - goto fail; + goto out; cmdq_error(item, "%s", cause); free(cause); goto fail; @@ -126,7 +126,14 @@ cmd_show_options_exec(struct cmd *self, struct cmdq_item *item) parent = 0; if (o != NULL) cmd_show_options_print(self, item, o, idx, parent); + else if (*name == '@') { + if (args_has(args, 'q')) + goto out; + cmdq_error(item, "invalid option: %s", argument); + goto fail; + } +out: free(name); free(argument); return (CMD_RETURN_NORMAL); diff --git a/external/bsd/tmux/dist/cmd-split-window.c b/external/bsd/tmux/dist/cmd-split-window.c index 77b1eac74d5..9947dfd399b 100644 --- a/external/bsd/tmux/dist/cmd-split-window.c +++ b/external/bsd/tmux/dist/cmd-split-window.c @@ -39,9 +39,10 @@ const struct cmd_entry cmd_split_window_entry = { .name = "split-window", .alias = "splitw", - .args = { "bc:de:fF:hIl:p:Pt:vZ", 0, -1 }, + .args = { "bc:de:fF:hIl:p:Pt:vZ", 0, -1, NULL }, .usage = "[-bdefhIPvZ] [-c start-directory] [-e environment] " - "[-F format] [-l size] " CMD_TARGET_PANE_USAGE " [command]", + "[-F format] [-l size] " CMD_TARGET_PANE_USAGE + "[shell-command]", .target = { 't', CMD_FIND_PANE, 0 }, @@ -55,19 +56,21 @@ cmd_split_window_exec(struct cmd *self, struct cmdq_item *item) struct args *args = cmd_get_args(self); struct cmd_find_state *current = cmdq_get_current(item); struct cmd_find_state *target = cmdq_get_target(item); - struct spawn_context sc; + struct spawn_context sc = { 0 }; struct client *tc = cmdq_get_target_client(item); struct session *s = target->s; struct winlink *wl = target->wl; + struct window *w = wl->window; struct window_pane *wp = target->wp, *new_wp; enum layout_type type; struct layout_cell *lc; struct cmd_find_state fs; int size, percentage, flags, input; - const char *template, *add, *errstr, *p; + const char *template, *errstr, *p; char *cause, *cp, *copy; size_t plen; - struct args_value *value; + struct args_value *av; + u_int count = args_count(args); if (args_has(args, 'h')) type = LAYOUT_LEFTRIGHT; @@ -84,10 +87,17 @@ cmd_split_window_exec(struct cmd *self, struct cmdq_item *item) cmdq_error(item, "percentage %s", errstr); return (CMD_RETURN_ERROR); } - if (type == LAYOUT_TOPBOTTOM) - size = (wp->sy * percentage) / 100; - else - size = (wp->sx * percentage) / 100; + if (args_has(args, 'f')) { + if (type == LAYOUT_TOPBOTTOM) + size = (w->sy * percentage) / 100; + else + size = (w->sx * percentage) / 100; + } else { + if (type == LAYOUT_TOPBOTTOM) + size = (wp->sy * percentage) / 100; + else + size = (wp->sx * percentage) / 100; + } } else { size = args_strtonum(args, 'l', 0, INT_MAX, &cause); if (cause != NULL) { @@ -103,22 +113,29 @@ cmd_split_window_exec(struct cmd *self, struct cmdq_item *item) free(cause); return (CMD_RETURN_ERROR); } - if (type == LAYOUT_TOPBOTTOM) - size = (wp->sy * percentage) / 100; - else - size = (wp->sx * percentage) / 100; + if (args_has(args, 'f')) { + if (type == LAYOUT_TOPBOTTOM) + size = (w->sy * percentage) / 100; + else + size = (w->sx * percentage) / 100; + } else { + if (type == LAYOUT_TOPBOTTOM) + size = (wp->sy * percentage) / 100; + else + size = (wp->sx * percentage) / 100; + } } else size = -1; window_push_zoom(wp->window, 1, args_has(args, 'Z')); - input = (args_has(args, 'I') && args->argc == 0); + input = (args_has(args, 'I') && count == 0); flags = 0; if (args_has(args, 'b')) flags |= SPAWN_BEFORE; if (args_has(args, 'f')) flags |= SPAWN_FULLSIZE; - if (input || (args->argc == 1 && *args->argv[0] == '\0')) + if (input || (count == 1 && *args_string(args, 0) == '\0')) flags |= SPAWN_EMPTY; lc = layout_split_pane(wp, type, size, flags); @@ -127,7 +144,6 @@ cmd_split_window_exec(struct cmd *self, struct cmdq_item *item) return (CMD_RETURN_ERROR); } - memset(&sc, 0, sizeof sc); sc.item = item; sc.s = s; sc.wl = wl; @@ -135,15 +151,13 @@ cmd_split_window_exec(struct cmd *self, struct cmdq_item *item) sc.wp0 = wp; sc.lc = lc; - sc.name = NULL; - sc.argc = args->argc; - sc.argv = args->argv; + args_to_vector(args, &sc.argc, &sc.argv); sc.environ = environ_create(); - add = args_first_value(args, 'e', &value); - while (add != NULL) { - environ_put(sc.environ, add, 0); - add = args_next_value(&value); + av = args_first_value(args, 'e'); + while (av != NULL) { + environ_put(sc.environ, av->string, 0); + av = args_next_value(av); } sc.idx = -1; @@ -158,15 +172,27 @@ cmd_split_window_exec(struct cmd *self, struct cmdq_item *item) if ((new_wp = spawn_pane(&sc, &cause)) == NULL) { cmdq_error(item, "create pane failed: %s", cause); free(cause); + if (sc.argv != NULL) + cmd_free_argv(sc.argc, sc.argv); + environ_free(sc.environ); return (CMD_RETURN_ERROR); } - if (input && window_pane_start_input(new_wp, item, &cause) != 0) { - server_client_remove_pane(new_wp); - layout_close_pane(new_wp); - window_remove_pane(wp->window, new_wp); - cmdq_error(item, "%s", cause); - free(cause); - return (CMD_RETURN_ERROR); + if (input) { + switch (window_pane_start_input(new_wp, item, &cause)) { + case -1: + server_client_remove_pane(new_wp); + layout_close_pane(new_wp); + window_remove_pane(wp->window, new_wp); + cmdq_error(item, "%s", cause); + free(cause); + if (sc.argv != NULL) + cmd_free_argv(sc.argc, sc.argv); + environ_free(sc.environ); + return (CMD_RETURN_ERROR); + case 1: + input = 0; + break; + } } if (!args_has(args, 'd')) cmd_find_from_winlink_pane(current, wl, new_wp, 0); @@ -185,6 +211,8 @@ cmd_split_window_exec(struct cmd *self, struct cmdq_item *item) cmd_find_from_winlink_pane(&fs, wl, new_wp, 0); cmdq_insert_hook(s, item, &fs, "after-split-window"); + if (sc.argv != NULL) + cmd_free_argv(sc.argc, sc.argv); environ_free(sc.environ); if (input) return (CMD_RETURN_WAIT); diff --git a/external/bsd/tmux/dist/cmd-wait-for.c b/external/bsd/tmux/dist/cmd-wait-for.c index 9d9902923c0..ebcb102a5ea 100644 --- a/external/bsd/tmux/dist/cmd-wait-for.c +++ b/external/bsd/tmux/dist/cmd-wait-for.c @@ -34,7 +34,7 @@ const struct cmd_entry cmd_wait_for_entry = { .name = "wait-for", .alias = "wait", - .args = { "LSU", 1, 1 }, + .args = { "LSU", 1, 1, NULL }, .usage = "[-L|-S|-U] channel", .flags = 0, @@ -121,11 +121,11 @@ static enum cmd_retval cmd_wait_for_exec(struct cmd *self, struct cmdq_item *item) { struct args *args = cmd_get_args(self); - const char *name = args->argv[0]; - struct wait_channel *wc, wc0; + const char *name = args_string(args, 0); + struct wait_channel *wc, find; - wc0.name = name; - wc = RB_FIND(wait_channels, &wait_channels, &wc0); + find.name = name; + wc = RB_FIND(wait_channels, &wait_channels, &find); if (args_has(args, 'S')) return (cmd_wait_for_signal(item, name, wc)); diff --git a/external/bsd/tmux/dist/colour.c b/external/bsd/tmux/dist/colour.c index 1d1729cab5d..a282d182503 100644 --- a/external/bsd/tmux/dist/colour.c +++ b/external/bsd/tmux/dist/colour.c @@ -105,6 +105,21 @@ colour_split_rgb(int c, u_char *r, u_char *g, u_char *b) *b = c & 0xff; } +/* Force colour to RGB if not already. */ +int +colour_force_rgb(int c) +{ + if (c & COLOUR_FLAG_RGB) + return (c); + if (c & COLOUR_FLAG_256) + return (colour_256toRGB(c)); + if (c >= 0 && c <= 7) + return (colour_256toRGB(c)); + if (c >= 90 && c <= 97) + return (colour_256toRGB(8 + c - 90)); + return (-1); +} + /* Convert colour to a string. */ const char * colour_tostring(int c) @@ -113,7 +128,7 @@ colour_tostring(int c) u_char r, g, b; if (c == -1) - return ("invalid"); + return ("none"); if (c & COLOUR_FLAG_RGB) { colour_split_rgb(c, &r, &g, &b); @@ -944,3 +959,115 @@ colour_byname(const char *name) } return (-1); } + +/* Initialize palette. */ +void +colour_palette_init(struct colour_palette *p) +{ + p->fg = 8; + p->bg = 8; + p->palette = NULL; + p->default_palette = NULL; +} + +/* Clear palette. */ +void +colour_palette_clear(struct colour_palette *p) +{ + if (p != NULL) { + p->fg = 8; + p->bg = 8; + free(p->palette); + p->palette = NULL; + } +} + +/* Free a palette. */ +void +colour_palette_free(struct colour_palette *p) +{ + if (p != NULL) { + free(p->palette); + p->palette = NULL; + free(p->default_palette); + p->default_palette = NULL; + } +} + +/* Get a colour from a palette. */ +int +colour_palette_get(struct colour_palette *p, int c) +{ + if (p == NULL) + return (-1); + + if (c >= 90 && c <= 97) + c = 8 + c - 90; + else if (c & COLOUR_FLAG_256) + c &= ~COLOUR_FLAG_256; + else if (c >= 8) + return (-1); + + if (p->palette != NULL && p->palette[c] != -1) + return (p->palette[c]); + if (p->default_palette != NULL && p->default_palette[c] != -1) + return (p->default_palette[c]); + return (-1); +} + +/* Set a colour in a palette. */ +int +colour_palette_set(struct colour_palette *p, int n, int c) +{ + u_int i; + + if (p == NULL || n > 255) + return (0); + + if (c == -1 && p->palette == NULL) + return (0); + + if (c != -1 && p->palette == NULL) { + if (p->palette == NULL) + p->palette = xcalloc(256, sizeof *p->palette); + for (i = 0; i < 256; i++) + p->palette[i] = -1; + } + p->palette[n] = c; + return (1); +} + +/* Build palette defaults from an option. */ +void +colour_palette_from_option(struct colour_palette *p, struct options *oo) +{ + struct options_entry *o; + struct options_array_item *a; + u_int i, n; + int c; + + if (p == NULL) + return; + + o = options_get(oo, "pane-colours"); + if ((a = options_array_first(o)) == NULL) { + if (p->default_palette != NULL) { + free(p->default_palette); + p->default_palette = NULL; + } + return; + } + if (p->default_palette == NULL) + p->default_palette = xcalloc(256, sizeof *p->default_palette); + for (i = 0; i < 256; i++) + p->default_palette[i] = -1; + while (a != NULL) { + n = options_array_item_index(a); + if (n < 256) { + c = options_array_item_value(a)->number; + p->default_palette[n] = c; + } + a = options_array_next(a); + } + +} diff --git a/external/bsd/tmux/dist/compat.h b/external/bsd/tmux/dist/compat.h index 6f27eb15085..84452e49d17 100644 --- a/external/bsd/tmux/dist/compat.h +++ b/external/bsd/tmux/dist/compat.h @@ -334,6 +334,11 @@ char *strndup(const char *, size_t); void *memmem(const void *, size_t, const void *, size_t); #endif +#ifndef HAVE_GETPEEREID +/* getpeereid.c */ +int getpeereid(int, uid_t *, gid_t *); +#endif + #ifndef HAVE_DAEMON /* daemon.c */ int daemon(int, int); @@ -416,6 +421,11 @@ void *reallocarray(void *, size_t, size_t); void *recallocarray(void *, size_t, size_t, size_t); #endif +#ifdef HAVE_SYSTEMD +/* systemd.c */ +int systemd_create_socket(int, char **); +#endif + #ifdef HAVE_UTF8PROC /* utf8proc.c */ int utf8proc_wcwidth(wchar_t); diff --git a/external/bsd/tmux/dist/control.c b/external/bsd/tmux/dist/control.c index 087a4960bf8..5a58bb41a09 100644 --- a/external/bsd/tmux/dist/control.c +++ b/external/bsd/tmux/dist/control.c @@ -385,7 +385,7 @@ control_pause_pane(struct client *c, struct window_pane *wp) } /* Write a line. */ -static void __printflike(2, 0) +static void printflike(2, 0) control_vwrite(struct client *c, const char *fmt, va_list ap) { struct control_state *cs = c->control_state; @@ -664,7 +664,7 @@ control_write_pending(struct client *c, struct control_pane *cp, size_t limit) uint64_t age, t = get_timer(); wp = control_window_pane(c, cp->pane); - if (wp == NULL) { + if (wp == NULL || wp->fd == -1) { TAILQ_FOREACH_SAFE(cb, &cp->blocks, entry, cb1) { TAILQ_REMOVE(&cp->blocks, cb, entry); control_free_block(cs, cb); @@ -864,7 +864,7 @@ control_check_subs_pane(struct client *c, struct control_sub *csub) struct control_sub_pane *csp, find; wp = window_pane_find_by_id(csub->id); - if (wp == NULL) + if (wp == NULL || wp->fd == -1) return; w = wp->window; diff --git a/external/bsd/tmux/dist/format.c b/external/bsd/tmux/dist/format.c index 9fa5b69c2e4..de61139cb7e 100644 --- a/external/bsd/tmux/dist/format.c +++ b/external/bsd/tmux/dist/format.c @@ -24,6 +24,7 @@ #include <fnmatch.h> #include <libgen.h> #include <math.h> +#include <pwd.h> #include <regex.h> #include <stdarg.h> #include <stdlib.h> @@ -101,6 +102,7 @@ format_job_cmp(struct format_job *fj1, struct format_job *fj2) #define FORMAT_WINDOW_NAME 0x4000 #define FORMAT_SESSION_NAME 0x8000 #define FORMAT_CHARACTER 0x10000 +#define FORMAT_COLOUR 0x20000 /* Limit on recursion. */ #define FORMAT_LOOP_LIMIT 100 @@ -371,9 +373,6 @@ format_job_get(struct format_expand_state *es, const char *cmd) fj->client = ft->client; fj->tag = ft->tag; fj->cmd = xstrdup(cmd); - fj->expanded = NULL; - - xasprintf(&fj->out, "<'%s' not ready>", fj->cmd); RB_INSERT(format_job_tree, jobs, fj); } @@ -393,7 +392,7 @@ format_job_get(struct format_expand_state *es, const char *cmd) if (force && fj->job != NULL) job_free(fj->job); if (force || (fj->job == NULL && fj->last != t)) { - fj->job = job_run(expanded, 0, NULL, NULL, + fj->job = job_run(expanded, 0, NULL, NULL, NULL, server_client_get_cwd(ft->client, NULL), format_job_update, format_job_complete, NULL, fj, JOB_NOWAIT, -1, -1); if (fj->job == NULL) { @@ -402,11 +401,14 @@ format_job_get(struct format_expand_state *es, const char *cmd) } fj->last = t; fj->updated = 0; - } + } else if (fj->job != NULL && (t - fj->last) > 1 && fj->out == NULL) + xasprintf(&fj->out, "<'%s' not ready>", fj->cmd); free(expanded); if (ft->flags & FORMAT_STATUS) fj->status = 1; + if (fj->out == NULL) + return (xstrdup("")); return (format_expand1(&next, fj->out)); } @@ -799,6 +801,20 @@ format_cb_start_command(struct format_tree *ft) return (cmd_stringify_argv(wp->argc, wp->argv)); } +/* Callback for pane_start_path. */ +static void * +format_cb_start_path(struct format_tree *ft) +{ + struct window_pane *wp = ft->wp; + + if (wp == NULL) + return (NULL); + + if (wp->cwd == NULL) + return (xstrdup("")); + return (xstrdup(wp->cwd)); +} + /* Callback for pane_current_command. */ static void * format_cb_current_command(struct format_tree *ft) @@ -929,6 +945,9 @@ format_cb_pane_fg(struct format_tree *ft) struct window_pane *wp = ft->wp; struct grid_cell gc; + if (wp == NULL) + return (NULL); + tty_default_colours(&gc, wp); return (xstrdup(colour_tostring(gc.fg))); } @@ -940,6 +959,9 @@ format_cb_pane_bg(struct format_tree *ft) struct window_pane *wp = ft->wp; struct grid_cell gc; + if (wp == NULL) + return (NULL); + tty_default_colours(&gc, wp); return (xstrdup(colour_tostring(gc.bg))); } @@ -1380,6 +1402,35 @@ format_cb_client_tty(struct format_tree *ft) return (NULL); } +/* Callback for client_uid. */ +static void * +format_cb_client_uid(struct format_tree *ft) +{ + uid_t uid; + + if (ft->c != NULL) { + uid = proc_get_peer_uid(ft->c->peer); + if (uid != (uid_t)-1) + return (format_printf("%ld", (long)uid)); + } + return (NULL); +} + +/* Callback for client_user. */ +static void * +format_cb_client_user(struct format_tree *ft) +{ + uid_t uid; + struct passwd *pw; + + if (ft->c != NULL) { + uid = proc_get_peer_uid(ft->c->peer); + if (uid != (uid_t)-1 && (pw = getpwuid(uid)) != NULL) + return (xstrdup(pw->pw_name)); + } + return (NULL); +} + /* Callback for client_utf8. */ static void * format_cb_client_utf8(struct format_tree *ft) @@ -1608,11 +1659,16 @@ format_cb_mouse_x(struct format_tree *ft) struct window_pane *wp; u_int x, y; - if (ft->m.valid) { - wp = cmd_mouse_pane(&ft->m, NULL, NULL); - if (wp != NULL && cmd_mouse_at(wp, &ft->m, &x, &y, 0) == 0) - return (format_printf("%u", x)); + if (!ft->m.valid) return (NULL); + wp = cmd_mouse_pane(&ft->m, NULL, NULL); + if (wp != NULL && cmd_mouse_at(wp, &ft->m, &x, &y, 0) == 0) + return (format_printf("%u", x)); + if (ft->c != NULL && (ft->c->tty.flags & TTY_STARTED)) { + if (ft->m.statusat == 0 && ft->m.y < ft->m.statuslines) + return (format_printf("%u", ft->m.x)); + if (ft->m.statusat > 0 && ft->m.y >= (u_int)ft->m.statusat) + return (format_printf("%u", ft->m.x)); } return (NULL); } @@ -1624,15 +1680,27 @@ format_cb_mouse_y(struct format_tree *ft) struct window_pane *wp; u_int x, y; - if (ft->m.valid) { - wp = cmd_mouse_pane(&ft->m, NULL, NULL); - if (wp != NULL && cmd_mouse_at(wp, &ft->m, &x, &y, 0) == 0) - return (format_printf("%u", y)); + if (!ft->m.valid) return (NULL); + wp = cmd_mouse_pane(&ft->m, NULL, NULL); + if (wp != NULL && cmd_mouse_at(wp, &ft->m, &x, &y, 0) == 0) + return (format_printf("%u", y)); + if (ft->c != NULL && (ft->c->tty.flags & TTY_STARTED)) { + if (ft->m.statusat == 0 && ft->m.y < ft->m.statuslines) + return (format_printf("%u", ft->m.y)); + if (ft->m.statusat > 0 && ft->m.y >= (u_int)ft->m.statusat) + return (format_printf("%u", ft->m.y - ft->m.statusat)); } return (NULL); } +/* Callback for next_session_id. */ +static void * +format_cb_next_session_id(__unused struct format_tree *ft) +{ + return (format_printf("$%u", next_session_id)); +} + /* Callback for origin_flag. */ static void * format_cb_origin_flag(struct format_tree *ft) @@ -1702,6 +1770,23 @@ format_cb_pane_dead(struct format_tree *ft) return (NULL); } +/* Callback for pane_dead_signal. */ +static void * +format_cb_pane_dead_signal(struct format_tree *ft) +{ + struct window_pane *wp = ft->wp; + const char *name; + + if (wp != NULL) { + if ((wp->flags & PANE_STATUSREADY) && WIFSIGNALED(wp->status)) { + name = sig2name(WTERMSIG(wp->status)); + return (format_printf("%s", name)); + } + return (NULL); + } + return (NULL); +} + /* Callback for pane_dead_status. */ static void * format_cb_pane_dead_status(struct format_tree *ft) @@ -1716,6 +1801,20 @@ format_cb_pane_dead_status(struct format_tree *ft) return (NULL); } +/* Callback for pane_dead_time. */ +static void * +format_cb_pane_dead_time(struct format_tree *ft) +{ + struct window_pane *wp = ft->wp; + + if (wp != NULL) { + if (wp->flags & PANE_STATUSDRAWN) + return (&wp->dead_time); + return (NULL); + } + return (NULL); +} + /* Callback for pane_format. */ static void * format_cb_pane_format(struct format_tree *ft) @@ -2079,7 +2178,7 @@ static void * format_cb_session_windows(struct format_tree *ft) { if (ft->s != NULL) - return (format_printf ("%u", winlink_count(&ft->s->windows))); + return (format_printf("%u", winlink_count(&ft->s->windows))); return (NULL); } @@ -2497,6 +2596,24 @@ format_cb_tree_mode_format(__unused struct format_tree *ft) return (xstrdup(window_tree_mode.default_format)); } +/* Callback for uid. */ +static void * +format_cb_uid(__unused struct format_tree *ft) +{ + return (format_printf("%ld", (long)getuid())); +} + +/* Callback for user. */ +static void * +format_cb_user(__unused struct format_tree *ft) +{ + struct passwd *pw; + + if ((pw = getpwuid(getuid())) != NULL) + return (xstrdup(pw->pw_name)); + return (NULL); +} + /* Format table type. */ enum format_table_type { FORMAT_TABLE_STRING, @@ -2603,6 +2720,12 @@ static const struct format_table_entry format_table[] = { { "client_tty", FORMAT_TABLE_STRING, format_cb_client_tty }, + { "client_uid", FORMAT_TABLE_STRING, + format_cb_client_uid + }, + { "client_user", FORMAT_TABLE_STRING, + format_cb_client_user + }, { "client_utf8", FORMAT_TABLE_STRING, format_cb_client_utf8 }, @@ -2690,6 +2813,9 @@ static const struct format_table_entry format_table[] = { { "mouse_y", FORMAT_TABLE_STRING, format_cb_mouse_y }, + { "next_session_id", FORMAT_TABLE_STRING, + format_cb_next_session_id + }, { "origin_flag", FORMAT_TABLE_STRING, format_cb_origin_flag }, @@ -2723,9 +2849,15 @@ static const struct format_table_entry format_table[] = { { "pane_dead", FORMAT_TABLE_STRING, format_cb_pane_dead }, + { "pane_dead_signal", FORMAT_TABLE_STRING, + format_cb_pane_dead_signal + }, { "pane_dead_status", FORMAT_TABLE_STRING, format_cb_pane_dead_status }, + { "pane_dead_time", FORMAT_TABLE_TIME, + format_cb_pane_dead_time + }, { "pane_fg", FORMAT_TABLE_STRING, format_cb_pane_fg }, @@ -2780,6 +2912,9 @@ static const struct format_table_entry format_table[] = { { "pane_start_command", FORMAT_TABLE_STRING, format_cb_start_command }, + { "pane_start_path", FORMAT_TABLE_STRING, + format_cb_start_path + }, { "pane_synchronized", FORMAT_TABLE_STRING, format_cb_pane_synchronized }, @@ -2879,6 +3014,12 @@ static const struct format_table_entry format_table[] = { { "tree_mode_format", FORMAT_TABLE_STRING, format_cb_tree_mode_format }, + { "uid", FORMAT_TABLE_STRING, + format_cb_uid + }, + { "user", FORMAT_TABLE_STRING, + format_cb_user + }, { "version", FORMAT_TABLE_STRING, format_cb_version }, @@ -3079,6 +3220,22 @@ format_free(struct format_tree *ft) free(ft); } +/* Log each format. */ +static void +format_log_debug_cb(const char *key, const char *value, void *arg) +{ + const char *prefix = arg; + + log_debug("%s: %s=%s", prefix, key, value); +} + +/* Log a format tree. */ +void +format_log_debug(struct format_tree *ft, const char *prefix) +{ + format_each(ft, format_log_debug_cb, __UNCONST(prefix)); +} + /* Walk each format. */ void format_each(struct format_tree *ft, void (*cb)(const char *, const char *, @@ -3305,7 +3462,7 @@ format_find(struct format_tree *ft, const char *key, int modifiers, fte = format_table_get(key); if (fte != NULL) { value = fte->cb(ft); - if (fte->type == FORMAT_TABLE_TIME) + if (fte->type == FORMAT_TABLE_TIME && value != NULL) t = ((struct timeval *)value)->tv_sec; else found = value; @@ -3523,7 +3680,7 @@ format_build_modifiers(struct format_expand_state *es, const char **s, /* * Modifiers are a ; separated list of the forms: - * l,m,C,a,b,d,n,t,w,q,E,T,S,W,P,<,> + * l,m,C,a,b,c,d,n,t,w,q,E,T,S,W,P,<,> * =a * =/a * =/a/ @@ -3540,7 +3697,7 @@ format_build_modifiers(struct format_expand_state *es, const char **s, cp++; /* Check single character modifiers with no arguments. */ - if (strchr("labdnwETSWP<>", cp[0]) != NULL && + if (strchr("labcdnwETSWP<>", cp[0]) != NULL && format_is_end(cp[1])) { format_add_modifier(&list, count, cp, 1, NULL, 0); cp++; @@ -3604,7 +3761,7 @@ format_build_modifiers(struct format_expand_state *es, const char **s, break; cp++; - argv = xreallocarray (argv, argc + 1, sizeof *argv); + argv = xreallocarray(argv, argc + 1, sizeof *argv); value = xstrndup(cp, end - cp); argv[argc++] = format_expand1(es, value); free(value); @@ -4020,10 +4177,10 @@ format_replace(struct format_expand_state *es, const char *key, size_t keylen, const char *errstr, *copy, *cp, *marker = NULL; const char *time_format = NULL; char *copy0, *condition, *found, *new; - char *value, *left, *right, c; + char *value, *left, *right; size_t valuelen; int modifiers = 0, limit = 0, width = 0; - int j; + int j, c; struct format_modifier *list, *cmp = NULL, *search = NULL; struct format_modifier **sub = NULL, *mexp = NULL, *fm = NULL; u_int i, count, nsub = 0; @@ -4056,8 +4213,7 @@ format_replace(struct format_expand_state *es, const char *key, size_t keylen, case 's': if (fm->argc < 2) break; - sub = xreallocarray (sub, nsub + 1, - sizeof *sub); + sub = xreallocarray(sub, nsub + 1, sizeof *sub); sub[nsub++] = fm; break; case '=': @@ -4095,6 +4251,9 @@ format_replace(struct format_expand_state *es, const char *key, size_t keylen, case 'b': modifiers |= FORMAT_BASENAME; break; + case 'c': + modifiers |= FORMAT_COLOUR; + break; case 'd': modifiers |= FORMAT_DIRNAME; break; @@ -4166,7 +4325,19 @@ format_replace(struct format_expand_state *es, const char *key, size_t keylen, value = xstrdup(""); else xasprintf(&value, "%c", c); - free (new); + free(new); + goto done; + } + + /* Is this a colour? */ + if (modifiers & FORMAT_COLOUR) { + new = format_expand1(es, copy); + c = colour_fromstring(new); + if (c == -1 || (c = colour_force_rgb(c)) == -1) + value = xstrdup(""); + else + xasprintf(&value, "%06x", c & 0xffffff); + free(new); goto done; } @@ -4278,15 +4449,14 @@ format_replace(struct format_expand_state *es, const char *key, size_t keylen, if (strcmp(found, condition) == 0) { free(found); found = xstrdup(""); - format_log(es, "condition '%s' found: %s", - condition, found); - } else { format_log(es, "condition '%s' not found; assuming false", condition); } - } else - format_log(es, "condition '%s' found", condition); + } else { + format_log(es, "condition '%s' found: %s", condition, + found); + } if (format_choose(es, cp + 1, &left, &right, 0) != 0) { format_log(es, "condition '%s' syntax error: %s", @@ -4731,7 +4901,7 @@ format_defaults(struct format_tree *ft, struct client *c, struct session *s, if (wp != NULL) format_defaults_pane(ft, wp); - pb = paste_get_top (NULL); + pb = paste_get_top(NULL); if (pb != NULL) format_defaults_paste_buffer(ft, pb); } @@ -4809,7 +4979,8 @@ format_grid_word(struct grid *gd, u_int x, u_int y) grid_get_cell(gd, x, y, &gc); if (gc.flags & GRID_FLAG_PADDING) break; - if (utf8_cstrhas(ws, &gc.data)) { + if (utf8_cstrhas(ws, &gc.data) || + (gc.data.size == 1 && *gc.data.data == ' ')) { found = 1; break; } @@ -4846,7 +5017,8 @@ format_grid_word(struct grid *gd, u_int x, u_int y) grid_get_cell(gd, x, y, &gc); if (gc.flags & GRID_FLAG_PADDING) break; - if (utf8_cstrhas(ws, &gc.data)) + if (utf8_cstrhas(ws, &gc.data) || + (gc.data.size == 1 && *gc.data.data == ' ')) break; ud = xreallocarray(ud, size + 2, sizeof *ud); diff --git a/external/bsd/tmux/dist/grid.c b/external/bsd/tmux/dist/grid.c index 2a07c9998cc..c82ab9b4595 100644 --- a/external/bsd/tmux/dist/grid.c +++ b/external/bsd/tmux/dist/grid.c @@ -826,6 +826,56 @@ grid_string_cells_bg(const struct grid_cell *gc, int *values) return (n); } +/* Get underscore colour sequence. */ +static size_t +grid_string_cells_us(const struct grid_cell *gc, int *values) +{ + size_t n; + u_char r, g, b; + + n = 0; + if (gc->us & COLOUR_FLAG_256) { + values[n++] = 58; + values[n++] = 5; + values[n++] = gc->us & 0xff; + } else if (gc->us & COLOUR_FLAG_RGB) { + values[n++] = 58; + values[n++] = 2; + colour_split_rgb(gc->us, &r, &g, &b); + values[n++] = r; + values[n++] = g; + values[n++] = b; + } + return (n); +} + +/* 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) +{ + u_int i; + char tmp[64]; + + 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); + 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); + } +} + /* * Returns ANSI code to set particular attributes (colour, bold and so on) * given a current state. @@ -861,7 +911,9 @@ grid_string_cells_code(const struct grid_cell *lastgc, /* If any attribute is removed, begin with 0. */ for (i = 0; i < nitems(attrs); i++) { - if (!(attr & attrs[i].mask) && (lastattr & attrs[i].mask)) { + if (((~attr & attrs[i].mask) && + (lastattr & attrs[i].mask)) || + (lastgc->us != 0 && gc->us == 0)) { s[n++] = 0; lastattr &= GRID_ATTR_CHARSET; break; @@ -897,42 +949,20 @@ grid_string_cells_code(const struct grid_cell *lastgc, /* If the foreground colour changed, write its parameters. */ nnewc = grid_string_cells_fg(gc, newc); noldc = grid_string_cells_fg(lastgc, oldc); - if (nnewc != noldc || - memcmp(newc, oldc, nnewc * sizeof newc[0]) != 0 || - (n != 0 && s[0] == 0)) { - if (escape_c0) - 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 - xsnprintf(tmp, sizeof tmp, "%d", newc[i]); - strlcat(buf, tmp, len); - } - strlcat(buf, "m", len); - } + grid_string_cells_add_code(buf, len, n, s, newc, oldc, nnewc, noldc, + escape_c0); /* If the background colour changed, append its parameters. */ nnewc = grid_string_cells_bg(gc, newc); noldc = grid_string_cells_bg(lastgc, oldc); - if (nnewc != noldc || - memcmp(newc, oldc, nnewc * sizeof newc[0]) != 0 || - (n != 0 && s[0] == 0)) { - if (escape_c0) - 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 - xsnprintf(tmp, sizeof tmp, "%d", newc[i]); - strlcat(buf, tmp, len); - } - strlcat(buf, "m", len); - } + grid_string_cells_add_code(buf, len, n, s, newc, oldc, nnewc, noldc, + escape_c0); + + /* 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); /* Append shift in/shift out if needed. */ if ((attr & GRID_ATTR_CHARSET) && !(lastattr & GRID_ATTR_CHARSET)) { @@ -973,7 +1003,7 @@ grid_string_cells(struct grid *gd, u_int px, u_int py, u_int nx, gl = grid_peek_line(gd, py); for (xx = px; xx < px + nx; xx++) { - if (gl == NULL || xx >= gl->cellsize) + if (gl == NULL || xx >= gl->cellused) break; grid_get_cell(gd, xx, py, &gc); if (gc.flags & GRID_FLAG_PADDING) diff --git a/external/bsd/tmux/dist/input-keys.c b/external/bsd/tmux/dist/input-keys.c index 13d06f519d9..003a7dc516d 100644 --- a/external/bsd/tmux/dist/input-keys.c +++ b/external/bsd/tmux/dist/input-keys.c @@ -333,7 +333,7 @@ input_key_cmp(struct input_key_entry *ike1, struct input_key_entry *ike2) /* Look for key in tree. */ static struct input_key_entry * -input_key_get (key_code key) +input_key_get(key_code key) { struct input_key_entry entry = { .key = key }; @@ -417,7 +417,7 @@ int input_key(struct screen *s, struct bufferevent *bev, key_code key) { struct input_key_entry *ike; - key_code justkey, newkey, outkey; + key_code justkey, newkey, outkey, modifiers; struct utf8_data ud; char tmp[64], modifier; @@ -518,7 +518,12 @@ input_key(struct screen *s, struct bufferevent *bev, key_code key) return (input_key(s, bev, key & ~KEYC_CTRL)); } outkey = (key & KEYC_MASK_KEY); - switch (key & KEYC_MASK_MODIFIERS) { + modifiers = (key & KEYC_MASK_MODIFIERS); + if (outkey < 32 && outkey != 9 && outkey != 13 && outkey != 27) { + outkey = 64 + outkey; + modifiers |= KEYC_CTRL; + } + switch (modifiers) { case KEYC_SHIFT: modifier = '2'; break; @@ -577,13 +582,13 @@ input_key_get_mouse(struct screen *s, struct mouse_event *m, u_int x, u_int y, */ if (m->sgr_type != ' ') { if (MOUSE_DRAG(m->sgr_b) && - MOUSE_BUTTONS(m->sgr_b) == 3 && + MOUSE_RELEASE(m->sgr_b) && (~s->mode & MODE_MOUSE_ALL)) return (0); } else { if (MOUSE_DRAG(m->b) && - MOUSE_BUTTONS(m->b) == 3 && - MOUSE_BUTTONS(m->lb) == 3 && + MOUSE_RELEASE(m->b) && + MOUSE_RELEASE(m->lb) && (~s->mode & MODE_MOUSE_ALL)) return (0); } @@ -601,19 +606,34 @@ input_key_get_mouse(struct screen *s, struct mouse_event *m, u_int x, u_int y, len = xsnprintf(buf, sizeof buf, "\033[<%u;%u;%u%c", m->sgr_b, x + 1, y + 1, m->sgr_type); } else if (s->mode & MODE_MOUSE_UTF8) { - if (m->b > 0x7ff - 32 || x > 0x7ff - 33 || y > 0x7ff - 33) + if (m->b > MOUSE_PARAM_UTF8_MAX - MOUSE_PARAM_BTN_OFF || + x > MOUSE_PARAM_UTF8_MAX - MOUSE_PARAM_POS_OFF || + y > MOUSE_PARAM_UTF8_MAX - MOUSE_PARAM_POS_OFF) return (0); len = xsnprintf(buf, sizeof buf, "\033[M"); - len += input_key_split2(m->b + 32, &buf[len]); - len += input_key_split2(x + 33, &buf[len]); - len += input_key_split2(y + 33, &buf[len]); + len += input_key_split2(m->b + MOUSE_PARAM_BTN_OFF, &buf[len]); + len += input_key_split2(x + MOUSE_PARAM_POS_OFF, &buf[len]); + len += input_key_split2(y + MOUSE_PARAM_POS_OFF, &buf[len]); } else { - if (m->b > 223) + if (m->b + MOUSE_PARAM_BTN_OFF > MOUSE_PARAM_MAX) return (0); + len = xsnprintf(buf, sizeof buf, "\033[M"); - buf[len++] = m->b + 32; - buf[len++] = x + 33; - buf[len++] = y + 33; + buf[len++] = m->b + MOUSE_PARAM_BTN_OFF; + + /* + * The incoming x and y may be out of the range which can be + * supported by the "normal" mouse protocol. Clamp the + * coordinates to the supported range. + */ + if (x + MOUSE_PARAM_POS_OFF > MOUSE_PARAM_MAX) + buf[len++] = MOUSE_PARAM_MAX; + else + buf[len++] = x + MOUSE_PARAM_POS_OFF; + if (y + MOUSE_PARAM_POS_OFF > MOUSE_PARAM_MAX) + buf[len++] = MOUSE_PARAM_MAX; + else + buf[len++] = y + MOUSE_PARAM_POS_OFF; } *rbuf = buf; diff --git a/external/bsd/tmux/dist/input.c b/external/bsd/tmux/dist/input.c index cb0a62aa069..1abfd5b8831 100644 --- a/external/bsd/tmux/dist/input.c +++ b/external/bsd/tmux/dist/input.c @@ -77,6 +77,7 @@ struct input_ctx { struct window_pane *wp; struct bufferevent *event; struct screen_write_ctx ctx; + struct colour_palette *palette; struct input_cell cell; @@ -136,10 +137,12 @@ static void input_reset_cell(struct input_ctx *); static void input_osc_4(struct input_ctx *, const char *); static void input_osc_10(struct input_ctx *, const char *); static void input_osc_11(struct input_ctx *, const char *); +static void input_osc_12(struct input_ctx *, const char *); static void input_osc_52(struct input_ctx *, const char *); static void input_osc_104(struct input_ctx *, const char *); static void input_osc_110(struct input_ctx *, const char *); static void input_osc_111(struct input_ctx *, const char *); +static void input_osc_112(struct input_ctx *, const char *); /* Transition entry/exit handlers. */ static void input_clear(struct input_ctx *); @@ -797,13 +800,15 @@ input_restore_state(struct input_ctx *ictx) /* Initialise input parser. */ struct input_ctx * -input_init(struct window_pane *wp, struct bufferevent *bev) +input_init(struct window_pane *wp, struct bufferevent *bev, + struct colour_palette *palette) { struct input_ctx *ictx; ictx = xcalloc(1, sizeof *ictx); ictx->wp = wp; ictx->event = bev; + ictx->palette = palette; ictx->input_space = INPUT_BUF_START; ictx->input_buf = xmalloc(INPUT_BUF_START); @@ -1073,6 +1078,9 @@ input_reply(struct input_ctx *ictx, const char *fmt, ...) va_list ap; char *reply; + if (bev == NULL) + return; + va_start(ap, fmt); xvasprintf(&reply, fmt, ap); va_end(ap); @@ -1252,7 +1260,6 @@ static int input_esc_dispatch(struct input_ctx *ictx) { struct screen_write_ctx *sctx = &ictx->ctx; - struct window_pane *wp = ictx->wp; struct screen *s = sctx->s; struct input_table_entry *entry; @@ -1269,10 +1276,10 @@ input_esc_dispatch(struct input_ctx *ictx) switch (entry->type) { case INPUT_ESC_RIS: - if (wp != NULL) - window_pane_reset_palette(wp); + colour_palette_clear(ictx->palette); input_reset_cell(ictx); screen_write_reset(sctx); + screen_write_fullredraw(sctx); break; case INPUT_ESC_IND: screen_write_linefeed(sctx, 0, ictx->cell.cell.bg); @@ -1615,7 +1622,7 @@ input_csi_dispatch(struct input_ctx *ictx) case INPUT_CSI_DECSCUSR: n = input_get(ictx, 0, 0, 0); if (n != -1) - screen_set_cursor_style(s, n); + screen_set_cursor_style(n, &s->cstyle, &s->mode); break; case INPUT_CSI_XDA: n = input_get(ictx, 0, 0, 0); @@ -1644,7 +1651,7 @@ input_csi_dispatch_rm(struct input_ctx *ictx) screen_write_mode_clear(sctx, MODE_INSERT); break; case 34: - screen_write_mode_set(sctx, MODE_BLINKING); + screen_write_mode_set(sctx, MODE_CURSOR_VERY_VISIBLE); break; default: log_debug("%s: unknown '%c'", __func__, ictx->ch); @@ -1680,7 +1687,8 @@ input_csi_dispatch_rm_private(struct input_ctx *ictx) screen_write_mode_clear(sctx, MODE_WRAP); break; case 12: - screen_write_mode_clear(sctx, MODE_BLINKING); + screen_write_mode_clear(sctx, MODE_CURSOR_BLINKING); + screen_write_mode_set(sctx, MODE_CURSOR_BLINKING_SET); break; case 25: /* TCEM */ screen_write_mode_clear(sctx, MODE_CURSOR); @@ -1732,7 +1740,7 @@ input_csi_dispatch_sm(struct input_ctx *ictx) screen_write_mode_set(sctx, MODE_INSERT); break; case 34: - screen_write_mode_clear(sctx, MODE_BLINKING); + screen_write_mode_clear(sctx, MODE_CURSOR_VERY_VISIBLE); break; default: log_debug("%s: unknown '%c'", __func__, ictx->ch); @@ -1769,7 +1777,8 @@ input_csi_dispatch_sm_private(struct input_ctx *ictx) screen_write_mode_set(sctx, MODE_WRAP); break; case 12: - screen_write_mode_set(sctx, MODE_BLINKING); + screen_write_mode_set(sctx, MODE_CURSOR_BLINKING); + screen_write_mode_set(sctx, MODE_CURSOR_BLINKING_SET); break; case 25: /* TCEM */ screen_write_mode_set(sctx, MODE_CURSOR); @@ -1790,8 +1799,14 @@ input_csi_dispatch_sm_private(struct input_ctx *ictx) if (sctx->s->mode & MODE_FOCUSON) break; screen_write_mode_set(sctx, MODE_FOCUSON); - if (wp != NULL) - wp->flags |= PANE_FOCUSPUSH; /* force update */ + if (wp == NULL) + break; + if (!options_get_number(global_options, "focus-events")) + break; + if (wp->flags & PANE_FOCUSED) + bufferevent_write(wp->event, "\033[I", 3); + else + bufferevent_write(wp->event, "\033[O", 3); break; case 1005: screen_write_mode_set(sctx, MODE_MOUSE_UTF8); @@ -1874,11 +1889,11 @@ input_csi_dispatch_winops(struct input_ctx *ictx) case 0: case 2: screen_pop_title(sctx->s); - if (wp != NULL) { - notify_pane("pane-title-changed", wp); - server_redraw_window_borders(wp->window); - server_status_window(wp->window); - } + if (wp == NULL) + break; + notify_pane("pane-title-changed", wp); + server_redraw_window_borders(wp->window); + server_status_window(wp->window); break; } break; @@ -2225,15 +2240,19 @@ input_enter_dcs(struct input_ctx *ictx) static int input_dcs_dispatch(struct input_ctx *ictx) { + struct window_pane *wp = ictx->wp; struct screen_write_ctx *sctx = &ictx->ctx; char *buf = (char *)ictx->input_buf; size_t len = ictx->input_len; const char prefix[] = "tmux;"; const u_int prefixlen = (sizeof prefix) - 1; + if (wp == NULL) + return (0); if (ictx->flags & INPUT_DISCARD) return (0); - + if (!options_get_number(ictx->wp->options, "allow-passthrough")) + return (0); log_debug("%s: \"%s\"", __func__, buf); if (len >= prefixlen && strncmp(buf, prefix, prefixlen) == 0) @@ -2304,8 +2323,7 @@ input_exit_osc(struct input_ctx *ictx) input_osc_11(ictx, p); break; case 12: - if (utf8_isvalid(p) && *p != '?') /* ? is colour request */ - screen_set_cursor_colour(sctx->s, p); + input_osc_12(ictx, p); break; case 52: input_osc_52(ictx, p); @@ -2320,8 +2338,7 @@ input_exit_osc(struct input_ctx *ictx) input_osc_111(ictx, p); break; case 112: - if (*p == '\0') /* no arguments allowed */ - screen_set_cursor_colour(sctx->s, ""); + input_osc_112(ictx, p); break; default: log_debug("%s: unknown '%u'", __func__, option); @@ -2375,6 +2392,7 @@ static void input_exit_rename(struct input_ctx *ictx) { struct window_pane *wp = ictx->wp; + struct window *w; struct options_entry *o; char *p = (char *)ictx->input_buf; @@ -2388,17 +2406,20 @@ input_exit_rename(struct input_ctx *ictx) if (!utf8_isvalid(p)) return; + w = wp->window; if (ictx->input_len == 0) { - o = options_get_only(wp->window->options, "automatic-rename"); + o = options_get_only(w->options, "automatic-rename"); if (o != NULL) options_remove_or_default(o, -1, NULL); - return; + if (!options_get_number(w->options, "automatic-rename")) + window_set_name(w, ""); + } else { + options_set_number(w->options, "automatic-rename", 0); + window_set_name(w, ictx->input_buf); } - window_set_name(wp->window, p); - options_set_number(wp->window->options, "automatic-rename", 0); - server_redraw_window_borders(wp->window); - server_status_window(wp->window); + server_redraw_window_borders(w); + server_status_window(w); } /* Open UTF-8 character. */ @@ -2485,7 +2506,9 @@ input_osc_colour_reply(struct input_ctx *ictx, u_int n, int c) u_char r, g, b; const char *end; - if (c == 8 || (~c & COLOUR_FLAG_RGB)) + if (c != -1) + c = colour_force_rgb(c); + if (c == -1) return; colour_split_rgb(c, &r, &g, &b); @@ -2493,44 +2516,49 @@ input_osc_colour_reply(struct input_ctx *ictx, u_int n, int c) end = "\007"; else end = "\033\\"; - input_reply(ictx, "\033]%u;rgb:%02hhx/%02hhx/%02hhx%s", n, r, g, b, end); + input_reply(ictx, "\033]%u;rgb:%02hhx%02hhx/%02hhx%02hhx/%02hhx%02hhx%s", + n, r, r, g, g, b, b, end); } /* Handle the OSC 4 sequence for setting (multiple) palette entries. */ static void input_osc_4(struct input_ctx *ictx, const char *p) { - struct window_pane *wp = ictx->wp; - char *copy, *s, *next = NULL; - long idx; - int c; - - if (wp == NULL) - return; + char *copy, *s, *next = NULL; + long idx; + int c, bad = 0, redraw = 0; copy = s = xstrdup(p); while (s != NULL && *s != '\0') { idx = strtol(s, &next, 10); - if (*next++ != ';') - goto bad; - if (idx < 0 || idx >= 0x100) - goto bad; + if (*next++ != ';') { + bad = 1; + break; + } + if (idx < 0 || idx >= 256) { + bad = 1; + break; + } s = strsep(&next, ";"); + if (strcmp(s, "?") == 0) { + c = colour_palette_get(ictx->palette, idx); + if (c != -1) + input_osc_colour_reply(ictx, 4, c); + continue; + } if ((c = input_osc_parse_colour(s)) == -1) { s = next; continue; } - - window_pane_set_palette(wp, idx, c); + if (colour_palette_set(ictx->palette, idx, c)) + redraw = 1; s = next; } - - free(copy); - return; - -bad: - log_debug("bad OSC 4: %s", p); + if (bad) + log_debug("bad OSC 4: %s", p); + if (redraw) + screen_write_fullredraw(&ictx->ctx); free(copy); } @@ -2542,40 +2570,40 @@ input_osc_10(struct input_ctx *ictx, const char *p) struct grid_cell defaults; int c; - if (wp == NULL) - return; - if (strcmp(p, "?") == 0) { - tty_default_colours(&defaults, wp); - input_osc_colour_reply(ictx, 10, defaults.fg); + if (wp != NULL) { + tty_default_colours(&defaults, wp); + input_osc_colour_reply(ictx, 10, defaults.fg); + } return; } - if ((c = input_osc_parse_colour(p)) == -1) - goto bad; - wp->fg = c; - wp->flags |= (PANE_REDRAW|PANE_STYLECHANGED); - - return; - -bad: - log_debug("bad OSC 10: %s", p); + if ((c = input_osc_parse_colour(p)) == -1) { + log_debug("bad OSC 10: %s", p); + return; + } + if (ictx->palette != NULL) { + ictx->palette->fg = c; + if (wp != NULL) + wp->flags |= PANE_STYLECHANGED; + screen_write_fullredraw(&ictx->ctx); + } } -/* Handle the OSC 110 sequence for resetting background colour. */ +/* Handle the OSC 110 sequence for resetting foreground colour. */ static void input_osc_110(struct input_ctx *ictx, const char *p) { struct window_pane *wp = ictx->wp; - if (wp == NULL) - return; - if (*p != '\0') return; - - wp->fg = 8; - wp->flags |= (PANE_REDRAW|PANE_STYLECHANGED); + if (ictx->palette != NULL) { + ictx->palette->fg = 8; + if (wp != NULL) + wp->flags |= PANE_STYLECHANGED; + screen_write_fullredraw(&ictx->ctx); + } } /* Handle the OSC 11 sequence for setting and querying background colour. */ @@ -2586,24 +2614,24 @@ input_osc_11(struct input_ctx *ictx, const char *p) struct grid_cell defaults; int c; - if (wp == NULL) - return; - if (strcmp(p, "?") == 0) { - tty_default_colours(&defaults, wp); - input_osc_colour_reply(ictx, 11, defaults.bg); + if (wp != NULL) { + tty_default_colours(&defaults, wp); + input_osc_colour_reply(ictx, 11, defaults.bg); + } return; } - if ((c = input_osc_parse_colour(p)) == -1) - goto bad; - wp->bg = c; - wp->flags |= (PANE_REDRAW|PANE_STYLECHANGED); - - return; - -bad: - log_debug("bad OSC 11: %s", p); + if ((c = input_osc_parse_colour(p)) == -1) { + log_debug("bad OSC 11: %s", p); + return; + } + if (ictx->palette != NULL) { + ictx->palette->bg = c; + if (wp != NULL) + wp->flags |= PANE_STYLECHANGED; + screen_write_fullredraw(&ictx->ctx); + } } /* Handle the OSC 111 sequence for resetting background colour. */ @@ -2612,24 +2640,57 @@ input_osc_111(struct input_ctx *ictx, const char *p) { struct window_pane *wp = ictx->wp; - if (wp == NULL) + if (*p != '\0') return; + if (ictx->palette != NULL) { + ictx->palette->bg = 8; + if (wp != NULL) + wp->flags |= PANE_STYLECHANGED; + screen_write_fullredraw(&ictx->ctx); + } +} - if (*p != '\0') +/* Handle the OSC 12 sequence for setting and querying cursor colour. */ +static void +input_osc_12(struct input_ctx *ictx, const char *p) +{ + struct window_pane *wp = ictx->wp; + int c; + + if (strcmp(p, "?") == 0) { + if (wp != NULL) { + c = ictx->ctx.s->ccolour; + if (c == -1) + c = ictx->ctx.s->default_ccolour; + input_osc_colour_reply(ictx, 12, c); + } return; + } - wp->bg = 8; - wp->flags |= (PANE_REDRAW|PANE_STYLECHANGED); + if ((c = input_osc_parse_colour(p)) == -1) { + log_debug("bad OSC 12: %s", p); + return; + } + screen_set_cursor_colour(ictx->ctx.s, c); } +/* Handle the OSC 112 sequence for resetting cursor colour. */ +static void +input_osc_112(struct input_ctx *ictx, const char *p) +{ + if (*p == '\0') /* no arguments allowed */ + screen_set_cursor_colour(ictx->ctx.s, -1); +} + + /* Handle the OSC 52 sequence for setting the clipboard. */ static void input_osc_52(struct input_ctx *ictx, const char *p) { struct window_pane *wp = ictx->wp; char *end; - const char *buf; - size_t len; + const char *buf = NULL; + size_t len = 0; u_char *out; int outlen, state; struct screen_write_ctx ctx; @@ -2649,26 +2710,12 @@ input_osc_52(struct input_ctx *ictx, const char *p) log_debug("%s: %s", __func__, end); if (strcmp(end, "?") == 0) { - if ((pb = paste_get_top(NULL)) != NULL) { + if ((pb = paste_get_top(NULL)) != NULL) buf = paste_buffer_data(pb, &len); - outlen = 4 * ((len + 2) / 3) + 1; - out = xmalloc(outlen); - if ((outlen = b64_ntop((const unsigned char *)buf, len, (char *)out, outlen)) == -1) { - free(out); - return; - } - } else { - outlen = 0; - out = NULL; - } - bufferevent_write(ictx->event, "\033]52;;", 6); - if (outlen != 0) - bufferevent_write(ictx->event, out, outlen); if (ictx->input_end == INPUT_END_BEL) - bufferevent_write(ictx->event, "\007", 1); + input_reply_clipboard(ictx->event, buf, len, "\007"); else - bufferevent_write(ictx->event, "\033\\", 2); - free(out); + input_reply_clipboard(ictx->event, buf, len, "\033\\"); return; } @@ -2694,34 +2741,58 @@ input_osc_52(struct input_ctx *ictx, const char *p) static void input_osc_104(struct input_ctx *ictx, const char *p) { - struct window_pane *wp = ictx->wp; - char *copy, *s; - long idx; - - if (wp == NULL) - return; + char *copy, *s; + long idx; + int bad = 0, redraw = 0; if (*p == '\0') { - window_pane_reset_palette(wp); + colour_palette_clear(ictx->palette); + screen_write_fullredraw(&ictx->ctx); return; } copy = s = xstrdup(p); while (*s != '\0') { idx = strtol(s, &s, 10); - if (*s != '\0' && *s != ';') - goto bad; - if (idx < 0 || idx >= 0x100) - goto bad; - - window_pane_unset_palette(wp, idx); + if (*s != '\0' && *s != ';') { + bad = 1; + break; + } + if (idx < 0 || idx >= 256) { + bad = 1; + break; + } + if (colour_palette_set(ictx->palette, idx, -1)) + redraw = 1; if (*s == ';') s++; } + if (bad) + log_debug("bad OSC 104: %s", p); + if (redraw) + screen_write_fullredraw(&ictx->ctx); free(copy); - return; +} -bad: - log_debug("bad OSC 104: %s", p); - free(copy); +void +input_reply_clipboard(struct bufferevent *bev, const char *buf, size_t len, + const char *end) +{ + char *out = NULL; + size_t outlen = 0; + + if (buf != NULL && len != 0) { + outlen = 4 * ((len + 2) / 3) + 1; + out = xmalloc(outlen); + if ((outlen = b64_ntop(buf, len, out, outlen)) == -1) { + free(out); + return; + } + } + + bufferevent_write(bev, "\033]52;;", 6); + if (outlen != 0) + bufferevent_write(bev, out, outlen); + bufferevent_write(bev, end, strlen(end)); + free(out); } diff --git a/external/bsd/tmux/dist/job.c b/external/bsd/tmux/dist/job.c index a1fc0cf5ecd..d2d9adbfdd4 100644 --- a/external/bsd/tmux/dist/job.c +++ b/external/bsd/tmux/dist/job.c @@ -50,6 +50,7 @@ struct job { char *cmd; pid_t pid; + char tty[TTY_NAME_MAX]; int status; int fd; @@ -68,7 +69,7 @@ static LIST_HEAD(joblist, job) all_jobs = LIST_HEAD_INITIALIZER(all_jobs); /* Start a job running. */ struct job * -job_run(const char *cmd, int argc, char **argv, struct session *s, +job_run(const char *cmd, int argc, char **argv, struct environ *e, struct session *s, const char *cwd, job_update_cb updatecb, job_complete_cb completecb, job_free_cb freecb, void *data, int flags, int sx, int sy) { @@ -79,13 +80,15 @@ job_run(const char *cmd, int argc, char **argv, struct session *s, const char *home; sigset_t set, oldset; struct winsize ws; - char **argvp; + char **argvp, tty[TTY_NAME_MAX]; /* * Do not set TERM during .tmux.conf, it is nice to be able to use * if-shell to decide on default-terminal based on outside TERM. */ env = environ_for_session(s, !cfg_finished); + if (e != NULL) + environ_copy(e, env); sigfillset(&set); sigprocmask(SIG_BLOCK, &set, &oldset); @@ -94,7 +97,7 @@ job_run(const char *cmd, int argc, char **argv, struct session *s, memset(&ws, 0, sizeof ws); ws.ws_col = sx; ws.ws_row = sy; - pid = fdforkpty(ptm_fd, &master, NULL, NULL, &ws); + pid = fdforkpty(ptm_fd, &master, tty, NULL, &ws); } else { if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, out) != 0) goto fail; @@ -136,7 +139,7 @@ job_run(const char *cmd, int argc, char **argv, struct session *s, close(out[1]); close(out[0]); - nullfd = open(_PATH_DEVNULL, O_RDWR, 0); + nullfd = open(_PATH_DEVNULL, O_RDWR); if (nullfd == -1) fatal("open failed"); if (dup2(nullfd, STDERR_FILENO) == -1) @@ -168,6 +171,7 @@ job_run(const char *cmd, int argc, char **argv, struct session *s, else job->cmd = cmd_stringify_argv(argc, argv); job->pid = pid; + strlcpy(job->tty, tty, sizeof job->tty); job->status = 0; LIST_INSERT_HEAD(&all_jobs, job, entry); @@ -199,6 +203,32 @@ fail: return (NULL); } +/* Take job's file descriptor and free the job. */ +int +job_transfer(struct job *job, pid_t *pid, char *tty, size_t ttylen) +{ + int fd = job->fd; + + log_debug("transfer job %p: %s", job, job->cmd); + + if (pid != NULL) + *pid = job->pid; + if (tty != NULL) + strlcpy(tty, job->tty, ttylen); + + LIST_REMOVE(job, entry); + free(job->cmd); + + if (job->freecb != NULL && job->data != NULL) + job->freecb(job->data); + + if (job->event != NULL) + bufferevent_free(job->event); + + free(job); + return (fd); +} + /* Kill and free an individual job. */ void job_free(struct job *job) diff --git a/external/bsd/tmux/dist/key-bindings.c b/external/bsd/tmux/dist/key-bindings.c index 2901c78e721..1c96ea04d56 100644 --- a/external/bsd/tmux/dist/key-bindings.c +++ b/external/bsd/tmux/dist/key-bindings.c @@ -29,7 +29,7 @@ " 'Previous' 'p' {switch-client -p}" \ " ''" \ " 'Renumber' 'N' {move-window -r}" \ - " 'Rename' 'n' {command-prompt -I \"#S\" \"rename-session -- '%%'\"}" \ + " 'Rename' 'n' {command-prompt -I \"#S\" {rename-session -- '%%'}}" \ " ''" \ " 'New Session' 's' {new-session}" \ " 'New Window' 'w' {new-window}" @@ -41,7 +41,7 @@ " 'Kill' 'X' {kill-window}" \ " 'Respawn' 'R' {respawn-window -k}" \ " '#{?pane_marked,Unmark,Mark}' 'm' {select-pane -m}" \ - " 'Rename' 'n' {command-prompt -I \"#W\" \"rename-window -- '%%'\"}" \ + " 'Rename' 'n' {command-prompt -FI \"#W\" {rename-window -t '#{window_id}' -- '%%'}}" \ " ''" \ " 'New After' 'w' {new-window -a}" \ " 'New At End' 'W' {new-window}" @@ -187,6 +187,7 @@ key_bindings_add(const char *name, key_code key, const char *note, int repeat, { struct key_table *table; struct key_binding *bd; + char *s; table = key_bindings_get_table(name, 1); @@ -216,8 +217,10 @@ key_bindings_add(const char *name, key_code key, const char *note, int repeat, bd->flags |= KEY_BINDING_REPEAT; bd->cmdlist = cmdlist; + s = cmd_list_print(bd->cmdlist, 0); log_debug("%s: %#llx %s = %s", __func__, bd->key, - key_string_lookup_key(bd->key, 1), cmd_list_print(bd->cmdlist, 0)); + key_string_lookup_key(bd->key, 1), s); + free(s); } void @@ -340,299 +343,303 @@ key_bindings_init(void) { static const char *defaults[] = { /* Prefix keys. */ - "bind -N 'Send the prefix key' C-b send-prefix", - "bind -N 'Rotate through the panes' C-o rotate-window", - "bind -N 'Suspend the current client' C-z suspend-client", - "bind -N 'Select next layout' Space next-layout", - "bind -N 'Break pane to a new window' ! break-pane", - "bind -N 'Split window vertically' '\"' split-window", - "bind -N 'List all paste buffers' '#' list-buffers", - "bind -N 'Rename current session' '$' command-prompt -I'#S' \"rename-session -- '%%'\"", - "bind -N 'Split window horizontally' % split-window -h", - "bind -N 'Kill current window' & confirm-before -p\"kill-window #W? (y/n)\" kill-window", - "bind -N 'Prompt for window index to select' \"'\" command-prompt -Wpindex \"select-window -t ':%%'\"", - "bind -N 'Switch to previous client' ( switch-client -p", - "bind -N 'Switch to next client' ) switch-client -n", - "bind -N 'Rename current window' , command-prompt -I'#W' \"rename-window -- '%%'\"", - "bind -N 'Delete the most recent paste buffer' - delete-buffer", - "bind -N 'Move the current window' . command-prompt -T \"move-window -t '%%'\"", - "bind -N 'Describe key binding' '/' command-prompt -kpkey 'list-keys -1N \"%%%\"'", - "bind -N 'Select window 0' 0 select-window -t:=0", - "bind -N 'Select window 1' 1 select-window -t:=1", - "bind -N 'Select window 2' 2 select-window -t:=2", - "bind -N 'Select window 3' 3 select-window -t:=3", - "bind -N 'Select window 4' 4 select-window -t:=4", - "bind -N 'Select window 5' 5 select-window -t:=5", - "bind -N 'Select window 6' 6 select-window -t:=6", - "bind -N 'Select window 7' 7 select-window -t:=7", - "bind -N 'Select window 8' 8 select-window -t:=8", - "bind -N 'Select window 9' 9 select-window -t:=9", - "bind -N 'Prompt for a command' : command-prompt", - "bind -N 'Move to the previously active pane' \\; last-pane", - "bind -N 'Choose a paste buffer from a list' = choose-buffer -Z", - "bind -N 'List key bindings' ? list-keys -N", - "bind -N 'Choose a client from a list' D choose-client -Z", - "bind -N 'Spread panes out evenly' E select-layout -E", - "bind -N 'Switch to the last client' L switch-client -l", - "bind -N 'Clear the marked pane' M select-pane -M", - "bind -N 'Enter copy mode' [ copy-mode", - "bind -N 'Paste the most recent paste buffer' ] paste-buffer -p", - "bind -N 'Create a new window' c new-window", - "bind -N 'Detach the current client' d detach-client", - "bind -N 'Search for a pane' f command-prompt \"find-window -Z -- '%%'\"", - "bind -N 'Display window information' i display-message", - "bind -N 'Select the previously current window' l last-window", - "bind -N 'Toggle the marked pane' m select-pane -m", - "bind -N 'Select the next window' n next-window", - "bind -N 'Select the next pane' o select-pane -t:.+", - "bind -N 'Customize options' C customize-mode -Z", - "bind -N 'Select the previous window' p previous-window", - "bind -N 'Display pane numbers' q display-panes", - "bind -N 'Redraw the current client' r refresh-client", - "bind -N 'Choose a session from a list' s choose-tree -Zs", - "bind -N 'Show a clock' t clock-mode", - "bind -N 'Choose a window from a list' w choose-tree -Zw", - "bind -N 'Kill the active pane' x confirm-before -p\"kill-pane #P? (y/n)\" kill-pane", - "bind -N 'Zoom the active pane' z resize-pane -Z", - "bind -N 'Swap the active pane with the pane above' '{' swap-pane -U", - "bind -N 'Swap the active pane with the pane below' '}' swap-pane -D", - "bind -N 'Show messages' '~' show-messages", - "bind -N 'Enter copy mode and scroll up' PPage copy-mode -u", - "bind -N 'Select the pane above the active pane' -r Up select-pane -U", - "bind -N 'Select the pane below the active pane' -r Down select-pane -D", - "bind -N 'Select the pane to the left of the active pane' -r Left select-pane -L", - "bind -N 'Select the pane to the right of the active pane' -r Right select-pane -R", - "bind -N 'Set the even-horizontal layout' M-1 select-layout even-horizontal", - "bind -N 'Set the even-vertical layout' M-2 select-layout even-vertical", - "bind -N 'Set the main-horizontal layout' M-3 select-layout main-horizontal", - "bind -N 'Set the main-vertical layout' M-4 select-layout main-vertical", - "bind -N 'Select the tiled layout' M-5 select-layout tiled", - "bind -N 'Select the next window with an alert' M-n next-window -a", - "bind -N 'Rotate through the panes in reverse' M-o rotate-window -D", - "bind -N 'Select the previous window with an alert' M-p previous-window -a", - "bind -N 'Move the visible part of the window up' -r S-Up refresh-client -U 10", - "bind -N 'Move the visible part of the window down' -r S-Down refresh-client -D 10", - "bind -N 'Move the visible part of the window left' -r S-Left refresh-client -L 10", - "bind -N 'Move the visible part of the window right' -r S-Right refresh-client -R 10", - "bind -N 'Reset so the visible part of the window follows the cursor' -r DC refresh-client -c", - "bind -N 'Resize the pane up by 5' -r M-Up resize-pane -U 5", - "bind -N 'Resize the pane down by 5' -r M-Down resize-pane -D 5", - "bind -N 'Resize the pane left by 5' -r M-Left resize-pane -L 5", - "bind -N 'Resize the pane right by 5' -r M-Right resize-pane -R 5", - "bind -N 'Resize the pane up' -r C-Up resize-pane -U", - "bind -N 'Resize the pane down' -r C-Down resize-pane -D", - "bind -N 'Resize the pane left' -r C-Left resize-pane -L", - "bind -N 'Resize the pane right' -r C-Right resize-pane -R", + "bind -N 'Send the prefix key' C-b { send-prefix }", + "bind -N 'Rotate through the panes' C-o { rotate-window }", + "bind -N 'Suspend the current client' C-z { suspend-client }", + "bind -N 'Select next layout' Space { next-layout }", + "bind -N 'Break pane to a new window' ! { break-pane }", + "bind -N 'Split window vertically' '\"' { split-window }", + "bind -N 'List all paste buffers' '#' { list-buffers }", + "bind -N 'Rename current session' '$' { command-prompt -I'#S' { rename-session -- '%%' } }", + "bind -N 'Split window horizontally' % { split-window -h }", + "bind -N 'Kill current window' & { confirm-before -p\"kill-window #W? (y/n)\" kill-window }", + "bind -N 'Prompt for window index to select' \"'\" { command-prompt -T window-target -pindex { select-window -t ':%%' } }", + "bind -N 'Switch to previous client' ( { switch-client -p }", + "bind -N 'Switch to next client' ) { switch-client -n }", + "bind -N 'Rename current window' , { command-prompt -I'#W' { rename-window -- '%%' } }", + "bind -N 'Delete the most recent paste buffer' - { delete-buffer }", + "bind -N 'Move the current window' . { command-prompt -T target { move-window -t '%%' } }", + "bind -N 'Describe key binding' '/' { command-prompt -kpkey { list-keys -1N '%%' } }", + "bind -N 'Select window 0' 0 { select-window -t:=0 }", + "bind -N 'Select window 1' 1 { select-window -t:=1 }", + "bind -N 'Select window 2' 2 { select-window -t:=2 }", + "bind -N 'Select window 3' 3 { select-window -t:=3 }", + "bind -N 'Select window 4' 4 { select-window -t:=4 }", + "bind -N 'Select window 5' 5 { select-window -t:=5 }", + "bind -N 'Select window 6' 6 { select-window -t:=6 }", + "bind -N 'Select window 7' 7 { select-window -t:=7 }", + "bind -N 'Select window 8' 8 { select-window -t:=8 }", + "bind -N 'Select window 9' 9 { select-window -t:=9 }", + "bind -N 'Prompt for a command' : { command-prompt }", + "bind -N 'Move to the previously active pane' \\; { last-pane }", + "bind -N 'Choose a paste buffer from a list' = { choose-buffer -Z }", + "bind -N 'List key bindings' ? { list-keys -N }", + "bind -N 'Choose a client from a list' D { choose-client -Z }", + "bind -N 'Spread panes out evenly' E { select-layout -E }", + "bind -N 'Switch to the last client' L { switch-client -l }", + "bind -N 'Clear the marked pane' M { select-pane -M }", + "bind -N 'Enter copy mode' [ { copy-mode }", + "bind -N 'Paste the most recent paste buffer' ] { paste-buffer -p }", + "bind -N 'Create a new window' c { new-window }", + "bind -N 'Detach the current client' d { detach-client }", + "bind -N 'Search for a pane' f { command-prompt { find-window -Z -- '%%' } }", + "bind -N 'Display window information' i { display-message }", + "bind -N 'Select the previously current window' l { last-window }", + "bind -N 'Toggle the marked pane' m { select-pane -m }", + "bind -N 'Select the next window' n { next-window }", + "bind -N 'Select the next pane' o { select-pane -t:.+ }", + "bind -N 'Customize options' C { customize-mode -Z }", + "bind -N 'Select the previous window' p { previous-window }", + "bind -N 'Display pane numbers' q { display-panes }", + "bind -N 'Redraw the current client' r { refresh-client }", + "bind -N 'Choose a session from a list' s { choose-tree -Zs }", + "bind -N 'Show a clock' t { clock-mode }", + "bind -N 'Choose a window from a list' w { choose-tree -Zw }", + "bind -N 'Kill the active pane' x { confirm-before -p\"kill-pane #P? (y/n)\" kill-pane }", + "bind -N 'Zoom the active pane' z { resize-pane -Z }", + "bind -N 'Swap the active pane with the pane above' '{' { swap-pane -U }", + "bind -N 'Swap the active pane with the pane below' '}' { swap-pane -D }", + "bind -N 'Show messages' '~' { show-messages }", + "bind -N 'Enter copy mode and scroll up' PPage { copy-mode -u }", + "bind -N 'Select the pane above the active pane' -r Up { select-pane -U }", + "bind -N 'Select the pane below the active pane' -r Down { select-pane -D }", + "bind -N 'Select the pane to the left of the active pane' -r Left { select-pane -L }", + "bind -N 'Select the pane to the right of the active pane' -r Right { select-pane -R }", + "bind -N 'Set the even-horizontal layout' M-1 { select-layout even-horizontal }", + "bind -N 'Set the even-vertical layout' M-2 { select-layout even-vertical }", + "bind -N 'Set the main-horizontal layout' M-3 { select-layout main-horizontal }", + "bind -N 'Set the main-vertical layout' M-4 { select-layout main-vertical }", + "bind -N 'Select the tiled layout' M-5 { select-layout tiled }", + "bind -N 'Select the next window with an alert' M-n { next-window -a }", + "bind -N 'Rotate through the panes in reverse' M-o { rotate-window -D }", + "bind -N 'Select the previous window with an alert' M-p { previous-window -a }", + "bind -N 'Move the visible part of the window up' -r S-Up { refresh-client -U 10 }", + "bind -N 'Move the visible part of the window down' -r S-Down { refresh-client -D 10 }", + "bind -N 'Move the visible part of the window left' -r S-Left { refresh-client -L 10 }", + "bind -N 'Move the visible part of the window right' -r S-Right { refresh-client -R 10 }", + "bind -N 'Reset so the visible part of the window follows the cursor' -r DC { refresh-client -c }", + "bind -N 'Resize the pane up by 5' -r M-Up { resize-pane -U 5 }", + "bind -N 'Resize the pane down by 5' -r M-Down { resize-pane -D 5 }", + "bind -N 'Resize the pane left by 5' -r M-Left { resize-pane -L 5 }", + "bind -N 'Resize the pane right by 5' -r M-Right { resize-pane -R 5 }", + "bind -N 'Resize the pane up' -r C-Up { resize-pane -U }", + "bind -N 'Resize the pane down' -r C-Down { resize-pane -D }", + "bind -N 'Resize the pane left' -r C-Left { resize-pane -L }", + "bind -N 'Resize the pane right' -r C-Right { resize-pane -R }", /* Menu keys */ - "bind < display-menu -xW -yW -T '#[align=centre]#{window_index}:#{window_name}' " DEFAULT_WINDOW_MENU, - "bind > display-menu -xP -yP -T '#[align=centre]#{pane_index} (#{pane_id})' " DEFAULT_PANE_MENU, + "bind < { display-menu -xW -yW -T '#[align=centre]#{window_index}:#{window_name}' " DEFAULT_WINDOW_MENU " }", + "bind > { display-menu -xP -yP -T '#[align=centre]#{pane_index} (#{pane_id})' " DEFAULT_PANE_MENU " }", /* Mouse button 1 down on pane. */ - "bind -n MouseDown1Pane select-pane -t=\\; send -M", + "bind -n MouseDown1Pane { select-pane -t=; send -M }", /* Mouse button 1 drag on pane. */ - "bind -n MouseDrag1Pane if -F '#{||:#{pane_in_mode},#{mouse_any_flag}}' { send -M } { copy-mode -M }", + "bind -n MouseDrag1Pane { if -F '#{||:#{pane_in_mode},#{mouse_any_flag}}' { send -M } { copy-mode -M } }", /* Mouse wheel up on pane. */ - "bind -n WheelUpPane if -F '#{||:#{pane_in_mode},#{mouse_any_flag}}' { send -M } { copy-mode -e }", + "bind -n WheelUpPane { if -F '#{||:#{pane_in_mode},#{mouse_any_flag}}' { send -M } { copy-mode -e } }", /* Mouse button 2 down on pane. */ - "bind -n MouseDown2Pane select-pane -t=\\; if -F '#{||:#{pane_in_mode},#{mouse_any_flag}}' { send -M } { paste -p }", + "bind -n MouseDown2Pane { select-pane -t=; if -F '#{||:#{pane_in_mode},#{mouse_any_flag}}' { send -M } { paste -p } }", /* Mouse button 1 double click on pane. */ - "bind -n DoubleClick1Pane select-pane -t=\\; if -F '#{||:#{pane_in_mode},#{mouse_any_flag}}' { send -M } { copy-mode -H; send -X select-word; run -d0.3; send -X copy-pipe-and-cancel }", + "bind -n DoubleClick1Pane { select-pane -t=; if -F '#{||:#{pane_in_mode},#{mouse_any_flag}}' { send -M } { copy-mode -H; send -X select-word; run -d0.3; send -X copy-pipe-and-cancel } }", /* Mouse button 1 triple click on pane. */ - "bind -n TripleClick1Pane select-pane -t=\\; if -F '#{||:#{pane_in_mode},#{mouse_any_flag}}' { send -M } { copy-mode -H; send -X select-line; run -d0.3; send -X copy-pipe-and-cancel }", + "bind -n TripleClick1Pane { select-pane -t=; if -F '#{||:#{pane_in_mode},#{mouse_any_flag}}' { send -M } { copy-mode -H; send -X select-line; run -d0.3; send -X copy-pipe-and-cancel } }", /* Mouse button 1 drag on border. */ - "bind -n MouseDrag1Border resize-pane -M", + "bind -n MouseDrag1Border { resize-pane -M }", /* Mouse button 1 down on status line. */ - "bind -n MouseDown1Status select-window -t=", + "bind -n MouseDown1Status { select-window -t= }", /* Mouse wheel down on status line. */ - "bind -n WheelDownStatus next-window", + "bind -n WheelDownStatus { next-window }", /* Mouse wheel up on status line. */ - "bind -n WheelUpStatus previous-window", + "bind -n WheelUpStatus { previous-window }", /* Mouse button 3 down on status left. */ - "bind -n MouseDown3StatusLeft display-menu -t= -xM -yW -T '#[align=centre]#{session_name}' " DEFAULT_SESSION_MENU, + "bind -n MouseDown3StatusLeft { display-menu -t= -xM -yW -T '#[align=centre]#{session_name}' " DEFAULT_SESSION_MENU " }", /* Mouse button 3 down on status line. */ - "bind -n MouseDown3Status display-menu -t= -xW -yW -T '#[align=centre]#{window_index}:#{window_name}' " DEFAULT_WINDOW_MENU, + "bind -n MouseDown3Status { display-menu -t= -xW -yW -T '#[align=centre]#{window_index}:#{window_name}' " DEFAULT_WINDOW_MENU "}", /* Mouse button 3 down on pane. */ - "bind -n MouseDown3Pane if -Ft= '#{||:#{mouse_any_flag},#{&&:#{pane_in_mode},#{?#{m/r:(copy|view)-mode,#{pane_mode}},0,1}}}' { select-pane -t=; send -M } { display-menu -t= -xM -yM -T '#[align=centre]#{pane_index} (#{pane_id})' " DEFAULT_PANE_MENU " }", - "bind -n M-MouseDown3Pane display-menu -t= -xM -yM -T '#[align=centre]#{pane_index} (#{pane_id})' " DEFAULT_PANE_MENU, + "bind -n MouseDown3Pane { if -Ft= '#{||:#{mouse_any_flag},#{&&:#{pane_in_mode},#{?#{m/r:(copy|view)-mode,#{pane_mode}},0,1}}}' { select-pane -t=; send -M } { display-menu -t= -xM -yM -T '#[align=centre]#{pane_index} (#{pane_id})' " DEFAULT_PANE_MENU " } }", + "bind -n M-MouseDown3Pane { display-menu -t= -xM -yM -T '#[align=centre]#{pane_index} (#{pane_id})' " DEFAULT_PANE_MENU " }", /* Copy mode (emacs) keys. */ - "bind -Tcopy-mode C-Space send -X begin-selection", - "bind -Tcopy-mode C-a send -X start-of-line", - "bind -Tcopy-mode C-c send -X cancel", - "bind -Tcopy-mode C-e send -X end-of-line", - "bind -Tcopy-mode C-f send -X cursor-right", - "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-end-of-line", - "bind -Tcopy-mode C-n send -X cursor-down", - "bind -Tcopy-mode C-p send -X cursor-up", - "bind -Tcopy-mode C-r command-prompt -ip'(search up)' -I'#{pane_search_string}' 'send -X search-backward-incremental \"%%%\"'", - "bind -Tcopy-mode C-s command-prompt -ip'(search down)' -I'#{pane_search_string}' 'send -X search-forward-incremental \"%%%\"'", - "bind -Tcopy-mode C-v send -X page-down", - "bind -Tcopy-mode C-w send -X copy-pipe-and-cancel", - "bind -Tcopy-mode Escape send -X cancel", - "bind -Tcopy-mode Space send -X page-down", - "bind -Tcopy-mode , send -X jump-reverse", - "bind -Tcopy-mode \\; send -X jump-again", - "bind -Tcopy-mode F command-prompt -1p'(jump backward)' 'send -X jump-backward \"%%%\"'", - "bind -Tcopy-mode N send -X search-reverse", - "bind -Tcopy-mode R send -X rectangle-toggle", - "bind -Tcopy-mode T command-prompt -1p'(jump to backward)' 'send -X jump-to-backward \"%%%\"'", - "bind -Tcopy-mode X send -X set-mark", - "bind -Tcopy-mode f command-prompt -1p'(jump forward)' 'send -X jump-forward \"%%%\"'", - "bind -Tcopy-mode g command-prompt -p'(goto line)' 'send -X goto-line \"%%%\"'", - "bind -Tcopy-mode n send -X search-again", - "bind -Tcopy-mode q send -X cancel", - "bind -Tcopy-mode r send -X refresh-from-pane", - "bind -Tcopy-mode t command-prompt -1p'(jump to forward)' 'send -X jump-to-forward \"%%%\"'", - "bind -Tcopy-mode Home send -X start-of-line", - "bind -Tcopy-mode End send -X end-of-line", + "bind -Tcopy-mode C-Space { send -X begin-selection }", + "bind -Tcopy-mode C-a { send -X start-of-line }", + "bind -Tcopy-mode C-c { send -X cancel }", + "bind -Tcopy-mode C-e { send -X end-of-line }", + "bind -Tcopy-mode C-f { send -X cursor-right }", + "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-n { send -X cursor-down }", + "bind -Tcopy-mode C-p { send -X cursor-up }", + "bind -Tcopy-mode C-r { command-prompt -T search -ip'(search up)' -I'#{pane_search_string}' { send -X search-backward-incremental '%%' } }", + "bind -Tcopy-mode C-s { command-prompt -T search -ip'(search down)' -I'#{pane_search_string}' { send -X search-forward-incremental '%%' } }", + "bind -Tcopy-mode C-v { send -X page-down }", + "bind -Tcopy-mode C-w { send -X copy-pipe-and-cancel }", + "bind -Tcopy-mode Escape { send -X cancel }", + "bind -Tcopy-mode Space { send -X page-down }", + "bind -Tcopy-mode , { send -X jump-reverse }", + "bind -Tcopy-mode \\; { send -X jump-again }", + "bind -Tcopy-mode F { command-prompt -1p'(jump backward)' { send -X jump-backward '%%' } }", + "bind -Tcopy-mode N { send -X search-reverse }", + "bind -Tcopy-mode P { send -X toggle-position }", + "bind -Tcopy-mode R { send -X rectangle-toggle }", + "bind -Tcopy-mode T { command-prompt -1p'(jump to backward)' { send -X jump-to-backward '%%' } }", + "bind -Tcopy-mode X { send -X set-mark }", + "bind -Tcopy-mode f { command-prompt -1p'(jump forward)' { send -X jump-forward '%%' } }", + "bind -Tcopy-mode g { command-prompt -p'(goto line)' { send -X goto-line '%%' } }", + "bind -Tcopy-mode n { send -X search-again }", + "bind -Tcopy-mode q { send -X cancel }", + "bind -Tcopy-mode r { send -X refresh-from-pane }", + "bind -Tcopy-mode t { command-prompt -1p'(jump to forward)' { send -X jump-to-forward '%%' } }", + "bind -Tcopy-mode Home { send -X start-of-line }", + "bind -Tcopy-mode End { send -X end-of-line }", "bind -Tcopy-mode MouseDown1Pane select-pane", - "bind -Tcopy-mode MouseDrag1Pane select-pane\\; send -X begin-selection", - "bind -Tcopy-mode MouseDragEnd1Pane send -X copy-pipe-and-cancel", - "bind -Tcopy-mode WheelUpPane select-pane\\; send -N5 -X scroll-up", - "bind -Tcopy-mode WheelDownPane select-pane\\; send -N5 -X scroll-down", - "bind -Tcopy-mode DoubleClick1Pane select-pane\\; send -X select-word\\; run -d0.3\\; send -X copy-pipe-and-cancel", - "bind -Tcopy-mode TripleClick1Pane select-pane\\; send -X select-line\\; run -d0.3\\; send -X copy-pipe-and-cancel", - "bind -Tcopy-mode NPage send -X page-down", - "bind -Tcopy-mode PPage send -X page-up", - "bind -Tcopy-mode Up send -X cursor-up", - "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 -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", - "bind -Tcopy-mode M-b send -X previous-word", - "bind -Tcopy-mode C-M-b send -X previous-matching-bracket", - "bind -Tcopy-mode M-f send -X next-word-end", - "bind -Tcopy-mode C-M-f send -X next-matching-bracket", - "bind -Tcopy-mode M-m send -X back-to-indentation", - "bind -Tcopy-mode M-r send -X middle-line", - "bind -Tcopy-mode M-v send -X page-up", - "bind -Tcopy-mode M-w send -X copy-pipe-and-cancel", - "bind -Tcopy-mode M-x send -X jump-to-mark", - "bind -Tcopy-mode 'M-{' send -X previous-paragraph", - "bind -Tcopy-mode 'M-}' send -X next-paragraph", - "bind -Tcopy-mode M-Up send -X halfpage-up", - "bind -Tcopy-mode M-Down send -X halfpage-down", - "bind -Tcopy-mode C-Up send -X scroll-up", - "bind -Tcopy-mode C-Down send -X scroll-down", + "bind -Tcopy-mode MouseDrag1Pane { select-pane; send -X begin-selection }", + "bind -Tcopy-mode MouseDragEnd1Pane { send -X copy-pipe-and-cancel }", + "bind -Tcopy-mode WheelUpPane { select-pane; send -N5 -X scroll-up }", + "bind -Tcopy-mode WheelDownPane { select-pane; send -N5 -X scroll-down }", + "bind -Tcopy-mode DoubleClick1Pane { select-pane; send -X select-word; run -d0.3; send -X copy-pipe-and-cancel }", + "bind -Tcopy-mode TripleClick1Pane { select-pane; send -X select-line; run -d0.3; send -X copy-pipe-and-cancel }", + "bind -Tcopy-mode NPage { send -X page-down }", + "bind -Tcopy-mode PPage { send -X page-up }", + "bind -Tcopy-mode Up { send -X cursor-up }", + "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 -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 }", + "bind -Tcopy-mode M-b { send -X previous-word }", + "bind -Tcopy-mode C-M-b { send -X previous-matching-bracket }", + "bind -Tcopy-mode M-f { send -X next-word-end }", + "bind -Tcopy-mode C-M-f { send -X next-matching-bracket }", + "bind -Tcopy-mode M-m { send -X back-to-indentation }", + "bind -Tcopy-mode M-r { send -X middle-line }", + "bind -Tcopy-mode M-v { send -X page-up }", + "bind -Tcopy-mode M-w { send -X copy-pipe-and-cancel }", + "bind -Tcopy-mode M-x { send -X jump-to-mark }", + "bind -Tcopy-mode 'M-{' { send -X previous-paragraph }", + "bind -Tcopy-mode 'M-}' { send -X next-paragraph }", + "bind -Tcopy-mode M-Up { send -X halfpage-up }", + "bind -Tcopy-mode M-Down { send -X halfpage-down }", + "bind -Tcopy-mode C-Up { send -X scroll-up }", + "bind -Tcopy-mode C-Down { send -X scroll-down }", /* Copy mode (vi) keys. */ - "bind -Tcopy-mode-vi '#' send -FX search-backward '#{copy_cursor_word}'", - "bind -Tcopy-mode-vi * send -FX search-forward '#{copy_cursor_word}'", - "bind -Tcopy-mode-vi C-c send -X cancel", - "bind -Tcopy-mode-vi C-d send -X halfpage-down", - "bind -Tcopy-mode-vi C-e send -X scroll-down", - "bind -Tcopy-mode-vi C-b send -X page-up", - "bind -Tcopy-mode-vi C-f send -X page-down", - "bind -Tcopy-mode-vi C-h send -X cursor-left", - "bind -Tcopy-mode-vi C-j send -X copy-pipe-and-cancel", - "bind -Tcopy-mode-vi Enter send -X copy-pipe-and-cancel", - "bind -Tcopy-mode-vi C-u send -X halfpage-up", - "bind -Tcopy-mode-vi C-v send -X rectangle-toggle", - "bind -Tcopy-mode-vi C-y send -X scroll-up", - "bind -Tcopy-mode-vi Escape send -X clear-selection", - "bind -Tcopy-mode-vi Space send -X begin-selection", - "bind -Tcopy-mode-vi '$' send -X end-of-line", - "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 -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 ? 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", - "bind -Tcopy-mode-vi D send -X copy-end-of-line", - "bind -Tcopy-mode-vi E send -X next-space-end", - "bind -Tcopy-mode-vi F command-prompt -1p'(jump backward)' 'send -X jump-backward \"%%%\"'", - "bind -Tcopy-mode-vi G send -X history-bottom", - "bind -Tcopy-mode-vi H send -X top-line", - "bind -Tcopy-mode-vi J send -X scroll-down", - "bind -Tcopy-mode-vi K send -X scroll-up", - "bind -Tcopy-mode-vi L send -X bottom-line", - "bind -Tcopy-mode-vi M send -X middle-line", - "bind -Tcopy-mode-vi N send -X search-reverse", - "bind -Tcopy-mode-vi T command-prompt -1p'(jump to backward)' 'send -X jump-to-backward \"%%%\"'", - "bind -Tcopy-mode-vi V send -X select-line", - "bind -Tcopy-mode-vi W send -X next-space", - "bind -Tcopy-mode-vi X send -X set-mark", - "bind -Tcopy-mode-vi ^ send -X back-to-indentation", - "bind -Tcopy-mode-vi b send -X previous-word", - "bind -Tcopy-mode-vi e send -X next-word-end", - "bind -Tcopy-mode-vi f command-prompt -1p'(jump forward)' 'send -X jump-forward \"%%%\"'", - "bind -Tcopy-mode-vi g send -X history-top", - "bind -Tcopy-mode-vi h send -X cursor-left", - "bind -Tcopy-mode-vi j send -X cursor-down", - "bind -Tcopy-mode-vi k send -X cursor-up", - "bind -Tcopy-mode-vi l send -X cursor-right", - "bind -Tcopy-mode-vi n send -X search-again", - "bind -Tcopy-mode-vi o send -X other-end", - "bind -Tcopy-mode-vi q send -X cancel", - "bind -Tcopy-mode-vi r send -X refresh-from-pane", - "bind -Tcopy-mode-vi t command-prompt -1p'(jump to forward)' 'send -X jump-to-forward \"%%%\"'", - "bind -Tcopy-mode-vi v send -X rectangle-toggle", - "bind -Tcopy-mode-vi w send -X next-word", - "bind -Tcopy-mode-vi '{' send -X previous-paragraph", - "bind -Tcopy-mode-vi '}' send -X next-paragraph", - "bind -Tcopy-mode-vi % send -X next-matching-bracket", - "bind -Tcopy-mode-vi MouseDown1Pane select-pane", - "bind -Tcopy-mode-vi MouseDrag1Pane select-pane\\; send -X begin-selection", - "bind -Tcopy-mode-vi MouseDragEnd1Pane send -X copy-pipe-and-cancel", - "bind -Tcopy-mode-vi WheelUpPane select-pane\\; send -N5 -X scroll-up", - "bind -Tcopy-mode-vi WheelDownPane select-pane\\; send -N5 -X scroll-down", - "bind -Tcopy-mode-vi DoubleClick1Pane select-pane\\; send -X select-word\\; run -d0.3\\; send -X copy-pipe-and-cancel", - "bind -Tcopy-mode-vi TripleClick1Pane select-pane\\; send -X select-line\\; run -d0.3\\; send -X copy-pipe-and-cancel", - "bind -Tcopy-mode-vi BSpace send -X cursor-left", - "bind -Tcopy-mode-vi NPage send -X page-down", - "bind -Tcopy-mode-vi PPage send -X page-up", - "bind -Tcopy-mode-vi Up send -X cursor-up", - "bind -Tcopy-mode-vi Down send -X cursor-down", - "bind -Tcopy-mode-vi Left send -X cursor-left", - "bind -Tcopy-mode-vi Right send -X cursor-right", - "bind -Tcopy-mode-vi M-x send -X jump-to-mark", - "bind -Tcopy-mode-vi C-Up send -X scroll-up", - "bind -Tcopy-mode-vi C-Down send -X scroll-down", + "bind -Tcopy-mode-vi '#' { send -FX search-backward '#{copy_cursor_word}' }", + "bind -Tcopy-mode-vi * { send -FX search-forward '#{copy_cursor_word}' }", + "bind -Tcopy-mode-vi C-c { send -X cancel }", + "bind -Tcopy-mode-vi C-d { send -X halfpage-down }", + "bind -Tcopy-mode-vi C-e { send -X scroll-down }", + "bind -Tcopy-mode-vi C-b { send -X page-up }", + "bind -Tcopy-mode-vi C-f { send -X page-down }", + "bind -Tcopy-mode-vi C-h { send -X cursor-left }", + "bind -Tcopy-mode-vi C-j { send -X copy-pipe-and-cancel }", + "bind -Tcopy-mode-vi Enter { send -X copy-pipe-and-cancel }", + "bind -Tcopy-mode-vi C-u { send -X halfpage-up }", + "bind -Tcopy-mode-vi C-v { send -X rectangle-toggle }", + "bind -Tcopy-mode-vi C-y { send -X scroll-up }", + "bind -Tcopy-mode-vi Escape { send -X clear-selection }", + "bind -Tcopy-mode-vi Space { send -X begin-selection }", + "bind -Tcopy-mode-vi '$' { send -X end-of-line }", + "bind -Tcopy-mode-vi , { send -X jump-reverse }", + "bind -Tcopy-mode-vi / { command-prompt -T search -p'(search down)' { send -X search-forward '%%' } }", + "bind -Tcopy-mode-vi 0 { send -X start-of-line }", + "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 ? { command-prompt -T search -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 }", + "bind -Tcopy-mode-vi D { send -X copy-pipe-end-of-line-and-cancel }", + "bind -Tcopy-mode-vi E { send -X next-space-end }", + "bind -Tcopy-mode-vi F { command-prompt -1p'(jump backward)' { send -X jump-backward '%%' } }", + "bind -Tcopy-mode-vi G { send -X history-bottom }", + "bind -Tcopy-mode-vi H { send -X top-line }", + "bind -Tcopy-mode-vi J { send -X scroll-down }", + "bind -Tcopy-mode-vi K { send -X scroll-up }", + "bind -Tcopy-mode-vi L { send -X bottom-line }", + "bind -Tcopy-mode-vi M { send -X middle-line }", + "bind -Tcopy-mode-vi N { send -X search-reverse }", + "bind -Tcopy-mode-vi P { send -X toggle-position }", + "bind -Tcopy-mode-vi T { command-prompt -1p'(jump to backward)' { send -X jump-to-backward '%%' } }", + "bind -Tcopy-mode-vi V { send -X select-line }", + "bind -Tcopy-mode-vi W { send -X next-space }", + "bind -Tcopy-mode-vi X { send -X set-mark }", + "bind -Tcopy-mode-vi ^ { send -X back-to-indentation }", + "bind -Tcopy-mode-vi b { send -X previous-word }", + "bind -Tcopy-mode-vi e { send -X next-word-end }", + "bind -Tcopy-mode-vi f { command-prompt -1p'(jump forward)' { send -X jump-forward '%%' } }", + "bind -Tcopy-mode-vi g { send -X history-top }", + "bind -Tcopy-mode-vi h { send -X cursor-left }", + "bind -Tcopy-mode-vi j { send -X cursor-down }", + "bind -Tcopy-mode-vi k { send -X cursor-up }", + "bind -Tcopy-mode-vi l { send -X cursor-right }", + "bind -Tcopy-mode-vi n { send -X search-again }", + "bind -Tcopy-mode-vi o { send -X other-end }", + "bind -Tcopy-mode-vi q { send -X cancel }", + "bind -Tcopy-mode-vi r { send -X refresh-from-pane }", + "bind -Tcopy-mode-vi t { command-prompt -1p'(jump to forward)' { send -X jump-to-forward '%%' } }", + "bind -Tcopy-mode-vi v { send -X rectangle-toggle }", + "bind -Tcopy-mode-vi w { send -X next-word }", + "bind -Tcopy-mode-vi '{' { send -X previous-paragraph }", + "bind -Tcopy-mode-vi '}' { send -X next-paragraph }", + "bind -Tcopy-mode-vi % { send -X next-matching-bracket }", + "bind -Tcopy-mode-vi MouseDown1Pane { select-pane }", + "bind -Tcopy-mode-vi MouseDrag1Pane { select-pane; send -X begin-selection }", + "bind -Tcopy-mode-vi MouseDragEnd1Pane { send -X copy-pipe-and-cancel }", + "bind -Tcopy-mode-vi WheelUpPane { select-pane; send -N5 -X scroll-up }", + "bind -Tcopy-mode-vi WheelDownPane { select-pane; send -N5 -X scroll-down }", + "bind -Tcopy-mode-vi DoubleClick1Pane { select-pane; send -X select-word; run -d0.3; send -X copy-pipe-and-cancel }", + "bind -Tcopy-mode-vi TripleClick1Pane { select-pane; send -X select-line; run -d0.3; send -X copy-pipe-and-cancel }", + "bind -Tcopy-mode-vi BSpace { send -X cursor-left }", + "bind -Tcopy-mode-vi NPage { send -X page-down }", + "bind -Tcopy-mode-vi PPage { send -X page-up }", + "bind -Tcopy-mode-vi Up { send -X cursor-up }", + "bind -Tcopy-mode-vi Down { send -X cursor-down }", + "bind -Tcopy-mode-vi Left { send -X cursor-left }", + "bind -Tcopy-mode-vi Right { send -X cursor-right }", + "bind -Tcopy-mode-vi M-x { send -X jump-to-mark }", + "bind -Tcopy-mode-vi C-Up { send -X scroll-up }", + "bind -Tcopy-mode-vi C-Down { send -X scroll-down }", }; u_int i; struct cmd_parse_result *pr; for (i = 0; i < nitems(defaults); i++) { pr = cmd_parse_from_string(defaults[i], NULL); - if (pr->status != CMD_PARSE_SUCCESS) + if (pr->status != CMD_PARSE_SUCCESS) { + log_debug("%s", pr->error); fatalx("bad default key: %s", defaults[i]); + } cmdq_append(NULL, cmdq_get_command(pr->cmdlist, NULL)); cmd_list_free(pr->cmdlist); } diff --git a/external/bsd/tmux/dist/log.c b/external/bsd/tmux/dist/log.c index 79165bd8084..ddd6919c4ad 100644 --- a/external/bsd/tmux/dist/log.c +++ b/external/bsd/tmux/dist/log.c @@ -29,9 +29,6 @@ static FILE *log_file; static int log_level; -static void log_event_cb(int, const char *); -static void log_vwrite(const char *, va_list) printflike(1, 0); - /* Log callback for libevent. */ static void log_event_cb(__unused int severity, const char *msg) @@ -100,29 +97,28 @@ log_close(void) } /* Write a log message. */ -static void -log_vwrite(const char *msg, va_list ap) +static void printflike(1, 0) +log_vwrite(const char *msg, va_list ap, const char *prefix) { - char *fmt, *out; + char *s, *out; struct timeval tv; if (log_file == NULL) return; - if (vasprintf(&fmt, msg, ap) == -1) + if (vasprintf(&s, msg, ap) == -1) return; - if (stravis(&out, fmt, VIS_OCTAL|VIS_CSTYLE|VIS_TAB|VIS_NL) == -1) { - free(fmt); + if (stravis(&out, s, VIS_OCTAL|VIS_CSTYLE|VIS_TAB|VIS_NL) == -1) { + free(s); return; } + free(s); gettimeofday(&tv, NULL); - if (fprintf(log_file, "%lld.%06d %s\n", (long long)tv.tv_sec, - (int)tv.tv_usec, out) != -1) + if (fprintf(log_file, "%lld.%06d %s%s\n", (long long)tv.tv_sec, + (int)tv.tv_usec, prefix, out) != -1) fflush(log_file); - free(out); - free(fmt); } /* Log a debug message. */ @@ -135,7 +131,7 @@ log_debug(const char *msg, ...) return; va_start(ap, msg); - log_vwrite(msg, ap); + log_vwrite(msg, ap, ""); va_end(ap); } @@ -148,14 +144,16 @@ log_debug(const char *msg, ...) __dead void fatal(const char *msg, ...) { - char *fmt; + char tmp[256]; va_list ap; - va_start(ap, msg); - if (asprintf(&fmt, "fatal: %s: %s", msg, strerror(errno)) == -1) + if (snprintf(tmp, sizeof tmp, "fatal: %s: ", strerror(errno)) < 0) exit(1); - log_vwrite(fmt, ap); + + va_start(ap, msg); + log_vwrite(msg, ap, tmp); va_end(ap); + exit(1); } @@ -163,14 +161,12 @@ fatal(const char *msg, ...) __dead void fatalx(const char *msg, ...) { - char *fmt; va_list ap; va_start(ap, msg); - if (asprintf(&fmt, "fatal: %s", msg) == -1) - exit(1); - log_vwrite(fmt, ap); + log_vwrite(msg, ap, "fatal: "); va_end(ap); + exit(1); } diff --git a/external/bsd/tmux/dist/menu.c b/external/bsd/tmux/dist/menu.c index 4feb74fcfc0..22a99b21e28 100644 --- a/external/bsd/tmux/dist/menu.c +++ b/external/bsd/tmux/dist/menu.c @@ -55,10 +55,11 @@ menu_add_item(struct menu *menu, const struct menu_item *item, struct cmdq_item *qitem, struct client *c, struct cmd_find_state *fs) { struct menu_item *new_item; - const char *key, *cmd; - char *s, *name; - u_int width; + const char *key = NULL, *cmd, *suffix = ""; + char *s, *trimmed, *name; + u_int width, max_width; int line; + size_t keylen, slen; line = (item == NULL || item->name == NULL || *item->name == '\0'); if (line && menu->count == 0) @@ -80,11 +81,36 @@ menu_add_item(struct menu *menu, const struct menu_item *item, menu->count--; return; } + max_width = c->tty.sx - 4; + + slen = strlen(s); if (*s != '-' && item->key != KEYC_UNKNOWN && item->key != KEYC_NONE) { key = key_string_lookup_key(item->key, 0); - xasprintf(&name, "%s#[default] #[align=right](%s)", s, key); + keylen = strlen(key) + 3; /* 3 = space and two brackets */ + + /* + * Add the key if it is shorter than a quarter of the available + * space or there is space for the entire item text and the + * key. + */ + if (keylen <= max_width / 4) + max_width -= keylen; + else if (keylen >= max_width || slen >= max_width - keylen) + key = NULL; + } + + if (slen > max_width) { + max_width--; + suffix = ">"; + } + trimmed = format_trim_right(s, max_width); + if (key != NULL) { + xasprintf(&name, "%s%s#[default] #[align=right](%s)", + trimmed, suffix, key); } else - xasprintf(&name, "%s", s); + xasprintf(&name, "%s%s", trimmed, suffix); + free(trimmed); + new_item->name = name; free(s); @@ -100,6 +126,8 @@ menu_add_item(struct menu *menu, const struct menu_item *item, new_item->key = item->key; width = format_width(new_item->name); + if (*new_item->name == '-') + width--; if (width > menu->width) menu->width = width; } @@ -131,18 +159,32 @@ menu_free(struct menu *menu) free(menu); } -static struct screen * -menu_mode_cb(struct client *c, __unused u_int *cx, __unused u_int *cy) +struct screen * +menu_mode_cb(__unused struct client *c, void *data, __unused u_int *cx, + __unused u_int *cy) { - struct menu_data *md = c->overlay_data; + struct menu_data *md = data; return (&md->s); } -static void -menu_draw_cb(struct client *c, __unused struct screen_redraw_ctx *ctx0) +/* Return parts of the input range which are not obstructed by the menu. */ +void +menu_check_cb(__unused struct client *c, void *data, u_int px, u_int py, + u_int nx, struct overlay_ranges *r) { - struct menu_data *md = c->overlay_data; + struct menu_data *md = data; + struct menu *menu = md->menu; + + server_client_overlay_range(md->px, md->py, menu->width + 4, + menu->count + 2, px, py, nx, r); +} + +void +menu_draw_cb(struct client *c, void *data, + __unused struct screen_redraw_ctx *rctx) +{ + struct menu_data *md = data; struct tty *tty = &c->tty; struct screen *s = &md->s; struct menu *menu = md->menu; @@ -163,10 +205,10 @@ menu_draw_cb(struct client *c, __unused struct screen_redraw_ctx *ctx0) } } -static void -menu_free_cb(struct client *c) +void +menu_free_cb(__unused struct client *c, void *data) { - struct menu_data *md = c->overlay_data; + struct menu_data *md = data; if (md->item != NULL) cmdq_continue(md->item); @@ -179,10 +221,10 @@ menu_free_cb(struct client *c) free(md); } -static int -menu_key_cb(struct client *c, struct key_event *event) +int +menu_key_cb(struct client *c, void *data, struct key_event *event) { - struct menu_data *md = c->overlay_data; + struct menu_data *md = data; struct menu *menu = md->menu; struct mouse_event *m = &event->m; u_int i; @@ -195,7 +237,7 @@ menu_key_cb(struct client *c, struct key_event *event) if (KEYC_IS_MOUSE(event->key)) { if (md->flags & MENU_NOMOUSE) { - if (MOUSE_BUTTONS(m->b) != 0) + if (MOUSE_BUTTONS(m->b) != MOUSE_BUTTON_1) return (1); return (0); } @@ -208,7 +250,7 @@ menu_key_cb(struct client *c, struct key_event *event) return (1); } else { if (!MOUSE_RELEASE(m->b) && - MOUSE_WHEEL(m->b) == 0 && + !MOUSE_WHEEL(m->b) && !MOUSE_DRAG(m->b)) return (1); } @@ -222,7 +264,7 @@ menu_key_cb(struct client *c, struct key_event *event) if (MOUSE_RELEASE(m->b)) goto chosen; } else { - if (MOUSE_WHEEL(m->b) == 0 && !MOUSE_DRAG(m->b)) + if (!MOUSE_WHEEL(m->b) && !MOUSE_DRAG(m->b)) goto chosen; } md->choice = m->y - (md->py + 1); @@ -342,8 +384,8 @@ chosen: return (1); } -int -menu_display(struct menu *menu, int flags, struct cmdq_item *item, u_int px, +struct menu_data * +menu_prepare(struct menu *menu, int flags, struct cmdq_item *item, u_int px, u_int py, struct client *c, struct cmd_find_state *fs, menu_choice_cb cb, void *data) { @@ -352,7 +394,7 @@ menu_display(struct menu *menu, int flags, struct cmdq_item *item, u_int px, const char *name; if (c->tty.sx < menu->width + 4 || c->tty.sy < menu->count + 2) - return (-1); + return (NULL); if (px + menu->width + 4 > c->tty.sx) px = c->tty.sx - menu->width - 4; if (py + menu->count + 2 > c->tty.sy) @@ -366,7 +408,7 @@ menu_display(struct menu *menu, int flags, struct cmdq_item *item, u_int px, cmd_find_copy_state(&md->fs, fs); screen_init(&md->s, menu->width + 4, menu->count + 2, 0); if (~md->flags & MENU_NOMOUSE) - md->s.mode |= MODE_MOUSE_ALL; + md->s.mode |= (MODE_MOUSE_ALL|MODE_MOUSE_BUTTON); md->s.mode &= ~MODE_CURSOR; md->px = px; @@ -388,8 +430,20 @@ menu_display(struct menu *menu, int flags, struct cmdq_item *item, u_int px, md->cb = cb; md->data = data; + return (md); +} +int +menu_display(struct menu *menu, int flags, struct cmdq_item *item, u_int px, + u_int py, struct client *c, struct cmd_find_state *fs, menu_choice_cb cb, + void *data) +{ + struct menu_data *md; + + md = menu_prepare(menu, flags, item, px, py, c, fs, cb, data); + if (md == NULL) + return (-1); server_client_set_overlay(c, 0, NULL, menu_mode_cb, menu_draw_cb, - menu_key_cb, menu_free_cb, md); + menu_key_cb, menu_free_cb, NULL, md); return (0); } diff --git a/external/bsd/tmux/dist/mode-tree.c b/external/bsd/tmux/dist/mode-tree.c index 93fdbc9bbd7..3315e1ab61b 100644 --- a/external/bsd/tmux/dist/mode-tree.c +++ b/external/bsd/tmux/dist/mode-tree.c @@ -104,7 +104,6 @@ struct mode_tree_menu { struct mode_tree_data *data; struct client *c; u_int line; - void *itemdata; }; static void mode_tree_free_items(struct mode_tree_list *); @@ -716,14 +715,14 @@ mode_tree_draw(struct mode_tree_data *mtd) screen_write_nputs(&ctx, w, &gc0, "%s", text); if (mti->text != NULL) { format_draw(&ctx, &gc0, w - width, mti->text, - NULL); + NULL, 0); } } else { screen_write_clearendofline(&ctx, gc.bg); screen_write_nputs(&ctx, w, &gc, "%s", text); if (mti->text != NULL) { format_draw(&ctx, &gc, w - width, mti->text, - NULL); + NULL, 0); } } free(text); @@ -736,10 +735,8 @@ mode_tree_draw(struct mode_tree_data *mtd) } sy = screen_size_y(s); - if (!mtd->preview || sy <= 4 || h <= 4 || sy - h <= 4 || w <= 4) { - screen_write_stop(&ctx); - return; - } + if (!mtd->preview || sy <= 4 || h <= 4 || sy - h <= 4 || w <= 4) + goto done; line = &mtd->line_list[mtd->current]; mti = line->item; @@ -747,7 +744,7 @@ mode_tree_draw(struct mode_tree_data *mtd) mti = mti->parent; screen_write_cursormove(&ctx, 0, h, 0); - screen_write_box(&ctx, w, sy - h); + screen_write_box(&ctx, w, sy - h, BOX_LINES_DEFAULT, NULL, NULL); if (mtd->sort_list != NULL) { xasprintf(&text, " %s (sort: %s%s)", mti->name, @@ -783,6 +780,8 @@ mode_tree_draw(struct mode_tree_data *mtd) mtd->drawcb(mtd->modedata, mti->itemdata, &ctx, box_x, box_y); } +done: + screen_write_cursormove(&ctx, 0, mtd->current - mtd->offset, 0); screen_write_stop(&ctx); } @@ -909,20 +908,16 @@ static void mode_tree_menu_callback(__unused struct menu *menu, __unused u_int idx, key_code key, void *data) { - struct mode_tree_menu *mtm = data; - struct mode_tree_data *mtd = mtm->data; - struct mode_tree_item *mti; + struct mode_tree_menu *mtm = data; + struct mode_tree_data *mtd = mtm->data; if (mtd->dead || key == KEYC_NONE) goto out; if (mtm->line >= mtd->line_size) goto out; - mti = mtd->line_list[mtm->line].item; - if (mti->itemdata != mtm->itemdata) - goto out; mtd->current = mtm->line; - mtd->menucb (mtd->modedata, mtm->c, key); + mtd->menucb(mtd->modedata, mtm->c, key); out: mode_tree_remove_ref(mtd); @@ -954,14 +949,13 @@ mode_tree_display_menu(struct mode_tree_data *mtd, struct client *c, u_int x, title = xstrdup(""); } menu = menu_create(title); - menu_add_items(menu, items, NULL, NULL, NULL); + menu_add_items(menu, items, NULL, c, NULL); free(title); mtm = xmalloc(sizeof *mtm); mtm->data = mtd; mtm->c = c; mtm->line = line; - mtm->itemdata = mti->itemdata; mtd->references++; if (x >= (menu->width + 4) / 2) @@ -1055,7 +1049,6 @@ mode_tree_key(struct mode_tree_data *mtd, struct client *c, key_code *key, case '\016': /* C-n */ mode_tree_down(mtd, 1); break; - case 'g': case KEYC_PPAGE: case '\002': /* C-b */ for (i = 0; i < mtd->height; i++) { @@ -1064,7 +1057,6 @@ mode_tree_key(struct mode_tree_data *mtd, struct client *c, key_code *key, mode_tree_up(mtd, 1); } break; - case 'G': case KEYC_NPAGE: case '\006': /* C-f */ for (i = 0; i < mtd->height; i++) { @@ -1073,10 +1065,12 @@ mode_tree_key(struct mode_tree_data *mtd, struct client *c, key_code *key, mode_tree_down(mtd, 1); } break; + case 'g': case KEYC_HOME: mtd->current = 0; mtd->offset = 0; break; + case 'G': case KEYC_END: mtd->current = mtd->line_size - 1; if (mtd->current > mtd->height - 1) @@ -1168,7 +1162,7 @@ mode_tree_key(struct mode_tree_data *mtd, struct client *c, key_code *key, mtd->references++; status_prompt_set(c, NULL, "(search) ", "", mode_tree_search_callback, mode_tree_search_free, mtd, - PROMPT_NOFORMAT); + PROMPT_NOFORMAT, PROMPT_TYPE_SEARCH); break; case 'n': mode_tree_search_set(mtd); @@ -1177,7 +1171,7 @@ mode_tree_key(struct mode_tree_data *mtd, struct client *c, key_code *key, mtd->references++; status_prompt_set(c, NULL, "(filter) ", mtd->filter, mode_tree_filter_callback, mode_tree_filter_free, mtd, - PROMPT_NOFORMAT); + PROMPT_NOFORMAT, PROMPT_TYPE_SEARCH); break; case 'v': mtd->preview = !mtd->preview; diff --git a/external/bsd/tmux/dist/notify.c b/external/bsd/tmux/dist/notify.c index 7129b5b3188..7beacb2af8f 100644 --- a/external/bsd/tmux/dist/notify.c +++ b/external/bsd/tmux/dist/notify.c @@ -25,29 +25,31 @@ struct notify_entry { const char *name; + struct cmd_find_state fs; + struct format_tree *formats; struct client *client; struct session *session; struct window *window; int pane; - - struct cmd_find_state fs; }; -static void -notify_hook_formats(struct cmdq_state *state, struct session *s, - struct window *w, int pane) +static struct cmdq_item * +notify_insert_one_hook(struct cmdq_item *item, struct notify_entry *ne, + struct cmd_list *cmdlist, struct cmdq_state *state) { - if (s != NULL) { - cmdq_add_format(state, "hook_session", "$%u", s->id); - cmdq_add_format(state, "hook_session_name", "%s", s->name); + struct cmdq_item *new_item; + char *s; + + if (cmdlist == NULL) + return (item); + if (log_get_level() != 0) { + s = cmd_list_print(cmdlist, 0); + log_debug("%s: hook %s is: %s", __func__, ne->name, s); + free(s); } - if (w != NULL) { - cmdq_add_format(state, "hook_window", "@%u", w->id); - cmdq_add_format(state, "hook_window_name", "%s", w->name); - } - if (pane != -1) - cmdq_add_format(state, "hook_pane", "%%%d", pane); + new_item = cmdq_get_command(cmdlist, state); + return (cmdq_insert_after(item, new_item)); } static void @@ -55,15 +57,14 @@ notify_insert_hook(struct cmdq_item *item, struct notify_entry *ne) { struct cmd_find_state fs; struct options *oo; - struct cmdq_item *new_item; - struct cmdq_state *new_state; - struct session *s = ne->session; - struct window *w = ne->window; + struct cmdq_state *state; struct options_entry *o; struct options_array_item *a; struct cmd_list *cmdlist; + const char *value; + struct cmd_parse_result *pr; - log_debug("%s: %s", __func__, ne->name); + log_debug("%s: inserting hook %s", __func__, ne->name); cmd_find_clear_state(&fs, 0); if (cmd_find_empty_state(&ne->fs) || !cmd_find_valid_state(&ne->fs)) @@ -84,24 +85,37 @@ notify_insert_hook(struct cmdq_item *item, struct notify_entry *ne) oo = fs.wl->window->options; o = options_get(oo, ne->name); } - if (o == NULL) + if (o == NULL) { + log_debug("%s: hook %s not found", __func__, ne->name); return; + } - new_state = cmdq_new_state(&fs, NULL, CMDQ_STATE_NOHOOKS); - cmdq_add_format(new_state, "hook", "%s", ne->name); - notify_hook_formats(new_state, s, w, ne->pane); - - a = options_array_first(o); - while (a != NULL) { - cmdlist = options_array_item_value(a)->cmdlist; - if (cmdlist != NULL) { - new_item = cmdq_get_command(cmdlist, new_state); - item = cmdq_insert_after(item, new_item); + state = cmdq_new_state(&fs, NULL, CMDQ_STATE_NOHOOKS); + cmdq_add_formats(state, ne->formats); + + if (*ne->name == '@') { + value = options_get_string(oo, ne->name); + pr = cmd_parse_from_string(value, NULL); + switch (pr->status) { + case CMD_PARSE_ERROR: + log_debug("%s: can't parse hook %s: %s", __func__, + ne->name, pr->error); + free(pr->error); + break; + case CMD_PARSE_SUCCESS: + notify_insert_one_hook(item, ne, pr->cmdlist, state); + break; + } + } else { + a = options_array_first(o); + while (a != NULL) { + cmdlist = options_array_item_value(a)->cmdlist; + item = notify_insert_one_hook(item, ne, cmdlist, state); + a = options_array_next(a); } - a = options_array_next(a); } - cmdq_free_state(new_state); + cmdq_free_state(state); } static enum cmd_retval @@ -148,6 +162,7 @@ notify_callback(struct cmdq_item *item, void *data) if (ne->fs.s != NULL) session_remove_ref(ne->fs.s, __func__); + format_free(ne->formats); free(__UNCONST(ne->name)); free(ne); @@ -171,11 +186,23 @@ notify_add(const char *name, struct cmd_find_state *fs, struct client *c, ne->client = c; ne->session = s; ne->window = w; + ne->pane = (wp != NULL ? wp->id : -1); + ne->formats = format_create(NULL, NULL, 0, FORMAT_NOJOBS); + format_add(ne->formats, "hook", "%s", name); + if (c != NULL) + format_add(ne->formats, "hook_client", "%s", c->name); + if (s != NULL) { + format_add(ne->formats, "hook_session", "$%u", s->id); + format_add(ne->formats, "hook_session_name", "%s", s->name); + } + if (w != NULL) { + format_add(ne->formats, "hook_window", "@%u", w->id); + format_add(ne->formats, "hook_window_name", "%s", w->name); + } if (wp != NULL) - ne->pane = wp->id; - else - ne->pane = -1; + format_add(ne->formats, "hook_pane", "%%%d", wp->id); + format_log_debug(ne->formats, __func__); if (c != NULL) c->references++; @@ -205,9 +232,14 @@ notify_hook(struct cmdq_item *item, const char *name) ne.client = cmdq_get_client(item); ne.session = target->s; ne.window = target->w; - ne.pane = target->wp->id; + ne.pane = (target->wp != NULL ? target->wp->id : -1); + + ne.formats = format_create(NULL, NULL, 0, FORMAT_NOJOBS); + format_add(ne.formats, "hook", "%s", name); + format_log_debug(ne.formats, __func__); notify_insert_hook(item, &ne); + format_free(ne.formats); } void diff --git a/external/bsd/tmux/dist/options.c b/external/bsd/tmux/dist/options.c index f7561df615a..133d3fbf828 100644 --- a/external/bsd/tmux/dist/options.c +++ b/external/bsd/tmux/dist/options.c @@ -402,7 +402,7 @@ options_array_clear(struct options_entry *o) return; RB_FOREACH_SAFE(a, options_array, &o->value.array, a1) - options_array_free(o, a); + options_array_free(o, a); } union options_value * @@ -424,7 +424,8 @@ options_array_set(struct options_entry *o, u_int idx, const char *value, { struct options_array_item *a; char *new; - struct cmd_parse_result *pr = NULL; // XXX: gcc + struct cmd_parse_result *pr; + long long number; if (!OPTIONS_IS_ARRAY(o)) { if (cause != NULL) @@ -442,10 +443,6 @@ options_array_set(struct options_entry *o, u_int idx, const char *value, if (OPTIONS_IS_COMMAND(o)) { pr = cmd_parse_from_string(value, NULL); switch (pr->status) { - case CMD_PARSE_EMPTY: - if (cause != NULL) - *cause = xstrdup("empty command"); - return (-1); case CMD_PARSE_ERROR: if (cause != NULL) *cause = pr->error; @@ -479,6 +476,20 @@ options_array_set(struct options_entry *o, u_int idx, const char *value, return (0); } + if (o->tableentry->type == OPTIONS_TABLE_COLOUR) { + if ((number = colour_fromstring(value)) == -1) { + xasprintf(cause, "bad colour: %s", value); + return (-1); + } + a = options_array_item(o, idx); + if (a == NULL) + a = options_array_new(o, idx); + else + options_value_free(o, &a->value); + a->value.number = number; + return (0); + } + if (cause != NULL) *cause = xstrdup("wrong array type"); return (-1); @@ -978,28 +989,39 @@ options_from_string_flag(struct options *oo, const char *name, return (0); } +int +options_find_choice(const struct options_table_entry *oe, const char *value, + char **cause) +{ + const char **cp; + int n = 0, choice = -1; + + for (cp = oe->choices; *cp != NULL; cp++) { + if (strcmp(*cp, value) == 0) + choice = n; + n++; + } + if (choice == -1) { + xasprintf(cause, "unknown value: %s", value); + return (-1); + } + return (choice); +} + static int options_from_string_choice(const struct options_table_entry *oe, struct options *oo, const char *name, const char *value, char **cause) { - const char **cp; - int n, choice = -1; + int choice = -1; if (value == NULL) { choice = options_get_number(oo, name); if (choice < 2) choice = !choice; } else { - n = 0; - for (cp = oe->choices; *cp != NULL; cp++) { - if (strcmp(*cp, value) == 0) - choice = n; - n++; - } - if (choice == -1) { - xasprintf(cause, "unknown value: %s", value); + choice = options_find_choice(oe, value, cause); + if (choice < 0) return (-1); - } } options_set_number(oo, name, choice); return (0); @@ -1084,15 +1106,36 @@ options_push_changes(const char *name) struct session *s; struct window *w; struct window_pane *wp; + int c; + + log_debug("%s: %s", __func__, name); if (strcmp(name, "automatic-rename") == 0) { RB_FOREACH(w, windows, &windows) { if (w->active == NULL) continue; - if (options_get_number(w->options, "automatic-rename")) + if (options_get_number(w->options, name)) w->active->flags |= PANE_CHANGED; } } + if (strcmp(name, "cursor-colour") == 0) { + RB_FOREACH(wp, window_pane_tree, &all_window_panes) { + c = options_get_number(wp->options, name); + wp->screen->default_ccolour = c; + } + } + if (strcmp(name, "cursor-style") == 0) { + RB_FOREACH(wp, window_pane_tree, &all_window_panes) { + wp->screen->default_mode = 0; + screen_set_cursor_style(options_get_number(wp->options, + name), &wp->screen->default_cstyle, + &wp->screen->default_mode); + } + } + if (strcmp(name, "fill-character") == 0) { + RB_FOREACH(w, windows, &windows) + window_set_fill_character(w); + } if (strcmp(name, "key-table") == 0) { TAILQ_FOREACH(loop, &clients, entry) server_client_set_key_table(loop, NULL); @@ -1113,6 +1156,10 @@ options_push_changes(const char *name) RB_FOREACH(wp, window_pane_tree, &all_window_panes) wp->flags |= PANE_STYLECHANGED; } + if (strcmp(name, "pane-colours") == 0) { + RB_FOREACH(wp, window_pane_tree, &all_window_panes) + colour_palette_from_option(&wp->palette, wp->options); + } if (strcmp(name, "pane-border-status") == 0) { RB_FOREACH(w, windows, &windows) layout_fix_panes(w, NULL); diff --git a/external/bsd/tmux/dist/proc.c b/external/bsd/tmux/dist/proc.c index 36bb03e4829..083f8bd5ee8 100644 --- a/external/bsd/tmux/dist/proc.c +++ b/external/bsd/tmux/dist/proc.c @@ -56,6 +56,7 @@ struct tmuxpeer { struct imsgbuf ibuf; struct event event; + uid_t uid; int flags; #define PEER_BAD 0x1 @@ -201,7 +202,7 @@ proc_start(const char *name) #endif , event_get_version(), event_get_method() #ifdef HAVE_UTF8PROC - , utf8proc_version () + , utf8proc_version() #endif ); @@ -308,6 +309,7 @@ proc_add_peer(struct tmuxproc *tp, int fd, void (*dispatchcb)(struct imsg *, void *), void *arg) { struct tmuxpeer *peer; + gid_t gid; peer = xcalloc(1, sizeof *peer); peer->parent = tp; @@ -318,6 +320,9 @@ proc_add_peer(struct tmuxproc *tp, int fd, imsg_init(&peer->ibuf, fd); event_set(&peer->event, fd, EV_READ, proc_event_cb, peer); + if (getpeereid(fd, &peer->uid, &gid) != 0) + peer->uid = (uid_t)-1; + log_debug("add peer %p: %d (%p)", peer, fd, arg); TAILQ_INSERT_TAIL(&tp->peers, peer, entry); @@ -345,6 +350,12 @@ proc_kill_peer(struct tmuxpeer *peer) } void +proc_flush_peer(struct tmuxpeer *peer) +{ + imsg_flush(&peer->ibuf); +} + +void proc_toggle_log(struct tmuxproc *tp) { log_toggle(tp->name); @@ -373,3 +384,9 @@ proc_fork_and_daemon(int *fd) return (pid); } } + +uid_t +proc_get_peer_uid(struct tmuxpeer *peer) +{ + return (peer->uid); +} diff --git a/external/bsd/tmux/dist/resize.c b/external/bsd/tmux/dist/resize.c index 38cda23d273..457fee0a7bd 100644 --- a/external/bsd/tmux/dist/resize.c +++ b/external/bsd/tmux/dist/resize.c @@ -51,7 +51,7 @@ resize_window(struct window *w, u_int sx, u_int sy, int xpixel, int ypixel) if (sy < w->layout_root->sy) sy = w->layout_root->sy; window_resize(w, sx, sy, xpixel, ypixel); - log_debug("%s: @%u resized to %u,%u; layout %u,%u", __func__, w->id, + log_debug("%s: @%u resized to %ux%u; layout %ux%u", __func__, w->id, sx, sy, w->layout_root->sx, w->layout_root->sy); /* Restore the window zoom state. */ @@ -61,6 +61,7 @@ resize_window(struct window *w, u_int sx, u_int sy, int xpixel, int ypixel) tty_update_window_offset(w); server_redraw_window(w); notify_window("window-layout-changed", w); + notify_window("window-resized", w); w->flags &= ~WINDOW_RESIZE; } @@ -87,7 +88,9 @@ ignore_client_size(struct client *c) return (1); } } - if ((c->flags & CLIENT_CONTROL) && (~c->flags & CLIENT_SIZECHANGED)) + if ((c->flags & CLIENT_CONTROL) && + (~c->flags & CLIENT_SIZECHANGED) && + (~c->flags & CLIENT_WINDOWSIZECHANGED)) return (1); return (0); } @@ -113,23 +116,25 @@ clients_calculate_size(int type, int current, struct client *c, int, int, struct session *, struct window *), u_int *sx, u_int *sy, u_int *xpixel, u_int *ypixel) { - struct client *loop; - u_int cx, cy, n = 0; - - /* Manual windows do not have their size changed based on a client. */ - if (type == WINDOW_SIZE_MANUAL) { - log_debug("%s: type is manual", __func__); - return (0); - } + struct client *loop; + struct client_window *cw; + u_int cx, cy, n = 0; /* * Start comparing with 0 for largest and UINT_MAX for smallest or * latest. */ - if (type == WINDOW_SIZE_LARGEST) - *sx = *sy = 0; - else - *sx = *sy = UINT_MAX; + if (type == WINDOW_SIZE_LARGEST) { + *sx = 0; + *sy = 0; + } else if (type == WINDOW_SIZE_MANUAL) { + *sx = w->manual_sx; + *sy = w->manual_sy; + log_debug("%s: manual size %ux%u", __func__, *sx, *sy); + } else { + *sx = UINT_MAX; + *sy = UINT_MAX; + } *xpixel = *ypixel = 0; /* @@ -139,14 +144,18 @@ clients_calculate_size(int type, int current, struct client *c, if (type == WINDOW_SIZE_LATEST && w != NULL) n = clients_with_window(w); + /* Skip setting the size if manual */ + if (type == WINDOW_SIZE_MANUAL) + goto skip; + /* Loop over the clients and work out the size. */ TAILQ_FOREACH(loop, &clients, entry) { if (loop != c && ignore_client_size(loop)) { - log_debug("%s: ignoring %s", __func__, loop->name); + log_debug("%s: ignoring %s (1)", __func__, loop->name); continue; } if (loop != c && skip_client(loop, type, current, s, w)) { - log_debug("%s: skipping %s", __func__, loop->name); + log_debug("%s: skipping %s (1)", __func__, loop->name); continue; } @@ -160,9 +169,23 @@ clients_calculate_size(int type, int current, struct client *c, continue; } + /* + * If the client has a per-window size, use this instead if it is + * smaller. + */ + if (w != NULL) + cw = server_client_get_client_window(loop, w->id); + else + cw = NULL; + /* Work out this client's size. */ - cx = loop->tty.sx; - cy = loop->tty.sy - status_line_size(loop); + if (cw != NULL && cw->sx != 0 && cw->sy != 0) { + cx = cw->sx; + cy = cw->sy; + } else { + cx = loop->tty.sx; + cy = loop->tty.sy - status_line_size(loop); + } /* * If it is larger or smaller than the best so far, update the @@ -186,8 +209,49 @@ clients_calculate_size(int type, int current, struct client *c, log_debug("%s: after %s (%ux%u), size is %ux%u", __func__, loop->name, cx, cy, *sx, *sy); } + if (*sx != UINT_MAX && *sy != UINT_MAX) + log_debug("%s: calculated size %ux%u", __func__, *sx, *sy); + else + log_debug("%s: no calculated size", __func__); + +skip: + /* + * Do not allow any size to be larger than the per-client window size + * if one exists. + */ + if (w != NULL) { + TAILQ_FOREACH(loop, &clients, entry) { + if (loop != c && ignore_client_size(loop)) + continue; + if (loop != c && skip_client(loop, type, current, s, w)) + continue; + + /* Look up per-window size if any. */ + if (~loop->flags & CLIENT_WINDOWSIZECHANGED) + continue; + cw = server_client_get_client_window(loop, w->id); + if (cw == NULL) + continue; + + /* Clamp the size. */ + log_debug("%s: %s size for @%u is %ux%u", __func__, + loop->name, w->id, cw->sx, cw->sy); + if (cw->sx != 0 && *sx > cw->sx) + *sx = cw->sx; + if (cw->sy != 0 && *sy > cw->sy) + *sy = cw->sy; + } + } + if (*sx != UINT_MAX && *sy != UINT_MAX) + log_debug("%s: calculated size %ux%u", __func__, *sx, *sy); + else + log_debug("%s: no calculated size", __func__); /* Return whether a suitable size was found. */ + if (type == WINDOW_SIZE_MANUAL) { + log_debug("%s: type is manual", __func__); + return (1); + } if (type == WINDOW_SIZE_LARGEST) { log_debug("%s: type is largest", __func__); return (*sx != 0 && *sy != 0); @@ -231,18 +295,23 @@ default_window_size(struct client *c, struct session *s, struct window *w, * Latest clients can use the given client if suitable. If there is no * client and no window, use the default size as for manual type. */ - if (type == WINDOW_SIZE_LATEST) { - if (c != NULL && !ignore_client_size(c)) { - *sx = c->tty.sx; - *sy = c->tty.sy - status_line_size(c); - *xpixel = c->tty.xpixel; - *ypixel = c->tty.ypixel; - log_debug("%s: using %ux%u from %s", __func__, *sx, *sy, - c->name); - goto done; - } + if (type == WINDOW_SIZE_LATEST && c != NULL && !ignore_client_size(c)) { + *sx = c->tty.sx; + *sy = c->tty.sy - status_line_size(c); + *xpixel = c->tty.xpixel; + *ypixel = c->tty.ypixel; + log_debug("%s: using %ux%u from %s", __func__, *sx, *sy, + c->name); + goto done; } + /* + * Ignore the given client if it is a control client - the creating + * client should only affect the size if it is not a control client. + */ + if (c != NULL && (c->flags & CLIENT_CONTROL)) + c = NULL; + /* * Look for a client to base the size on. If none exists (or the type * is manual), use the default-size option. @@ -280,6 +349,8 @@ recalculate_size_skip_client(struct client *loop, __unused int type, * is not the current window - this is used for aggressive-resize. * Otherwise skip any session that doesn't contain the window. */ + if (loop->session->curw == NULL) + return (1); if (current) return (loop->session->curw->window != w); return (session_has(loop->session, w) == 0); @@ -297,7 +368,7 @@ recalculate_size(struct window *w, int now) */ if (w->active == NULL) return; - log_debug("%s: @%u is %u,%u", __func__, w->id, w->sx, w->sy); + log_debug("%s: @%u is %ux%u", __func__, w->id, w->sx, w->sy); /* * Type is manual, smallest, largest, latest. Current is the @@ -328,6 +399,7 @@ recalculate_size(struct window *w, int now) * size. */ if (!changed) { + log_debug("%s: @%u no size change", __func__, w->id); tty_update_window_offset(w); return; } @@ -337,7 +409,7 @@ recalculate_size(struct window *w, int now) * the size immediately. Otherwise set the flag and it will be done * later. */ - log_debug("%s: @%u new size %u,%u", __func__, w->id, sx, sy); + log_debug("%s: @%u new size %ux%u", __func__, w->id, sx, sy); if (now || type == WINDOW_SIZE_MANUAL) resize_window(w, sx, sy, xpixel, ypixel); else { diff --git a/external/bsd/tmux/dist/screen-write.c b/external/bsd/tmux/dist/screen-write.c index 8f76472f322..37a6268d2be 100644 --- a/external/bsd/tmux/dist/screen-write.c +++ b/external/bsd/tmux/dist/screen-write.c @@ -171,15 +171,6 @@ screen_write_initctx(struct screen_write_ctx *ctx, struct tty_ctx *ttyctx, memset(ttyctx, 0, sizeof *ttyctx); - if (ctx->wp != NULL) { - tty_default_colours(&ttyctx->defaults, ctx->wp); - ttyctx->palette = ctx->wp->palette; - } else { - memcpy(&ttyctx->defaults, &grid_default_cell, - sizeof ttyctx->defaults); - ttyctx->palette = NULL; - } - ttyctx->s = s; ttyctx->sx = screen_size_x(s); ttyctx->sy = screen_size_y(s); @@ -189,20 +180,39 @@ screen_write_initctx(struct screen_write_ctx *ctx, struct tty_ctx *ttyctx, ttyctx->orlower = s->rlower; ttyctx->orupper = s->rupper; - if (ctx->init_ctx_cb != NULL) + memcpy(&ttyctx->defaults, &grid_default_cell, sizeof ttyctx->defaults); + if (ctx->init_ctx_cb != NULL) { ctx->init_ctx_cb(ctx, ttyctx); - else { + if (ttyctx->palette != NULL) { + if (ttyctx->defaults.fg == 8) + ttyctx->defaults.fg = ttyctx->palette->fg; + if (ttyctx->defaults.bg == 8) + ttyctx->defaults.bg = ttyctx->palette->bg; + } + } else { ttyctx->redraw_cb = screen_write_redraw_cb; - if (ctx->wp == NULL) - ttyctx->set_client_cb = NULL; - else + if (ctx->wp != NULL) { + tty_default_colours(&ttyctx->defaults, ctx->wp); + ttyctx->palette = &ctx->wp->palette; ttyctx->set_client_cb = screen_write_set_client_cb; - ttyctx->arg = ctx->wp; + ttyctx->arg = ctx->wp; + } } - if (ctx->wp != NULL && - (~ctx->flags & SCREEN_WRITE_SYNC) && - (sync || ctx->wp != ctx->wp->window->active)) { + if (~ctx->flags & SCREEN_WRITE_SYNC) { + /* + * For the active pane or for an overlay (no pane), we want to + * only use synchronized updates if requested (commands that + * move the cursor); for other panes, always use it, since the + * cursor will have to move. + */ + if (ctx->wp != NULL) { + if (ctx->wp != ctx->wp->window->active) + ttyctx->num = 1; + else + ttyctx->num = sync; + } else + ttyctx->num = 0x10|sync; tty_write(tty_cmd_syncstart, ttyctx); ctx->flags |= SCREEN_WRITE_SYNC; } @@ -596,7 +606,7 @@ screen_write_hline(struct screen_write_ctx *ctx, u_int nx, int left, int right) screen_write_set_cursor(ctx, cx, cy); } -/* Draw a horizontal line on screen. */ +/* Draw a vertical line on screen. */ void screen_write_vline(struct screen_write_ctx *ctx, u_int ny, int top, int bottom) { @@ -637,9 +647,8 @@ screen_write_menu(struct screen_write_ctx *ctx, struct menu *menu, memcpy(&default_gc, &grid_default_cell, sizeof default_gc); - screen_write_box(ctx, menu->width + 4, menu->count + 2); - screen_write_cursormove(ctx, cx + 2, cy, 0); - format_draw(ctx, &default_gc, menu->width, menu->title, NULL); + screen_write_box(ctx, menu->width + 4, menu->count + 2, + BOX_LINES_DEFAULT, &default_gc, menu->title); for (i = 0; i < menu->count; i++) { name = menu->items[i].name; @@ -656,10 +665,12 @@ screen_write_menu(struct screen_write_ctx *ctx, struct menu *menu, if (*name == '-') { name++; default_gc.attr |= GRID_ATTR_DIM; - format_draw(ctx, gc, menu->width, name, NULL); + format_draw(ctx, gc, menu->width, name, NULL, + 0); default_gc.attr &= ~GRID_ATTR_DIM; } else - format_draw(ctx, gc, menu->width, name, NULL); + format_draw(ctx, gc, menu->width, name, NULL, + gc == choice_gc); gc = &default_gc; } } @@ -667,38 +678,95 @@ screen_write_menu(struct screen_write_ctx *ctx, struct menu *menu, screen_write_set_cursor(ctx, cx, cy); } +static void +screen_write_box_border_set(enum box_lines box_lines, int cell_type, + struct grid_cell *gc) +{ + switch (box_lines) { + case BOX_LINES_NONE: + break; + case BOX_LINES_DOUBLE: + gc->attr &= ~GRID_ATTR_CHARSET; + utf8_copy(&gc->data, tty_acs_double_borders(cell_type)); + break; + case BOX_LINES_HEAVY: + gc->attr &= ~GRID_ATTR_CHARSET; + utf8_copy(&gc->data, tty_acs_heavy_borders(cell_type)); + break; + case BOX_LINES_ROUNDED: + gc->attr &= ~GRID_ATTR_CHARSET; + utf8_copy(&gc->data, tty_acs_rounded_borders(cell_type)); + break; + case BOX_LINES_SIMPLE: + gc->attr &= ~GRID_ATTR_CHARSET; + utf8_set(&gc->data, SIMPLE_BORDERS[cell_type]); + break; + case BOX_LINES_PADDED: + gc->attr &= ~GRID_ATTR_CHARSET; + utf8_set(&gc->data, PADDED_BORDERS[cell_type]); + break; + case BOX_LINES_SINGLE: + case BOX_LINES_DEFAULT: + gc->attr |= GRID_ATTR_CHARSET; + utf8_set(&gc->data, CELL_BORDERS[cell_type]); + break; + } +} + /* Draw a box on screen. */ void -screen_write_box(struct screen_write_ctx *ctx, u_int nx, u_int ny) +screen_write_box(struct screen_write_ctx *ctx, u_int nx, u_int ny, + enum box_lines lines, const struct grid_cell *gcp, const char *title) { struct screen *s = ctx->s; - struct grid_cell gc; + struct grid_cell gc; u_int cx, cy, i; cx = s->cx; cy = s->cy; - memcpy(&gc, &grid_default_cell, sizeof gc); + if (gcp != NULL) + memcpy(&gc, gcp, sizeof gc); + else + memcpy(&gc, &grid_default_cell, sizeof gc); + gc.attr |= GRID_ATTR_CHARSET; + gc.flags |= GRID_FLAG_NOPALETTE; - screen_write_putc(ctx, &gc, 'l'); + /* Draw top border */ + screen_write_box_border_set(lines, CELL_TOPLEFT, &gc); + screen_write_cell(ctx, &gc); + screen_write_box_border_set(lines, CELL_LEFTRIGHT, &gc); for (i = 1; i < nx - 1; i++) - screen_write_putc(ctx, &gc, 'q'); - screen_write_putc(ctx, &gc, 'k'); + screen_write_cell(ctx, &gc); + screen_write_box_border_set(lines, CELL_TOPRIGHT, &gc); + screen_write_cell(ctx, &gc); + /* Draw bottom border */ screen_write_set_cursor(ctx, cx, cy + ny - 1); - screen_write_putc(ctx, &gc, 'm'); + screen_write_box_border_set(lines, CELL_BOTTOMLEFT, &gc); + screen_write_cell(ctx, &gc); + screen_write_box_border_set(lines, CELL_LEFTRIGHT, &gc); for (i = 1; i < nx - 1; i++) - screen_write_putc(ctx, &gc, 'q'); - screen_write_putc(ctx, &gc, 'j'); + screen_write_cell(ctx, &gc); + screen_write_box_border_set(lines, CELL_BOTTOMRIGHT, &gc); + screen_write_cell(ctx, &gc); + /* Draw sides */ + screen_write_box_border_set(lines, CELL_TOPBOTTOM, &gc); for (i = 1; i < ny - 1; i++) { + /* left side */ screen_write_set_cursor(ctx, cx, cy + i); - screen_write_putc(ctx, &gc, 'x'); - } - for (i = 1; i < ny - 1; i++) { + screen_write_cell(ctx, &gc); + /* right side */ screen_write_set_cursor(ctx, cx + nx - 1, cy + i); - screen_write_putc(ctx, &gc, 'x'); + screen_write_cell(ctx, &gc); + } + + if (title != NULL) { + gc.attr &= ~GRID_ATTR_CHARSET; + screen_write_cursormove(ctx, cx + 2, cy, 0); + format_draw(ctx, &gc, nx - 4, title, NULL, 0); } screen_write_set_cursor(ctx, cx, cy); @@ -769,6 +837,9 @@ screen_write_mode_set(struct screen_write_ctx *ctx, int mode) struct screen *s = ctx->s; s->mode |= mode; + + if (log_get_level() != 0) + log_debug("%s: %s", __func__, screen_mode_to_string(mode)); } /* Clear a mode. */ @@ -778,6 +849,9 @@ screen_write_mode_clear(struct screen_write_ctx *ctx, int mode) struct screen *s = ctx->s; s->mode &= ~mode; + + if (log_get_level() != 0) + log_debug("%s: %s", __func__, screen_mode_to_string(mode)); } /* Cursor up by ny. */ @@ -1353,7 +1427,11 @@ screen_write_clearendofscreen(struct screen_write_ctx *ctx, u_int bg) ttyctx.bg = bg; /* Scroll into history if it is enabled and clearing entire screen. */ - if (s->cx == 0 && s->cy == 0 && (gd->flags & GRID_HISTORY)) + if (s->cx == 0 && + s->cy == 0 && + (gd->flags & GRID_HISTORY) && + ctx->wp != NULL && + options_get_number(ctx->wp->options, "scroll-on-clear")) grid_view_clear_history(gd, bg); else { if (s->cx <= sx - 1) @@ -1401,7 +1479,9 @@ screen_write_clearscreen(struct screen_write_ctx *ctx, u_int bg) ttyctx.bg = bg; /* Scroll into history if it is enabled. */ - if (s->grid->flags & GRID_HISTORY) + if ((s->grid->flags & GRID_HISTORY) && + ctx->wp != NULL && + options_get_number(ctx->wp->options, "scroll-on-clear")) grid_view_clear_history(s->grid, bg); else grid_view_clear(s->grid, 0, 0, sx, sy, bg); @@ -1417,6 +1497,18 @@ screen_write_clearhistory(struct screen_write_ctx *ctx) grid_clear_history(ctx->s->grid); } +/* Force a full redraw. */ +void +screen_write_fullredraw(struct screen_write_ctx *ctx) +{ + struct tty_ctx ttyctx; + + screen_write_collect_flush(ctx, 0, __func__); + + screen_write_initctx(ctx, &ttyctx, 1); + ttyctx.redraw_cb(&ttyctx); +} + /* Trim collected items. */ static struct screen_write_citem * screen_write_collect_trim(struct screen_write_ctx *ctx, u_int y, u_int x, @@ -1720,6 +1812,8 @@ screen_write_cell(struct screen_write_ctx *ctx, const struct grid_cell *gc) { struct screen *s = ctx->s; struct grid *gd = s->grid; + const struct utf8_data *ud = &gc->data; + const struct utf8_data zwj = { "\342\200\215", 0, 3, 0 }; struct grid_line *gl; struct grid_cell_entry *gce; struct grid_cell tmp_gc, now_gc; @@ -1732,10 +1826,32 @@ screen_write_cell(struct screen_write_ctx *ctx, const struct grid_cell *gc) if (gc->flags & GRID_FLAG_PADDING) return; - /* If the width is zero, combine onto the previous character. */ - if (width == 0) { + /* + * If this is a zero width joiner, set the flag so the next character + * will be treated as zero width and appended. Note that we assume a + * ZWJ will not change the width - the width of the first character is + * used. + */ + if (ud->size == 3 && memcmp(ud->data, "\342\200\215", 3) == 0) { + log_debug("zero width joiner at %u,%u", s->cx, s->cy); + ctx->flags |= SCREEN_WRITE_ZWJ; + return; + } + + /* + * If the width is zero, combine onto the previous character. We always + * combine with the cell to the left of the cursor position. In theory, + * the application could have moved the cursor somewhere else, but if + * they are silly enough to do that, who cares? + */ + if (ctx->flags & SCREEN_WRITE_ZWJ) { + screen_write_collect_flush(ctx, 0, __func__); + screen_write_combine(ctx, &zwj, &xx); + } + if (width == 0 || (ctx->flags & SCREEN_WRITE_ZWJ)) { + ctx->flags &= ~SCREEN_WRITE_ZWJ; screen_write_collect_flush(ctx, 0, __func__); - if ((gc = screen_write_combine(ctx, &gc->data, &xx)) != 0) { + if ((gc = screen_write_combine(ctx, ud, &xx)) != NULL) { cx = s->cx; cy = s->cy; screen_write_set_cursor(ctx, xx, s->cy); screen_write_initctx(ctx, &ttyctx, 0); diff --git a/external/bsd/tmux/dist/screen.c b/external/bsd/tmux/dist/screen.c index 2b83c2854d3..eceef642b8f 100644 --- a/external/bsd/tmux/dist/screen.c +++ b/external/bsd/tmux/dist/screen.c @@ -80,8 +80,11 @@ screen_init(struct screen *s, u_int sx, u_int sy, u_int hlimit) s->titles = NULL; s->path = NULL; - s->cstyle = 0; - s->ccolour = xstrdup(""); + s->cstyle = SCREEN_CURSOR_DEFAULT; + s->default_cstyle = SCREEN_CURSOR_DEFAULT; + s->default_mode = 0; + s->ccolour = -1; + s->default_ccolour = -1; s->tabs = NULL; s->sel = NULL; @@ -100,7 +103,7 @@ screen_reinit(struct screen *s) s->rupper = 0; s->rlower = screen_size_y(s) - 1; - s->mode = MODE_CURSOR|MODE_WRAP; + s->mode = MODE_CURSOR|MODE_WRAP|(s->mode & MODE_CRLF); if (options_get_number(global_options, "extended-keys") == 2) s->mode |= MODE_KEXTENDED; @@ -125,7 +128,6 @@ screen_free(struct screen *s) free(s->tabs); free(s->path); free(s->title); - free(s->ccolour); if (s->write_list != NULL) screen_write_free_list(s); @@ -151,22 +153,47 @@ screen_reset_tabs(struct screen *s) bit_set(s->tabs, i); } -/* Set screen cursor style. */ +/* Set screen cursor style and mode. */ void -screen_set_cursor_style(struct screen *s, u_int style) +screen_set_cursor_style(u_int style, enum screen_cursor_style *cstyle, + int *mode) { - if (style <= 6) { - s->cstyle = style; - s->mode &= ~MODE_BLINKING; + switch (style) { + case 0: + *cstyle = SCREEN_CURSOR_DEFAULT; + break; + case 1: + *cstyle = SCREEN_CURSOR_BLOCK; + *mode |= MODE_CURSOR_BLINKING; + break; + case 2: + *cstyle = SCREEN_CURSOR_BLOCK; + *mode &= ~MODE_CURSOR_BLINKING; + break; + case 3: + *cstyle = SCREEN_CURSOR_UNDERLINE; + *mode |= MODE_CURSOR_BLINKING; + break; + case 4: + *cstyle = SCREEN_CURSOR_UNDERLINE; + *mode &= ~MODE_CURSOR_BLINKING; + break; + case 5: + *cstyle = SCREEN_CURSOR_BAR; + *mode |= MODE_CURSOR_BLINKING; + break; + case 6: + *cstyle = SCREEN_CURSOR_BAR; + *mode &= ~MODE_CURSOR_BLINKING; + break; } } /* Set screen cursor colour. */ void -screen_set_cursor_colour(struct screen *s, const char *colour) +screen_set_cursor_colour(struct screen *s, int colour) { - free(s->ccolour); - s->ccolour = xstrdup(colour); + s->ccolour = colour; } /* Set screen title. */ @@ -626,3 +653,53 @@ screen_alternate_off(struct screen *s, struct grid_cell *gc, int cursor) if (s->cy > screen_size_y(s) - 1) s->cy = screen_size_y(s) - 1; } + +/* Get mode as a string. */ +const char * +screen_mode_to_string(int mode) +{ + static char tmp[1024]; + + if (mode == 0) + return ("NONE"); + if (mode == ALL_MODES) + return ("ALL"); + + *tmp = '\0'; + if (mode & MODE_CURSOR) + strlcat(tmp, "CURSOR,", sizeof tmp); + if (mode & MODE_INSERT) + strlcat(tmp, "INSERT,", sizeof tmp); + if (mode & MODE_KCURSOR) + strlcat(tmp, "KCURSOR,", sizeof tmp); + if (mode & MODE_KKEYPAD) + strlcat(tmp, "KKEYPAD,", sizeof tmp); + if (mode & MODE_WRAP) + strlcat(tmp, "WRAP,", sizeof tmp); + if (mode & MODE_MOUSE_STANDARD) + strlcat(tmp, "MOUSE_STANDARD,", sizeof tmp); + if (mode & MODE_MOUSE_BUTTON) + strlcat(tmp, "MOUSE_BUTTON,", sizeof tmp); + if (mode & MODE_CURSOR_BLINKING) + strlcat(tmp, "CURSOR_BLINKING,", sizeof tmp); + if (mode & MODE_CURSOR_VERY_VISIBLE) + strlcat(tmp, "CURSOR_VERY_VISIBLE,", sizeof tmp); + if (mode & MODE_MOUSE_UTF8) + strlcat(tmp, "UTF8,", sizeof tmp); + if (mode & MODE_MOUSE_SGR) + strlcat(tmp, "SGR,", sizeof tmp); + if (mode & MODE_BRACKETPASTE) + strlcat(tmp, "BRACKETPASTE,", sizeof tmp); + if (mode & MODE_FOCUSON) + strlcat(tmp, "FOCUSON,", sizeof tmp); + if (mode & MODE_MOUSE_ALL) + strlcat(tmp, "MOUSE_ALL,", sizeof tmp); + if (mode & MODE_ORIGIN) + strlcat(tmp, "ORIGIN,", sizeof tmp); + if (mode & MODE_CRLF) + strlcat(tmp, "CRLF,", sizeof tmp); + if (mode & MODE_KEXTENDED) + strlcat(tmp, "KEXTENDED,", sizeof tmp); + tmp[strlen(tmp) - 1] = '\0'; + return (tmp); +} diff --git a/external/bsd/tmux/dist/server-client.c b/external/bsd/tmux/dist/server-client.c index ecf0ae7c01a..2ba88e9b425 100644 --- a/external/bsd/tmux/dist/server-client.c +++ b/external/bsd/tmux/dist/server-client.c @@ -30,7 +30,6 @@ #include "tmux.h" static void server_client_free(int, short, void *); -static void server_client_check_pane_focus(struct window_pane *); static void server_client_check_pane_resize(struct window_pane *); static void server_client_check_pane_buffer(struct window_pane *); static void server_client_check_window_resize(struct window *); @@ -41,6 +40,7 @@ static void server_client_check_exit(struct client *); static void server_client_check_redraw(struct client *); static void server_client_check_modes(struct client *); static void server_client_set_title(struct client *); +static void server_client_set_path(struct client *); static void server_client_reset_state(struct client *); static int server_client_assume_paste(struct session *); static void server_client_update_latest(struct client *); @@ -90,7 +90,7 @@ void server_client_set_overlay(struct client *c, u_int delay, overlay_check_cb checkcb, overlay_mode_cb modecb, overlay_draw_cb drawcb, overlay_key_cb keycb, overlay_free_cb freecb, - void *data) + overlay_resize_cb resizecb, void *data) { struct timeval tv; @@ -111,9 +111,11 @@ server_client_set_overlay(struct client *c, u_int delay, c->overlay_draw = drawcb; c->overlay_key = keycb; c->overlay_free = freecb; + c->overlay_resize = resizecb; c->overlay_data = data; - c->tty.flags |= TTY_FREEZE; + if (c->overlay_check == NULL) + c->tty.flags |= TTY_FREEZE; if (c->overlay_mode == NULL) c->tty.flags |= TTY_NOCURSOR; server_redraw_client(c); @@ -130,7 +132,7 @@ server_client_clear_overlay(struct client *c) evtimer_del(&c->overlay_timer); if (c->overlay_free != NULL) - c->overlay_free(c); + c->overlay_free(c, c->overlay_data); c->overlay_check = NULL; c->overlay_mode = NULL; @@ -143,6 +145,54 @@ server_client_clear_overlay(struct client *c) server_redraw_client(c); } +/* + * Given overlay position and dimensions, return parts of the input range which + * are visible. + */ +void +server_client_overlay_range(u_int x, u_int y, u_int sx, u_int sy, u_int px, + u_int py, u_int nx, struct overlay_ranges *r) +{ + u_int ox, onx; + + /* Return up to 2 ranges. */ + r->px[2] = 0; + r->nx[2] = 0; + + /* Trivial case of no overlap in the y direction. */ + if (py < y || py > y + sy - 1) { + r->px[0] = px; + r->nx[0] = nx; + r->px[1] = 0; + r->nx[1] = 0; + return; + } + + /* Visible bit to the left of the popup. */ + if (px < x) { + r->px[0] = px; + r->nx[0] = x - px; + if (r->nx[0] > nx) + r->nx[0] = nx; + } else { + r->px[0] = 0; + r->nx[0] = 0; + } + + /* Visible bit to the right of the popup. */ + ox = x + sx; + if (px > ox) + ox = px; + onx = px + nx; + if (onx > ox) { + r->px[1] = ox; + r->nx[1] = onx - ox; + } else { + r->px[1] = 0; + r->nx[1] = 0; + } +} + /* Check if this client is inside this server. */ int server_client_check_nested(struct client *c) @@ -276,7 +326,7 @@ server_client_open(struct client *c, char **cause) static void server_client_attached_lost(struct client *c) { - struct session *s = c->session; + struct session *s; struct window *w; struct client *loop; struct client *found; @@ -296,9 +346,8 @@ server_client_attached_lost(struct client *c) s = loop->session; if (loop == c || s == NULL || s->curw->window != w) continue; - if (found == NULL || - timercmp(&loop->activity_time, &found->activity_time, - >)) + if (found == NULL || timercmp(&loop->activity_time, + &found->activity_time, >)) found = loop; } if (found != NULL) @@ -306,6 +355,39 @@ server_client_attached_lost(struct client *c) } } +/* Set client session. */ +void +server_client_set_session(struct client *c, struct session *s) +{ + struct session *old = c->session; + + if (s != NULL && c->session != NULL && c->session != s) + c->last_session = c->session; + else if (s == NULL) + c->last_session = NULL; + c->session = s; + c->flags |= CLIENT_FOCUSED; + + if (old != NULL && old->curw != NULL) + window_update_focus(old->curw->window); + if (s != NULL) { + recalculate_sizes(); + window_update_focus(s->curw->window); + session_update_activity(s, NULL); + gettimeofday(&s->last_attached_time, NULL); + s->curw->flags &= ~WINLINK_ALERTFLAGS; + s->curw->window->latest = c; + alerts_check_session(s); + tty_update_client_offset(c); + status_timer_start(c); + notify_client("client-session-changed", c); + server_redraw_client(c); + } + + server_check_unattached(); + server_update_socket(); +} + /* Lost a client. */ void server_client_lost(struct client *c) @@ -341,6 +423,7 @@ server_client_lost(struct client *c) if (c->flags & CLIENT_TERMINAL) tty_free(&c->tty); free(c->ttyname); + free(c->clipboard_panes); free(c->term_name); free(c->term_type); @@ -432,7 +515,7 @@ server_client_detach(struct client *c, enum msgtype msgtype) { struct session *s = c->session; - if (s == NULL || (c->flags & CLIENT_UNATTACHEDFLAGS)) + if (s == NULL || (c->flags & CLIENT_NODETACHFLAGS)) return; c->flags |= CLIENT_EXIT; @@ -512,11 +595,11 @@ server_client_check_mouse(struct client *c, struct key_event *event) log_debug("double-click at %u,%u", x, y); } else if ((m->sgr_type != ' ' && MOUSE_DRAG(m->sgr_b) && - MOUSE_BUTTONS(m->sgr_b) == 3) || + MOUSE_RELEASE(m->sgr_b)) || (m->sgr_type == ' ' && MOUSE_DRAG(m->b) && - MOUSE_BUTTONS(m->b) == 3 && - MOUSE_BUTTONS(m->lb) == 3)) { + MOUSE_RELEASE(m->b) && + MOUSE_RELEASE(m->lb))) { type = MOVE; x = m->x, y = m->y, b = 0; log_debug("move at %u,%u", x, y); @@ -669,7 +752,7 @@ have_event: m->wp = -1; /* Stop dragging if needed. */ - if (type != DRAG && type != WHEEL && c->tty.mouse_drag_flag) { + if (type != DRAG && type != WHEEL && c->tty.mouse_drag_flag != 0) { if (c->tty.mouse_drag_release != NULL) c->tty.mouse_drag_release(c, m); @@ -680,8 +763,8 @@ have_event: * End a mouse drag by passing a MouseDragEnd key corresponding * to the button that started the drag. */ - switch (c->tty.mouse_drag_flag) { - case 1: + switch (c->tty.mouse_drag_flag - 1) { + case MOUSE_BUTTON_1: if (where == PANE) key = KEYC_MOUSEDRAGEND1_PANE; if (where == STATUS) @@ -695,7 +778,7 @@ have_event: if (where == BORDER) key = KEYC_MOUSEDRAGEND1_BORDER; break; - case 2: + case MOUSE_BUTTON_2: if (where == PANE) key = KEYC_MOUSEDRAGEND2_PANE; if (where == STATUS) @@ -709,7 +792,7 @@ have_event: if (where == BORDER) key = KEYC_MOUSEDRAGEND2_BORDER; break; - case 3: + case MOUSE_BUTTON_3: if (where == PANE) key = KEYC_MOUSEDRAGEND3_PANE; if (where == STATUS) @@ -723,6 +806,90 @@ have_event: if (where == BORDER) key = KEYC_MOUSEDRAGEND3_BORDER; break; + case MOUSE_BUTTON_6: + if (where == PANE) + key = KEYC_MOUSEDRAGEND6_PANE; + if (where == STATUS) + key = KEYC_MOUSEDRAGEND6_STATUS; + if (where == STATUS_LEFT) + key = KEYC_MOUSEDRAGEND6_STATUS_LEFT; + if (where == STATUS_RIGHT) + key = KEYC_MOUSEDRAGEND6_STATUS_RIGHT; + if (where == STATUS_DEFAULT) + key = KEYC_MOUSEDRAGEND6_STATUS_DEFAULT; + if (where == BORDER) + key = KEYC_MOUSEDRAGEND6_BORDER; + break; + case MOUSE_BUTTON_7: + if (where == PANE) + key = KEYC_MOUSEDRAGEND7_PANE; + if (where == STATUS) + key = KEYC_MOUSEDRAGEND7_STATUS; + if (where == STATUS_LEFT) + key = KEYC_MOUSEDRAGEND7_STATUS_LEFT; + if (where == STATUS_RIGHT) + key = KEYC_MOUSEDRAGEND7_STATUS_RIGHT; + if (where == STATUS_DEFAULT) + key = KEYC_MOUSEDRAGEND7_STATUS_DEFAULT; + if (where == BORDER) + key = KEYC_MOUSEDRAGEND7_BORDER; + break; + case MOUSE_BUTTON_8: + if (where == PANE) + key = KEYC_MOUSEDRAGEND8_PANE; + if (where == STATUS) + key = KEYC_MOUSEDRAGEND8_STATUS; + if (where == STATUS_LEFT) + key = KEYC_MOUSEDRAGEND8_STATUS_LEFT; + if (where == STATUS_RIGHT) + key = KEYC_MOUSEDRAGEND8_STATUS_RIGHT; + if (where == STATUS_DEFAULT) + key = KEYC_MOUSEDRAGEND8_STATUS_DEFAULT; + if (where == BORDER) + key = KEYC_MOUSEDRAGEND8_BORDER; + break; + case MOUSE_BUTTON_9: + if (where == PANE) + key = KEYC_MOUSEDRAGEND9_PANE; + if (where == STATUS) + key = KEYC_MOUSEDRAGEND9_STATUS; + if (where == STATUS_LEFT) + key = KEYC_MOUSEDRAGEND9_STATUS_LEFT; + if (where == STATUS_RIGHT) + key = KEYC_MOUSEDRAGEND9_STATUS_RIGHT; + if (where == STATUS_DEFAULT) + key = KEYC_MOUSEDRAGEND9_STATUS_DEFAULT; + if (where == BORDER) + key = KEYC_MOUSEDRAGEND9_BORDER; + break; + case MOUSE_BUTTON_10: + if (where == PANE) + key = KEYC_MOUSEDRAGEND10_PANE; + if (where == STATUS) + key = KEYC_MOUSEDRAGEND10_STATUS; + if (where == STATUS_LEFT) + key = KEYC_MOUSEDRAGEND10_STATUS_LEFT; + if (where == STATUS_RIGHT) + key = KEYC_MOUSEDRAGEND10_STATUS_RIGHT; + if (where == STATUS_DEFAULT) + key = KEYC_MOUSEDRAGEND10_STATUS_DEFAULT; + if (where == BORDER) + key = KEYC_MOUSEDRAGEND10_BORDER; + break; + case MOUSE_BUTTON_11: + if (where == PANE) + key = KEYC_MOUSEDRAGEND11_PANE; + if (where == STATUS) + key = KEYC_MOUSEDRAGEND11_STATUS; + if (where == STATUS_LEFT) + key = KEYC_MOUSEDRAGEND11_STATUS_LEFT; + if (where == STATUS_RIGHT) + key = KEYC_MOUSEDRAGEND11_STATUS_RIGHT; + if (where == STATUS_DEFAULT) + key = KEYC_MOUSEDRAGEND11_STATUS_DEFAULT; + if (where == BORDER) + key = KEYC_MOUSEDRAGEND11_BORDER; + break; default: key = KEYC_MOUSE; break; @@ -755,7 +922,7 @@ have_event: key = KEYC_DRAGGING; else { switch (MOUSE_BUTTONS(b)) { - case 0: + case MOUSE_BUTTON_1: if (where == PANE) key = KEYC_MOUSEDRAG1_PANE; if (where == STATUS) @@ -769,7 +936,7 @@ have_event: if (where == BORDER) key = KEYC_MOUSEDRAG1_BORDER; break; - case 1: + case MOUSE_BUTTON_2: if (where == PANE) key = KEYC_MOUSEDRAG2_PANE; if (where == STATUS) @@ -783,7 +950,7 @@ have_event: if (where == BORDER) key = KEYC_MOUSEDRAG2_BORDER; break; - case 2: + case MOUSE_BUTTON_3: if (where == PANE) key = KEYC_MOUSEDRAG3_PANE; if (where == STATUS) @@ -797,6 +964,90 @@ have_event: if (where == BORDER) key = KEYC_MOUSEDRAG3_BORDER; break; + case MOUSE_BUTTON_6: + if (where == PANE) + key = KEYC_MOUSEDRAG6_PANE; + if (where == STATUS) + key = KEYC_MOUSEDRAG6_STATUS; + if (where == STATUS_LEFT) + key = KEYC_MOUSEDRAG6_STATUS_LEFT; + if (where == STATUS_RIGHT) + key = KEYC_MOUSEDRAG6_STATUS_RIGHT; + if (where == STATUS_DEFAULT) + key = KEYC_MOUSEDRAG6_STATUS_DEFAULT; + if (where == BORDER) + key = KEYC_MOUSEDRAG6_BORDER; + break; + case MOUSE_BUTTON_7: + if (where == PANE) + key = KEYC_MOUSEDRAG7_PANE; + if (where == STATUS) + key = KEYC_MOUSEDRAG7_STATUS; + if (where == STATUS_LEFT) + key = KEYC_MOUSEDRAG7_STATUS_LEFT; + if (where == STATUS_RIGHT) + key = KEYC_MOUSEDRAG7_STATUS_RIGHT; + if (where == STATUS_DEFAULT) + key = KEYC_MOUSEDRAG7_STATUS_DEFAULT; + if (where == BORDER) + key = KEYC_MOUSEDRAG7_BORDER; + break; + case MOUSE_BUTTON_8: + if (where == PANE) + key = KEYC_MOUSEDRAG8_PANE; + if (where == STATUS) + key = KEYC_MOUSEDRAG8_STATUS; + if (where == STATUS_LEFT) + key = KEYC_MOUSEDRAG8_STATUS_LEFT; + if (where == STATUS_RIGHT) + key = KEYC_MOUSEDRAG8_STATUS_RIGHT; + if (where == STATUS_DEFAULT) + key = KEYC_MOUSEDRAG8_STATUS_DEFAULT; + if (where == BORDER) + key = KEYC_MOUSEDRAG8_BORDER; + break; + case MOUSE_BUTTON_9: + if (where == PANE) + key = KEYC_MOUSEDRAG9_PANE; + if (where == STATUS) + key = KEYC_MOUSEDRAG9_STATUS; + if (where == STATUS_LEFT) + key = KEYC_MOUSEDRAG9_STATUS_LEFT; + if (where == STATUS_RIGHT) + key = KEYC_MOUSEDRAG9_STATUS_RIGHT; + if (where == STATUS_DEFAULT) + key = KEYC_MOUSEDRAG9_STATUS_DEFAULT; + if (where == BORDER) + key = KEYC_MOUSEDRAG9_BORDER; + break; + case MOUSE_BUTTON_10: + if (where == PANE) + key = KEYC_MOUSEDRAG10_PANE; + if (where == STATUS) + key = KEYC_MOUSEDRAG10_STATUS; + if (where == STATUS_LEFT) + key = KEYC_MOUSEDRAG10_STATUS_LEFT; + if (where == STATUS_RIGHT) + key = KEYC_MOUSEDRAG10_STATUS_RIGHT; + if (where == STATUS_DEFAULT) + key = KEYC_MOUSEDRAG10_STATUS_DEFAULT; + if (where == BORDER) + key = KEYC_MOUSEDRAG10_BORDER; + break; + case MOUSE_BUTTON_11: + if (where == PANE) + key = KEYC_MOUSEDRAG11_PANE; + if (where == STATUS) + key = KEYC_MOUSEDRAG11_STATUS; + if (where == STATUS_LEFT) + key = KEYC_MOUSEDRAG11_STATUS_LEFT; + if (where == STATUS_RIGHT) + key = KEYC_MOUSEDRAG11_STATUS_RIGHT; + if (where == STATUS_DEFAULT) + key = KEYC_MOUSEDRAG11_STATUS_DEFAULT; + if (where == BORDER) + key = KEYC_MOUSEDRAG11_BORDER; + break; } } @@ -837,7 +1088,7 @@ have_event: break; case UP: switch (MOUSE_BUTTONS(b)) { - case 0: + case MOUSE_BUTTON_1: if (where == PANE) key = KEYC_MOUSEUP1_PANE; if (where == STATUS) @@ -851,7 +1102,7 @@ have_event: if (where == BORDER) key = KEYC_MOUSEUP1_BORDER; break; - case 1: + case MOUSE_BUTTON_2: if (where == PANE) key = KEYC_MOUSEUP2_PANE; if (where == STATUS) @@ -865,7 +1116,7 @@ have_event: if (where == BORDER) key = KEYC_MOUSEUP2_BORDER; break; - case 2: + case MOUSE_BUTTON_3: if (where == PANE) key = KEYC_MOUSEUP3_PANE; if (where == STATUS) @@ -879,11 +1130,95 @@ have_event: if (where == BORDER) key = KEYC_MOUSEUP3_BORDER; break; + case MOUSE_BUTTON_6: + if (where == PANE) + key = KEYC_MOUSEUP6_PANE; + if (where == STATUS) + key = KEYC_MOUSEUP6_STATUS; + if (where == STATUS_LEFT) + key = KEYC_MOUSEUP6_STATUS_LEFT; + if (where == STATUS_RIGHT) + key = KEYC_MOUSEUP6_STATUS_RIGHT; + if (where == STATUS_DEFAULT) + key = KEYC_MOUSEUP6_STATUS_DEFAULT; + if (where == BORDER) + key = KEYC_MOUSEUP6_BORDER; + break; + case MOUSE_BUTTON_7: + if (where == PANE) + key = KEYC_MOUSEUP7_PANE; + if (where == STATUS) + key = KEYC_MOUSEUP7_STATUS; + if (where == STATUS_LEFT) + key = KEYC_MOUSEUP7_STATUS_LEFT; + if (where == STATUS_RIGHT) + key = KEYC_MOUSEUP7_STATUS_RIGHT; + if (where == STATUS_DEFAULT) + key = KEYC_MOUSEUP7_STATUS_DEFAULT; + if (where == BORDER) + key = KEYC_MOUSEUP7_BORDER; + break; + case MOUSE_BUTTON_8: + if (where == PANE) + key = KEYC_MOUSEUP8_PANE; + if (where == STATUS) + key = KEYC_MOUSEUP8_STATUS; + if (where == STATUS_LEFT) + key = KEYC_MOUSEUP8_STATUS_LEFT; + if (where == STATUS_RIGHT) + key = KEYC_MOUSEUP8_STATUS_RIGHT; + if (where == STATUS_DEFAULT) + key = KEYC_MOUSEUP8_STATUS_DEFAULT; + if (where == BORDER) + key = KEYC_MOUSEUP8_BORDER; + break; + case MOUSE_BUTTON_9: + if (where == PANE) + key = KEYC_MOUSEUP9_PANE; + if (where == STATUS) + key = KEYC_MOUSEUP9_STATUS; + if (where == STATUS_LEFT) + key = KEYC_MOUSEUP9_STATUS_LEFT; + if (where == STATUS_RIGHT) + key = KEYC_MOUSEUP9_STATUS_RIGHT; + if (where == STATUS_DEFAULT) + key = KEYC_MOUSEUP9_STATUS_DEFAULT; + if (where == BORDER) + key = KEYC_MOUSEUP9_BORDER; + break; + case MOUSE_BUTTON_10: + if (where == PANE) + key = KEYC_MOUSEUP1_PANE; + if (where == STATUS) + key = KEYC_MOUSEUP1_STATUS; + if (where == STATUS_LEFT) + key = KEYC_MOUSEUP1_STATUS_LEFT; + if (where == STATUS_RIGHT) + key = KEYC_MOUSEUP1_STATUS_RIGHT; + if (where == STATUS_DEFAULT) + key = KEYC_MOUSEUP1_STATUS_DEFAULT; + if (where == BORDER) + key = KEYC_MOUSEUP1_BORDER; + break; + case MOUSE_BUTTON_11: + if (where == PANE) + key = KEYC_MOUSEUP11_PANE; + if (where == STATUS) + key = KEYC_MOUSEUP11_STATUS; + if (where == STATUS_LEFT) + key = KEYC_MOUSEUP11_STATUS_LEFT; + if (where == STATUS_RIGHT) + key = KEYC_MOUSEUP11_STATUS_RIGHT; + if (where == STATUS_DEFAULT) + key = KEYC_MOUSEUP11_STATUS_DEFAULT; + if (where == BORDER) + key = KEYC_MOUSEUP11_BORDER; + break; } break; case DOWN: switch (MOUSE_BUTTONS(b)) { - case 0: + case MOUSE_BUTTON_1: if (where == PANE) key = KEYC_MOUSEDOWN1_PANE; if (where == STATUS) @@ -897,7 +1232,7 @@ have_event: if (where == BORDER) key = KEYC_MOUSEDOWN1_BORDER; break; - case 1: + case MOUSE_BUTTON_2: if (where == PANE) key = KEYC_MOUSEDOWN2_PANE; if (where == STATUS) @@ -911,7 +1246,7 @@ have_event: if (where == BORDER) key = KEYC_MOUSEDOWN2_BORDER; break; - case 2: + case MOUSE_BUTTON_3: if (where == PANE) key = KEYC_MOUSEDOWN3_PANE; if (where == STATUS) @@ -925,11 +1260,95 @@ have_event: if (where == BORDER) key = KEYC_MOUSEDOWN3_BORDER; break; + case MOUSE_BUTTON_6: + if (where == PANE) + key = KEYC_MOUSEDOWN6_PANE; + if (where == STATUS) + key = KEYC_MOUSEDOWN6_STATUS; + if (where == STATUS_LEFT) + key = KEYC_MOUSEDOWN6_STATUS_LEFT; + if (where == STATUS_RIGHT) + key = KEYC_MOUSEDOWN6_STATUS_RIGHT; + if (where == STATUS_DEFAULT) + key = KEYC_MOUSEDOWN6_STATUS_DEFAULT; + if (where == BORDER) + key = KEYC_MOUSEDOWN6_BORDER; + break; + case MOUSE_BUTTON_7: + if (where == PANE) + key = KEYC_MOUSEDOWN7_PANE; + if (where == STATUS) + key = KEYC_MOUSEDOWN7_STATUS; + if (where == STATUS_LEFT) + key = KEYC_MOUSEDOWN7_STATUS_LEFT; + if (where == STATUS_RIGHT) + key = KEYC_MOUSEDOWN7_STATUS_RIGHT; + if (where == STATUS_DEFAULT) + key = KEYC_MOUSEDOWN7_STATUS_DEFAULT; + if (where == BORDER) + key = KEYC_MOUSEDOWN7_BORDER; + break; + case MOUSE_BUTTON_8: + if (where == PANE) + key = KEYC_MOUSEDOWN8_PANE; + if (where == STATUS) + key = KEYC_MOUSEDOWN8_STATUS; + if (where == STATUS_LEFT) + key = KEYC_MOUSEDOWN8_STATUS_LEFT; + if (where == STATUS_RIGHT) + key = KEYC_MOUSEDOWN8_STATUS_RIGHT; + if (where == STATUS_DEFAULT) + key = KEYC_MOUSEDOWN8_STATUS_DEFAULT; + if (where == BORDER) + key = KEYC_MOUSEDOWN8_BORDER; + break; + case MOUSE_BUTTON_9: + if (where == PANE) + key = KEYC_MOUSEDOWN9_PANE; + if (where == STATUS) + key = KEYC_MOUSEDOWN9_STATUS; + if (where == STATUS_LEFT) + key = KEYC_MOUSEDOWN9_STATUS_LEFT; + if (where == STATUS_RIGHT) + key = KEYC_MOUSEDOWN9_STATUS_RIGHT; + if (where == STATUS_DEFAULT) + key = KEYC_MOUSEDOWN9_STATUS_DEFAULT; + if (where == BORDER) + key = KEYC_MOUSEDOWN9_BORDER; + break; + case MOUSE_BUTTON_10: + if (where == PANE) + key = KEYC_MOUSEDOWN10_PANE; + if (where == STATUS) + key = KEYC_MOUSEDOWN10_STATUS; + if (where == STATUS_LEFT) + key = KEYC_MOUSEDOWN10_STATUS_LEFT; + if (where == STATUS_RIGHT) + key = KEYC_MOUSEDOWN10_STATUS_RIGHT; + if (where == STATUS_DEFAULT) + key = KEYC_MOUSEDOWN10_STATUS_DEFAULT; + if (where == BORDER) + key = KEYC_MOUSEDOWN10_BORDER; + break; + case MOUSE_BUTTON_11: + if (where == PANE) + key = KEYC_MOUSEDOWN11_PANE; + if (where == STATUS) + key = KEYC_MOUSEDOWN11_STATUS; + if (where == STATUS_LEFT) + key = KEYC_MOUSEDOWN11_STATUS_LEFT; + if (where == STATUS_RIGHT) + key = KEYC_MOUSEDOWN11_STATUS_RIGHT; + if (where == STATUS_DEFAULT) + key = KEYC_MOUSEDOWN11_STATUS_DEFAULT; + if (where == BORDER) + key = KEYC_MOUSEDOWN11_BORDER; + break; } break; case SECOND: switch (MOUSE_BUTTONS(b)) { - case 0: + case MOUSE_BUTTON_1: if (where == PANE) key = KEYC_SECONDCLICK1_PANE; if (where == STATUS) @@ -943,7 +1362,7 @@ have_event: if (where == BORDER) key = KEYC_SECONDCLICK1_BORDER; break; - case 1: + case MOUSE_BUTTON_2: if (where == PANE) key = KEYC_SECONDCLICK2_PANE; if (where == STATUS) @@ -957,7 +1376,7 @@ have_event: if (where == BORDER) key = KEYC_SECONDCLICK2_BORDER; break; - case 2: + case MOUSE_BUTTON_3: if (where == PANE) key = KEYC_SECONDCLICK3_PANE; if (where == STATUS) @@ -971,11 +1390,95 @@ have_event: if (where == BORDER) key = KEYC_SECONDCLICK3_BORDER; break; + case MOUSE_BUTTON_6: + if (where == PANE) + key = KEYC_SECONDCLICK6_PANE; + if (where == STATUS) + key = KEYC_SECONDCLICK6_STATUS; + if (where == STATUS_LEFT) + key = KEYC_SECONDCLICK6_STATUS_LEFT; + if (where == STATUS_RIGHT) + key = KEYC_SECONDCLICK6_STATUS_RIGHT; + if (where == STATUS_DEFAULT) + key = KEYC_SECONDCLICK6_STATUS_DEFAULT; + if (where == BORDER) + key = KEYC_SECONDCLICK6_BORDER; + break; + case MOUSE_BUTTON_7: + if (where == PANE) + key = KEYC_SECONDCLICK7_PANE; + if (where == STATUS) + key = KEYC_SECONDCLICK7_STATUS; + if (where == STATUS_LEFT) + key = KEYC_SECONDCLICK7_STATUS_LEFT; + if (where == STATUS_RIGHT) + key = KEYC_SECONDCLICK7_STATUS_RIGHT; + if (where == STATUS_DEFAULT) + key = KEYC_SECONDCLICK7_STATUS_DEFAULT; + if (where == BORDER) + key = KEYC_SECONDCLICK7_BORDER; + break; + case MOUSE_BUTTON_8: + if (where == PANE) + key = KEYC_SECONDCLICK8_PANE; + if (where == STATUS) + key = KEYC_SECONDCLICK8_STATUS; + if (where == STATUS_LEFT) + key = KEYC_SECONDCLICK8_STATUS_LEFT; + if (where == STATUS_RIGHT) + key = KEYC_SECONDCLICK8_STATUS_RIGHT; + if (where == STATUS_DEFAULT) + key = KEYC_SECONDCLICK8_STATUS_DEFAULT; + if (where == BORDER) + key = KEYC_SECONDCLICK8_BORDER; + break; + case MOUSE_BUTTON_9: + if (where == PANE) + key = KEYC_SECONDCLICK9_PANE; + if (where == STATUS) + key = KEYC_SECONDCLICK9_STATUS; + if (where == STATUS_LEFT) + key = KEYC_SECONDCLICK9_STATUS_LEFT; + if (where == STATUS_RIGHT) + key = KEYC_SECONDCLICK9_STATUS_RIGHT; + if (where == STATUS_DEFAULT) + key = KEYC_SECONDCLICK9_STATUS_DEFAULT; + if (where == BORDER) + key = KEYC_SECONDCLICK9_BORDER; + break; + case MOUSE_BUTTON_10: + if (where == PANE) + key = KEYC_SECONDCLICK10_PANE; + if (where == STATUS) + key = KEYC_SECONDCLICK10_STATUS; + if (where == STATUS_LEFT) + key = KEYC_SECONDCLICK10_STATUS_LEFT; + if (where == STATUS_RIGHT) + key = KEYC_SECONDCLICK10_STATUS_RIGHT; + if (where == STATUS_DEFAULT) + key = KEYC_SECONDCLICK10_STATUS_DEFAULT; + if (where == BORDER) + key = KEYC_SECONDCLICK10_BORDER; + break; + case MOUSE_BUTTON_11: + if (where == PANE) + key = KEYC_SECONDCLICK11_PANE; + if (where == STATUS) + key = KEYC_SECONDCLICK11_STATUS; + if (where == STATUS_LEFT) + key = KEYC_SECONDCLICK11_STATUS_LEFT; + if (where == STATUS_RIGHT) + key = KEYC_SECONDCLICK11_STATUS_RIGHT; + if (where == STATUS_DEFAULT) + key = KEYC_SECONDCLICK11_STATUS_DEFAULT; + if (where == BORDER) + key = KEYC_SECONDCLICK11_BORDER; + break; } break; case DOUBLE: switch (MOUSE_BUTTONS(b)) { - case 0: + case MOUSE_BUTTON_1: if (where == PANE) key = KEYC_DOUBLECLICK1_PANE; if (where == STATUS) @@ -989,7 +1492,7 @@ have_event: if (where == BORDER) key = KEYC_DOUBLECLICK1_BORDER; break; - case 1: + case MOUSE_BUTTON_2: if (where == PANE) key = KEYC_DOUBLECLICK2_PANE; if (where == STATUS) @@ -1003,7 +1506,7 @@ have_event: if (where == BORDER) key = KEYC_DOUBLECLICK2_BORDER; break; - case 2: + case MOUSE_BUTTON_3: if (where == PANE) key = KEYC_DOUBLECLICK3_PANE; if (where == STATUS) @@ -1017,11 +1520,95 @@ have_event: if (where == BORDER) key = KEYC_DOUBLECLICK3_BORDER; break; + case MOUSE_BUTTON_6: + if (where == PANE) + key = KEYC_DOUBLECLICK6_PANE; + if (where == STATUS) + key = KEYC_DOUBLECLICK6_STATUS; + if (where == STATUS_LEFT) + key = KEYC_DOUBLECLICK6_STATUS_LEFT; + if (where == STATUS_RIGHT) + key = KEYC_DOUBLECLICK6_STATUS_RIGHT; + if (where == STATUS_DEFAULT) + key = KEYC_DOUBLECLICK6_STATUS_DEFAULT; + if (where == BORDER) + key = KEYC_DOUBLECLICK6_BORDER; + break; + case MOUSE_BUTTON_7: + if (where == PANE) + key = KEYC_DOUBLECLICK7_PANE; + if (where == STATUS) + key = KEYC_DOUBLECLICK7_STATUS; + if (where == STATUS_LEFT) + key = KEYC_DOUBLECLICK7_STATUS_LEFT; + if (where == STATUS_RIGHT) + key = KEYC_DOUBLECLICK7_STATUS_RIGHT; + if (where == STATUS_DEFAULT) + key = KEYC_DOUBLECLICK7_STATUS_DEFAULT; + if (where == BORDER) + key = KEYC_DOUBLECLICK7_BORDER; + break; + case MOUSE_BUTTON_8: + if (where == PANE) + key = KEYC_DOUBLECLICK8_PANE; + if (where == STATUS) + key = KEYC_DOUBLECLICK8_STATUS; + if (where == STATUS_LEFT) + key = KEYC_DOUBLECLICK8_STATUS_LEFT; + if (where == STATUS_RIGHT) + key = KEYC_DOUBLECLICK8_STATUS_RIGHT; + if (where == STATUS_DEFAULT) + key = KEYC_DOUBLECLICK8_STATUS_DEFAULT; + if (where == BORDER) + key = KEYC_DOUBLECLICK8_BORDER; + break; + case MOUSE_BUTTON_9: + if (where == PANE) + key = KEYC_DOUBLECLICK9_PANE; + if (where == STATUS) + key = KEYC_DOUBLECLICK9_STATUS; + if (where == STATUS_LEFT) + key = KEYC_DOUBLECLICK9_STATUS_LEFT; + if (where == STATUS_RIGHT) + key = KEYC_DOUBLECLICK9_STATUS_RIGHT; + if (where == STATUS_DEFAULT) + key = KEYC_DOUBLECLICK9_STATUS_DEFAULT; + if (where == BORDER) + key = KEYC_DOUBLECLICK9_BORDER; + break; + case MOUSE_BUTTON_10: + if (where == PANE) + key = KEYC_DOUBLECLICK10_PANE; + if (where == STATUS) + key = KEYC_DOUBLECLICK10_STATUS; + if (where == STATUS_LEFT) + key = KEYC_DOUBLECLICK10_STATUS_LEFT; + if (where == STATUS_RIGHT) + key = KEYC_DOUBLECLICK10_STATUS_RIGHT; + if (where == STATUS_DEFAULT) + key = KEYC_DOUBLECLICK10_STATUS_DEFAULT; + if (where == BORDER) + key = KEYC_DOUBLECLICK10_BORDER; + break; + case MOUSE_BUTTON_11: + if (where == PANE) + key = KEYC_DOUBLECLICK11_PANE; + if (where == STATUS) + key = KEYC_DOUBLECLICK11_STATUS; + if (where == STATUS_LEFT) + key = KEYC_DOUBLECLICK11_STATUS_LEFT; + if (where == STATUS_RIGHT) + key = KEYC_DOUBLECLICK11_STATUS_RIGHT; + if (where == STATUS_DEFAULT) + key = KEYC_DOUBLECLICK11_STATUS_DEFAULT; + if (where == BORDER) + key = KEYC_DOUBLECLICK11_BORDER; + break; } break; case TRIPLE: switch (MOUSE_BUTTONS(b)) { - case 0: + case MOUSE_BUTTON_1: if (where == PANE) key = KEYC_TRIPLECLICK1_PANE; if (where == STATUS) @@ -1035,7 +1622,7 @@ have_event: if (where == BORDER) key = KEYC_TRIPLECLICK1_BORDER; break; - case 1: + case MOUSE_BUTTON_2: if (where == PANE) key = KEYC_TRIPLECLICK2_PANE; if (where == STATUS) @@ -1049,7 +1636,7 @@ have_event: if (where == BORDER) key = KEYC_TRIPLECLICK2_BORDER; break; - case 2: + case MOUSE_BUTTON_3: if (where == PANE) key = KEYC_TRIPLECLICK3_PANE; if (where == STATUS) @@ -1063,6 +1650,90 @@ have_event: if (where == BORDER) key = KEYC_TRIPLECLICK3_BORDER; break; + case MOUSE_BUTTON_6: + if (where == PANE) + key = KEYC_TRIPLECLICK6_PANE; + if (where == STATUS) + key = KEYC_TRIPLECLICK6_STATUS; + if (where == STATUS_LEFT) + key = KEYC_TRIPLECLICK6_STATUS_LEFT; + if (where == STATUS_RIGHT) + key = KEYC_TRIPLECLICK6_STATUS_RIGHT; + if (where == STATUS_DEFAULT) + key = KEYC_TRIPLECLICK6_STATUS_DEFAULT; + if (where == BORDER) + key = KEYC_TRIPLECLICK6_BORDER; + break; + case MOUSE_BUTTON_7: + if (where == PANE) + key = KEYC_TRIPLECLICK7_PANE; + if (where == STATUS) + key = KEYC_TRIPLECLICK7_STATUS; + if (where == STATUS_LEFT) + key = KEYC_TRIPLECLICK7_STATUS_LEFT; + if (where == STATUS_RIGHT) + key = KEYC_TRIPLECLICK7_STATUS_RIGHT; + if (where == STATUS_DEFAULT) + key = KEYC_TRIPLECLICK7_STATUS_DEFAULT; + if (where == BORDER) + key = KEYC_TRIPLECLICK7_BORDER; + break; + case MOUSE_BUTTON_8: + if (where == PANE) + key = KEYC_TRIPLECLICK8_PANE; + if (where == STATUS) + key = KEYC_TRIPLECLICK8_STATUS; + if (where == STATUS_LEFT) + key = KEYC_TRIPLECLICK8_STATUS_LEFT; + if (where == STATUS_RIGHT) + key = KEYC_TRIPLECLICK8_STATUS_RIGHT; + if (where == STATUS_DEFAULT) + key = KEYC_TRIPLECLICK8_STATUS_DEFAULT; + if (where == BORDER) + key = KEYC_TRIPLECLICK8_BORDER; + break; + case MOUSE_BUTTON_9: + if (where == PANE) + key = KEYC_TRIPLECLICK9_PANE; + if (where == STATUS) + key = KEYC_TRIPLECLICK9_STATUS; + if (where == STATUS_LEFT) + key = KEYC_TRIPLECLICK9_STATUS_LEFT; + if (where == STATUS_RIGHT) + key = KEYC_TRIPLECLICK9_STATUS_RIGHT; + if (where == STATUS_DEFAULT) + key = KEYC_TRIPLECLICK9_STATUS_DEFAULT; + if (where == BORDER) + key = KEYC_TRIPLECLICK9_BORDER; + break; + case MOUSE_BUTTON_10: + if (where == PANE) + key = KEYC_TRIPLECLICK10_PANE; + if (where == STATUS) + key = KEYC_TRIPLECLICK10_STATUS; + if (where == STATUS_LEFT) + key = KEYC_TRIPLECLICK10_STATUS_LEFT; + if (where == STATUS_RIGHT) + key = KEYC_TRIPLECLICK10_STATUS_RIGHT; + if (where == STATUS_DEFAULT) + key = KEYC_TRIPLECLICK10_STATUS_DEFAULT; + if (where == BORDER) + key = KEYC_TRIPLECLICK10_BORDER; + break; + case MOUSE_BUTTON_11: + if (where == PANE) + key = KEYC_TRIPLECLICK11_PANE; + if (where == STATUS) + key = KEYC_TRIPLECLICK11_STATUS; + if (where == STATUS_LEFT) + key = KEYC_TRIPLECLICK11_STATUS_LEFT; + if (where == STATUS_RIGHT) + key = KEYC_TRIPLECLICK11_STATUS_RIGHT; + if (where == STATUS_DEFAULT) + key = KEYC_TRIPLECLICK11_STATUS_DEFAULT; + if (where == BORDER) + key = KEYC_TRIPLECLICK11_BORDER; + break; } break; } @@ -1123,6 +1794,8 @@ server_client_update_latest(struct client *c) if (options_get_number(w->options, "window-size") == WINDOW_SIZE_LATEST) recalculate_size(w, 0); + + notify_client("client-active", c); } /* @@ -1351,7 +2024,7 @@ server_client_handle_key(struct client *c, struct key_event *event) status_message_clear(c); } if (c->overlay_key != NULL) { - switch (c->overlay_key(c, event)) { + switch (c->overlay_key(c, c->overlay_data, event)) { case 0: return (0); case 1: @@ -1382,7 +2055,6 @@ server_client_loop(void) struct client *c; struct window *w; struct window_pane *wp; - int focus; /* Check for window resize. This is done before redrawing. */ RB_FOREACH(w, windows, &windows) @@ -1400,14 +2072,11 @@ server_client_loop(void) /* * Any windows will have been redrawn as part of clients, so clear - * their flags now. Also check pane focus and resize. + * their flags now. */ - focus = options_get_number(global_options, "focus-events"); RB_FOREACH(w, windows, &windows) { TAILQ_FOREACH(wp, &w->panes, entry) { if (wp->fd != -1) { - if (focus) - server_client_check_pane_focus(wp); server_client_check_pane_resize(wp); server_client_check_pane_buffer(wp); } @@ -1519,7 +2188,6 @@ server_client_check_pane_resize(struct window_pane *wp) evtimer_add(&wp->resize_timer, &tv); } - /* Check pane buffer size. */ static void server_client_check_pane_buffer(struct window_pane *wp) @@ -1608,54 +2276,6 @@ out: bufferevent_enable(wp->event, EV_READ); } -/* Check whether pane should be focused. */ -static void -server_client_check_pane_focus(struct window_pane *wp) -{ - struct client *c; - int push; - - /* Do we need to push the focus state? */ - push = wp->flags & PANE_FOCUSPUSH; - wp->flags &= ~PANE_FOCUSPUSH; - - /* If we're not the active pane in our window, we're not focused. */ - if (wp->window->active != wp) - goto not_focused; - - /* - * If our window is the current window in any focused clients with an - * attached session, we're focused. - */ - TAILQ_FOREACH(c, &clients, entry) { - if (c->session == NULL || !(c->flags & CLIENT_FOCUSED)) - continue; - if (c->session->attached == 0) - continue; - - if (c->session->curw->window == wp->window) - goto focused; - } - -not_focused: - if (push || (wp->flags & PANE_FOCUSED)) { - if (wp->base.mode & MODE_FOCUSON) - bufferevent_write(wp->event, "\033[O", 3); - notify_pane("pane-focus-out", wp); - } - wp->flags &= ~PANE_FOCUSED; - return; - -focused: - if (push || !(wp->flags & PANE_FOCUSED)) { - if (wp->base.mode & MODE_FOCUSON) - bufferevent_write(wp->event, "\033[I", 3); - notify_pane("pane-focus-in", wp); - session_update_activity(c->session, NULL); - } - wp->flags |= PANE_FOCUSED; -} - /* * Update cursor position and mode settings. The scroll region and attributes * are cleared when idle (waiting for an event) as this is the most likely time @@ -1673,7 +2293,7 @@ server_client_reset_state(struct client *c) struct window_pane *wp = server_client_get_pane(c), *loop; struct screen *s = NULL; struct options *oo = c->session->options; - int mode = 0, cursor, flags; + int mode = 0, cursor, flags, n; u_int cx = 0, cy = 0, ox, oy, sx, sy; if (c->flags & (CLIENT_CONTROL|CLIENT_SUSPENDED)) @@ -1686,19 +2306,35 @@ server_client_reset_state(struct client *c) /* Get mode from overlay if any, else from screen. */ if (c->overlay_draw != NULL) { if (c->overlay_mode != NULL) - s = c->overlay_mode(c, &cx, &cy); + s = c->overlay_mode(c, c->overlay_data, &cx, &cy); } else s = wp->screen; if (s != NULL) mode = s->mode; - log_debug("%s: client %s mode %x", __func__, c->name, mode); + if (log_get_level() != 0) { + log_debug("%s: client %s mode %s", __func__, c->name, + screen_mode_to_string(mode)); + } /* Reset region and margin. */ tty_region_off(tty); tty_margin_off(tty); /* Move cursor to pane cursor and offset. */ - if (c->overlay_draw == NULL) { + if (c->prompt_string != NULL) { + n = options_get_number(c->session->options, "status-position"); + if (n == 0) + cy = 0; + else { + n = status_line_size(c); + if (n == 0) + cy = tty->sy - 1; + else + cy = tty->sy - n; + } + cx = c->prompt_cursor; + mode &= ~MODE_CURSOR; + } else if (c->overlay_draw == NULL) { cursor = 0; tty_window_offset(tty, &ox, &oy, &sx, &sy); if (wp->xoff + s->cx >= ox && wp->xoff + s->cx <= ox + sx && @@ -1965,8 +2601,10 @@ server_client_check_redraw(struct client *c) } if (c->flags & CLIENT_ALLREDRAWFLAGS) { - if (options_get_number(s->options, "set-titles")) + if (options_get_number(s->options, "set-titles")) { server_client_set_title(c); + server_client_set_path(c); + } screen_redraw_screen(c); } @@ -2012,6 +2650,26 @@ server_client_set_title(struct client *c) format_free(ft); } +/* Set client path. */ +static void +server_client_set_path(struct client *c) +{ + struct session *s = c->session; + const char *path; + + if (s->curw == NULL) + return; + if (s->curw->window->active->base.path == NULL) + path = ""; + else + path = s->curw->window->active->base.path; + if (c->path == NULL || strcmp(path, c->path) != 0) { + free(c->path); + c->path = xstrdup(path); + tty_set_path(&c->tty, c->path); + } +} + /* Dispatch message from client. */ static void server_client_dispatch(struct imsg *imsg, void *arg) @@ -2055,9 +2713,12 @@ server_client_dispatch(struct imsg *imsg, void *arg) if (c->flags & CLIENT_CONTROL) break; server_client_update_latest(c); - server_client_clear_overlay(c); tty_resize(&c->tty); recalculate_sizes(); + if (c->overlay_resize == NULL) + server_client_clear_overlay(c); + else + c->overlay_resize(c, c->overlay_data); server_redraw_client(c); if (c->session != NULL) notify_client("client-resized", c); @@ -2065,7 +2726,8 @@ server_client_dispatch(struct imsg *imsg, void *arg) case MSG_EXITING: if (datalen != 0) fatalx("bad MSG_EXITING size"); - c->session = NULL; + server_client_set_session(c, NULL); + recalculate_sizes(); tty_close(&c->tty); proc_send(c->peer, MSG_EXITED, -1, NULL, 0); break; @@ -2110,6 +2772,14 @@ server_client_dispatch(struct imsg *imsg, void *arg) } } +/* Callback when command is not allowed. */ +static enum cmd_retval +server_client_read_only(struct cmdq_item *item, __unused void *data) +{ + cmdq_error(item, "client is read-only"); + return (CMD_RETURN_ERROR); +} + /* Callback when command is done. */ static enum cmd_retval server_client_command_done(struct cmdq_item *item, __unused void *data) @@ -2133,6 +2803,8 @@ server_client_dispatch_command(struct client *c, struct imsg *imsg) int argc; char **argv, *cause; struct cmd_parse_result *pr; + struct args_value *values; + struct cmdq_item *new_item; if (c->flags & CLIENT_EXIT) return; @@ -2158,20 +2830,25 @@ server_client_dispatch_command(struct client *c, struct imsg *imsg) *argv = xstrdup("new-session"); } - pr = cmd_parse_from_arguments(argc, argv, NULL); + values = args_from_vector(argc, argv); + pr = cmd_parse_from_arguments(values, argc, NULL); switch (pr->status) { - case CMD_PARSE_EMPTY: - cause = xstrdup("empty command"); - goto error; case CMD_PARSE_ERROR: cause = pr->error; goto error; case CMD_PARSE_SUCCESS: break; } + args_free_values(values, argc); + free(values); cmd_free_argv(argc, argv); - cmdq_append(c, cmdq_get_command(pr->cmdlist, NULL)); + if ((c->flags & CLIENT_READONLY) && + !cmd_list_all_have(pr->cmdlist, CMD_READONLY)) + new_item = cmdq_get_callback(server_client_read_only, NULL); + else + new_item = cmdq_get_command(pr->cmdlist, NULL); + cmdq_append(c, new_item); cmdq_append(c, cmdq_get_callback(server_client_command_done, NULL)); cmd_list_free(pr->cmdlist); @@ -2389,7 +3066,7 @@ server_client_set_flags(struct client *c, const char *flags) uint64_t flag; int not; - s = copy = xstrdup (flags); + s = copy = xstrdup(flags); while ((next = strsep(&s, ",")) != NULL) { not = (*next == '!'); if (not) @@ -2409,9 +3086,11 @@ server_client_set_flags(struct client *c, const char *flags) continue; log_debug("client %s set flag %s", c->name, next); - if (not) + if (not) { + if (c->flags & CLIENT_READONLY) + flag &= ~CLIENT_READONLY; c->flags &= ~flag; - else + } else c->flags |= flag; if (flag == CLIENT_CONTROL_NOOUTPUT) control_reset_offsets(c); @@ -2459,7 +3138,7 @@ server_client_get_flags(struct client *c) } /* Get client window. */ -static struct client_window * +struct client_window * server_client_get_client_window(struct client *c, u_int id) { struct client_window cw = { .window = id }; @@ -2467,6 +3146,21 @@ server_client_get_client_window(struct client *c, u_int id) return (RB_FIND(client_windows, &c->windows, &cw)); } +/* Add client window. */ +struct client_window * +server_client_add_client_window(struct client *c, u_int id) +{ + struct client_window *cw; + + cw = server_client_get_client_window(c, id); + if (cw == NULL) { + cw = xcalloc(1, sizeof *cw); + cw->window = id; + RB_INSERT(client_windows, &c->windows, cw); + } + return (cw); +} + /* Get client active pane. */ struct window_pane * server_client_get_pane(struct client *c) @@ -2495,12 +3189,7 @@ server_client_set_pane(struct client *c, struct window_pane *wp) if (s == NULL) return; - cw = server_client_get_client_window(c, s->curw->window->id); - if (cw == NULL) { - cw = xcalloc(1, sizeof *cw); - cw->window = s->curw->window->id; - RB_INSERT(client_windows, &c->windows, cw); - } + cw = server_client_add_client_window(c, s->curw->window->id); cw->pane = wp; log_debug("%s pane now %%%u", c->name, wp->id); } diff --git a/external/bsd/tmux/dist/server-fn.c b/external/bsd/tmux/dist/server-fn.c index 656de08ecc9..2a79f3e3d76 100644 --- a/external/bsd/tmux/dist/server-fn.c +++ b/external/bsd/tmux/dist/server-fn.c @@ -310,9 +310,11 @@ server_destroy_pane(struct window_pane *wp, int notify) struct window *w = wp->window; struct screen_write_ctx ctx; struct grid_cell gc; - time_t t; - char tim[26]; int remain_on_exit; + const char *s; + char *expanded; + u_int sx = screen_size_x(&wp->base); + u_int sy = screen_size_y(&wp->base); if (wp->fd != -1) { #ifdef HAVE_UTEMPTER @@ -339,32 +341,26 @@ server_destroy_pane(struct window_pane *wp, int notify) return; wp->flags |= PANE_STATUSDRAWN; + gettimeofday(&wp->dead_time, NULL); if (notify) notify_pane("pane-died", wp); - screen_write_start_pane(&ctx, wp, &wp->base); - screen_write_scrollregion(&ctx, 0, screen_size_y(ctx.s) - 1); - screen_write_cursormove(&ctx, 0, screen_size_y(ctx.s) - 1, 0); - screen_write_linefeed(&ctx, 1, 8); - memcpy(&gc, &grid_default_cell, sizeof gc); - - time(&t); - ctime_r(&t, tim); - tim[strcspn(tim, "\n")] = '\0'; - - if (WIFEXITED(wp->status)) { - screen_write_nputs(&ctx, -1, &gc, - "Pane is dead (status %d, %s)", - WEXITSTATUS(wp->status), - tim); - } else if (WIFSIGNALED(wp->status)) { - screen_write_nputs(&ctx, -1, &gc, - "Pane is dead (signal %s, %s)", - sig2name(WTERMSIG(wp->status)), - tim); + s = options_get_string(wp->options, "remain-on-exit-format"); + if (*s != '\0') { + screen_write_start_pane(&ctx, wp, &wp->base); + screen_write_scrollregion(&ctx, 0, sy - 1); + screen_write_cursormove(&ctx, 0, sy - 1, 0); + screen_write_linefeed(&ctx, 1, 8); + memcpy(&gc, &grid_default_cell, sizeof gc); + + expanded = format_single(NULL, s, NULL, NULL, NULL, wp); + format_draw(&ctx, &gc, sx, expanded, NULL, 0); + free(expanded); + + screen_write_stop(&ctx); } + wp->base.mode &= ~MODE_CURSOR; - screen_write_stop(&ctx); wp->flags |= PANE_REDRAW; return; } @@ -446,21 +442,9 @@ server_destroy_session(struct session *s) TAILQ_FOREACH(c, &clients, entry) { if (c->session != s) continue; - if (s_new == NULL) { - c->session = NULL; + server_client_set_session(c, s_new); + if (s_new == NULL) c->flags |= CLIENT_EXIT; - } else { - c->last_session = NULL; - c->session = s_new; - server_client_set_key_table(c, NULL); - tty_update_client_offset(c); - status_timer_start(c); - notify_client("client-session-changed", c); - session_update_activity(s_new, NULL); - gettimeofday(&s_new->last_attached_time, NULL); - server_redraw_client(c); - alerts_check_session(s_new); - } } recalculate_sizes(); } diff --git a/external/bsd/tmux/dist/server.c b/external/bsd/tmux/dist/server.c index f7963fb5df5..0deb6cd2e7a 100644 --- a/external/bsd/tmux/dist/server.c +++ b/external/bsd/tmux/dist/server.c @@ -100,7 +100,7 @@ server_check_marked(void) } /* Create server socket. */ -static int +int server_create_socket(int flags, char **cause) { struct sockaddr_un sa; @@ -213,7 +213,11 @@ server_start(struct tmuxproc *client, int flags, struct event_base *base, gettimeofday(&start_time, NULL); +#ifdef HAVE_SYSTEMD + server_fd = systemd_create_socket(flags, &cause); +#else server_fd = server_create_socket(flags, &cause); +#endif if (server_fd != -1) server_update_socket(); if (~flags & CLIENT_NOFORK) @@ -229,15 +233,19 @@ server_start(struct tmuxproc *client, int flags, struct event_base *base, if (cause != NULL) { if (c != NULL) { - cmdq_append(c, cmdq_get_error(cause)); + c->exit_message = cause; c->flags |= CLIENT_EXIT; + } else { + fprintf(stderr, "%s\n", cause); + exit(1); } - free(cause); } evtimer_set(&server_ev_tidy, server_tidy_event, NULL); evtimer_add(&server_ev_tidy, &tv); + server_acl_init(); + server_add_accept(0); proc_loop(server_proc, server_loop); @@ -354,9 +362,10 @@ server_update_socket(void) static void server_accept(int fd, short events, __unused void *data) { - struct sockaddr_storage sa; - socklen_t slen = sizeof sa; - int newfd; + struct sockaddr_storage sa; + socklen_t slen = sizeof sa; + int newfd; + struct client *c; server_add_accept(0); if (!(events & EV_READ)) @@ -373,11 +382,16 @@ server_accept(int fd, short events, __unused void *data) } fatal("accept failed"); } + if (server_exit) { close(newfd); return; } - server_client_create(newfd); + c = server_client_create(newfd); + if (!server_acl_join(c)) { + c->exit_message = xstrdup("access not allowed"); + c->flags |= CLIENT_EXIT; + } } /* diff --git a/external/bsd/tmux/dist/session.c b/external/bsd/tmux/dist/session.c index d40277798f5..9fdaf328597 100644 --- a/external/bsd/tmux/dist/session.c +++ b/external/bsd/tmux/dist/session.c @@ -27,7 +27,7 @@ #include "tmux.h" struct sessions sessions; -static u_int next_session_id; +u_int next_session_id; struct session_groups session_groups = RB_INITIALIZER(&session_groups); static void session_free(int, short, void *); @@ -203,6 +203,9 @@ session_destroy(struct session *s, int notify, const char *from) struct winlink *wl; log_debug("session %s destroyed (%s)", s->name, from); + + if (s->curw == NULL) + return; s->curw = NULL; RB_REMOVE(sessions, &sessions, s); @@ -235,6 +238,8 @@ session_check_name(const char *name) { char *copy, *cp, *new_name; + if (*name == '\0') + return (NULL); copy = xstrdup(name); for (cp = copy; *cp != '\0'; cp++) { if (*cp == ':' || *cp == '.') @@ -485,6 +490,8 @@ session_last(struct session *s) int session_set_current(struct session *s, struct winlink *wl) { + struct winlink *old = s->curw; + if (wl == NULL) return (-1); if (wl == s->curw) @@ -493,6 +500,11 @@ session_set_current(struct session *s, struct winlink *wl) winlink_stack_remove(&s->lastw, wl); winlink_stack_push(&s->lastw, s->curw); s->curw = wl; + if (options_get_number(global_options, "focus-events")) { + if (old != NULL) + window_update_focus(old->window); + window_update_focus(wl->window); + } winlink_clear_flags(wl); window_update_activity(wl->window); tty_update_window_offset(wl->window); diff --git a/external/bsd/tmux/dist/spawn.c b/external/bsd/tmux/dist/spawn.c index 065b3e5e004..283ab80c64f 100644 --- a/external/bsd/tmux/dist/spawn.c +++ b/external/bsd/tmux/dist/spawn.c @@ -177,6 +177,7 @@ spawn_window(struct spawn_context *sc, char **cause) /* Set the name of the new window. */ if (~sc->flags & SPAWN_RESPAWN) { + free(w->name); if (sc->name != NULL) { w->name = format_single(item, sc->name, c, s, NULL, NULL); @@ -208,7 +209,7 @@ spawn_pane(struct spawn_context *sc, char **cause) struct window_pane *new_wp; struct environ *child; struct environ_entry *ee; - char **argv, *cp, **argvp, *argv0, *cwd; + char **argv, *cp, **argvp, *argv0, *cwd, *new_cwd; const char *cmd, *tmp; int argc; u_int idx; @@ -224,9 +225,15 @@ spawn_pane(struct spawn_context *sc, char **cause) * Work out the current working directory. If respawning, use * the pane's stored one unless specified. */ - if (sc->cwd != NULL) + if (sc->cwd != NULL) { cwd = format_single(item, sc->cwd, c, target->s, NULL, NULL); - else if (~sc->flags & SPAWN_RESPAWN) + if (*cwd != '/') { + xasprintf(&new_cwd, "%s/%s", server_client_get_cwd(c, + target->s), cwd); + free(cwd); + cwd = new_cwd; + } + } else if (~sc->flags & SPAWN_RESPAWN) cwd = xstrdup(server_client_get_cwd(c, target->s)); else cwd = NULL; @@ -334,8 +341,7 @@ spawn_pane(struct spawn_context *sc, char **cause) log_debug("%s: cmd=%s", __func__, cp); free(cp); } - if (cwd != NULL) - log_debug("%s: cwd=%s", __func__, cwd); + log_debug("%s: cwd=%s", __func__, new_wp->cwd); cmd_log_argv(new_wp->argc, new_wp->argv, "%s", __func__); environ_log(child, "%s: environment ", __func__); @@ -381,9 +387,13 @@ spawn_pane(struct spawn_context *sc, char **cause) * Child process. Change to the working directory or home if that * fails. */ - if (chdir(new_wp->cwd) != 0 && - ((tmp = find_home()) == NULL || chdir(tmp) != 0) && - chdir("/") != 0) + if (chdir(new_wp->cwd) == 0) + environ_set(child, "PWD", 0, "%s", new_wp->cwd); + else if ((tmp = find_home()) != NULL || chdir(tmp) == 0) + environ_set(child, "PWD", 0, "%s", tmp); + else if (chdir("/") == 0) + environ_set(child, "PWD", 0, "/"); + else fatal("chdir failed"); /* diff --git a/external/bsd/tmux/dist/status.c b/external/bsd/tmux/dist/status.c index 7566b98e5a1..97de8ea3501 100644 --- a/external/bsd/tmux/dist/status.c +++ b/external/bsd/tmux/dist/status.c @@ -33,9 +33,9 @@ static void status_message_callback(int, short, void *); static void status_timer_callback(int, short, void *); static char *status_prompt_find_history_file(void); -static const char *status_prompt_up_history(u_int *); -static const char *status_prompt_down_history(u_int *); -static void status_prompt_add_history(const char *); +static const char *status_prompt_up_history(u_int *, u_int); +static const char *status_prompt_down_history(u_int *, u_int); +static void status_prompt_add_history(const char *, u_int); static char *status_prompt_complete(struct client *, const char *, u_int); static char *status_prompt_complete_window_menu(struct client *, @@ -49,10 +49,16 @@ struct status_prompt_menu { char flag; }; +static const char *prompt_type_strings[] = { + "command", + "search", + "target", + "window-target" +}; + /* Status prompt history. */ -#define PROMPT_HISTORY 100 -static char **status_prompt_hlist; -static u_int status_prompt_hsize; +char **status_prompt_hlist[PROMPT_NTYPES]; +u_int status_prompt_hsize[PROMPT_NTYPES]; /* Find the history file to load/save from/to. */ static char * @@ -75,6 +81,28 @@ status_prompt_find_history_file(void) return (path); } +/* Add loaded history item to the appropriate list. */ +static void +status_prompt_add_typed_history(char *line) +{ + char *typestr; + enum prompt_type type = PROMPT_TYPE_INVALID; + + typestr = strsep(&line, ":"); + if (line != NULL) + type = status_prompt_type(typestr); + if (type == PROMPT_TYPE_INVALID) { + /* + * Invalid types are not expected, but this provides backward + * compatibility with old history files. + */ + if (line != NULL) + *(--line) = ':'; + status_prompt_add_history(typestr, PROMPT_TYPE_COMMAND); + } else + status_prompt_add_history(line, type); +} + /* Load status prompt history from file. */ void status_prompt_load_history(void) @@ -102,12 +130,12 @@ status_prompt_load_history(void) if (length > 0) { if (line[length - 1] == '\n') { line[length - 1] = '\0'; - status_prompt_add_history(line); + status_prompt_add_typed_history(line); } else { tmp = xmalloc(length + 1); memcpy(tmp, line, length); tmp[length] = '\0'; - status_prompt_add_history(tmp); + status_prompt_add_typed_history(tmp); free(tmp); } } @@ -120,7 +148,7 @@ void status_prompt_save_history(void) { FILE *f; - u_int i; + u_int i, type; char *history_file; if ((history_file = status_prompt_find_history_file()) == NULL) @@ -135,9 +163,13 @@ status_prompt_save_history(void) } free(history_file); - for (i = 0; i < status_prompt_hsize; i++) { - fputs(status_prompt_hlist[i], f); - fputc('\n', f); + for (type = 0; type < PROMPT_NTYPES; type++) { + for (i = 0; i < status_prompt_hsize[type]; i++) { + fputs(prompt_type_strings[type], f); + fputc(':', f); + fputs(status_prompt_hlist[type][i], f); + fputc('\n', f); + } } fclose(f); @@ -358,10 +390,10 @@ status_redraw(struct client *c) /* Set up default colour. */ style_apply(&gc, s->options, "status-style", ft); fg = options_get_number(s->options, "status-fg"); - if (fg != 8) + if (!COLOUR_DEFAULT(fg)) gc.fg = fg; bg = options_get_number(s->options, "status-bg"); - if (bg != 8) + if (!COLOUR_DEFAULT(bg)) gc.bg = bg; if (!grid_cells_equal(&gc, &sl->style)) { force = 1; @@ -407,7 +439,8 @@ status_redraw(struct client *c) screen_write_cursormove(&ctx, 0, i, 0); status_free_ranges(&sle->ranges); - format_draw(&ctx, &gc, width, expanded, &sle->ranges); + format_draw(&ctx, &gc, width, expanded, &sle->ranges, + 0); free(sle->expanded); sle->expanded = expanded; @@ -530,7 +563,7 @@ status_message_redraw(struct client *c) if (c->message_ignore_styles) screen_write_nputs(&ctx, len, &gc, "%s", c->message_string); else - format_draw(&ctx, &gc, c->tty.sx, c->message_string, NULL); + format_draw(&ctx, &gc, c->tty.sx, c->message_string, NULL, 0); screen_write_stop(&ctx); if (grid_compare(sl->active->grid, old_screen.grid) == 0) { @@ -545,7 +578,7 @@ status_message_redraw(struct client *c) void status_prompt_set(struct client *c, struct cmd_find_state *fs, const char *msg, const char *input, prompt_input_cb inputcb, - prompt_free_cb freecb, void *data, int flags) + prompt_free_cb freecb, void *data, int flags, enum prompt_type prompt_type) { struct format_tree *ft; char *tmp; @@ -581,9 +614,10 @@ status_prompt_set(struct client *c, struct cmd_find_state *fs, c->prompt_freecb = freecb; c->prompt_data = data; - c->prompt_hindex = 0; + memset(c->prompt_hindex, 0, sizeof c->prompt_hindex); c->prompt_flags = flags; + c->prompt_type = prompt_type; c->prompt_mode = PROMPT_ENTRY; if (~flags & PROMPT_INCREMENTAL) @@ -644,7 +678,7 @@ status_prompt_update(struct client *c, const char *msg, const char *input) c->prompt_buffer = utf8_fromcstr(tmp); c->prompt_index = utf8_strlen(c->prompt_buffer); - c->prompt_hindex = 0; + memset(c->prompt_hindex, 0, sizeof c->prompt_hindex); c->flags |= CLIENT_REDRAWSTATUS; @@ -684,7 +718,7 @@ status_prompt_redraw(struct client *c) memcpy(&cursorgc, &gc, sizeof cursorgc); cursorgc.attr ^= GRID_ATTR_REVERSE; - start = screen_write_strlen("%s", c->prompt_string); + start = format_width(c->prompt_string); if (start > c->tty.sx) start = c->tty.sx; @@ -694,7 +728,7 @@ status_prompt_redraw(struct client *c) for (offset = 0; offset < c->tty.sx; offset++) screen_write_putc(&ctx, &gc, ' '); screen_write_cursormove(&ctx, 0, lines - 1, 0); - screen_write_nputs(&ctx, start, &gc, "%s", c->prompt_string); + format_draw(&ctx, &gc, start, c->prompt_string, NULL, 0); screen_write_cursormove(&ctx, start, lines - 1, 0); left = c->tty.sx - start; @@ -714,6 +748,7 @@ status_prompt_redraw(struct client *c) offset = 0; if (pwidth > left) pwidth = left; + c->prompt_cursor = start + c->prompt_index - offset; width = 0; for (i = 0; c->prompt_buffer[i].size != 0; i++) { @@ -768,7 +803,7 @@ status_prompt_space(const struct utf8_data *ud) } /* - * Translate key from emacs to vi. Return 0 to drop key, 1 to process the key + * Translate key from vi to emacs. Return 0 to drop key, 1 to process the key * as an emacs key; return 2 to append to the buffer. */ static int @@ -776,14 +811,23 @@ status_prompt_translate_key(struct client *c, key_code key, key_code *new_key) { if (c->prompt_mode == PROMPT_ENTRY) { switch (key) { + case '\001': /* C-a */ case '\003': /* C-c */ + case '\005': /* C-e */ case '\007': /* C-g */ case '\010': /* C-h */ case '\011': /* Tab */ + case '\013': /* C-k */ + case '\016': /* C-n */ + case '\020': /* C-p */ + case '\024': /* C-t */ case '\025': /* C-u */ case '\027': /* C-w */ + case '\031': /* C-y */ case '\n': case '\r': + case KEYC_LEFT|KEYC_CTRL: + case KEYC_RIGHT|KEYC_CTRL: case KEYC_BSPACE: case KEYC_DC: case KEYC_DOWN: @@ -804,6 +848,9 @@ status_prompt_translate_key(struct client *c, key_code key, key_code *new_key) } switch (key) { + case KEYC_BSPACE: + *new_key = KEYC_LEFT; + return (1); case 'A': case 'I': case 'C': @@ -843,17 +890,25 @@ status_prompt_translate_key(struct client *c, key_code key, key_code *new_key) *new_key = KEYC_BSPACE; return (1); case 'b': - case 'B': *new_key = 'b'|KEYC_META; return (1); + case 'B': + *new_key = 'B'|KEYC_VI; + return (1); case 'd': - *new_key = '\025'; + *new_key = '\025'; /* C-u */ return (1); case 'e': + *new_key = 'e'|KEYC_VI; + return (1); case 'E': + *new_key = 'E'|KEYC_VI; + return (1); case 'w': + *new_key = 'w'|KEYC_VI; + return (1); case 'W': - *new_key = 'f'|KEYC_META; + *new_key = 'W'|KEYC_VI; return (1); case 'p': *new_key = '\031'; /* C-y */ @@ -1028,16 +1083,125 @@ status_prompt_replace_complete(struct client *c, const char *s) return (1); } +/* Prompt forward to the next beginning of a word. */ +static void +status_prompt_forward_word(struct client *c, size_t size, int vi, + const char *separators) +{ + size_t idx = c->prompt_index; + int word_is_separators; + + /* In emacs mode, skip until the first non-whitespace character. */ + if (!vi) + while (idx != size && + status_prompt_space(&c->prompt_buffer[idx])) + idx++; + + /* Can't move forward if we're already at the end. */ + if (idx == size) { + c->prompt_index = idx; + return; + } + + /* Determine the current character class (separators or not). */ + word_is_separators = status_prompt_in_list(separators, + &c->prompt_buffer[idx]) && + !status_prompt_space(&c->prompt_buffer[idx]); + + /* Skip ahead until the first space or opposite character class. */ + do { + idx++; + if (status_prompt_space(&c->prompt_buffer[idx])) { + /* In vi mode, go to the start of the next word. */ + if (vi) + while (idx != size && + status_prompt_space(&c->prompt_buffer[idx])) + idx++; + break; + } + } while (idx != size && word_is_separators == status_prompt_in_list( + separators, &c->prompt_buffer[idx])); + + c->prompt_index = idx; +} + +/* Prompt forward to the next end of a word. */ +static void +status_prompt_end_word(struct client *c, size_t size, const char *separators) +{ + size_t idx = c->prompt_index; + int word_is_separators; + + /* Can't move forward if we're already at the end. */ + if (idx == size) + return; + + /* Find the next word. */ + do { + idx++; + if (idx == size) { + c->prompt_index = idx; + return; + } + } while (status_prompt_space(&c->prompt_buffer[idx])); + + /* Determine the character class (separators or not). */ + word_is_separators = status_prompt_in_list(separators, + &c->prompt_buffer[idx]); + + /* Skip ahead until the next space or opposite character class. */ + do { + idx++; + if (idx == size) + break; + } while (!status_prompt_space(&c->prompt_buffer[idx]) && + word_is_separators == status_prompt_in_list(separators, + &c->prompt_buffer[idx])); + + /* Back up to the previous character to stop at the end of the word. */ + c->prompt_index = idx - 1; +} + +/* Prompt backward to the previous beginning of a word. */ +static void +status_prompt_backward_word(struct client *c, const char *separators) +{ + size_t idx = c->prompt_index; + int word_is_separators; + + /* Find non-whitespace. */ + while (idx != 0) { + --idx; + if (!status_prompt_space(&c->prompt_buffer[idx])) + break; + } + word_is_separators = status_prompt_in_list(separators, + &c->prompt_buffer[idx]); + + /* Find the character before the beginning of the word. */ + while (idx != 0) { + --idx; + if (status_prompt_space(&c->prompt_buffer[idx]) || + word_is_separators != status_prompt_in_list(separators, + &c->prompt_buffer[idx])) { + /* Go back to the word. */ + idx++; + break; + } + } + c->prompt_index = idx; +} + /* Handle keys in prompt. */ int status_prompt_key(struct client *c, key_code key) { struct options *oo = c->session->options; char *s, *cp, prefix = '='; - const char *histstr, *ws = NULL, *keystring; + const char *histstr, *separators = NULL, *keystring; size_t size, idx; struct utf8_data tmp; - int keys; + int keys, word_is_separators; if (c->prompt_flags & PROMPT_KEY) { keystring = key_string_lookup_key(key, 0); @@ -1140,20 +1304,24 @@ process_key: } break; case '\027': /* C-w */ - ws = options_get_string(oo, "word-separators"); + separators = options_get_string(oo, "word-separators"); idx = c->prompt_index; - /* Find a non-separator. */ + /* Find non-whitespace. */ while (idx != 0) { idx--; - if (!status_prompt_in_list(ws, &c->prompt_buffer[idx])) + if (!status_prompt_space(&c->prompt_buffer[idx])) break; } + word_is_separators = status_prompt_in_list(separators, + &c->prompt_buffer[idx]); - /* Find the separator at the beginning of the word. */ + /* Find the character before the beginning of the word. */ while (idx != 0) { idx--; - if (status_prompt_in_list(ws, &c->prompt_buffer[idx])) { + if (status_prompt_space(&c->prompt_buffer[idx]) || + word_is_separators != status_prompt_in_list( + separators, &c->prompt_buffer[idx])) { /* Go back to the word. */ idx++; break; @@ -1175,54 +1343,37 @@ process_key: c->prompt_index = idx; goto changed; - case 'f'|KEYC_META: case KEYC_RIGHT|KEYC_CTRL: - ws = options_get_string(oo, "word-separators"); - - /* Find a word. */ - while (c->prompt_index != size) { - idx = ++c->prompt_index; - if (!status_prompt_in_list(ws, &c->prompt_buffer[idx])) - break; - } - - /* Find the separator at the end of the word. */ - while (c->prompt_index != size) { - idx = ++c->prompt_index; - if (status_prompt_in_list(ws, &c->prompt_buffer[idx])) - break; - } - - /* Back up to the end-of-word like vi. */ - if (options_get_number(oo, "status-keys") == MODEKEY_VI && - c->prompt_index != 0) - c->prompt_index--; - + case 'f'|KEYC_META: + separators = options_get_string(oo, "word-separators"); + status_prompt_forward_word(c, size, 0, separators); + goto changed; + case 'E'|KEYC_VI: + status_prompt_end_word(c, size, ""); + goto changed; + case 'e'|KEYC_VI: + separators = options_get_string(oo, "word-separators"); + status_prompt_end_word(c, size, separators); + goto changed; + case 'W'|KEYC_VI: + status_prompt_forward_word(c, size, 1, ""); + goto changed; + case 'w'|KEYC_VI: + separators = options_get_string(oo, "word-separators"); + status_prompt_forward_word(c, size, 1, separators); + goto changed; + case 'B'|KEYC_VI: + status_prompt_backward_word(c, ""); goto changed; - case 'b'|KEYC_META: case KEYC_LEFT|KEYC_CTRL: - ws = options_get_string(oo, "word-separators"); - - /* Find a non-separator. */ - while (c->prompt_index != 0) { - idx = --c->prompt_index; - if (!status_prompt_in_list(ws, &c->prompt_buffer[idx])) - break; - } - - /* Find the separator at the beginning of the word. */ - while (c->prompt_index != 0) { - idx = --c->prompt_index; - if (status_prompt_in_list(ws, &c->prompt_buffer[idx])) { - /* Go back to the word. */ - c->prompt_index++; - break; - } - } + case 'b'|KEYC_META: + separators = options_get_string(oo, "word-separators"); + status_prompt_backward_word(c, separators); goto changed; case KEYC_UP: case '\020': /* C-p */ - histstr = status_prompt_up_history(&c->prompt_hindex); + histstr = status_prompt_up_history(c->prompt_hindex, + c->prompt_type); if (histstr == NULL) break; free(c->prompt_buffer); @@ -1231,7 +1382,8 @@ process_key: goto changed; case KEYC_DOWN: case '\016': /* C-n */ - histstr = status_prompt_down_history(&c->prompt_hindex); + histstr = status_prompt_down_history(c->prompt_hindex, + c->prompt_type); if (histstr == NULL) break; free(c->prompt_buffer); @@ -1259,7 +1411,7 @@ process_key: case '\n': s = utf8_tocstr(c->prompt_buffer); if (*s != '\0') - status_prompt_add_history(s); + status_prompt_add_history(s, c->prompt_type); if (c->prompt_inputcb(c, c->prompt_data, s, 1) == 0) status_prompt_clear(c); free(s); @@ -1275,7 +1427,7 @@ process_key: break; if (c->prompt_buffer[0].size == 0) { prefix = '='; - free (c->prompt_buffer); + free(c->prompt_buffer); c->prompt_buffer = utf8_fromcstr(c->prompt_last); c->prompt_index = utf8_strlen(c->prompt_buffer); } else @@ -1286,7 +1438,7 @@ process_key: break; if (c->prompt_buffer[0].size == 0) { prefix = '='; - free (c->prompt_buffer); + free(c->prompt_buffer); c->prompt_buffer = utf8_fromcstr(c->prompt_last); c->prompt_index = utf8_strlen(c->prompt_buffer); } else @@ -1304,8 +1456,10 @@ append_key: return (0); if (key <= 0x7f) utf8_set(&tmp, key); - else + else if (KEYC_IS_UNICODE(key)) utf8_to_data(key, &tmp); + else + return (0); c->prompt_buffer = xreallocarray(c->prompt_buffer, size + 2, sizeof *c->prompt_buffer); @@ -1348,61 +1502,99 @@ changed: /* Get previous line from the history. */ static const char * -status_prompt_up_history(u_int *idx) +status_prompt_up_history(u_int *idx, u_int type) { /* * History runs from 0 to size - 1. Index is from 0 to size. Zero is * empty. */ - if (status_prompt_hsize == 0 || *idx == status_prompt_hsize) + if (status_prompt_hsize[type] == 0 || + idx[type] == status_prompt_hsize[type]) return (NULL); - (*idx)++; - return (status_prompt_hlist[status_prompt_hsize - *idx]); + idx[type]++; + return (status_prompt_hlist[type][status_prompt_hsize[type] - idx[type]]); } /* Get next line from the history. */ static const char * -status_prompt_down_history(u_int *idx) +status_prompt_down_history(u_int *idx, u_int type) { - if (status_prompt_hsize == 0 || *idx == 0) + if (status_prompt_hsize[type] == 0 || idx[type] == 0) return (""); - (*idx)--; - if (*idx == 0) + idx[type]--; + if (idx[type] == 0) return (""); - return (status_prompt_hlist[status_prompt_hsize - *idx]); + return (status_prompt_hlist[type][status_prompt_hsize[type] - idx[type]]); } /* Add line to the history. */ static void -status_prompt_add_history(const char *line) +status_prompt_add_history(const char *line, u_int type) { - size_t size; + u_int i, oldsize, newsize, freecount, hlimit, new = 1; + size_t movesize; + + oldsize = status_prompt_hsize[type]; + if (oldsize > 0 && + strcmp(status_prompt_hlist[type][oldsize - 1], line) == 0) + new = 0; + + hlimit = options_get_number(global_options, "prompt-history-limit"); + if (hlimit > oldsize) { + if (new == 0) + return; + newsize = oldsize + new; + } else { + newsize = hlimit; + freecount = oldsize + new - newsize; + if (freecount > oldsize) + freecount = oldsize; + if (freecount == 0) + return; + for (i = 0; i < freecount; i++) + free(status_prompt_hlist[type][i]); + movesize = (oldsize - freecount) * + sizeof *status_prompt_hlist[type]; + if (movesize > 0) { + memmove(&status_prompt_hlist[type][0], + &status_prompt_hlist[type][freecount], movesize); + } + } - if (status_prompt_hsize > 0 && - strcmp(status_prompt_hlist[status_prompt_hsize - 1], line) == 0) - return; + if (newsize == 0) { + free(status_prompt_hlist[type]); + status_prompt_hlist[type] = NULL; + } else if (newsize != oldsize) { + status_prompt_hlist[type] = + xreallocarray(status_prompt_hlist[type], newsize, + sizeof *status_prompt_hlist[type]); + } - if (status_prompt_hsize == PROMPT_HISTORY) { - free(status_prompt_hlist[0]); + if (new == 1 && newsize > 0) + status_prompt_hlist[type][newsize - 1] = xstrdup(line); + status_prompt_hsize[type] = newsize; +} - size = (PROMPT_HISTORY - 1) * sizeof *status_prompt_hlist; - memmove(&status_prompt_hlist[0], &status_prompt_hlist[1], size); +/* Add to completion list. */ +static void +status_prompt_add_list(char ***list, u_int *size, const char *s) +{ + u_int i; - status_prompt_hlist[status_prompt_hsize - 1] = xstrdup(line); - return; + for (i = 0; i < *size; i++) { + if (strcmp((*list)[i], s) == 0) + return; } - - status_prompt_hlist = xreallocarray(status_prompt_hlist, - status_prompt_hsize + 1, sizeof *status_prompt_hlist); - status_prompt_hlist[status_prompt_hsize++] = xstrdup(line); + *list = xreallocarray(*list, (*size) + 1, sizeof **list); + (*list)[(*size)++] = xstrdup(s); } /* Build completion list. */ static char ** status_prompt_complete_list(u_int *size, const char *s, int at_start) { - char **list = NULL; + char **list = NULL, *tmp; const char **layout, *value, *cp; const struct cmd_entry **cmdent; const struct options_table_entry *oe; @@ -1416,15 +1608,11 @@ status_prompt_complete_list(u_int *size, const char *s, int at_start) *size = 0; for (cmdent = cmd_table; *cmdent != NULL; cmdent++) { - if (strncmp((*cmdent)->name, s, slen) == 0) { - list = xreallocarray(list, (*size) + 1, sizeof *list); - list[(*size)++] = xstrdup((*cmdent)->name); - } + if (strncmp((*cmdent)->name, s, slen) == 0) + status_prompt_add_list(&list, size, (*cmdent)->name); if ((*cmdent)->alias != NULL && - strncmp((*cmdent)->alias, s, slen) == 0) { - list = xreallocarray(list, (*size) + 1, sizeof *list); - list[(*size)++] = xstrdup((*cmdent)->alias); - } + strncmp((*cmdent)->alias, s, slen) == 0) + status_prompt_add_list(&list, size, (*cmdent)->alias); } o = options_get_only(global_options, "command-alias"); if (o != NULL) { @@ -1437,8 +1625,9 @@ status_prompt_complete_list(u_int *size, const char *s, int at_start) if (slen > valuelen || strncmp(value, s, slen) != 0) goto next; - list = xreallocarray(list, (*size) + 1, sizeof *list); - list[(*size)++] = xstrndup(value, valuelen); + xasprintf(&tmp, "%.*s", (int)valuelen, value); + status_prompt_add_list(&list, size, tmp); + free(tmp); next: a = options_array_next(a); @@ -1446,18 +1635,13 @@ status_prompt_complete_list(u_int *size, const char *s, int at_start) } if (at_start) return (list); - for (oe = options_table; oe->name != NULL; oe++) { - if (strncmp(oe->name, s, slen) == 0) { - list = xreallocarray(list, (*size) + 1, sizeof *list); - list[(*size)++] = xstrdup(oe->name); - } + if (strncmp(oe->name, s, slen) == 0) + status_prompt_add_list(&list, size, oe->name); } for (layout = layouts; *layout != NULL; layout++) { - if (strncmp(*layout, s, slen) == 0) { - list = xreallocarray(list, (*size) + 1, sizeof *list); - list[(*size)++] = xstrdup(*layout); - } + if (strncmp(*layout, s, slen) == 0) + status_prompt_add_list(&list, size, *layout); } return (list); } @@ -1501,7 +1685,7 @@ status_prompt_menu_callback(__unused struct menu *menu, u_int idx, key_code key, s = xstrdup(spm->list[idx]); else xasprintf(&s, "-%c%s", spm->flag, spm->list[idx]); - if (c->prompt_flags & PROMPT_WINDOW) { + if (c->prompt_type == PROMPT_TYPE_WINDOW_TARGET) { free(c->prompt_buffer); c->prompt_buffer = utf8_fromcstr(s); c->prompt_index = utf8_strlen(c->prompt_buffer); @@ -1550,7 +1734,7 @@ status_prompt_complete_list_menu(struct client *c, char **list, u_int size, item.name = list[i]; item.key = '0' + (i - spm->start); item.command = NULL; - menu_add_item(menu, &item, NULL, NULL, NULL); + menu_add_item(menu, &item, NULL, c, NULL); } if (options_get_number(c->session->options, "status-position") == 0) @@ -1609,7 +1793,7 @@ status_prompt_complete_window_menu(struct client *c, struct session *s, } list = xreallocarray(list, size + 1, sizeof *list); - if (c->prompt_flags & PROMPT_WINDOW) { + if (c->prompt_type == PROMPT_TYPE_WINDOW_TARGET) { xasprintf(&tmp, "%d (%s)", wl->idx, wl->window->name); xasprintf(&list[size++], "%d", wl->idx); } else { @@ -1620,7 +1804,7 @@ status_prompt_complete_window_menu(struct client *c, struct session *s, item.name = tmp; item.key = '0' + size - 1; item.command = NULL; - menu_add_item(menu, &item, NULL, NULL, NULL); + menu_add_item(menu, &item, NULL, c, NULL); free(tmp); if (size == height) @@ -1717,10 +1901,12 @@ status_prompt_complete(struct client *c, const char *word, u_int offset) u_int size = 0, i; if (*word == '\0' && - ((c->prompt_flags & (PROMPT_TARGET|PROMPT_WINDOW)) == 0)) + c->prompt_type != PROMPT_TYPE_TARGET && + c->prompt_type != PROMPT_TYPE_WINDOW_TARGET) return (NULL); - if (((c->prompt_flags & (PROMPT_TARGET|PROMPT_WINDOW)) == 0) && + if (c->prompt_type != PROMPT_TYPE_TARGET && + c->prompt_type != PROMPT_TYPE_WINDOW_TARGET && strncmp(word, "-t", 2) != 0 && strncmp(word, "-s", 2) != 0) { list = status_prompt_complete_list(&size, word, offset == 0); @@ -1733,7 +1919,8 @@ status_prompt_complete(struct client *c, const char *word, u_int offset) goto found; } - if (c->prompt_flags & (PROMPT_TARGET|PROMPT_WINDOW)) { + if (c->prompt_type == PROMPT_TYPE_TARGET || + c->prompt_type == PROMPT_TYPE_WINDOW_TARGET) { s = word; flag = '\0'; } else { @@ -1743,7 +1930,7 @@ status_prompt_complete(struct client *c, const char *word, u_int offset) } /* If this is a window completion, open the window menu. */ - if (c->prompt_flags & PROMPT_WINDOW) { + if (c->prompt_type == PROMPT_TYPE_WINDOW_TARGET) { out = status_prompt_complete_window_menu(c, c->session, s, offset, '\0'); goto found; @@ -1793,3 +1980,25 @@ found: } return (out); } + +/* Return the type of the prompt as an enum. */ +enum prompt_type +status_prompt_type(const char *type) +{ + u_int i; + + for (i = 0; i < PROMPT_NTYPES; i++) { + if (strcmp(type, status_prompt_type_string(i)) == 0) + return (i); + } + return (PROMPT_TYPE_INVALID); +} + +/* Accessor for prompt_type_strings. */ +const char * +status_prompt_type_string(u_int type) +{ + if (type >= PROMPT_NTYPES) + return ("invalid"); + return (prompt_type_strings[type]); +} diff --git a/external/bsd/tmux/dist/style.c b/external/bsd/tmux/dist/style.c index bd8cf7f93dc..108f500206d 100644 --- a/external/bsd/tmux/dist/style.c +++ b/external/bsd/tmux/dist/style.c @@ -51,7 +51,7 @@ int style_parse(struct style *sy, const struct grid_cell *base, const char *in) { struct style saved; - const char delimiters[] = " ,", *cp; + const char delimiters[] = " ,\n", *cp; char tmp[256], *found; int value; size_t end; diff --git a/external/bsd/tmux/dist/tmux.1 b/external/bsd/tmux/dist/tmux.1 index 1e91b82ce47..cc217d9561f 100644 --- a/external/bsd/tmux/dist/tmux.1 +++ b/external/bsd/tmux/dist/tmux.1 @@ -43,7 +43,7 @@ then later reattached. .Pp When .Nm -is started it creates a new +is started, it creates a new .Em session with a single .Em window @@ -140,7 +140,10 @@ By default, loads the system configuration file from .Pa @SYSCONFDIR@/tmux.conf , if present, then looks for a user configuration file at -.Pa ~/.tmux.conf . +.Pa ~/.tmux.conf, +.Pa $XDG_CONFIG_HOME/tmux/tmux.conf +or +.Pa ~/.config/tmux/tmux.conf . .Pp The configuration file is a set of .Nm @@ -1027,13 +1030,14 @@ section. .Pp The following commands are available to manage clients and sessions: .Bl -tag -width Ds +.Tg attach .It Xo Ic attach-session .Op Fl dErx .Op Fl c Ar working-directory .Op Fl f Ar flags .Op Fl t Ar target-session .Xc -.D1 (alias: Ic attach ) +.D1 Pq alias: Ic attach If run from outside .Nm , create a new client in the current terminal and attach it to @@ -1113,13 +1117,14 @@ If is used, the .Ic update-environment option will not be applied. +.Tg detach .It Xo Ic detach-client .Op Fl aP .Op Fl E Ar shell-command .Op Fl s Ar target-session .Op Fl t Ar target-client .Xc -.D1 (alias: Ic detach ) +.D1 Pq alias: Ic detach Detach the current client if bound to a key, the client specified with .Fl t , or all clients currently attached to the session specified by @@ -1139,8 +1144,9 @@ With run .Ar shell-command to replace the client. +.Tg has .It Ic has-session Op Fl t Ar target-session -.D1 (alias: Ic has ) +.D1 Pq alias: Ic has Report an error and exit with 1 if the specified session does not exist. If it does exist, exit with 0. .It Ic kill-server @@ -1160,11 +1166,12 @@ The .Fl C flag clears alerts (bell, activity, or silence) in all windows linked to the session. +.Tg lsc .It Xo Ic list-clients .Op Fl F Ar format .Op Fl t Ar target-session .Xc -.D1 (alias: Ic lsc ) +.D1 Pq alias: Ic lsc List all clients attached to the server. For the meaning of the .Fl F @@ -1174,20 +1181,22 @@ section. If .Ar target-session is specified, list only clients connected to that session. +.Tg lscm .It Xo Ic list-commands .Op Fl F Ar format .Op Ar command .Xc -.D1 (alias: Ic lscm ) +.D1 Pq alias: Ic lscm List the syntax of .Ar command or - if omitted - of all commands supported by .Nm . +.Tg ls .It Xo Ic list-sessions .Op Fl F Ar format .Op Fl f Ar filter .Xc -.D1 (alias: Ic ls ) +.D1 Pq alias: Ic ls List all sessions managed by the server. .Fl F specifies the format of each line and @@ -1197,17 +1206,20 @@ Only sessions for which the filter is true are shown. See the .Sx FORMATS section. +.Tg lockc .It Ic lock-client Op Fl t Ar target-client -.D1 (alias: Ic lockc ) +.D1 Pq alias: Ic lockc Lock .Ar target-client , see the .Ic lock-server command. +.Tg locks .It Ic lock-session Op Fl t Ar target-session -.D1 (alias: Ic locks ) +.D1 Pq alias: Ic locks Lock all clients attached to .Ar target-session . +.Tg new .It Xo Ic new-session .Op Fl AdDEPX .Op Fl c Ar start-directory @@ -1221,7 +1233,7 @@ Lock all clients attached to .Op Fl y Ar height .Op Ar shell-command .Xc -.D1 (alias: Ic new ) +.D1 Pq alias: Ic new Create a new session with name .Ar session-name . .Pp @@ -1327,16 +1339,18 @@ takes the form .Ql VARIABLE=value and sets an environment variable for the newly created session; it may be specified multiple times. +.Tg refresh .It Xo Ic refresh-client -.Op Fl cDlLRSU +.Op Fl cDLRSU .Op Fl A Ar pane:state .Op Fl B Ar name:what:format -.Op Fl C Ar XxY +.Op Fl C Ar size .Op Fl f Ar flags +.Op Fl l Op Ar target-pane .Op Fl t Ar target-client .Op Ar adjustment .Xc -.D1 (alias: Ic refresh ) +.D1 Pq alias: Ic refresh Refresh the current client if bound to a key, or a single client if one is given with .Fl t . @@ -1375,7 +1389,17 @@ window, changing the current window in the attached session will reset it. .Pp .Fl C -sets the width and height of a control mode client. +sets the width and height of a control mode client or of a window for a +control mode client, +.Ar size +must be one of +.Ql widthxheight +or +.Ql window ID:widthxheight , +for example +.Ql 80x24 +or +.Ql @0:80x24 . .Fl A allows a control mode client to trigger actions on a pane. The argument is a pane ID (with leading @@ -1436,7 +1460,11 @@ sets a comma-separated list of client flags, see .Fl l requests the clipboard from the client using the .Xr xterm 1 -escape sequence and stores it in a new paste buffer. +escape sequence. +If +Ar target-pane +is given, the clipboard is sent (in encoded form), otherwise it is stored in a +new paste buffer. .Pp .Fl L , .Fl R , @@ -1452,18 +1480,58 @@ resets so that the position follows the cursor. See the .Ic window-size option. +.Tg rename .It Xo Ic rename-session .Op Fl t Ar target-session .Ar new-name .Xc -.D1 (alias: Ic rename ) +.D1 Pq alias: Ic rename Rename the session to .Ar new-name . +.It Xo Ic server-access +.Op Fl adlrw +.Op Ar user +.Xc +Change the access or read/write permission of +.Ar user . +The user running the +.Nm +server (its owner) and the root user cannot be changed and are always +permitted access. +.Pp +.Fl a +and +.Fl d +are used to give or revoke access for the specified user. +If the user is already attached, the +.Fl d +flag causes their clients to be detached. +.Pp +.Fl r +and +.Fl w +change the permissions for +.Ar user : +.Fl r +makes their clients read-only and +.Fl w +writable. +.Fl l +lists current access permissions. +.Pp +By default, the access list is empty and +.Nm +creates sockets with file system permissions preventing access by any user +other than the owner (and root). +These permissions must be changed manually. +Great care should be taken not to allow access to untrusted users even +read-only. +.Tg showmsgs .It Xo Ic show-messages .Op Fl JT .Op Fl t Ar target-client .Xc -.D1 (alias: Ic showmsgs ) +.D1 Pq alias: Ic showmsgs Show server messages or information. Messages are stored, up to a maximum of the limit set by the .Ar message-limit @@ -1472,12 +1540,13 @@ server option. and .Fl T show debugging information about jobs and terminals. +.Tg source .It Xo Ic source-file .Op Fl Fnqv .Ar path .Ar ... .Xc -.D1 (alias: Ic source ) +.D1 Pq alias: Ic source Execute commands from one or more files specified by .Ar path (which may be @@ -1498,8 +1567,9 @@ With the file is parsed but no commands are executed. .Fl v shows the parsed commands and line numbers if possible. +.Tg start .It Ic start-server -.D1 (alias: Ic start ) +.D1 Pq alias: Ic start Start the .Nm server, if not already running, without creating any sessions. @@ -1514,20 +1584,22 @@ For example: .Bd -literal -offset indent $ tmux start \\; show -g .Ed +.Tg suspendc .It Xo Ic suspend-client .Op Fl t Ar target-client .Xc -.D1 (alias: Ic suspendc ) +.D1 Pq alias: Ic suspendc Suspend a client by sending .Dv SIGTSTP (tty stop). +.Tg switchc .It Xo Ic switch-client .Op Fl ElnprZ .Op Fl c Ar target-client .Op Fl t Ar target-session .Op Fl T Ar key-table .Xc -.D1 (alias: Ic switchc ) +.D1 Pq alias: Ic switchc Switch the current session for client .Ar target-client to @@ -1676,8 +1748,14 @@ The following commands are supported in copy mode: .It Li "bottom-line" Ta "L" Ta "" .It Li "cancel" Ta "q" Ta "Escape" .It Li "clear-selection" Ta "Escape" Ta "C-g" -.It Li "copy-end-of-line [<prefix>]" Ta "D" Ta "C-k" +.It Li "copy-end-of-line [<prefix>]" Ta "" Ta "" +.It Li "copy-end-of-line-and-cancel [<prefix>]" Ta "" Ta "" +.It Li "copy-pipe-end-of-line [<command>] [<prefix>]" Ta "" Ta "" +.It Li "copy-pipe-end-of-line-and-cancel [<command>] [<prefix>]" Ta "D" Ta "C-k" .It Li "copy-line [<prefix>]" Ta "" Ta "" +.It Li "copy-line-and-cancel [<prefix>]" Ta "" Ta "" +.It Li "copy-pipe-line [<command>] [<prefix>]" Ta "" Ta "" +.It Li "copy-pipe-line-and-cancel [<command>] [<prefix>]" Ta "" Ta "" .It Li "copy-pipe [<command>] [<prefix>]" Ta "" Ta "" .It Li "copy-pipe-no-clear [<command>] [<prefix>]" Ta "" Ta "" .It Li "copy-pipe-and-cancel [<command>] [<prefix>]" Ta "" Ta "" @@ -1741,6 +1819,7 @@ The following commands are supported in copy mode: .It Li "set-mark" Ta "X" Ta "X" .It Li "start-of-line" Ta "0" Ta "C-a" .It Li "stop-selection" Ta "" Ta "" +.It Li "toggle-position" Ta "P" Ta "P" .It Li "top-line" Ta "H" Ta "M-R" .El .Pp @@ -1782,19 +1861,18 @@ commands) or when the cursor reaches the bottom (for scrolling commands). .Ql -no-clear variants do not clear the selection. .Pp -The next and previous word keys use space and the -.Ql - , -.Ql _ -and -.Ql @ -characters as word delimiters by default, but this can be adjusted by -setting the +The next and previous word keys skip over whitespace and treat consecutive +runs of either word separators or other letters as words. +Word separators can be customized with the .Em word-separators session option. Next word moves to the start of the next word, next word end to the end of the next word and previous word to the start of the previous word. The three next and previous space keys work similarly but use a space alone as the word separator. +Setting +.Em word-separators +to the empty string makes next/previous word equivalent to next/previous space. .Pp The jump commands enable quick movement within a line. For instance, typing @@ -1906,6 +1984,7 @@ from which the layout was originally defined. .Pp Commands related to windows and panes are as follows: .Bl -tag -width Ds +.Tg breakp .It Xo Ic break-pane .Op Fl abdP .Op Fl F Ar format @@ -1913,7 +1992,7 @@ Commands related to windows and panes are as follows: .Op Fl s Ar src-pane .Op Fl t Ar dst-window .Xc -.D1 (alias: Ic breakp ) +.D1 Pq alias: Ic breakp Break .Ar src-pane off from its containing window to make it the only pane in @@ -1934,6 +2013,7 @@ By default, it uses the format .Ql #{session_name}:#{window_index}.#{pane_index} but a different format may be specified with .Fl F . +.Tg capturep .It Xo Ic capture-pane .Op Fl aepPqCJN .Op Fl b Ar buffer-name @@ -1941,7 +2021,7 @@ but a different format may be specified with .Op Fl S Ar start-line .Op Fl t Ar target-pane .Xc -.D1 (alias: Ic capturep ) +.D1 Pq alias: Ic capturep Capture the contents of a pane. If .Fl p @@ -2103,9 +2183,11 @@ The following keys may be used in tree mode: .It Li "q" Ta "Exit mode" .El .Pp -After a session, window or pane is chosen, +After a session, window or pane is chosen, the first instance of .Ql %% -is replaced by the target in +and all instances of +.Ql %1 +are replaced by the target in .Ar template and the result executed as a command. If @@ -2184,13 +2266,14 @@ specifies the format for each item in the tree. starts without the option information. This command works only if at least one client is attached. .It Xo +.Tg displayp .Ic display-panes .Op Fl bN .Op Fl d Ar duration .Op Fl t Ar target-client .Op Ar template .Xc -.D1 (alias: Ic displayp ) +.D1 Pq alias: Ic displayp Display a visible indicator of each pane shown by .Ar target-client . See the @@ -2224,12 +2307,13 @@ is "select-pane -t '%%'". With .Fl b , other commands are not blocked from running until the indicator is closed. +.Tg findw .It Xo Ic find-window .Op Fl iCNrTZ .Op Fl t Ar target-pane .Ar match-string .Xc -.D1 (alias: Ic findw ) +.D1 Pq alias: Ic findw Search for a .Xr fnmatch 3 pattern or, with @@ -2252,13 +2336,14 @@ The default is zooms the pane. .Pp This command works only if at least one client is attached. +.Tg joinp .It Xo Ic join-pane .Op Fl bdfhv .Op Fl l Ar size .Op Fl s Ar src-pane .Op Fl t Ar dst-pane .Xc -.D1 (alias: Ic joinp ) +.D1 Pq alias: Ic joinp Like .Ic split-window , but instead of splitting @@ -2281,22 +2366,24 @@ is omitted and a marked pane is present (see .Ic select-pane .Fl m ) , the marked pane is used rather than the current pane. +.Tg killp .It Xo Ic kill-pane .Op Fl a .Op Fl t Ar target-pane .Xc -.D1 (alias: Ic killp ) +.D1 Pq alias: Ic killp Destroy the given pane. If no panes remain in the containing window, it is also destroyed. The .Fl a option kills all but the pane given with .Fl t . +.Tg killw .It Xo Ic kill-window .Op Fl a .Op Fl t Ar target-window .Xc -.D1 (alias: Ic killw ) +.D1 Pq alias: Ic killw Kill the current window or the window at .Ar target-window , removing it from any sessions to which it is linked. @@ -2304,11 +2391,12 @@ The .Fl a option kills all but the window given with .Fl t . +.Tg lastp .It Xo Ic last-pane .Op Fl deZ .Op Fl t Ar target-window .Xc -.D1 (alias: Ic lastp ) +.D1 Pq alias: Ic lastp Select the last (previously selected) pane. .Fl Z keeps the window zoomed if it was zoomed. @@ -2316,18 +2404,20 @@ keeps the window zoomed if it was zoomed. enables or .Fl d disables input to the pane. +.Tg last .It Ic last-window Op Fl t Ar target-session -.D1 (alias: Ic last ) +.D1 Pq alias: Ic last Select the last (previously selected) window. If no .Ar target-session is specified, select the last window of the current session. +.Tg link .It Xo Ic link-window .Op Fl abdk .Op Fl s Ar src-window .Op Fl t Ar dst-window .Xc -.D1 (alias: Ic linkw ) +.D1 Pq alias: Ic linkw Link the window at .Ar src-window to the specified @@ -2352,13 +2442,14 @@ exists, it is killed, otherwise an error is generated. If .Fl d is given, the newly linked window is not selected. +.Tg lsp .It Xo Ic list-panes .Op Fl as .Op Fl F Ar format .Op Fl f Ar filter .Op Fl t Ar target .Xc -.D1 (alias: Ic lsp ) +.D1 Pq alias: Ic lsp If .Fl a is given, @@ -2380,13 +2471,14 @@ Only panes for which the filter is true are shown. See the .Sx FORMATS section. +.Tg lsw .It Xo Ic list-windows .Op Fl a .Op Fl F Ar format .Op Fl f Ar filter .Op Fl t Ar target-session .Xc -.D1 (alias: Ic lsw ) +.D1 Pq alias: Ic lsw If .Fl a is given, list all windows on the server. @@ -2400,21 +2492,23 @@ Only windows for which the filter is true are shown. See the .Sx FORMATS section. +.Tg movep .It Xo Ic move-pane .Op Fl bdfhv .Op Fl l Ar size .Op Fl s Ar src-pane .Op Fl t Ar dst-pane .Xc -.D1 (alias: Ic movep ) +.D1 Pq alias: Ic movep Does the same as .Ic join-pane . +.Tg movew .It Xo Ic move-window .Op Fl abrdk .Op Fl s Ar src-window .Op Fl t Ar dst-window .Xc -.D1 (alias: Ic movew ) +.D1 Pq alias: Ic movew This is similar to .Ic link-window , except the window at @@ -2427,6 +2521,7 @@ all windows in the session are renumbered in sequential order, respecting the .Ic base-index option. +.Tg neww .It Xo Ic new-window .Op Fl abdkPS .Op Fl c Ar start-directory @@ -2436,7 +2531,7 @@ option. .Op Fl t Ar target-window .Op Ar shell-command .Xc -.D1 (alias: Ic neww ) +.D1 Pq alias: Ic neww Create a new window. With .Fl a @@ -2509,24 +2604,27 @@ By default, it uses the format .Ql #{session_name}:#{window_index} but a different format may be specified with .Fl F . +.Tg nextl .It Ic next-layout Op Fl t Ar target-window -.D1 (alias: Ic nextl ) +.D1 Pq alias: Ic nextl Move a window to the next layout and rearrange the panes to fit. +.Tg next .It Xo Ic next-window .Op Fl a .Op Fl t Ar target-session .Xc -.D1 (alias: Ic next ) +.D1 Pq alias: Ic next Move to the next window in the session. If .Fl a is used, move to the next window with an alert. +.Tg pipep .It Xo Ic pipe-pane .Op Fl IOo .Op Fl t Ar target-pane .Op Ar shell-command .Xc -.D1 (alias: Ic pipep ) +.D1 Pq alias: Ic pipep Pipe output sent by the program in .Ar target-pane to a shell command or vice versa. @@ -2569,29 +2667,33 @@ be toggled with a single key, for example: .Bd -literal -offset indent bind-key C-p pipe-pane -o 'cat >>~/output.#I-#P' .Ed +.Tg prevl .It Xo Ic previous-layout .Op Fl t Ar target-window .Xc -.D1 (alias: Ic prevl ) +.D1 Pq alias: Ic prevl Move to the previous layout in the session. +.Tg prev .It Xo Ic previous-window .Op Fl a .Op Fl t Ar target-session .Xc -.D1 (alias: Ic prev ) +.D1 Pq alias: Ic prev Move to the previous window in the session. With .Fl a , move to the previous window with an alert. +.Tg renamew .It Xo Ic rename-window .Op Fl t Ar target-window .Ar new-name .Xc -.D1 (alias: Ic renamew ) +.D1 Pq alias: Ic renamew Rename the current window, or the window at .Ar target-window if specified, to .Ar new-name . +.Tg resizep .It Xo Ic resize-pane .Op Fl DLMRTUZ .Op Fl t Ar target-pane @@ -2599,7 +2701,7 @@ if specified, to .Op Fl y Ar height .Op Ar adjustment .Xc -.D1 (alias: Ic resizep ) +.D1 Pq alias: Ic resizep Resize a pane, up, down, left or right by .Ar adjustment with @@ -2636,6 +2738,7 @@ begins mouse resizing (only valid if bound to a mouse key binding, see .Fl T trims all lines below the current cursor position and moves lines out of the history to replace them. +.Tg resizew .It Xo Ic resize-window .Op Fl aADLRU .Op Fl t Ar target-window @@ -2643,7 +2746,7 @@ history to replace them. .Op Fl y Ar height .Op Ar adjustment .Xc -.D1 (alias: Ic resizew ) +.D1 Pq alias: Ic resizew Resize a window, up, down, left or right by .Ar adjustment with @@ -2668,6 +2771,7 @@ the size of the smallest. This command will automatically set .Ic window-size to manual in the window options. +.Tg respawnp .It Xo Ic respawn-pane .Op Fl k .Op Fl c Ar start-directory @@ -2675,7 +2779,7 @@ to manual in the window options. .Op Fl t Ar target-pane .Op Ar shell-command .Xc -.D1 (alias: Ic respawnp ) +.D1 Pq alias: Ic respawnp Reactivate a pane in which the command has exited (see the .Ic remain-on-exit window option). @@ -2693,6 +2797,7 @@ The option has the same meaning as for the .Ic new-window command. +.Tg respawnw .It Xo Ic respawn-window .Op Fl k .Op Fl c Ar start-directory @@ -2700,7 +2805,7 @@ command. .Op Fl t Ar target-window .Op Ar shell-command .Xc -.D1 (alias: Ic respawnw ) +.D1 Pq alias: Ic respawnw Reactivate a window in which the command has exited (see the .Ic remain-on-exit window option). @@ -2718,23 +2823,25 @@ The option has the same meaning as for the .Ic new-window command. +.Tg rotatew .It Xo Ic rotate-window .Op Fl DUZ .Op Fl t Ar target-window .Xc -.D1 (alias: Ic rotatew ) +.D1 Pq alias: Ic rotatew Rotate the positions of the panes within a window, either upward (numerically lower) with .Fl U or downward (numerically higher). .Fl Z keeps the window zoomed if it was zoomed. +.Tg selectl .It Xo Ic select-layout .Op Fl Enop .Op Fl t Ar target-pane .Op Ar layout-name .Xc -.D1 (alias: Ic selectl ) +.D1 Pq alias: Ic selectl Choose a specific layout for a window. If .Ar layout-name @@ -2751,12 +2858,13 @@ commands. applies the last set layout if possible (undoes the most recent layout change). .Fl E spreads the current pane and any panes next to it out evenly. +.Tg selectp .It Xo Ic select-pane .Op Fl DdeLlMmRUZ .Op Fl T Ar title .Op Fl t Ar target-pane .Xc -.D1 (alias: Ic selectp ) +.D1 Pq alias: Ic selectp Make pane .Ar target-pane the active pane in its window. @@ -2795,11 +2903,12 @@ to .Ic swap-pane and .Ic swap-window . +.Tg selectw .It Xo Ic select-window .Op Fl lnpT .Op Fl t Ar target-window .Xc -.D1 (alias: Ic selectw ) +.D1 Pq alias: Ic selectw Select the window at .Ar target-window . .Fl l , @@ -2817,6 +2926,7 @@ If is given and the selected window is already the current window, the command behaves like .Ic last-window . +.Tg splitw .It Xo Ic split-window .Op Fl bdfhIvPZ .Op Fl c Ar start-directory @@ -2826,7 +2936,7 @@ the command behaves like .Op Ar shell-command .Op Fl F Ar format .Xc -.D1 (alias: Ic splitw ) +.D1 Pq alias: Ic splitw Create a new pane by splitting .Ar target-pane : .Fl h @@ -2877,12 +2987,13 @@ $ make 2>&1|tmux splitw -dI & All other options have the same meaning as for the .Ic new-window command. +.Tg swapp .It Xo Ic swap-pane .Op Fl dDUZ .Op Fl s Ar src-pane .Op Fl t Ar dst-pane .Xc -.D1 (alias: Ic swapp ) +.D1 Pq alias: Ic swapp Swap two panes. If .Fl U @@ -2905,12 +3016,13 @@ is omitted and a marked pane is present (see .Ic select-pane .Fl m ) , the marked pane is used rather than the current pane. +.Tg swapw .It Xo Ic swap-window .Op Fl d .Op Fl s Ar src-window .Op Fl t Ar dst-window .Xc -.D1 (alias: Ic swapw ) +.D1 Pq alias: Ic swapw This is similar to .Ic link-window , except the source and destination windows are swapped. @@ -2926,11 +3038,12 @@ is omitted and a marked pane is present (see .Ic select-pane .Fl m ) , the window containing the marked pane is used rather than the current window. +.Tg unlinkw .It Xo Ic unlink-window .Op Fl k .Op Fl t Ar target-window .Xc -.D1 (alias: Ic unlinkw ) +.D1 Pq alias: Ic unlinkw Unlink .Ar target-window . Unless @@ -2996,13 +3109,14 @@ key will execute for all keys which do not have a more specific binding. .Pp Commands related to key bindings are as follows: .Bl -tag -width Ds +.Tg bind .It Xo Ic bind-key .Op Fl nr .Op Fl N Ar note .Op Fl T Ar key-table .Ar key command Op Ar arguments .Xc -.D1 (alias: Ic bind ) +.D1 Pq alias: Ic bind Bind key .Ar key to @@ -3054,12 +3168,13 @@ attaches a note to the key (shown with To view the default bindings and possible commands, see the .Ic list-keys command. +.Tg lsk .It Xo Ic list-keys .Op Fl 1aN .Op Fl P Ar prefix-string Fl T Ar key-table .Op Ar key .Xc -.D1 (alias: Ic lsk ) +.D1 Pq alias: Ic lsk List key bindings. There are two forms: the default lists keys as .Ic bind-key @@ -3089,13 +3204,14 @@ specifies a prefix to print before each key and lists only the first matching key. .Fl a lists the command for keys that do not have a note rather than skipping them. +.Tg send .It Xo Ic send-keys .Op Fl FHlMRX .Op Fl N Ar repeat-count .Op Fl t Ar target-pane .Ar key Ar ... .Xc -.D1 (alias: Ic send ) +.D1 Pq alias: Ic send Send a key or keys to a window. Each argument .Ar key @@ -3106,6 +3222,7 @@ or to send; if the string is not recognised as a key, it is sent as a series of characters. All arguments are sent sequentially from first to last. +If no keys are given and the command is bound to a key, then that key is used. .Pp The .Fl l @@ -3139,12 +3256,13 @@ expands formats in arguments where appropriate. Send the prefix key, or with .Fl 2 the secondary prefix key, to a window as if it was pressed. +.Tg unbind .It Xo Ic unbind-key .Op Fl anq .Op Fl T Ar key-table .Ar key .Xc -.D1 (alias: Ic unbind ) +.D1 Pq alias: Ic unbind Unbind the command bound to .Ar key . .Fl n @@ -3234,12 +3352,13 @@ abc123 .Pp Commands which set options are as follows: .Bl -tag -width Ds +.Tg set .It Xo Ic set-option .Op Fl aFgopqsuUw .Op Fl t Ar target-pane .Ar option Ar value .Xc -.D1 (alias: Ic set ) +.D1 Pq alias: Ic set Set a pane option with .Fl p , a window option with @@ -3308,12 +3427,13 @@ blue foreground. Without .Fl a , the result would be the default background and a blue foreground. +.Tg show .It Xo Ic show-options .Op Fl AgHpqsvw .Op Fl t Ar target-pane .Op Ar option .Xc -.D1 (alias: Ic show ) +.D1 Pq alias: Ic show Show the pane options (or a single option if .Ar option is provided) with @@ -3453,7 +3573,9 @@ will write command prompt history on exit and load it from on start. .It Ic message-limit Ar number Set the number of error or information messages to save in the message log for each client. -The default is 100. +.It Ic prompt-history-limit Ar number +Set the number of history items to save in the history file for each type of +command prompt. .It Xo Ic set-clipboard .Op Ic on | external | off .Xc @@ -3543,6 +3665,8 @@ Supports DECSLRM margins. Supports .Xr xterm 1 mouse sequences. +.It osc7 +Supports the OSC 7 working directory extension. .It overline Supports the overline SGR attribute. .It rectfill @@ -3976,8 +4100,6 @@ If set to both, a bell and a message are produced. Sets the session's conception of what characters are considered word separators, for the purposes of the next and previous word commands in copy mode. -The default is -.Ql \ -_@ . .El .Pp Available window options are: @@ -4035,6 +4157,9 @@ Set clock colour. .Xc Set clock hour format. .Pp +.It Ic fill-character Ar character +Set the character used to fill areas of the terminal unused by a window. +.Pp .It Ic main-pane-height Ar height .It Ic main-pane-width Ar width Set the width or height of the main (left or top) pane in the @@ -4150,6 +4275,12 @@ but set the starting index for pane numbers. .It Ic pane-border-format Ar format Set the text shown in pane border status lines. .Pp +.It Xo Ic pane-border-indicators +.Op Ic off | colour | arrows | both +.Xc +Indicate active pane by colouring only half of the border in windows with +exactly two panes, by displaying arrow markers, by drawing both or neither. +.Pp .It Ic pane-border-lines Ar type Set the type of characters used for drawing pane borders. .Ar type @@ -4186,6 +4317,50 @@ see the section. Attributes are ignored. .Pp +.It Ic popup-style Ar style +Set the popup style. +For how to specify +.Ar style , +see the +.Sx STYLES +section. +Attributes are ignored. +.Pp +.It Ic popup-border-style Ar style +Set the popup border style. +For how to specify +.Ar style , +see the +.Sx STYLES +section. +Attributes are ignored. +.Pp +.It Ic popup-border-lines Ar type +Set the type of characters used for drawing popup borders. +.Ar type +may be one of: +.Bl -tag -width Ds +.It single +single lines using ACS or UTF-8 characters (default) +.It rounded +variation of single with rounded corners using UTF-8 characters +.It double +double lines using UTF-8 characters +.It heavy +heavy lines using UTF-8 characters +.It simple +simple ASCII characters +.It padded +simple ASCII space character +.It none +no border +.El +.Pp +.Ql double +and +.Ql heavy +will fall back to standard ACS line drawing when UTF-8 is not supported. +.Pp .It Ic window-status-activity-style Ar style Set status line style for windows with an activity alert. For how to specify @@ -4279,6 +4454,13 @@ The default is on. Available pane options are: .Pp .Bl -tag -width Ds -compact +.It Xo Ic allow-passthrough +.Op Ic on | off +.Xc +Allow programs in the pane to bypass +.Nm +using a terminal escape sequence (\eePtmux;...\ee\e\e). +.Pp .It Xo Ic allow-rename .Op Ic on | off .Xc @@ -4299,6 +4481,27 @@ The alternate screen feature preserves the contents of the window when an interactive application starts and restores it on exit, so that any output visible before the application starts reappears unchanged after it exits. .Pp +.It Ic cursor-colour Ar colour +Set the colour of the cursor. +.Pp +.It Ic pane-colours[] Ar colour +The default colour palette. +Each entry in the array defines the colour +.Nm +uses when the colour with that index is requested. +The index may be from zero to 255. +.Pp +.It Ic cursor-style Ar style +Set the style of the cursor. +Available styles are: +.Ic default , +.Ic blinking-block , +.Ic block , +.Ic blinking-underline , +.Ic underline , +.Ic blinking-bar , +.Ic bar . +.Pp .It Xo Ic remain-on-exit .Op Ic on | off | failed .Xc @@ -4311,6 +4514,17 @@ The pane may be reactivated with the .Ic respawn-pane command. .Pp +.It Ic remain-on-exit-format Ar string +Set the text shown at the bottom of exited panes when +.Ic remain-on-exit +is enabled. +.Pp +.It Xo Ic scroll-on-clear +.Op Ic on | off +.Xc +When the entire screen is cleared and this option is on, scroll the contents of +the screen into history before clearing it. +.Pp .It Xo Ic synchronize-panes .Op Ic on | off .Xc @@ -4395,10 +4609,16 @@ See Run when a window has been silent. See .Ic monitor-silence . +.It client-active +Run when a client becomes the latest active client of its session. .It client-attached Run when a client is attached. .It client-detached Run when a client is detached +.It client-focus-in +Run when focus enters a client +.It client-focus-out +Run when focus exits a client .It client-resized Run when a client is resized. .It client-session-changed @@ -4431,6 +4651,11 @@ Run when a session is renamed. Run when a window is linked into a session. .It window-renamed Run when a window is renamed. +.It window-resized +Run when a window is resized. +This may be after the +.Ar client-resized +hook is run. .It window-unlinked Run when a window is unlinked from a session. .El @@ -4701,6 +4926,10 @@ replaces a numeric argument by its ASCII equivalent, so .Ql #{a:98} results in .Ql b . +.Ql c +replaces a +.Nm +colour by its six-digit hexadecimal RGB value. .Pp A limit may be placed on the length of the resultant string by prefixing it by an @@ -4841,7 +5070,9 @@ commands to finish; instead, the previous result from running the same command i or a placeholder if the command has not been run before. If the command hasn't exited, the most recent line of output will be used, but the status line will not be updated more than once a second. -Commands are executed with the +Commands are executed using +.Pa /bin/sh +and with the .Nm global environment set (see the .Sx GLOBAL AND SESSION ENVIRONMENT @@ -4879,12 +5110,14 @@ The following variables are available, where appropriate: .It Li "client_name" Ta "" Ta "Name of client" .It Li "client_pid" Ta "" Ta "PID of client process" .It Li "client_prefix" Ta "" Ta "1 if prefix key has been pressed" -.It Li "client_readonly" Ta "" Ta "1 if client is readonly" +.It Li "client_readonly" Ta "" Ta "1 if client is read-only" .It Li "client_session" Ta "" Ta "Name of the client's session" .It Li "client_termfeatures" Ta "" Ta "Terminal features of client, if any" .It Li "client_termname" Ta "" Ta "Terminal name of client" .It Li "client_termtype" Ta "" Ta "Terminal type of client, if available" .It Li "client_tty" Ta "" Ta "Pseudo terminal of client" +.It Li "client_uid" Ta "" Ta "UID of client process" +.It Li "client_user" Ta "" Ta "User of client process" .It Li "client_utf8" Ta "" Ta "1 if client supports UTF-8" .It Li "client_width" Ta "" Ta "Width of client" .It Li "client_written" Ta "" Ta "Bytes written to client" @@ -4906,6 +5139,7 @@ The following variables are available, where appropriate: .It Li "history_limit" Ta "" Ta "Maximum window history lines" .It Li "history_size" Ta "" Ta "Size of history in lines" .It Li "hook" Ta "" Ta "Name of running hook, if any" +.It Li "hook_client" Ta "" Ta "Name of client where hook was run, if any" .It Li "hook_pane" Ta "" Ta "ID of pane where hook was run, if any" .It Li "hook_session" Ta "" Ta "ID of session where hook was run, if any" .It Li "hook_session_name" Ta "" Ta "Name of session where hook was run, if any" @@ -4928,6 +5162,7 @@ The following variables are available, where appropriate: .It Li "mouse_word" Ta "" Ta "Word under mouse, if any" .It Li "mouse_x" Ta "" Ta "Mouse X position, if any" .It Li "mouse_y" Ta "" Ta "Mouse Y position, if any" +.It Li "next_session_id" Ta "" Ta "Unique session ID for next new session" .It Li "origin_flag" Ta "" Ta "Pane origin flag" .It Li "pane_active" Ta "" Ta "1 if active pane" .It Li "pane_at_bottom" Ta "" Ta "1 if pane is at the bottom of window" @@ -4939,7 +5174,9 @@ The following variables are available, where appropriate: .It Li "pane_current_command" Ta "" Ta "Current command if available" .It Li "pane_current_path" Ta "" Ta "Current path if available" .It Li "pane_dead" Ta "" Ta "1 if pane is dead" +.It Li "pane_dead_signal" Ta "" Ta "Exit signal of process in dead pane" .It Li "pane_dead_status" Ta "" Ta "Exit status of process in dead pane" +.It Li "pane_dead_time" Ta "" Ta "Exit time of process in dead pane" .It Li "pane_fg" Ta "" Ta "Pane foreground colour" .It Li "pane_format" Ta "" Ta "1 if format is for a pane" .It Li "pane_height" Ta "" Ta "Height of pane" @@ -4958,6 +5195,7 @@ The following variables are available, where appropriate: .It Li "pane_right" Ta "" Ta "Right of pane" .It Li "pane_search_string" Ta "" Ta "Last search string in copy mode" .It Li "pane_start_command" Ta "" Ta "Command pane started with" +.It Li "pane_start_path" Ta "" Ta "Path pane started with" .It Li "pane_synchronized" Ta "" Ta "1 if pane is synchronized" .It Li "pane_tabs" Ta "" Ta "Pane tab positions" .It Li "pane_title" Ta "#T" Ta "Title of pane (can be set by application)" @@ -5000,6 +5238,8 @@ The following variables are available, where appropriate: .It Li "session_windows" Ta "" Ta "Number of windows in session" .It Li "socket_path" Ta "" Ta "Server socket path" .It Li "start_time" Ta "" Ta "Server start time" +.It Li "uid" Ta "" Ta "Server UID" +.It Li "user" Ta "" Ta "Server user" .It Li "version" Ta "" Ta "Server version" .It Li "window_active" Ta "" Ta "1 if window active" .It Li "window_active_clients" Ta "" Ta "Number of clients viewing this window" @@ -5014,7 +5254,6 @@ The following variables are available, where appropriate: .It Li "window_cell_width" Ta "" Ta "Width of each cell in pixels" .It Li "window_end_flag" Ta "" Ta "1 if window has the highest index" .It Li "window_flags" Ta "#F" Ta "Window flags with # escaped as ##" -.It Li "window_raw_flags" Ta "" Ta "Window flags with nothing escaped" .It Li "window_format" Ta "" Ta "1 if format is for a window" .It Li "window_height" Ta "" Ta "Height of window" .It Li "window_id" Ta "" Ta "Unique window ID" @@ -5029,6 +5268,7 @@ The following variables are available, where appropriate: .It Li "window_offset_x" Ta "" Ta "X offset into window if larger than client" .It Li "window_offset_y" Ta "" Ta "Y offset into window if larger than client" .It Li "window_panes" Ta "" Ta "Number of panes in window" +.It Li "window_raw_flags" Ta "" Ta "Window flags with nothing escaped" .It Li "window_silence_flag" Ta "" Ta "1 if window has silence alert" .It Li "window_stack_index" Ta "" Ta "Index in session most recent stack" .It Li "window_start_flag" Ta "" Ta "1 if window has the lowest index" @@ -5271,12 +5511,13 @@ section). .Pp Commands to alter and view the environment are: .Bl -tag -width Ds +.Tg setenv .It Xo Ic set-environment .Op Fl Fhgru .Op Fl t Ar target-session .Ar name Op Ar value .Xc -.D1 (alias: Ic setenv ) +.D1 Pq alias: Ic setenv Set or unset an environment variable. If .Fl g @@ -5296,12 +5537,13 @@ indicates the variable is to be removed from the environment before starting a new process. .Fl h marks the variable as hidden. +.Tg showenv .It Xo Ic show-environment .Op Fl hgs .Op Fl t Ar target-session .Op Ar variable .Xc -.D1 (alias: Ic showenv ) +.D1 Pq alias: Ic showenv Display the environment for .Ar target-session or the global environment with @@ -5380,11 +5622,26 @@ session option. .Pp Commands related to the status line are as follows: .Bl -tag -width Ds +.Tg clearphist +.It Xo Ic clear-prompt-history +.Op Fl T Ar prompt-type +.Xc +.D1 Pq alias: Ic clearphist +Clear status prompt history for prompt type +.Ar prompt-type . +If +.Fl T +is omitted, then clear history for all types. +See +.Ic command-prompt +for possible values for +.Ar prompt-type . .It Xo Ic command-prompt -.Op Fl 1ikNTW +.Op Fl 1bFikN .Op Fl I Ar inputs .Op Fl p Ar prompts .Op Fl t Ar target-client +.Op Fl T Ar prompt-type .Op Ar template .Xc Open the command prompt in a client. @@ -5395,6 +5652,11 @@ to execute commands interactively. If .Ar template is specified, it is used as the command. +With +.Fl F , +.Ar template +is expanded as a format. +.Pp If present, .Fl I is a comma-separated list of the initial text for each prompt. @@ -5440,14 +5702,20 @@ makes the prompt only accept numeric key presses. .Fl i executes the command every time the prompt input changes instead of when the user exits the command prompt. +.Pp .Fl T tells .Nm -that the prompt is for a target which affects what completions are offered when +the prompt type. +This affects what completions are offered when .Em Tab -is pressed; -.Fl W -is similar but indicates the prompt is for a window. +is pressed. +Available types are: +.Ql command , +.Ql search , +.Ql target +and +.Ql window-target . .Pp The following keys have a special meaning in the command prompt, depending on the value of the @@ -5472,12 +5740,19 @@ option: .It Li "Move cursor to start" Ta "0" Ta "C-a" .It Li "Transpose characters" Ta "" Ta "C-t" .El +.Pp +With +.Fl b , +the prompt is shown in the background and the invoking client does not exit +until it is dismissed. +.Tg confirm .It Xo Ic confirm-before +.Op Fl b .Op Fl p Ar prompt .Op Fl t Ar target-client .Ar command .Xc -.D1 (alias: Ic confirm ) +.D1 Pq alias: Ic confirm Ask for confirmation before executing .Ar command . If @@ -5489,9 +5764,11 @@ is the prompt to display; otherwise a prompt is constructed from It may contain the special character sequences supported by the .Ic status-left option. -.Pp -This command works only from inside -.Nm . +With +.Fl b , +the prompt is shown in the background and the invoking client does not exit +until it is dismissed. +.Tg menu .It Xo Ic display-menu .Op Fl O .Op Fl c Ar target-client @@ -5504,7 +5781,7 @@ This command works only from inside .Ar command .Ar ... .Xc -.D1 (alias: Ic menu ) +.D1 Pq alias: Ic menu Display a menu on .Ar target-client . .Ar target-pane @@ -5583,6 +5860,7 @@ The following keys are also available: .It Li "Down" Ta "Select next item" .It Li "q" Ta "Exit menu" .El +.Tg display .It Xo Ic display-message .Op Fl aINpv .Op Fl c Ar target-client @@ -5590,7 +5868,7 @@ The following keys are also available: .Op Fl t Ar target-pane .Op Ar message .Xc -.D1 (alias: Ic display ) +.D1 Pq alias: Ic display Display a message. If .Fl p @@ -5602,7 +5880,7 @@ milliseconds. If .Ar delay is not given, the -.Ic message-time +.Ic display-time option is used; a delay of zero waits for a key press. .Ql N ignores key presses and closes only after the delay expires. @@ -5624,18 +5902,24 @@ lists the format variables and their values. .Fl I forwards any input read from stdin to the empty pane given by .Ar target-pane . +.Tg popup .It Xo Ic display-popup -.Op Fl CE +.Op Fl BCE +.Op Fl b Ar border-lines .Op Fl c Ar target-client .Op Fl d Ar start-directory +.Op Fl e Ar environment .Op Fl h Ar height +.Op Fl s Ar style +.Op Fl S Ar border-style .Op Fl t Ar target-pane +.Op Fl T Ar title .Op Fl w Ar width .Op Fl x Ar position .Op Fl y Ar position .Op Ar shell-command .Xc -.D1 (alias: Ic popup ) +.D1 Pq alias: Ic popup Display a popup running .Ar shell-command on @@ -5666,9 +5950,58 @@ give the width and height - both may be a percentage (followed by .Ql % ) . If omitted, half of the terminal size is used. .Pp +.Fl B +does not surround the popup by a border. +.Pp +.Fl b +sets the type of border line for the popup. +When +.Fl B +is specified, the +.Fl b +option is ignored. +See +.Ic popup-border-lines +for possible values for +.Ar border-lines . +.Pp +.Fl s +sets the style for the popup and +.Fl S +sets the style for the popup border. +For how to specify +.Ar style , +see the +.Sx STYLES +section. +.Pp +.Fl e +takes the form +.Ql VARIABLE=value +and sets an environment variable for the popup; it may be specified multiple +times. +.Pp +.Fl T +is a format for the popup title (see +.Sx FORMATS ) . +.Pp The .Fl C flag closes any popup on the client. +.Tg showphist +.It Xo Ic show-prompt-history +.Op Fl T Ar prompt-type +.Xc +.D1 Pq alias: Ic showphist +Display status prompt history for prompt type +.Ar prompt-type . +If +.Fl T +is omitted, then show history for all types. +See +.Ic command-prompt +for possible values for +.Ar prompt-type . .El .Sh BUFFERS .Nm @@ -5785,19 +6118,22 @@ a format for each shortcut key; both are evaluated once for each line. .Fl N starts without the preview. This command works only if at least one client is attached. +.Tg clearhist .It Ic clear-history Op Fl t Ar target-pane -.D1 (alias: Ic clearhist ) +.D1 Pq alias: Ic clearhist Remove and free the history for the specified pane. +.Tg deleteb .It Ic delete-buffer Op Fl b Ar buffer-name -.D1 (alias: Ic deleteb ) +.D1 Pq alias: Ic deleteb Delete the buffer named .Ar buffer-name , or the most recently added automatically named buffer if not specified. +.Tg lsb .It Xo Ic list-buffers .Op Fl F Ar format .Op Fl f Ar filter .Xc -.D1 (alias: Ic lsb ) +.D1 Pq alias: Ic lsb List the global buffers. .Fl F specifies the format of each line and @@ -5813,7 +6149,8 @@ section. .Op Fl t Ar target-client .Ar path .Xc -.D1 (alias: Ic loadb ) +.Tg loadb +.D1 Pq alias: Ic loadb Load the contents of the specified paste buffer from .Ar path . If @@ -5823,13 +6160,14 @@ is given, the buffer is also sent to the clipboard for using the .Xr xterm 1 escape sequence, if possible. +.Tg pasteb .It Xo Ic paste-buffer .Op Fl dpr .Op Fl b Ar buffer-name .Op Fl s Ar separator .Op Fl t Ar target-pane .Xc -.D1 (alias: Ic pasteb ) +.D1 Pq alias: Ic pasteb Insert the contents of a paste buffer into the specified pane. If not specified, paste into the current one. With @@ -5847,12 +6185,13 @@ If .Fl p is specified, paste bracket control codes are inserted around the buffer if the application has requested bracketed paste mode. +.Tg saveb .It Xo Ic save-buffer .Op Fl a .Op Fl b Ar buffer-name .Ar path .Xc -.D1 (alias: Ic saveb ) +.D1 Pq alias: Ic saveb Save the contents of the specified paste buffer to .Ar path . The @@ -5862,10 +6201,11 @@ option appends to rather than overwriting the file. .Op Fl aw .Op Fl b Ar buffer-name .Op Fl t Ar target-client +.Tg setb .Op Fl n Ar new-buffer-name .Ar data .Xc -.D1 (alias: Ic setb ) +.D1 Pq alias: Ic setb Set the contents of the specified buffer to .Ar data . If @@ -5882,10 +6222,11 @@ The .Fl n option renames the buffer to .Ar new-buffer-name . +.Tg showb .It Xo Ic show-buffer .Op Fl b Ar buffer-name .Xc -.D1 (alias: Ic showb ) +.D1 Pq alias: Ic showb Display the contents of the specified buffer. .El .Sh MISCELLANEOUS @@ -5893,17 +6234,20 @@ Miscellaneous commands are as follows: .Bl -tag -width Ds .It Ic clock-mode Op Fl t Ar target-pane Display a large clock. +.Tg if .It Xo Ic if-shell .Op Fl bF .Op Fl t Ar target-pane .Ar shell-command command .Op Ar command .Xc -.D1 (alias: Ic if ) +.D1 Pq alias: Ic if Execute the first .Ar command if .Ar shell-command +(run with +.Pa /bin/sh ) returns success or the second .Ar command otherwise. @@ -5924,20 +6268,24 @@ is given, .Ar shell-command is not executed but considered success if neither empty nor zero (after formats are expanded). +.Tg lock .It Ic lock-server -.D1 (alias: Ic lock ) +.D1 Pq alias: Ic lock Lock each client individually by running the command specified by the .Ic lock-command option. +.Tg run .It Xo Ic run-shell .Op Fl bC .Op Fl d Ar delay .Op Fl t Ar target-pane .Op Ar shell-command .Xc -.D1 (alias: Ic run ) +.D1 Pq alias: Ic run Execute .Ar shell-command +using +.Pa /bin/sh or (with .Fl C ) a @@ -5962,11 +6310,12 @@ specified by .Fl t or the current pane if omitted) after the command finishes. If the command fails, the exit status is also displayed. +.Tg wait .It Xo Ic wait-for .Op Fl L | S | U .Ar channel .Xc -.D1 (alias: Ic wait ) +.D1 Pq alias: Ic wait When used without options, prevents the client from exiting until woken using .Ic wait-for .Fl S @@ -6038,6 +6387,11 @@ to change the cursor colour from inside .Bd -literal -offset indent $ printf '\e033]12;red\e033\e\e' .Ed +.Pp +The colour is an +.Xr X 7 +colour, see +.Xr XParseColor 3 . .It Em \&Cmg, \&Clmg, \&Dsmg , \&Enmg Set, clear, disable or enable DECSLRM margins. These are set automatically if the terminal reports it is @@ -6081,6 +6435,11 @@ $ printf '\e033[4 q' If .Em Se is not set, \&Ss with argument 0 will be used to reset the cursor style instead. +.It Em \&Swd +Set the opening sequence for the working directory notification. +The sequence is terminated using the standard +.Em fsl +capability. .It Em \&Sync Start (parameter is 1) or end (parameter is 2) a synchronized update. .It Em \&Tc @@ -6253,6 +6612,14 @@ are for future use and should be ignored. The window with ID .Ar window-id was created but is not linked to the current session. +.It Ic %unlinked-window-close Ar window-id +The window with ID +.Ar window-id , +which is not linked to the current session, was closed. +.It Ic %unlinked-window-renamed Ar window-id +The window with ID +.Ar window-id , +which is not linked to the current session, was renamed. .It Ic %window-add Ar window-id The window with ID .Ar window-id @@ -6311,7 +6678,7 @@ are replaced with underscores For input, .Nm always runs with a UTF-8 locale. -If en_US.UTF-8 is provided by the operating system it is used and +If en_US.UTF-8 is provided by the operating system, it is used and .Ev LC_CTYPE is ignored for input. Otherwise, @@ -6360,6 +6727,8 @@ options. .Sh FILES .Bl -tag -width "@SYSCONFDIR@/tmux.confXXX" -compact .It Pa ~/.tmux.conf +.It Pa $XDG_CONFIG_HOME/tmux/tmux.conf +.It Pa ~/.config/tmux/tmux.conf Default .Nm configuration file. diff --git a/external/bsd/tmux/dist/tmux.c b/external/bsd/tmux/dist/tmux.c index 29921781eeb..b9f2be30bab 100644 --- a/external/bsd/tmux/dist/tmux.c +++ b/external/bsd/tmux/dist/tmux.c @@ -207,16 +207,23 @@ make_label(const char *label, char **cause) free(paths); xasprintf(&base, "%s/tmux-%ld", path, (long)uid); - if (mkdir(base, S_IRWXU) != 0 && errno != EEXIST) + free(path); + if (mkdir(base, S_IRWXU) != 0 && errno != EEXIST) { + xasprintf(cause, "couldn't create directory %s (%s)", base, + strerror(errno)); goto fail; - if (lstat(base, &sb) != 0) + } + if (lstat(base, &sb) != 0) { + xasprintf(cause, "couldn't read directory %s (%s)", base, + strerror(errno)); goto fail; + } if (!S_ISDIR(sb.st_mode)) { - errno = ENOTDIR; + xasprintf(cause, "%s is not a directory", base); goto fail; } if (sb.st_uid != uid || (sb.st_mode & S_IRWXO) != 0) { - errno = EACCES; + xasprintf(cause, "directory %s has unsafe permissions", base); goto fail; } xasprintf(&path, "%s/%s", base, label); @@ -224,7 +231,6 @@ make_label(const char *label, char **cause) return (path); fail: - xasprintf(cause, "error creating %s (%s)", base, strerror(errno)); free(base); return (NULL); } @@ -319,7 +325,7 @@ find_home(void) const char * getversion(void) { - return TMUX_VERSION; + return (TMUX_VERSION); } int diff --git a/external/bsd/tmux/dist/tmux.h b/external/bsd/tmux/dist/tmux.h index a4c10659ef1..53084b8b071 100644 --- a/external/bsd/tmux/dist/tmux.h +++ b/external/bsd/tmux/dist/tmux.h @@ -32,12 +32,13 @@ #endif #include "compat.h" +#include "tmux-protocol.h" #include "xmalloc.h" extern char **environ; struct args; -struct args_value; +struct args_command_state; struct client; struct cmd; struct cmd_find_state; @@ -51,6 +52,7 @@ struct format_job_tree; struct format_tree; struct input_ctx; struct job; +struct menu_data; struct mode_tree_data; struct mouse_event; struct options; @@ -61,13 +63,12 @@ struct screen_write_cline; struct screen_write_ctx; struct session; struct tty_ctx; +struct tty_code; +struct tty_key; struct tmuxpeer; struct tmuxproc; struct winlink; -/* Client-server protocol version. */ -#define PROTOCOL_VERSION 8 - /* Default configuration files and socket paths. */ #ifndef TMUX_CONF #define TMUX_CONF "/etc/tmux.conf:~/.tmux.conf" @@ -75,6 +76,9 @@ struct winlink; #ifndef TMUX_SOCK #define TMUX_SOCK "$TMUX_TMPDIR:" _PATH_TMP #endif +#ifndef TMUX_TERM +#define TMUX_TERM "screen" +#endif /* Minimum layout cell size, NOT including border lines. */ #define PANE_MINIMUM 1 @@ -131,6 +135,7 @@ struct winlink; #define KEYC_CURSOR 0x04000000000000ULL #define KEYC_IMPLIED_META 0x08000000000000ULL #define KEYC_BUILD_MODIFIERS 0x10000000000000ULL +#define KEYC_VI 0x20000000000000ULL /* Masks for key bits. */ #define KEYC_MASK_MODIFIERS 0x00f00000000000ULL @@ -197,26 +202,68 @@ enum { KEYC_MOUSE_KEY(MOUSEDOWN1), KEYC_MOUSE_KEY(MOUSEDOWN2), KEYC_MOUSE_KEY(MOUSEDOWN3), + KEYC_MOUSE_KEY(MOUSEDOWN6), + KEYC_MOUSE_KEY(MOUSEDOWN7), + KEYC_MOUSE_KEY(MOUSEDOWN8), + KEYC_MOUSE_KEY(MOUSEDOWN9), + KEYC_MOUSE_KEY(MOUSEDOWN10), + KEYC_MOUSE_KEY(MOUSEDOWN11), KEYC_MOUSE_KEY(MOUSEUP1), KEYC_MOUSE_KEY(MOUSEUP2), KEYC_MOUSE_KEY(MOUSEUP3), + KEYC_MOUSE_KEY(MOUSEUP6), + KEYC_MOUSE_KEY(MOUSEUP7), + KEYC_MOUSE_KEY(MOUSEUP8), + KEYC_MOUSE_KEY(MOUSEUP9), + KEYC_MOUSE_KEY(MOUSEUP10), + KEYC_MOUSE_KEY(MOUSEUP11), KEYC_MOUSE_KEY(MOUSEDRAG1), KEYC_MOUSE_KEY(MOUSEDRAG2), KEYC_MOUSE_KEY(MOUSEDRAG3), + KEYC_MOUSE_KEY(MOUSEDRAG6), + KEYC_MOUSE_KEY(MOUSEDRAG7), + KEYC_MOUSE_KEY(MOUSEDRAG8), + KEYC_MOUSE_KEY(MOUSEDRAG9), + KEYC_MOUSE_KEY(MOUSEDRAG10), + KEYC_MOUSE_KEY(MOUSEDRAG11), KEYC_MOUSE_KEY(MOUSEDRAGEND1), KEYC_MOUSE_KEY(MOUSEDRAGEND2), KEYC_MOUSE_KEY(MOUSEDRAGEND3), + KEYC_MOUSE_KEY(MOUSEDRAGEND6), + KEYC_MOUSE_KEY(MOUSEDRAGEND7), + KEYC_MOUSE_KEY(MOUSEDRAGEND8), + KEYC_MOUSE_KEY(MOUSEDRAGEND9), + KEYC_MOUSE_KEY(MOUSEDRAGEND10), + KEYC_MOUSE_KEY(MOUSEDRAGEND11), KEYC_MOUSE_KEY(WHEELUP), KEYC_MOUSE_KEY(WHEELDOWN), KEYC_MOUSE_KEY(SECONDCLICK1), KEYC_MOUSE_KEY(SECONDCLICK2), KEYC_MOUSE_KEY(SECONDCLICK3), + KEYC_MOUSE_KEY(SECONDCLICK6), + KEYC_MOUSE_KEY(SECONDCLICK7), + KEYC_MOUSE_KEY(SECONDCLICK8), + KEYC_MOUSE_KEY(SECONDCLICK9), + KEYC_MOUSE_KEY(SECONDCLICK10), + KEYC_MOUSE_KEY(SECONDCLICK11), KEYC_MOUSE_KEY(DOUBLECLICK1), KEYC_MOUSE_KEY(DOUBLECLICK2), KEYC_MOUSE_KEY(DOUBLECLICK3), + KEYC_MOUSE_KEY(DOUBLECLICK6), + KEYC_MOUSE_KEY(DOUBLECLICK7), + KEYC_MOUSE_KEY(DOUBLECLICK8), + KEYC_MOUSE_KEY(DOUBLECLICK9), + KEYC_MOUSE_KEY(DOUBLECLICK10), + KEYC_MOUSE_KEY(DOUBLECLICK11), KEYC_MOUSE_KEY(TRIPLECLICK1), KEYC_MOUSE_KEY(TRIPLECLICK2), KEYC_MOUSE_KEY(TRIPLECLICK3), + KEYC_MOUSE_KEY(TRIPLECLICK6), + KEYC_MOUSE_KEY(TRIPLECLICK7), + KEYC_MOUSE_KEY(TRIPLECLICK8), + KEYC_MOUSE_KEY(TRIPLECLICK9), + KEYC_MOUSE_KEY(TRIPLECLICK10), + KEYC_MOUSE_KEY(TRIPLECLICK11), /* Backspace key. */ KEYC_BSPACE, @@ -493,6 +540,7 @@ enum tty_code_code { TTYC_SMULX, TTYC_SMXX, TTYC_SS, + TTYC_SWD, TTYC_SYNC, TTYC_TC, TTYC_TSL, @@ -501,94 +549,8 @@ enum tty_code_code { TTYC_XT }; -/* Message codes. */ -enum msgtype { - MSG_VERSION = 12, - - MSG_IDENTIFY_FLAGS = 100, - MSG_IDENTIFY_TERM, - MSG_IDENTIFY_TTYNAME, - MSG_IDENTIFY_OLDCWD, /* unused */ - MSG_IDENTIFY_STDIN, - MSG_IDENTIFY_ENVIRON, - MSG_IDENTIFY_DONE, - MSG_IDENTIFY_CLIENTPID, - MSG_IDENTIFY_CWD, - MSG_IDENTIFY_FEATURES, - MSG_IDENTIFY_STDOUT, - MSG_IDENTIFY_LONGFLAGS, - MSG_IDENTIFY_TERMINFO, - - MSG_COMMAND = 200, - MSG_DETACH, - MSG_DETACHKILL, - MSG_EXIT, - MSG_EXITED, - MSG_EXITING, - MSG_LOCK, - MSG_READY, - MSG_RESIZE, - MSG_SHELL, - MSG_SHUTDOWN, - MSG_OLDSTDERR, /* unused */ - MSG_OLDSTDIN, /* unused */ - MSG_OLDSTDOUT, /* unused */ - MSG_SUSPEND, - MSG_UNLOCK, - MSG_WAKEUP, - MSG_EXEC, - MSG_FLAGS, - - MSG_READ_OPEN = 300, - MSG_READ, - MSG_READ_DONE, - MSG_WRITE_OPEN, - MSG_WRITE, - MSG_WRITE_READY, - MSG_WRITE_CLOSE -}; - -/* - * Message data. - * - * Don't forget to bump PROTOCOL_VERSION if any of these change! - */ -struct msg_command { - int argc; -}; /* followed by packed argv */ - -struct msg_read_open { - int stream; - int fd; -}; /* followed by path */ - -struct msg_read_data { - int stream; -}; - -struct msg_read_done { - int stream; - int error; -}; - -struct msg_write_open { - int stream; - int fd; - int flags; -}; /* followed by path */ - -struct msg_write_data { - int stream; -}; /* followed by data */ - -struct msg_write_ready { - int stream; - int error; -}; - -struct msg_write_close { - int stream; -}; +/* Character classes. */ +#define WHITESPACE " " /* Mode keys. */ #define MODEKEY_EMACS 0 @@ -602,7 +564,7 @@ struct msg_write_close { #define MODE_WRAP 0x10 #define MODE_MOUSE_STANDARD 0x20 #define MODE_MOUSE_BUTTON 0x40 -#define MODE_BLINKING 0x80 +#define MODE_CURSOR_BLINKING 0x80 #define MODE_MOUSE_UTF8 0x100 #define MODE_MOUSE_SGR 0x200 #define MODE_BRACKETPASTE 0x400 @@ -611,10 +573,19 @@ struct msg_write_close { #define MODE_ORIGIN 0x2000 #define MODE_CRLF 0x4000 #define MODE_KEXTENDED 0x8000 +#define MODE_CURSOR_VERY_VISIBLE 0x10000 +#define MODE_CURSOR_BLINKING_SET 0x20000 #define ALL_MODES 0xffffff #define ALL_MOUSE_MODES (MODE_MOUSE_STANDARD|MODE_MOUSE_BUTTON|MODE_MOUSE_ALL) #define MOTION_MOUSE_MODES (MODE_MOUSE_BUTTON|MODE_MOUSE_ALL) +#define CURSOR_MODES (MODE_CURSOR|MODE_CURSOR_BLINKING|MODE_CURSOR_VERY_VISIBLE) + +/* Mouse protocol constants. */ +#define MOUSE_PARAM_MAX 0xff +#define MOUSE_PARAM_UTF8_MAX 0x7ff +#define MOUSE_PARAM_BTN_OFF 0x20 +#define MOUSE_PARAM_POS_OFF 0x21 /* A single UTF-8 character. */ typedef u_int utf8_char; @@ -646,6 +617,15 @@ enum utf8_state { /* Special colours. */ #define COLOUR_DEFAULT(c) ((c) == 8 || (c) == 9) +/* Replacement palette. */ +struct colour_palette { + int fg; + int bg; + + int *palette; + int *default_palette; +}; + /* Grid attributes. Anything above 0xff is stored in an extended cell. */ #define GRID_ATTR_BRIGHT 0x1 #define GRID_ATTR_DIM 0x2 @@ -684,6 +664,24 @@ enum utf8_state { #define GRID_LINE_EXTENDED 0x2 #define GRID_LINE_DEAD 0x4 +#define CELL_INSIDE 0 +#define CELL_TOPBOTTOM 1 +#define CELL_LEFTRIGHT 2 +#define CELL_TOPLEFT 3 +#define CELL_TOPRIGHT 4 +#define CELL_BOTTOMLEFT 5 +#define CELL_BOTTOMRIGHT 6 +#define CELL_TOPJOIN 7 +#define CELL_BOTTOMJOIN 8 +#define CELL_LEFTJOIN 9 +#define CELL_RIGHTJOIN 10 +#define CELL_JOIN 11 +#define CELL_OUTSIDE 12 + +#define CELL_BORDERS " xqlkmjwvtun~" +#define SIMPLE_BORDERS " |-+++++++++." +#define PADDED_BORDERS " " + /* Grid cell data. */ struct grid_cell { struct utf8_data data; @@ -720,15 +718,15 @@ struct grid_cell_entry { /* Grid line. */ struct grid_line { + struct grid_cell_entry *celldata; u_int cellused; u_int cellsize; - struct grid_cell_entry *celldata; - u_int extdsize; struct grid_extd_entry *extddata; + u_int extdsize; int flags; -} __packed; +}; /* Entire grid of cells. */ struct grid { @@ -810,6 +808,14 @@ struct style { enum style_default_type default_type; }; +/* Cursor style. */ +enum screen_cursor_style { + SCREEN_CURSOR_DEFAULT, + SCREEN_CURSOR_BLOCK, + SCREEN_CURSOR_UNDERLINE, + SCREEN_CURSOR_BAR +}; + /* Virtual screen. */ struct screen_sel; struct screen_titles; @@ -823,13 +829,16 @@ struct screen { u_int cx; /* cursor x */ u_int cy; /* cursor y */ - u_int cstyle; /* cursor style */ - char *ccolour; /* cursor colour string */ + enum screen_cursor_style cstyle; /* cursor style */ + enum screen_cursor_style default_cstyle; + int ccolour; /* cursor colour */ + int default_ccolour; u_int rupper; /* scroll region top */ u_int rlower; /* scroll region bottom */ int mode; + int default_mode; u_int saved_cx; u_int saved_cy; @@ -852,6 +861,7 @@ struct screen_write_ctx { int flags; #define SCREEN_WRITE_SYNC 0x1 +#define SCREEN_WRITE_ZWJ 0x2 screen_write_init_ctx_cb init_ctx_cb; void *arg; @@ -861,6 +871,33 @@ struct screen_write_ctx { u_int bg; }; +/* Box border lines option. */ +enum box_lines { + BOX_LINES_DEFAULT = -1, + BOX_LINES_SINGLE, + BOX_LINES_DOUBLE, + BOX_LINES_HEAVY, + BOX_LINES_SIMPLE, + BOX_LINES_ROUNDED, + BOX_LINES_PADDED, + BOX_LINES_NONE +}; + +/* Pane border lines option. */ +enum pane_lines { + PANE_LINES_SINGLE, + PANE_LINES_DOUBLE, + PANE_LINES_HEAVY, + PANE_LINES_SIMPLE, + PANE_LINES_NUMBER +}; + +/* Pane border indicator option. */ +#define PANE_BORDER_OFF 0 +#define PANE_BORDER_COLOUR 1 +#define PANE_BORDER_ARROWS 2 +#define PANE_BORDER_BOTH 3 + /* Screen redraw context. */ struct screen_redraw_ctx { struct client *c; @@ -869,7 +906,10 @@ struct screen_redraw_ctx { int statustop; int pane_status; - int pane_lines; + enum pane_lines pane_lines; + + struct grid_cell no_pane_gc; + int no_pane_gc_set; u_int sx; u_int sy; @@ -971,16 +1011,13 @@ struct window_pane { u_int xoff; u_int yoff; - int fg; - int bg; - int flags; #define PANE_REDRAW 0x1 #define PANE_DROP 0x2 #define PANE_FOCUSED 0x4 /* 0x8 unused */ /* 0x10 unused */ -#define PANE_FOCUSPUSH 0x20 +/* 0x20 unused */ #define PANE_INPUTOFF 0x40 #define PANE_CHANGED 0x80 #define PANE_EXITED 0x100 @@ -997,6 +1034,7 @@ struct window_pane { pid_t pid; char tty[TTY_NAME_MAX]; int status; + struct timeval dead_time; int fd; struct bufferevent *event; @@ -1011,7 +1049,7 @@ struct window_pane { struct grid_cell cached_gc; struct grid_cell cached_active_gc; - int *palette; + struct colour_palette palette; int pipe_fd; struct bufferevent *pipe_event; @@ -1039,38 +1077,41 @@ RB_HEAD(window_pane_tree, window_pane); /* Window structure. */ struct window { - u_int id; - void *latest; + u_int id; + void *latest; - char *name; - struct event name_event; - struct timeval name_time; + char *name; + struct event name_event; + struct timeval name_time; - struct event alerts_timer; - struct event offset_timer; + struct event alerts_timer; + struct event offset_timer; - struct timeval activity_time; + struct timeval activity_time; - struct window_pane *active; - struct window_pane *last; - struct window_panes panes; + struct window_pane *active; + struct window_pane *last; + struct window_panes panes; - int lastlayout; - struct layout_cell *layout_root; - struct layout_cell *saved_layout_root; - char *old_layout; + int lastlayout; + struct layout_cell *layout_root; + struct layout_cell *saved_layout_root; + char *old_layout; - u_int sx; - u_int sy; - u_int xpixel; - u_int ypixel; + u_int sx; + u_int sy; + u_int manual_sx; + u_int manual_sy; + u_int xpixel; + u_int ypixel; - u_int new_sx; - u_int new_sy; - u_int new_xpixel; - u_int new_ypixel; + u_int new_sx; + u_int new_sy; + u_int new_xpixel; + u_int new_ypixel; - int flags; + struct utf8_data *fill_character; + int flags; #define WINDOW_BELL 0x1 #define WINDOW_ACTIVITY 0x2 #define WINDOW_SILENCE 0x4 @@ -1079,15 +1120,15 @@ struct window { #define WINDOW_RESIZE 0x20 #define WINDOW_ALERTFLAGS (WINDOW_BELL|WINDOW_ACTIVITY|WINDOW_SILENCE) - int alerts_queued; - TAILQ_ENTRY(window) alerts_entry; + int alerts_queued; + TAILQ_ENTRY(window) alerts_entry; - struct options *options; + struct options *options; - u_int references; - TAILQ_HEAD(, winlink) winlinks; + u_int references; + TAILQ_HEAD(, winlink) winlinks; - RB_ENTRY(window) entry; + RB_ENTRY(window) entry; }; RB_HEAD(windows, window); @@ -1121,13 +1162,6 @@ TAILQ_HEAD(winlink_stack, winlink); #define PANE_STATUS_TOP 1 #define PANE_STATUS_BOTTOM 2 -/* Pane border lines option. */ -#define PANE_LINES_SINGLE 0 -#define PANE_LINES_DOUBLE 1 -#define PANE_LINES_HEAVY 2 -#define PANE_LINES_SIMPLE 3 -#define PANE_LINES_NUMBER 4 - /* Layout direction. */ enum layout_type { LAYOUT_LEFTRIGHT, @@ -1216,20 +1250,33 @@ struct session { RB_HEAD(sessions, session); /* Mouse button masks. */ -#define MOUSE_MASK_BUTTONS 3 +#define MOUSE_MASK_BUTTONS 195 #define MOUSE_MASK_SHIFT 4 #define MOUSE_MASK_META 8 #define MOUSE_MASK_CTRL 16 #define MOUSE_MASK_DRAG 32 -#define MOUSE_MASK_WHEEL 64 - -/* Mouse wheel states. */ -#define MOUSE_WHEEL_UP 0 -#define MOUSE_WHEEL_DOWN 1 +#define MOUSE_MASK_MODIFIERS (MOUSE_MASK_SHIFT|MOUSE_MASK_META|MOUSE_MASK_CTRL) + +/* Mouse wheel type. */ +#define MOUSE_WHEEL_UP 64 +#define MOUSE_WHEEL_DOWN 65 + +/* Mouse button type. */ +#define MOUSE_BUTTON_1 0 +#define MOUSE_BUTTON_2 1 +#define MOUSE_BUTTON_3 2 +#define MOUSE_BUTTON_6 66 +#define MOUSE_BUTTON_7 67 +#define MOUSE_BUTTON_8 128 +#define MOUSE_BUTTON_9 129 +#define MOUSE_BUTTON_10 130 +#define MOUSE_BUTTON_11 131 /* Mouse helpers. */ #define MOUSE_BUTTONS(b) ((b) & MOUSE_MASK_BUTTONS) -#define MOUSE_WHEEL(b) ((b) & MOUSE_MASK_WHEEL) +#define MOUSE_WHEEL(b) \ + (((b) & MOUSE_MASK_BUTTONS) == MOUSE_WHEEL_UP || \ + ((b) & MOUSE_MASK_BUTTONS) == MOUSE_WHEEL_DOWN) #define MOUSE_DRAG(b) ((b) & MOUSE_MASK_DRAG) #define MOUSE_RELEASE(b) (((b) & MOUSE_MASK_BUTTONS) == 3) @@ -1268,18 +1315,7 @@ struct key_event { struct mouse_event m; }; -/* TTY information. */ -struct tty_key { - char ch; - key_code key; - - struct tty_key *left; - struct tty_key *right; - - struct tty_key *next; -}; - -struct tty_code; +/* Terminal definition. */ struct tty_term { char *name; struct tty *tty; @@ -1301,9 +1337,11 @@ struct tty_term { }; LIST_HEAD(tty_terms, tty_term); +/* Client terminal. */ struct tty { struct client *client; struct event start_timer; + struct event clipboard_timer; u_int sx; u_int sy; @@ -1312,8 +1350,8 @@ struct tty { u_int cx; u_int cy; - u_int cstyle; - char *ccolour; + enum screen_cursor_style cstyle; + int ccolour; int oflag; u_int oox; @@ -1344,10 +1382,10 @@ struct tty { #define TTY_NOCURSOR 0x1 #define TTY_FREEZE 0x2 #define TTY_TIMER 0x4 -/* 0x8 unused */ +#define TTY_NOBLOCK 0x8 #define TTY_STARTED 0x10 #define TTY_OPENED 0x20 -/* 0x40 unused */ +#define TTY_OSC52QUERY 0x40 #define TTY_BLOCK 0x80 #define TTY_HAVEDA 0x100 #define TTY_HAVEXDA 0x200 @@ -1369,7 +1407,7 @@ struct tty { struct tty_key *key_tree; }; -/* TTY command context. */ +/* Terminal command context. */ typedef void (*tty_ctx_redraw_cb)(const struct tty_ctx *); typedef int (*tty_ctx_set_client_cb)(struct tty_ctx *, struct client *); struct tty_ctx { @@ -1409,7 +1447,7 @@ struct tty_ctx { /* The default colours and palette. */ struct grid_cell defaults; - int *palette; + struct colour_palette *palette; /* Containing region (usually window) offset and size. */ int bigger; @@ -1429,13 +1467,43 @@ struct message_entry { }; TAILQ_HEAD(message_list, message_entry); -/* Parsed arguments structures. */ +/* Argument type. */ +enum args_type { + ARGS_NONE, + ARGS_STRING, + ARGS_COMMANDS +}; + +/* Argument value. */ +struct args_value { + enum args_type type; + union { + char *string; + struct cmd_list *cmdlist; + }; + char *cached; + TAILQ_ENTRY(args_value) entry; +}; + +/* Arguments set. */ struct args_entry; RB_HEAD(args_tree, args_entry); -struct args { - struct args_tree tree; - int argc; - char **argv; + +/* Arguments parsing type. */ +enum args_parse_type { + ARGS_PARSE_INVALID, + ARGS_PARSE_STRING, + ARGS_PARSE_COMMANDS_OR_STRING, + ARGS_PARSE_COMMANDS +}; + +/* Arguments parsing state. */ +typedef enum args_parse_type (*args_parse_cb)(struct args *, u_int, char **); +struct args_parse { + const char *template; + int lower; + int upper; + args_parse_cb cb; }; /* Command find structures. */ @@ -1481,7 +1549,6 @@ enum cmd_retval { /* Command parse result. */ enum cmd_parse_status { - CMD_PARSE_EMPTY, CMD_PARSE_ERROR, CMD_PARSE_SUCCESS }; @@ -1526,11 +1593,7 @@ struct cmd_entry { const char *name; const char *alias; - struct { - const char *template; - int lower; - int upper; - } args; + struct args_parse args; const char *usage; struct cmd_entry_flag source; @@ -1564,6 +1627,16 @@ struct status_line { struct status_line_entry entries[STATUS_LINES_LIMIT]; }; +/* Prompt type. */ +#define PROMPT_NTYPES 4 +enum prompt_type { + PROMPT_TYPE_COMMAND, + PROMPT_TYPE_SEARCH, + PROMPT_TYPE_TARGET, + PROMPT_TYPE_WINDOW_TARGET, + PROMPT_TYPE_INVALID = 0xff +}; + /* File in client. */ typedef void (*client_file_cb) (struct client *, const char *, int, int, struct evbuffer *, void *); @@ -1593,63 +1666,79 @@ RB_HEAD(client_files, client_file); struct client_window { u_int window; struct window_pane *pane; + + u_int sx; + u_int sy; + RB_ENTRY(client_window) entry; }; RB_HEAD(client_windows, client_window); +/* Visible areas not obstructed by overlays. */ +#define OVERLAY_MAX_RANGES 3 +struct overlay_ranges { + u_int px[OVERLAY_MAX_RANGES]; + u_int nx[OVERLAY_MAX_RANGES]; +}; + /* Client connection. */ typedef int (*prompt_input_cb)(struct client *, void *, const char *, int); typedef void (*prompt_free_cb)(void *); -typedef int (*overlay_check_cb)(struct client *, u_int, u_int); -typedef struct screen *(*overlay_mode_cb)(struct client *, u_int *, u_int *); -typedef void (*overlay_draw_cb)(struct client *, struct screen_redraw_ctx *); -typedef int (*overlay_key_cb)(struct client *, struct key_event *); -typedef void (*overlay_free_cb)(struct client *); +typedef void (*overlay_check_cb)(struct client*, void *, u_int, u_int, u_int, + struct overlay_ranges *); +typedef struct screen *(*overlay_mode_cb)(struct client *, void *, u_int *, + u_int *); +typedef void (*overlay_draw_cb)(struct client *, void *, + struct screen_redraw_ctx *); +typedef int (*overlay_key_cb)(struct client *, void *, struct key_event *); +typedef void (*overlay_free_cb)(struct client *, void *); +typedef void (*overlay_resize_cb)(struct client *, void *); struct client { - const char *name; - struct tmuxpeer *peer; - struct cmdq_list *queue; + const char *name; + struct tmuxpeer *peer; + struct cmdq_list *queue; - struct client_windows windows; + struct client_windows windows; - struct control_state *control_state; - u_int pause_age; + struct control_state *control_state; + u_int pause_age; - pid_t pid; - int fd; - int out_fd; - struct event event; - int retval; + pid_t pid; + int fd; + int out_fd; + struct event event; + int retval; - struct timeval creation_time; - struct timeval activity_time; + struct timeval creation_time; + struct timeval activity_time; - struct environ *environ; + struct environ *environ; struct format_job_tree *jobs; - char *title; - const char *cwd; + char *title; + char *path; + const char *cwd; - char *term_name; - int term_features; - char *term_type; - char **term_caps; - u_int term_ncaps; + char *term_name; + int term_features; + char *term_type; + char **term_caps; + u_int term_ncaps; - char *ttyname; - struct tty tty; + char *ttyname; + struct tty tty; - size_t written; - size_t discarded; - size_t redraw; + size_t written; + size_t discarded; + size_t redraw; - struct event repeat_timer; + struct event repeat_timer; - struct event click_timer; - u_int click_button; - struct mouse_event click_event; + struct event click_timer; + u_int click_button; + struct mouse_event click_event; - struct status_line status; + struct status_line status; #define CLIENT_TERMINAL 0x1 #define CLIENT_LOGIN 0x2 @@ -1685,6 +1774,8 @@ struct client { #define CLIENT_ACTIVEPANE 0x80000000ULL #define CLIENT_CONTROL_PAUSEAFTER 0x100000000ULL #define CLIENT_CONTROL_WAITEXIT 0x200000000ULL +#define CLIENT_WINDOWSIZECHANGED 0x400000000ULL +#define CLIENT_CLIPBOARDBUFFER 0x800000000ULL #define CLIENT_ALLREDRAWFLAGS \ (CLIENT_REDRAWWINDOW| \ CLIENT_REDRAWSTATUS| \ @@ -1696,70 +1787,79 @@ struct client { (CLIENT_DEAD| \ CLIENT_SUSPENDED| \ CLIENT_EXIT) +#define CLIENT_NODETACHFLAGS \ + (CLIENT_DEAD| \ + CLIENT_EXIT) #define CLIENT_NOSIZEFLAGS \ (CLIENT_DEAD| \ CLIENT_SUSPENDED| \ CLIENT_EXIT) - uint64_t flags; + uint64_t flags; enum { CLIENT_EXIT_RETURN, CLIENT_EXIT_SHUTDOWN, CLIENT_EXIT_DETACH - } exit_type; - enum msgtype exit_msgtype; - char *exit_session; - char *exit_message; - - struct key_table *keytable; - - uint64_t redraw_panes; - - int message_ignore_keys; - int message_ignore_styles; - char *message_string; - struct event message_timer; - - char *prompt_string; - struct utf8_data *prompt_buffer; - char *prompt_last; - size_t prompt_index; - prompt_input_cb prompt_inputcb; - prompt_free_cb prompt_freecb; - void *prompt_data; - u_int prompt_hindex; - enum { PROMPT_ENTRY, PROMPT_COMMAND } prompt_mode; - struct utf8_data *prompt_saved; - + } exit_type; + enum msgtype exit_msgtype; + char *exit_session; + char *exit_message; + + struct key_table *keytable; + + uint64_t redraw_panes; + + int message_ignore_keys; + int message_ignore_styles; + char *message_string; + struct event message_timer; + + char *prompt_string; + struct utf8_data *prompt_buffer; + char *prompt_last; + size_t prompt_index; + prompt_input_cb prompt_inputcb; + prompt_free_cb prompt_freecb; + void *prompt_data; + u_int prompt_hindex[PROMPT_NTYPES]; + enum { + PROMPT_ENTRY, + PROMPT_COMMAND + } prompt_mode; + struct utf8_data *prompt_saved; #define PROMPT_SINGLE 0x1 #define PROMPT_NUMERIC 0x2 #define PROMPT_INCREMENTAL 0x4 #define PROMPT_NOFORMAT 0x8 #define PROMPT_KEY 0x10 -#define PROMPT_WINDOW 0x20 -#define PROMPT_TARGET 0x40 - int prompt_flags; + int prompt_flags; + enum prompt_type prompt_type; + int prompt_cursor; - struct session *session; - struct session *last_session; + struct session *session; + struct session *last_session; - int references; + int references; + + void *pan_window; + u_int pan_ox; + u_int pan_oy; - void *pan_window; - u_int pan_ox; - u_int pan_oy; + overlay_check_cb overlay_check; + overlay_mode_cb overlay_mode; + overlay_draw_cb overlay_draw; + overlay_key_cb overlay_key; + overlay_free_cb overlay_free; + overlay_resize_cb overlay_resize; + void *overlay_data; + struct event overlay_timer; - overlay_check_cb overlay_check; - overlay_mode_cb overlay_mode; - overlay_draw_cb overlay_draw; - overlay_key_cb overlay_key; - overlay_free_cb overlay_free; - void *overlay_data; - struct event overlay_timer; + struct client_files files; - struct client_files files; + u_int *clipboard_panes; + u_int clipboard_npanes; - TAILQ_ENTRY(client) entry; + TAILQ_ENTRY(client) entry; }; TAILQ_HEAD(clients, client); @@ -1799,11 +1899,11 @@ RB_HEAD(key_tables, key_table); /* Option data. */ RB_HEAD(options_array, options_array_item); union options_value { - char *string; - long long number; - struct style style; - struct options_array array; - struct cmd_list *cmdlist; + char *string; + long long number; + struct style style; + struct options_array array; + struct cmd_list *cmdlist; }; /* Option table entries. */ @@ -1931,8 +2031,10 @@ struct tmuxpeer *proc_add_peer(struct tmuxproc *, int, void (*)(struct imsg *, void *), void *); void proc_remove_peer(struct tmuxpeer *); void proc_kill_peer(struct tmuxpeer *); +void proc_flush_peer(struct tmuxpeer *); void proc_toggle_log(struct tmuxproc *); pid_t proc_fork_and_daemon(int *); +uid_t proc_get_peer_uid(struct tmuxpeer *); /* cfg.c */ extern int cfg_finished; @@ -1989,6 +2091,7 @@ void printflike(3, 4) format_add(struct format_tree *, const char *, void format_add_tv(struct format_tree *, const char *, struct timeval *); void format_add_cb(struct format_tree *, const char *, format_cb); +void format_log_debug(struct format_tree *, const char *); void format_each(struct format_tree *, void (*)(const char *, const char *, void *), void *); char *format_expand_time(struct format_tree *, const char *); @@ -2018,7 +2121,7 @@ char *format_grid_line(struct grid *, u_int); /* format-draw.c */ void format_draw(struct screen_write_ctx *, const struct grid_cell *, u_int, const char *, - struct style_ranges *); + struct style_ranges *, int); u_int format_width(const char *); char *format_trim_left(const char *, u_int); char *format_trim_right(const char *, u_int); @@ -2084,6 +2187,8 @@ struct style *options_string_to_style(struct options *, const char *, int options_from_string(struct options *, const struct options_table_entry *, const char *, const char *, int, char **); +int options_find_choice(const struct options_table_entry *, + const char *, char **); void options_push_changes(const char *); int options_remove_or_default(struct options_entry *, int, char **); @@ -2099,10 +2204,11 @@ typedef void (*job_free_cb) (void *); #define JOB_NOWAIT 0x1 #define JOB_KEEPWRITE 0x2 #define JOB_PTY 0x4 -struct job *job_run(const char *, int, char **, struct session *, - const char *, job_update_cb, job_complete_cb, job_free_cb, - void *, int, int, int); +struct job *job_run(const char *, int, char **, struct environ *, + struct session *, const char *, job_update_cb, + job_complete_cb, job_free_cb, void *, int, int, int); void job_free(struct job *); +int job_transfer(struct job *, pid_t *, char *, size_t); void job_resize(struct job *, u_int, u_int); void job_check_died(pid_t, int); int job_get_status(struct job *); @@ -2137,11 +2243,12 @@ void tty_update_window_offset(struct window *); void tty_update_client_offset(struct client *); void tty_raw(struct tty *, const char *); void tty_attributes(struct tty *, const struct grid_cell *, - const struct grid_cell *, int *); + const struct grid_cell *, struct colour_palette *); void tty_reset(struct tty *); void tty_region_off(struct tty *); void tty_margin_off(struct tty *); void tty_cursor(struct tty *, u_int, u_int); +void tty_clipboard_query(struct tty *); void tty_putcode(struct tty *, enum tty_code_code); void tty_putcode1(struct tty *, enum tty_code_code, int); void tty_putcode2(struct tty *, enum tty_code_code, int, int); @@ -2153,7 +2260,7 @@ void tty_puts(struct tty *, const char *); void tty_putc(struct tty *, u_char); void tty_putn(struct tty *, const void *, size_t, u_int); void tty_cell(struct tty *, const struct grid_cell *, - const struct grid_cell *, int *); + const struct grid_cell *, struct colour_palette *); int tty_init(struct tty *, struct client *); void tty_resize(struct tty *); void tty_set_size(struct tty *, u_int, u_int, u_int, u_int); @@ -2161,9 +2268,10 @@ void tty_start_tty(struct tty *); void tty_send_requests(struct tty *); void tty_stop_tty(struct tty *); void tty_set_title(struct tty *, const char *); +void tty_set_path(struct tty *, const char *); void tty_update_mode(struct tty *, int, struct screen *); void tty_draw_line(struct tty *, struct screen *, u_int, u_int, u_int, - u_int, u_int, const struct grid_cell *, int *); + u_int, u_int, const struct grid_cell *, struct colour_palette *); void tty_sync_start(struct tty *); void tty_sync_end(struct tty *); int tty_open(struct tty *, char **); @@ -2233,6 +2341,9 @@ void tty_default_features(int *, const char *, u_int); int tty_acs_needed(struct tty *); const char *tty_acs_get(struct tty *, u_char); int tty_acs_reverse_get(struct tty *, const char *, size_t); +const struct utf8_data *tty_acs_double_borders(int); +const struct utf8_data *tty_acs_heavy_borders(int); +const struct utf8_data *tty_acs_rounded_borders(int); /* tty-keys.c */ void tty_keys_build(struct tty *); @@ -2240,8 +2351,15 @@ void tty_keys_free(struct tty *); int tty_keys_next(struct tty *); /* arguments.c */ -void args_set(struct args *, u_char, const char *); -struct args *args_parse(const char *, int, char **); +void args_set(struct args *, u_char, struct args_value *); +struct args *args_create(void); +struct args *args_parse(const struct args_parse *, struct args_value *, + u_int, char **); +struct args *args_copy(struct args *, int, char **); +void args_to_vector(struct args *, int *, char ***); +struct args_value *args_from_vector(int, char **); +void args_free_value(struct args_value *); +void args_free_values(struct args_value *, u_int); void args_free(struct args *); char *args_print(struct args *); char *args_escape(const char *); @@ -2249,8 +2367,20 @@ int args_has(struct args *, u_char); const char *args_get(struct args *, u_char); u_char args_first(struct args *, struct args_entry **); u_char args_next(struct args_entry **); -const char *args_first_value(struct args *, u_char, struct args_value **); -const char *args_next_value(struct args_value **); +u_int args_count(struct args *); +struct args_value *args_values(struct args *); +struct args_value *args_value(struct args *, u_int); +const char *args_string(struct args *, u_int); +struct cmd_list *args_make_commands_now(struct cmd *, struct cmdq_item *, + u_int, int); +struct args_command_state *args_make_commands_prepare(struct cmd *, + struct cmdq_item *, u_int, const char *, int, int); +struct cmd_list *args_make_commands(struct args_command_state *, int, char **, + char **); +void args_make_commands_free(struct args_command_state *); +char *args_make_commands_get_command(struct args_command_state *); +struct args_value *args_first_value(struct args *, u_char); +struct args_value *args_next_value(struct args_value *); long long args_strtonum(struct args *, u_char, long long, long long, char **); long long args_percentage(struct args *, u_char, long long, @@ -2289,8 +2419,8 @@ int cmd_find_from_nothing(struct cmd_find_state *, int); /* cmd.c */ extern const struct cmd_entry *cmd_table[]; void printflike(3, 4) cmd_log_argv(int, char **, const char *, ...); -void cmd_prepend_argv(int *, char ***, char *); -void cmd_append_argv(int *, char ***, char *); +void cmd_prepend_argv(int *, char ***, const char *); +void cmd_append_argv(int *, char ***, const char *); int cmd_pack_argv(int, char **, char *, size_t); int cmd_unpack_argv(char *, size_t, int, char ***); char **cmd_copy_argv(int, char **); @@ -2301,11 +2431,15 @@ const struct cmd_entry *cmd_get_entry(struct cmd *); struct args *cmd_get_args(struct cmd *); u_int cmd_get_group(struct cmd *); void cmd_get_source(struct cmd *, const char **, u_int *); -struct cmd *cmd_parse(int, char **, const char *, u_int, char **); +struct cmd *cmd_parse(struct args_value *, u_int, const char *, u_int, + char **); +struct cmd *cmd_copy(struct cmd *, int, char **); void cmd_free(struct cmd *); char *cmd_print(struct cmd *); struct cmd_list *cmd_list_new(void); +struct cmd_list *cmd_list_copy(struct cmd_list *, int, char **); void cmd_list_append(struct cmd_list *, struct cmd *); +void cmd_list_append_all(struct cmd_list *, struct cmd_list *); void cmd_list_move(struct cmd_list *, struct cmd_list *); void cmd_list_free(struct cmd_list *); char *cmd_list_print(struct cmd_list *, int); @@ -2337,7 +2471,7 @@ enum cmd_parse_status cmd_parse_and_append(const char *, struct cmdq_state *, char **); struct cmd_parse_result *cmd_parse_from_buffer(const void *, size_t, struct cmd_parse_input *); -struct cmd_parse_result *cmd_parse_from_arguments(int, char **, +struct cmd_parse_result *cmd_parse_from_arguments(struct args_value *, u_int, struct cmd_parse_input *); /* cmd-queue.c */ @@ -2348,6 +2482,7 @@ struct cmdq_state *cmdq_copy_state(struct cmdq_state *); void cmdq_free_state(struct cmdq_state *); void printflike(3, 4) cmdq_add_format(struct cmdq_state *, const char *, const char *, ...); +void cmdq_add_formats(struct cmdq_state *, struct format_tree *); void cmdq_merge_formats(struct cmdq_item *, struct format_tree *); struct cmdq_list *cmdq_new(void); void cmdq_free(struct cmdq_list *); @@ -2455,14 +2590,17 @@ int server_start(struct tmuxproc *, int, struct event_base *, int, char *); void server_update_socket(void); void server_add_accept(int); void printflike(1, 2) server_add_message(const char *, ...); +int server_create_socket(int, char **); /* server-client.c */ RB_PROTOTYPE(client_windows, client_window, entry, server_client_window_cmp); u_int server_client_how_many(void); void server_client_set_overlay(struct client *, u_int, overlay_check_cb, overlay_mode_cb, overlay_draw_cb, overlay_key_cb, - overlay_free_cb, void *); + overlay_free_cb, overlay_resize_cb, void *); void server_client_clear_overlay(struct client *); +void server_client_overlay_range(u_int, u_int, u_int, u_int, u_int, u_int, + u_int, struct overlay_ranges *); void server_client_set_key_table(struct client *, const char *); const char *server_client_get_key_table(struct client *); int server_client_check_nested(struct client *); @@ -2470,6 +2608,7 @@ int server_client_handle_key(struct client *, struct key_event *); struct client *server_client_create(int); int server_client_open(struct client *, char **); void server_client_unref(struct client *); +void server_client_set_session(struct client *, struct session *); void server_client_lost(struct client *); void server_client_suspend(struct client *); void server_client_detach(struct client *, enum msgtype); @@ -2480,6 +2619,8 @@ void server_client_push_stderr(struct client *); const char *server_client_get_cwd(struct client *, struct session *); void server_client_set_flags(struct client *, const char *); const char *server_client_get_flags(struct client *); +struct client_window *server_client_get_client_window(struct client *, u_int); +struct client_window *server_client_add_client_window(struct client *, u_int); struct window_pane *server_client_get_pane(struct client *); void server_client_set_pane(struct client *, struct window_pane *); void server_client_remove_pane(struct window_pane *); @@ -2510,6 +2651,8 @@ void server_check_unattached(void); void server_unzoom_window(struct window *); /* status.c */ +extern char **status_prompt_hlist[]; +extern u_int status_prompt_hsize[]; void status_timer_start(struct client *); void status_timer_start_all(void); void status_update_cache(struct session *); @@ -2519,19 +2662,21 @@ struct style_range *status_get_range(struct client *, u_int, u_int); void status_init(struct client *); void status_free(struct client *); int status_redraw(struct client *); -void status_message_set(struct client *, int, int, int, const char *, ...) - __printflike(5, 0); +void printflike(5, 6) status_message_set(struct client *, int, int, int, + const char *, ...); void status_message_clear(struct client *); int status_message_redraw(struct client *); void status_prompt_set(struct client *, struct cmd_find_state *, const char *, const char *, prompt_input_cb, prompt_free_cb, - void *, int); + void *, int, enum prompt_type); void status_prompt_clear(struct client *); int status_prompt_redraw(struct client *); 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); +const char *status_prompt_type_string(u_int); +enum prompt_type status_prompt_type(const char *type); /* resize.c */ void resize_window(struct window *, u_int, u_int, int, int); @@ -2542,7 +2687,8 @@ void recalculate_sizes(void); void recalculate_sizes_now(int); /* input.c */ -struct input_ctx *input_init(struct window_pane *, struct bufferevent *); +struct input_ctx *input_init(struct window_pane *, struct bufferevent *, + struct colour_palette *); void input_free(struct input_ctx *); void input_reset(struct input_ctx *, int); struct evbuffer *input_pending(struct input_ctx *); @@ -2550,6 +2696,8 @@ void input_parse_pane(struct window_pane *); void input_parse_buffer(struct window_pane *, u_char *, size_t); void input_parse_screen(struct input_ctx *, struct screen *, screen_write_init_ctx_cb, void *, u_char *, size_t); +void input_reply_clipboard(struct bufferevent *, const char *, size_t, + const char *); /* input-key.c */ void input_key_build(void); @@ -2562,11 +2710,18 @@ int input_key_get_mouse(struct screen *, struct mouse_event *, u_int, int colour_find_rgb(u_char, u_char, u_char); int colour_join_rgb(u_char, u_char, u_char); void colour_split_rgb(int, u_char *, u_char *, u_char *); +int colour_force_rgb(int); const char *colour_tostring(int); int colour_fromstring(const char *s); int colour_256toRGB(int); int colour_256to16(int); int colour_byname(const char *); +void colour_palette_init(struct colour_palette *); +void colour_palette_clear(struct colour_palette *); +void colour_palette_free(struct colour_palette *); +int colour_palette_get(struct colour_palette *, int); +int colour_palette_set(struct colour_palette *, int, int); +void colour_palette_from_option(struct colour_palette *, struct options *); /* attributes.c */ const char *attributes_tostring(int); @@ -2621,7 +2776,7 @@ void grid_reader_cursor_end_of_line(struct grid_reader *, int, int); void grid_reader_cursor_next_word(struct grid_reader *, const char *); void grid_reader_cursor_next_word_end(struct grid_reader *, const char *); void grid_reader_cursor_previous_word(struct grid_reader *, const char *, - int); + int, int); int grid_reader_cursor_jump(struct grid_reader *, const struct utf8_data *); int grid_reader_cursor_jump_back(struct grid_reader *, @@ -2676,7 +2831,8 @@ void screen_write_hline(struct screen_write_ctx *, u_int, int, int); void screen_write_vline(struct screen_write_ctx *, u_int, int, int); void screen_write_menu(struct screen_write_ctx *, struct menu *, int, const struct grid_cell *); -void screen_write_box(struct screen_write_ctx *, u_int, u_int); +void screen_write_box(struct screen_write_ctx *, u_int, u_int, int, + const struct grid_cell *, const char *); void screen_write_preview(struct screen_write_ctx *, struct screen *, u_int, u_int); void screen_write_backspace(struct screen_write_ctx *); @@ -2706,6 +2862,7 @@ void screen_write_clearendofscreen(struct screen_write_ctx *, u_int); void screen_write_clearstartofscreen(struct screen_write_ctx *, u_int); void screen_write_clearscreen(struct screen_write_ctx *, u_int); void screen_write_clearhistory(struct screen_write_ctx *); +void screen_write_fullredraw(struct screen_write_ctx *); void screen_write_collect_end(struct screen_write_ctx *); void screen_write_collect_add(struct screen_write_ctx *, const struct grid_cell *); @@ -2726,8 +2883,8 @@ void screen_init(struct screen *, u_int, u_int, u_int); void screen_reinit(struct screen *); void screen_free(struct screen *); void screen_reset_tabs(struct screen *); -void screen_set_cursor_style(struct screen *, u_int); -void screen_set_cursor_colour(struct screen *, const char *); +void screen_set_cursor_style(u_int, enum screen_cursor_style *, int *); +void screen_set_cursor_colour(struct screen *, int); int screen_set_title(struct screen *, const char *); void screen_set_path(struct screen *, const char *); void screen_push_title(struct screen *); @@ -2743,6 +2900,7 @@ void screen_select_cell(struct screen *, struct grid_cell *, const struct grid_cell *); void screen_alternate_on(struct screen *, struct grid_cell *, int); void screen_alternate_off(struct screen *, struct grid_cell *, int); +const char *screen_mode_to_string(int); /* window.c */ extern struct windows windows; @@ -2778,6 +2936,8 @@ struct window_pane *window_find_string(struct window *, const char *); int window_has_pane(struct window *, struct window_pane *); int window_set_active_pane(struct window *, struct window_pane *, int); +void window_update_focus(struct window *); +void window_pane_update_focus(struct window_pane *); void window_redraw_active_switch(struct window *, struct window_pane *); struct window_pane *window_add_pane(struct window *, struct window_pane *, @@ -2802,10 +2962,6 @@ struct window_pane *window_pane_find_by_id_str(const char *); struct window_pane *window_pane_find_by_id(u_int); int window_pane_destroy_ready(struct window_pane *); void window_pane_resize(struct window_pane *, u_int, u_int); -void window_pane_set_palette(struct window_pane *, u_int, int); -void window_pane_unset_palette(struct window_pane *, u_int); -void window_pane_reset_palette(struct window_pane *); -int window_pane_get_palette(struct window_pane *, int); int window_pane_set_mode(struct window_pane *, struct window_pane *, const struct window_mode *, struct cmd_find_state *, struct args *); @@ -2833,6 +2989,7 @@ void *window_pane_get_new_data(struct window_pane *, struct window_pane_offset *, size_t *); void window_pane_update_used_data(struct window_pane *, struct window_pane_offset *, size_t); +void window_set_fill_character(struct window *); /* layout.c */ u_int layout_count_cells(struct layout_cell *); @@ -2869,7 +3026,7 @@ void layout_spread_out(struct window_pane *); /* layout-custom.c */ char *layout_dump(struct layout_cell *); -int layout_parse(struct window *, const char *); +int layout_parse(struct window *, const char *, char **); /* layout-set.c */ int layout_set_lookup(const char *); @@ -2934,8 +3091,10 @@ extern const struct window_mode window_client_mode; /* window-copy.c */ extern const struct window_mode window_copy_mode; extern const struct window_mode window_view_mode; -void printflike(2, 3) window_copy_add(struct window_pane *, const char *, ...); -void printflike(2, 0) window_copy_vadd(struct window_pane *, const char *, va_list); +void printflike(3, 4) window_copy_add(struct window_pane *, int, const char *, + ...); +void printflike(3, 0) window_copy_vadd(struct window_pane *, int, const char *, + va_list); void window_copy_pageup(struct window_pane *, int); void window_copy_start_drag(struct client *, struct mouse_event *); char *window_copy_get_word(struct window_pane *, u_int, u_int); @@ -2985,6 +3144,7 @@ void control_notify_session_window_changed(struct session *); /* session.c */ extern struct sessions sessions; +extern u_int next_session_id; int session_cmp(struct session *, struct session *); RB_PROTOTYPE(sessions, session, entry, session_cmp); int session_alive(struct session *); @@ -3071,18 +3231,31 @@ void menu_add_item(struct menu *, const struct menu_item *, struct cmdq_item *, struct client *, struct cmd_find_state *); void menu_free(struct menu *); +struct menu_data *menu_prepare(struct menu *, int, struct cmdq_item *, u_int, + u_int, struct client *, struct cmd_find_state *, + menu_choice_cb, void *); int menu_display(struct menu *, int, struct cmdq_item *, u_int, u_int, struct client *, struct cmd_find_state *, menu_choice_cb, void *); +struct screen *menu_mode_cb(struct client *, void *, u_int *, u_int *); +void menu_check_cb(struct client *, void *, u_int, u_int, u_int, + struct overlay_ranges *); +void menu_draw_cb(struct client *, void *, + struct screen_redraw_ctx *); +void menu_free_cb(struct client *, void *); +int menu_key_cb(struct client *, void *, struct key_event *); /* popup.c */ #define POPUP_CLOSEEXIT 0x1 #define POPUP_CLOSEEXITZERO 0x2 +#define POPUP_INTERNAL 0x4 typedef void (*popup_close_cb)(int, void *); typedef void (*popup_finish_edit_cb)(char *, size_t, void *); -int popup_display(int, struct cmdq_item *, u_int, u_int, u_int, - u_int, const char *, int, char **, const char *, - struct client *, struct session *, popup_close_cb, void *); +int popup_display(int, int, struct cmdq_item *, u_int, u_int, + u_int, u_int, struct environ *, const char *, int, char **, + const char *, const char *, struct client *, + struct session *, const char *, const char *, + popup_close_cb, void *); int popup_editor(struct client *, const char *, size_t, popup_finish_edit_cb, void *); @@ -3104,4 +3277,15 @@ struct window_pane *spawn_pane(struct spawn_context *, char **); /* regsub.c */ char *regsub(const char *, const char *, const char *, int); +/* server-acl.c */ +void server_acl_init(void); +struct server_acl_user *server_acl_user_find(uid_t); +void server_acl_display(struct cmdq_item *); +void server_acl_user_allow(uid_t); +void server_acl_user_deny(uid_t); +void server_acl_user_allow_write(uid_t); +void server_acl_user_deny_write(uid_t); +int server_acl_join(struct client *); +uid_t server_acl_get_uid(struct server_acl_user *); + #endif /* TMUX_H */ diff --git a/external/bsd/tmux/dist/tty-acs.c b/external/bsd/tmux/dist/tty-acs.c index 4edb8bebf98..1b3c2a62e26 100644 --- a/external/bsd/tmux/dist/tty-acs.c +++ b/external/bsd/tmux/dist/tty-acs.c @@ -25,7 +25,7 @@ /* Table mapping ACS entries to UTF-8. */ struct tty_acs_entry { - u_char key; + u_char key; const char *string; }; static const struct tty_acs_entry tty_acs_table[] = { @@ -61,7 +61,7 @@ static const struct tty_acs_entry tty_acs_table[] = { { 'x', "\342\224\202" }, /* vertical line */ { 'y', "\342\211\244" }, /* less-than-or-equal-to */ { 'z', "\342\211\245" }, /* greater-than-or-equal-to */ - { '{', "\317\200" }, /* greek pi */ + { '{', "\317\200" }, /* greek pi */ { '|', "\342\211\240" }, /* not-equal */ { '}', "\302\243" }, /* UK pound sign */ { '~', "\302\267" } /* bullet */ @@ -110,6 +110,78 @@ static const struct tty_acs_reverse_entry tty_acs_reverse3[] = { { "\342\225\254", 'n' }, }; +/* UTF-8 double borders. */ +static const struct utf8_data tty_acs_double_borders_list[] = { + { "", 0, 0, 0 }, + { "\342\225\221", 0, 3, 1 }, /* U+2551 */ + { "\342\225\220", 0, 3, 1 }, /* U+2550 */ + { "\342\225\224", 0, 3, 1 }, /* U+2554 */ + { "\342\225\227", 0, 3, 1 }, /* U+2557 */ + { "\342\225\232", 0, 3, 1 }, /* U+255A */ + { "\342\225\235", 0, 3, 1 }, /* U+255D */ + { "\342\225\246", 0, 3, 1 }, /* U+2566 */ + { "\342\225\251", 0, 3, 1 }, /* U+2569 */ + { "\342\225\240", 0, 3, 1 }, /* U+2560 */ + { "\342\225\243", 0, 3, 1 }, /* U+2563 */ + { "\342\225\254", 0, 3, 1 }, /* U+256C */ + { "\302\267", 0, 2, 1 } /* U+00B7 */ +}; + +/* UTF-8 heavy borders. */ +static const struct utf8_data tty_acs_heavy_borders_list[] = { + { "", 0, 0, 0 }, + { "\342\224\203", 0, 3, 1 }, /* U+2503 */ + { "\342\224\201", 0, 3, 1 }, /* U+2501 */ + { "\342\224\217", 0, 3, 1 }, /* U+250F */ + { "\342\224\223", 0, 3, 1 }, /* U+2513 */ + { "\342\224\227", 0, 3, 1 }, /* U+2517 */ + { "\342\224\233", 0, 3, 1 }, /* U+251B */ + { "\342\224\263", 0, 3, 1 }, /* U+2533 */ + { "\342\224\273", 0, 3, 1 }, /* U+253B */ + { "\342\224\243", 0, 3, 1 }, /* U+2523 */ + { "\342\224\253", 0, 3, 1 }, /* U+252B */ + { "\342\225\213", 0, 3, 1 }, /* U+254B */ + { "\302\267", 0, 2, 1 } /* U+00B7 */ +}; + +/* UTF-8 rounded borders. */ +static const struct utf8_data tty_acs_rounded_borders_list[] = { + { "", 0, 0, 0 }, + { "\342\224\202", 0, 3, 1 }, /* U+2502 */ + { "\342\224\200", 0, 3, 1 }, /* U+2500 */ + { "\342\225\255", 0, 3, 1 }, /* U+256D */ + { "\342\225\256", 0, 3, 1 }, /* U+256E */ + { "\342\225\260", 0, 3, 1 }, /* U+2570 */ + { "\342\225\257", 0, 3, 1 }, /* U+256F */ + { "\342\224\263", 0, 3, 1 }, /* U+2533 */ + { "\342\224\273", 0, 3, 1 }, /* U+253B */ + { "\342\224\243", 0, 3, 1 }, /* U+2523 */ + { "\342\224\253", 0, 3, 1 }, /* U+252B */ + { "\342\225\213", 0, 3, 1 }, /* U+254B */ + { "\302\267", 0, 2, 1 } /* U+00B7 */ +}; + +/* Get cell border character for double style. */ +const struct utf8_data * +tty_acs_double_borders(int cell_type) +{ + return (&tty_acs_double_borders_list[cell_type]); +} + +/* Get cell border character for heavy style. */ +const struct utf8_data * +tty_acs_heavy_borders(int cell_type) +{ + return (&tty_acs_heavy_borders_list[cell_type]); +} + +/* Get cell border character for rounded style. */ +const struct utf8_data * +tty_acs_rounded_borders(int cell_type) +{ + return (&tty_acs_rounded_borders_list[cell_type]); +} + static int tty_acs_cmp(const void *key, const void *value) { diff --git a/external/bsd/tmux/dist/tty-keys.c b/external/bsd/tmux/dist/tty-keys.c index 9c081b57093..39a2cae6547 100644 --- a/external/bsd/tmux/dist/tty-keys.c +++ b/external/bsd/tmux/dist/tty-keys.c @@ -58,6 +58,17 @@ static int tty_keys_device_attributes(struct tty *, const char *, size_t, static int tty_keys_extended_device_attributes(struct tty *, const char *, size_t, size_t *); +/* A key tree entry. */ +struct tty_key { + char ch; + key_code key; + + struct tty_key *left; + struct tty_key *right; + + struct tty_key *next; +}; + /* Default raw keys. */ struct tty_default_key_raw { const char *string; @@ -820,10 +831,15 @@ complete_key: tty->flags &= ~TTY_TIMER; /* Check for focus events. */ - if (key == KEYC_FOCUS_OUT) - tty->client->flags &= ~CLIENT_FOCUSED; - else if (key == KEYC_FOCUS_IN) - tty->client->flags |= CLIENT_FOCUSED; + if (key == KEYC_FOCUS_OUT) { + c->flags &= ~CLIENT_FOCUSED; + window_update_focus(c->session->curw->window); + notify_client("client-focus-out", c); + } else if (key == KEYC_FOCUS_IN) { + c->flags |= CLIENT_FOCUSED; + notify_client("client-focus-in", c); + window_update_focus(c->session->curw->window); + } /* Fire the key. */ if (key != KEYC_UNKNOWN) { @@ -1045,17 +1061,13 @@ tty_keys_mouse(struct tty *tty, const char *buf, size_t len, size_t *size, log_debug("%s: mouse input: %.*s", c->name, (int)*size, buf); /* Check and return the mouse input. */ - if (b < 32) + if (b < MOUSE_PARAM_BTN_OFF || + x < MOUSE_PARAM_POS_OFF || + y < MOUSE_PARAM_POS_OFF) return (-1); - b -= 32; - if (x >= 33) - x -= 33; - else - x = 256 - x; - if (y >= 33) - y -= 33; - else - y = 256 - y; + b -= MOUSE_PARAM_BTN_OFF; + x -= MOUSE_PARAM_POS_OFF; + y -= MOUSE_PARAM_POS_OFF; } else if (buf[2] == '<') { /* Read the three inputs. */ *size = 3; @@ -1102,7 +1114,7 @@ tty_keys_mouse(struct tty *tty, const char *buf, size_t len, size_t *size, /* Type is M for press, m for release. */ sgr_type = ch; if (sgr_type == 'm') - b |= 3; + b = 3; /* * Some terminals (like PuTTY 0.63) mistakenly send @@ -1110,7 +1122,7 @@ tty_keys_mouse(struct tty *tty, const char *buf, size_t len, size_t *size, * Discard it before it reaches any program running inside * tmux. */ - if (sgr_type == 'm' && (sgr_b & 64)) + if (sgr_type == 'm' && MOUSE_WHEEL(sgr_b)) return (-2); } else return (-1); @@ -1138,12 +1150,14 @@ tty_keys_mouse(struct tty *tty, const char *buf, size_t len, size_t *size, * partial. */ static int -tty_keys_clipboard(__unused struct tty *tty, const char *buf, size_t len, - size_t *size) +tty_keys_clipboard(struct tty *tty, const char *buf, size_t len, size_t *size) { - size_t end, terminator, needed; - char *copy, *out; - int outlen; + struct client *c = tty->client; + struct window_pane *wp; + size_t end, terminator, needed; + char *copy, *out; + int outlen; + u_int i; *size = 0; @@ -1189,6 +1203,9 @@ tty_keys_clipboard(__unused struct tty *tty, const char *buf, size_t len, buf += 5; end -= 5; + /* Adjust end so that it points to the start of the terminator. */ + end -= terminator - 1; + /* Get the second argument. */ while (end != 0 && *buf != ';') { buf++; @@ -1199,6 +1216,12 @@ tty_keys_clipboard(__unused struct tty *tty, const char *buf, size_t len, buf++; end--; + /* If we did not request this, ignore it. */ + if (~tty->flags & TTY_OSC52QUERY) + return (0); + tty->flags &= ~TTY_OSC52QUERY; + evtimer_del(&tty->clipboard_timer); + /* It has to be a string so copy it. */ copy = xmalloc(end + 1); memcpy(copy, buf, end); @@ -1214,9 +1237,20 @@ tty_keys_clipboard(__unused struct tty *tty, const char *buf, size_t len, } free(copy); - /* Create a new paste buffer. */ + /* Create a new paste buffer and forward to panes. */ log_debug("%s: %.*s", __func__, outlen, out); - paste_add(NULL, out, outlen); + if (c->flags & CLIENT_CLIPBOARDBUFFER) { + paste_add(NULL, out, outlen); + c->flags &= ~CLIENT_CLIPBOARDBUFFER; + } + for (i = 0; i < c->clipboard_npanes; i++) { + wp = window_pane_find_by_id(c->clipboard_panes[i]); + if (wp != NULL) + input_reply_clipboard(wp->event, out, outlen, "\033\\"); + } + free(c->clipboard_panes); + c->clipboard_panes = NULL; + c->clipboard_npanes = 0; return (0); } diff --git a/external/bsd/tmux/dist/tty-term.c b/external/bsd/tmux/dist/tty-term.c index 5f7322d45c4..01d30172b9f 100644 --- a/external/bsd/tmux/dist/tty-term.c +++ b/external/bsd/tmux/dist/tty-term.c @@ -277,6 +277,7 @@ static const struct tty_term_code_entry tty_term_codes[] = { [TTYC_SMUL] = { TTYCODE_STRING, "smul" }, [TTYC_SMXX] = { TTYCODE_STRING, "smxx" }, [TTYC_SS] = { TTYCODE_STRING, "Ss" }, + [TTYC_SWD] = { TTYCODE_STRING, "Swd" }, [TTYC_SYNC] = { TTYCODE_STRING, "Sync" }, [TTYC_TC] = { TTYCODE_FLAG, "Tc" }, [TTYC_TSL] = { TTYCODE_STRING, "tsl" }, @@ -670,7 +671,7 @@ tty_term_read_list(const char *name, int fd, char ***caps, u_int *ncaps, const char *s; char tmp[11]; - if (setupterm(name, fd, &error) != OK) { + if (setupterm(__UNCONST(name), fd, &error) != OK) { switch (error) { case 1: xasprintf(cause, "can't use hardcopy terminal: %s", diff --git a/external/bsd/tmux/dist/tty.c b/external/bsd/tmux/dist/tty.c index 3d473a9d932..64549387dc4 100644 --- a/external/bsd/tmux/dist/tty.c +++ b/external/bsd/tmux/dist/tty.c @@ -38,16 +38,19 @@ static int tty_client_ready(struct client *); static void tty_set_italics(struct tty *); static int tty_try_colour(struct tty *, int, const char *); -static void tty_force_cursor_colour(struct tty *, const char *); +static void tty_force_cursor_colour(struct tty *, int); static void tty_cursor_pane(struct tty *, const struct tty_ctx *, u_int, u_int); static void tty_cursor_pane_unless_wrap(struct tty *, const struct tty_ctx *, u_int, u_int); static void tty_invalidate(struct tty *); static void tty_colours(struct tty *, const struct grid_cell *); -static void tty_check_fg(struct tty *, int *, struct grid_cell *); -static void tty_check_bg(struct tty *, int *, struct grid_cell *); -static void tty_check_us(struct tty *, int *, struct grid_cell *); +static void tty_check_fg(struct tty *, struct colour_palette *, + struct grid_cell *); +static void tty_check_bg(struct tty *, struct colour_palette *, + struct grid_cell *); +static void tty_check_us(struct tty *, struct colour_palette *, + struct grid_cell *); static void tty_colours_fg(struct tty *, const struct grid_cell *); static void tty_colours_bg(struct tty *, const struct grid_cell *); static void tty_colours_us(struct tty *, const struct grid_cell *); @@ -66,7 +69,10 @@ static void tty_emulate_repeat(struct tty *, enum tty_code_code, static void tty_repeat_space(struct tty *, u_int); static void tty_draw_pane(struct tty *, const struct tty_ctx *, u_int); static void tty_default_attributes(struct tty *, const struct grid_cell *, - int *, u_int); + struct colour_palette *, u_int); +static int tty_check_overlay(struct tty *, u_int, u_int); +static void tty_check_overlay_range(struct tty *, u_int, u_int, u_int, + struct overlay_ranges *); #define tty_use_margin(tty) \ (tty->term->flags & TERM_DECSLRM) @@ -77,6 +83,8 @@ static void tty_default_attributes(struct tty *, const struct grid_cell *, #define TTY_BLOCK_START(tty) (1 + ((tty)->sx * (tty)->sy) * 8) #define TTY_BLOCK_STOP(tty) (1 + ((tty)->sx * (tty)->sy) / 8) +#define TTY_QUERY_TIMEOUT 5 + void tty_create_log(void) { @@ -98,8 +106,8 @@ tty_init(struct tty *tty, struct client *c) memset(tty, 0, sizeof *tty); tty->client = c; - tty->cstyle = 0; - tty->ccolour = xstrdup(""); + tty->cstyle = SCREEN_CURSOR_DEFAULT; + tty->ccolour = -1; if (tcgetattr(c->fd, &tty->tio) != 0) return (-1); @@ -200,6 +208,11 @@ tty_block_maybe(struct tty *tty) size_t size = EVBUFFER_LENGTH(tty->out); struct timeval tv = { .tv_usec = TTY_BLOCK_INTERVAL }; + if (size == 0) + tty->flags &= ~TTY_NOBLOCK; + else if (tty->flags & TTY_NOBLOCK) + return (0); + if (size < TTY_BLOCK_START(tty)) return (0); @@ -296,7 +309,7 @@ tty_start_tty(struct tty *tty) { struct client *c = tty->client; struct termios tio; - struct timeval tv = { .tv_sec = 1 }; + struct timeval tv = { .tv_sec = TTY_QUERY_TIMEOUT }; setblocking(c->fd, 0); event_add(&tty->event_in, NULL); @@ -310,7 +323,7 @@ tty_start_tty(struct tty *tty) tio.c_cc[VMIN] = 1; tio.c_cc[VTIME] = 0; if (tcsetattr(c->fd, TCSANOW, &tio) == 0) - tcflush(c->fd, TCIOFLUSH); + tcflush(c->fd, TCOFLUSH); tty_putcode(tty, TTYC_SMCUP); @@ -335,8 +348,8 @@ tty_start_tty(struct tty *tty) tty->flags |= TTY_STARTED; tty_invalidate(tty); - if (*tty->ccolour != '\0') - tty_force_cursor_colour(tty, ""); + if (tty->ccolour != -1) + tty_force_cursor_colour(tty, -1); tty->mouse_drag_flag = 0; tty->mouse_drag_update = NULL; @@ -392,15 +405,15 @@ tty_stop_tty(struct tty *tty) tty_raw(tty, tty_term_string(tty->term, TTYC_SGR0)); tty_raw(tty, tty_term_string(tty->term, TTYC_RMKX)); tty_raw(tty, tty_term_string(tty->term, TTYC_CLEAR)); - if (tty_term_has(tty->term, TTYC_SS) && tty->cstyle != 0) { + if (tty->cstyle != SCREEN_CURSOR_DEFAULT) { if (tty_term_has(tty->term, TTYC_SE)) tty_raw(tty, tty_term_string(tty->term, TTYC_SE)); - else + else if (tty_term_has(tty->term, TTYC_SS)) tty_raw(tty, tty_term_string1(tty->term, TTYC_SS, 0)); } if (tty->mode & MODE_BRACKETPASTE) tty_raw(tty, tty_term_string(tty->term, TTYC_DSBP)); - if (*tty->ccolour != '\0') + if (tty->ccolour != -1) tty_raw(tty, tty_term_string(tty->term, TTYC_CR)); tty_raw(tty, tty_term_string(tty->term, TTYC_CNORM)); @@ -445,7 +458,6 @@ void tty_free(struct tty *tty) { tty_close(tty); - free(tty->ccolour); } void @@ -643,90 +655,169 @@ tty_set_title(struct tty *tty, const char *title) tty_putcode(tty, TTYC_FSL); } +void +tty_set_path(struct tty *tty, const char *title) +{ + if (!tty_term_has(tty->term, TTYC_SWD) || + !tty_term_has(tty->term, TTYC_FSL)) + return; + + tty_putcode(tty, TTYC_SWD); + tty_puts(tty, title); + tty_putcode(tty, TTYC_FSL); +} + static void -tty_force_cursor_colour(struct tty *tty, const char *ccolour) +tty_force_cursor_colour(struct tty *tty, int c) { - if (*ccolour == '\0') + u_char r, g, b; + char s[13] = ""; + + if (c != -1) + c = colour_force_rgb(c); + if (c == tty->ccolour) + return; + if (c == -1) tty_putcode(tty, TTYC_CR); - else - tty_putcode_ptr1(tty, TTYC_CS, ccolour); - free(tty->ccolour); - tty->ccolour = xstrdup(ccolour); + else { + colour_split_rgb(c, &r, &g, &b); + xsnprintf(s, sizeof s, "rgb:%02hhx/%02hhx/%02hhx", r, g, b); + tty_putcode_ptr1(tty, TTYC_CS, s); + } + tty->ccolour = c; } -void -tty_update_mode(struct tty *tty, int mode, struct screen *s) +static int +tty_update_cursor(struct tty *tty, int mode, struct screen *s) { - struct client *c = tty->client; - int changed; + enum screen_cursor_style cstyle; + int ccolour, changed, cmode = mode; - if (s != NULL && strcmp(s->ccolour, tty->ccolour) != 0) - tty_force_cursor_colour(tty, s->ccolour); + /* Set cursor colour if changed. */ + if (s != NULL) { + ccolour = s->ccolour; + if (s->ccolour == -1) + ccolour = s->default_ccolour; + tty_force_cursor_colour(tty, ccolour); + } - if (tty->flags & TTY_NOCURSOR) - mode &= ~MODE_CURSOR; + /* If cursor is off, set as invisible. */ + if (~cmode & MODE_CURSOR) { + if (tty->mode & MODE_CURSOR) + tty_putcode(tty, TTYC_CIVIS); + return (cmode); + } - changed = mode ^ tty->mode; - if (changed != 0) - log_debug("%s: update mode %x to %x", c->name, tty->mode, mode); + /* Check if blinking or very visible flag changed or style changed. */ + if (s == NULL) + cstyle = tty->cstyle; + else { + cstyle = s->cstyle; + if (cstyle == SCREEN_CURSOR_DEFAULT) { + if (~cmode & MODE_CURSOR_BLINKING_SET) { + if (s->default_mode & MODE_CURSOR_BLINKING) + cmode |= MODE_CURSOR_BLINKING; + else + cmode &= ~MODE_CURSOR_BLINKING; + } + cstyle = s->default_cstyle; + } + } + + /* If nothing changed, do nothing. */ + changed = cmode ^ tty->mode; + if ((changed & CURSOR_MODES) == 0 && cstyle == tty->cstyle) + return (cmode); /* - * The cursor blinking flag can be reset by setting the cursor style, so - * set the style first. + * Set cursor style. If an explicit style has been set with DECSCUSR, + * set it if supported, otherwise send cvvis for blinking styles. + * + * If no style, has been set (SCREEN_CURSOR_DEFAULT), then send cvvis + * if either the blinking or very visible flags are set. */ - if (s != NULL && tty->cstyle != s->cstyle) { - if (tty_term_has(tty->term, TTYC_SS)) { - if (s->cstyle == 0 && tty_term_has(tty->term, TTYC_SE)) + tty_putcode(tty, TTYC_CNORM); + switch (cstyle) { + case SCREEN_CURSOR_DEFAULT: + if (tty->cstyle != SCREEN_CURSOR_DEFAULT) { + if (tty_term_has(tty->term, TTYC_SE)) tty_putcode(tty, TTYC_SE); else - tty_putcode1(tty, TTYC_SS, s->cstyle); + tty_putcode1(tty, TTYC_SS, 0); } - tty->cstyle = s->cstyle; - changed |= (MODE_CURSOR|MODE_BLINKING); + if (cmode & (MODE_CURSOR_BLINKING|MODE_CURSOR_VERY_VISIBLE)) + tty_putcode(tty, TTYC_CVVIS); + break; + case SCREEN_CURSOR_BLOCK: + if (tty_term_has(tty->term, TTYC_SS)) { + if (cmode & MODE_CURSOR_BLINKING) + tty_putcode1(tty, TTYC_SS, 1); + else + tty_putcode1(tty, TTYC_SS, 2); + } else if (cmode & MODE_CURSOR_BLINKING) + tty_putcode(tty, TTYC_CVVIS); + break; + case SCREEN_CURSOR_UNDERLINE: + if (tty_term_has(tty->term, TTYC_SS)) { + if (cmode & MODE_CURSOR_BLINKING) + tty_putcode1(tty, TTYC_SS, 3); + else + tty_putcode1(tty, TTYC_SS, 4); + } else if (cmode & MODE_CURSOR_BLINKING) + tty_putcode(tty, TTYC_CVVIS); + break; + case SCREEN_CURSOR_BAR: + if (tty_term_has(tty->term, TTYC_SS)) { + if (cmode & MODE_CURSOR_BLINKING) + tty_putcode1(tty, TTYC_SS, 5); + else + tty_putcode1(tty, TTYC_SS, 6); + } else if (cmode & MODE_CURSOR_BLINKING) + tty_putcode(tty, TTYC_CVVIS); + break; } + tty->cstyle = cstyle; + return (cmode); + } - /* - * Cursor invisible (RM ?25) overrides cursor blinking (SM ?12 or RM - * 34), and we need to be careful not send cnorm after cvvis since it - * can undo it. - */ - if (changed & (MODE_CURSOR|MODE_BLINKING)) { - log_debug("%s: cursor %s, %sblinking", __func__, - (mode & MODE_CURSOR) ? "on" : "off", - (mode & MODE_BLINKING) ? "" : "not "); - if (~mode & MODE_CURSOR) - tty_putcode(tty, TTYC_CIVIS); - else if (mode & MODE_BLINKING) { - tty_putcode(tty, TTYC_CNORM); - if (tty_term_has(tty->term, TTYC_CVVIS)) - tty_putcode(tty, TTYC_CVVIS); - } else - tty_putcode(tty, TTYC_CNORM); +void +tty_update_mode(struct tty *tty, int mode, struct screen *s) +{ + struct tty_term *term = tty->term; + struct client *c = tty->client; + int changed; + + if (tty->flags & TTY_NOCURSOR) + mode &= ~MODE_CURSOR; + + if (tty_update_cursor(tty, mode, s) & MODE_CURSOR_BLINKING) + mode |= MODE_CURSOR_BLINKING; + else + mode &= ~MODE_CURSOR_BLINKING; + + changed = mode ^ tty->mode; + if (log_get_level() != 0 && changed != 0) { + log_debug("%s: current mode %s", c->name, + screen_mode_to_string(tty->mode)); + log_debug("%s: setting mode %s", c->name, + screen_mode_to_string(mode)); } - if ((changed & ALL_MOUSE_MODES) && - tty_term_has(tty->term, TTYC_KMOUS)) { + if ((changed & ALL_MOUSE_MODES) && tty_term_has(term, TTYC_KMOUS)) { /* - * If the mouse modes have changed, clear any that are set and - * apply again. There are differences in how terminals track - * the various bits. + * If the mouse modes have changed, clear then all and apply + * again. There are differences in how terminals track the + * various bits. */ - if (tty->mode & MODE_MOUSE_SGR) - tty_puts(tty, "\033[?1006l"); - if (tty->mode & MODE_MOUSE_STANDARD) - tty_puts(tty, "\033[?1000l"); - if (tty->mode & MODE_MOUSE_BUTTON) - tty_puts(tty, "\033[?1002l"); - if (tty->mode & MODE_MOUSE_ALL) - tty_puts(tty, "\033[?1003l"); + tty_puts(tty, "\033[?1006l\033[?1000l\033[?1002l\033[?1003l"); if (mode & ALL_MOUSE_MODES) tty_puts(tty, "\033[?1006h"); - if (mode & MODE_MOUSE_STANDARD) - tty_puts(tty, "\033[?1000h"); - if (mode & MODE_MOUSE_BUTTON) - tty_puts(tty, "\033[?1002h"); if (mode & MODE_MOUSE_ALL) - tty_puts(tty, "\033[?1003h"); + tty_puts(tty, "\033[?1000h\033[?1002h\033[?1003h"); + else if (mode & MODE_MOUSE_BUTTON) + tty_puts(tty, "\033[?1000h\033[?1002h"); + else if (mode & MODE_MOUSE_STANDARD) + tty_puts(tty, "\033[?1000h"); } if (changed & MODE_BRACKETPASTE) { if (mode & MODE_BRACKETPASTE) @@ -858,7 +949,9 @@ tty_update_window_offset(struct window *w) struct client *c; TAILQ_FOREACH(c, &clients, entry) { - if (c->session != NULL && c->session->curw->window == w) + if (c->session != NULL && + c->session->curw != NULL && + c->session->curw->window == w) tty_update_client_offset(c); } } @@ -891,27 +984,6 @@ tty_update_client_offset(struct client *c) c->flags |= (CLIENT_REDRAWWINDOW|CLIENT_REDRAWSTATUS); } -/* Get a palette entry. */ -static int -tty_get_palette(int *palette, int c) -{ - int new; - - if (palette == NULL) - return (-1); - - new = -1; - if (c < 8) - new = palette[c]; - else if (c >= 90 && c <= 97) - new = palette[8 + c - 90]; - else if (c & COLOUR_FLAG_256) - new = palette[c & ~COLOUR_FLAG_256]; - if (new == 0) - return (-1); - return (new); -} - /* * Is the region large enough to be worth redrawing once later rather than * probably several times now? Currently yes if it is more than 50% of the @@ -1021,7 +1093,9 @@ static void tty_clear_line(struct tty *tty, const struct grid_cell *defaults, u_int py, u_int px, u_int nx, u_int bg) { - struct client *c = tty->client; + struct client *c = tty->client; + struct overlay_ranges r; + u_int i; log_debug("%s: %s, %u at %u,%u", __func__, c->name, nx, px, py); @@ -1030,7 +1104,7 @@ tty_clear_line(struct tty *tty, const struct grid_cell *defaults, u_int py, return; /* If genuine BCE is available, can try escape sequences. */ - if (!tty_fake_bce(tty, defaults, bg)) { + if (c->overlay_check == NULL && !tty_fake_bce(tty, defaults, bg)) { /* Off the end of the line, use EL if available. */ if (px + nx >= tty->sx && tty_term_has(tty->term, TTYC_EL)) { tty_cursor(tty, px, py); @@ -1053,9 +1127,17 @@ tty_clear_line(struct tty *tty, const struct grid_cell *defaults, u_int py, } } - /* Couldn't use an escape sequence, use spaces. */ - tty_cursor(tty, px, py); - tty_repeat_space(tty, nx); + /* + * Couldn't use an escape sequence, use spaces. Clear only the visible + * bit if there is an overlay. + */ + tty_check_overlay_range(tty, px, py, nx, &r); + for (i = 0; i < OVERLAY_MAX_RANGES; i++) { + if (r.nx[i] == 0) + continue; + tty_cursor(tty, r.px[i], py); + tty_repeat_space(tty, r.nx[i]); + } } /* Clear a line, adjusting to visible part of pane. */ @@ -1150,7 +1232,7 @@ tty_clear_area(struct tty *tty, const struct grid_cell *defaults, u_int py, return; /* If genuine BCE is available, can try escape sequences. */ - if (!tty_fake_bce(tty, defaults, bg)) { + if (c->overlay_check == NULL && !tty_fake_bce(tty, defaults, bg)) { /* Use ED if clearing off the bottom of the terminal. */ if (px == 0 && px + nx >= tty->sx && @@ -1267,32 +1349,67 @@ tty_check_codeset(struct tty *tty, const struct grid_cell *gc) return (&new); } +/* + * Check if a single character is obstructed by the overlay and return a + * boolean. + */ static int tty_check_overlay(struct tty *tty, u_int px, u_int py) { + struct overlay_ranges r; + + /* + * A unit width range will always return nx[2] == 0 from a check, even + * with multiple overlays, so it's sufficient to check just the first + * two entries. + */ + tty_check_overlay_range(tty, px, py, 1, &r); + if (r.nx[0] + r.nx[1] == 0) + return (0); + return (1); +} + +/* Return parts of the input range which are visible. */ +static void +tty_check_overlay_range(struct tty *tty, u_int px, u_int py, u_int nx, + struct overlay_ranges *r) +{ struct client *c = tty->client; - if (c->overlay_check == NULL) - return (1); - return (c->overlay_check(c, px, py)); + if (c->overlay_check == NULL) { + r->px[0] = px; + r->nx[0] = nx; + r->px[1] = 0; + r->nx[1] = 0; + r->px[2] = 0; + r->nx[2] = 0; + return; + } + + c->overlay_check(c, c->overlay_data, px, py, nx, r); } void tty_draw_line(struct tty *tty, struct screen *s, u_int px, u_int py, u_int nx, - u_int atx, u_int aty, const struct grid_cell *defaults, int *palette) + u_int atx, u_int aty, const struct grid_cell *defaults, + struct colour_palette *palette) { struct grid *gd = s->grid; struct grid_cell gc, last; const struct grid_cell *gcp; struct grid_line *gl; - u_int i, j, ux, sx, width; + struct client *c = tty->client; + struct overlay_ranges r; + u_int i, j, ux, sx, width, hidden, eux, nxx; + u_int cellsize; int flags, cleared = 0, wrapped = 0; char buf[512]; size_t len; - u_int cellsize; log_debug("%s: px=%u py=%u nx=%u atx=%u aty=%u", __func__, px, py, nx, atx, aty); + log_debug("%s: defaults: fg=%d, bg=%d", __func__, defaults->fg, + defaults->bg); /* * py is the line in the screen to draw. @@ -1336,7 +1453,8 @@ tty_draw_line(struct tty *tty, struct screen *s, u_int px, u_int py, u_int nx, atx == 0 && px + sx != nx && tty_term_has(tty->term, TTYC_EL1) && - !tty_fake_bce(tty, defaults, 8)) { + !tty_fake_bce(tty, defaults, 8) && + c->overlay_check == NULL) { tty_default_attributes(tty, defaults, palette, 8); tty_cursor(tty, nx - 1, aty); tty_putcode(tty, TTYC_EL1); @@ -1385,17 +1503,33 @@ tty_draw_line(struct tty *tty, struct screen *s, u_int px, u_int py, u_int nx, screen_select_cell(s, &last, gcp); else memcpy(&last, gcp, sizeof last); - if (!tty_check_overlay(tty, atx + ux, aty)) { + + tty_check_overlay_range(tty, atx + ux, aty, gcp->data.width, + &r); + hidden = 0; + for (j = 0; j < OVERLAY_MAX_RANGES; j++) + hidden += r.nx[j]; + hidden = gcp->data.width - hidden; + if (hidden != 0 && hidden == gcp->data.width) { if (~gcp->flags & GRID_FLAG_PADDING) ux += gcp->data.width; - } else if (ux + gcp->data.width > nx) { - tty_attributes(tty, &last, defaults, palette); - tty_cursor(tty, atx + ux, aty); - for (j = 0; j < gcp->data.width; j++) { - if (ux + j > nx) - break; - tty_putc(tty, ' '); - ux++; + } else if (hidden != 0 || ux + gcp->data.width > nx) { + if (~gcp->flags & GRID_FLAG_PADDING) { + tty_attributes(tty, &last, defaults, palette); + for (j = 0; j < OVERLAY_MAX_RANGES; j++) { + if (r.nx[j] == 0) + continue; + /* Effective width drawn so far. */ + eux = r.px[j] - atx; + if (eux < nx) { + tty_cursor(tty, r.px[j], aty); + nxx = nx - eux; + if (r.nx[j] > nxx) + r.nx[j] = nxx; + tty_repeat_space(tty, r.nx[j]); + ux = eux + r.nx[j]; + } + } } } else if (gcp->attr & GRID_ATTR_CHARSET) { tty_attributes(tty, &last, defaults, palette); @@ -1500,11 +1634,14 @@ tty_write(void (*cmdfn)(struct tty *, const struct tty_ctx *), void tty_cmd_insertcharacter(struct tty *tty, const struct tty_ctx *ctx) { + struct client *c = tty->client; + if (ctx->bigger || !tty_full_width(tty, ctx) || tty_fake_bce(tty, &ctx->defaults, ctx->bg) || (!tty_term_has(tty->term, TTYC_ICH) && - !tty_term_has(tty->term, TTYC_ICH1))) { + !tty_term_has(tty->term, TTYC_ICH1)) || + c->overlay_check != NULL) { tty_draw_pane(tty, ctx, ctx->ocy); return; } @@ -1519,11 +1656,14 @@ tty_cmd_insertcharacter(struct tty *tty, const struct tty_ctx *ctx) void tty_cmd_deletecharacter(struct tty *tty, const struct tty_ctx *ctx) { + struct client *c = tty->client; + if (ctx->bigger || !tty_full_width(tty, ctx) || tty_fake_bce(tty, &ctx->defaults, ctx->bg) || (!tty_term_has(tty->term, TTYC_DCH) && - !tty_term_has(tty->term, TTYC_DCH1))) { + !tty_term_has(tty->term, TTYC_DCH1)) || + c->overlay_check != NULL) { tty_draw_pane(tty, ctx, ctx->ocy); return; } @@ -1546,13 +1686,16 @@ tty_cmd_clearcharacter(struct tty *tty, const struct tty_ctx *ctx) void tty_cmd_insertline(struct tty *tty, const struct tty_ctx *ctx) { + struct client *c = tty->client; + if (ctx->bigger || !tty_full_width(tty, ctx) || tty_fake_bce(tty, &ctx->defaults, ctx->bg) || !tty_term_has(tty->term, TTYC_CSR) || !tty_term_has(tty->term, TTYC_IL1) || ctx->sx == 1 || - ctx->sy == 1) { + ctx->sy == 1 || + c->overlay_check != NULL) { tty_redraw_region(tty, ctx); return; } @@ -1570,13 +1713,16 @@ tty_cmd_insertline(struct tty *tty, const struct tty_ctx *ctx) void tty_cmd_deleteline(struct tty *tty, const struct tty_ctx *ctx) { + struct client *c = tty->client; + if (ctx->bigger || !tty_full_width(tty, ctx) || tty_fake_bce(tty, &ctx->defaults, ctx->bg) || !tty_term_has(tty->term, TTYC_CSR) || !tty_term_has(tty->term, TTYC_DL1) || ctx->sx == 1 || - ctx->sy == 1) { + ctx->sy == 1 || + c->overlay_check != NULL) { tty_redraw_region(tty, ctx); return; } @@ -1620,6 +1766,8 @@ tty_cmd_clearstartofline(struct tty *tty, const struct tty_ctx *ctx) void tty_cmd_reverseindex(struct tty *tty, const struct tty_ctx *ctx) { + struct client *c = tty->client; + if (ctx->ocy != ctx->orupper) return; @@ -1630,7 +1778,8 @@ tty_cmd_reverseindex(struct tty *tty, const struct tty_ctx *ctx) (!tty_term_has(tty->term, TTYC_RI) && !tty_term_has(tty->term, TTYC_RIN)) || ctx->sx == 1 || - ctx->sy == 1) { + ctx->sy == 1 || + c->overlay_check != NULL) { tty_redraw_region(tty, ctx); return; } @@ -1650,6 +1799,8 @@ tty_cmd_reverseindex(struct tty *tty, const struct tty_ctx *ctx) void tty_cmd_linefeed(struct tty *tty, const struct tty_ctx *ctx) { + struct client *c = tty->client; + if (ctx->ocy != ctx->orlower) return; @@ -1658,7 +1809,8 @@ tty_cmd_linefeed(struct tty *tty, const struct tty_ctx *ctx) tty_fake_bce(tty, &ctx->defaults, 8) || !tty_term_has(tty->term, TTYC_CSR) || ctx->sx == 1 || - ctx->sy == 1) { + ctx->sy == 1 || + c->overlay_check != NULL) { tty_redraw_region(tty, ctx); return; } @@ -1689,14 +1841,16 @@ tty_cmd_linefeed(struct tty *tty, const struct tty_ctx *ctx) void tty_cmd_scrollup(struct tty *tty, const struct tty_ctx *ctx) { - u_int i; + struct client *c = tty->client; + u_int i; if (ctx->bigger || (!tty_full_width(tty, ctx) && !tty_use_margin(tty)) || tty_fake_bce(tty, &ctx->defaults, 8) || !tty_term_has(tty->term, TTYC_CSR) || ctx->sx == 1 || - ctx->sy == 1) { + ctx->sy == 1 || + c->overlay_check != NULL) { tty_redraw_region(tty, ctx); return; } @@ -1725,7 +1879,8 @@ tty_cmd_scrollup(struct tty *tty, const struct tty_ctx *ctx) void tty_cmd_scrolldown(struct tty *tty, const struct tty_ctx *ctx) { - u_int i; + u_int i; + struct client *c = tty->client; if (ctx->bigger || (!tty_full_width(tty, ctx) && !tty_use_margin(tty)) || @@ -1734,7 +1889,8 @@ tty_cmd_scrolldown(struct tty *tty, const struct tty_ctx *ctx) (!tty_term_has(tty->term, TTYC_RI) && !tty_term_has(tty->term, TTYC_RIN)) || ctx->sx == 1 || - ctx->sy == 1) { + ctx->sy == 1 || + c->overlay_check != NULL) { tty_redraw_region(tty, ctx); return; } @@ -1844,9 +2000,29 @@ tty_cmd_alignmenttest(struct tty *tty, const struct tty_ctx *ctx) void tty_cmd_cell(struct tty *tty, const struct tty_ctx *ctx) { - if (!tty_is_visible(tty, ctx, ctx->ocx, ctx->ocy, 1, 1)) + const struct grid_cell *gcp = ctx->cell; + struct screen *s = ctx->s; + struct overlay_ranges r; + u_int px, py, i, vis = 0; + + px = ctx->xoff + ctx->ocx - ctx->wox; + py = ctx->yoff + ctx->ocy - ctx->woy; + if (!tty_is_visible(tty, ctx, ctx->ocx, ctx->ocy, 1, 1) || + (gcp->data.width == 1 && !tty_check_overlay(tty, px, py))) return; + /* Handle partially obstructed wide characters. */ + if (gcp->data.width > 1) { + tty_check_overlay_range(tty, px, py, gcp->data.width, &r); + for (i = 0; i < OVERLAY_MAX_RANGES; i++) + vis += r.nx[i]; + if (vis < gcp->data.width) { + tty_draw_line(tty, s, s->cx, s->cy, gcp->data.width, + px, py, &ctx->defaults, ctx->palette); + return; + } + } + if (ctx->xoff + ctx->ocx - ctx->wox > tty->sx - 1 && ctx->ocy == ctx->orlower && tty_full_width(tty, ctx)) @@ -1861,6 +2037,10 @@ tty_cmd_cell(struct tty *tty, const struct tty_ctx *ctx) void tty_cmd_cells(struct tty *tty, const struct tty_ctx *ctx) { + struct overlay_ranges r; + u_int i, px, py, cx; + char *cp = ctx->ptr; + if (!tty_is_visible(tty, ctx, ctx->ocx, ctx->ocy, ctx->num, 1)) return; @@ -1882,9 +2062,21 @@ tty_cmd_cells(struct tty *tty, const struct tty_ctx *ctx) tty_margin_off(tty); tty_cursor_pane_unless_wrap(tty, ctx, ctx->ocx, ctx->ocy); - tty_attributes(tty, ctx->cell, &ctx->defaults, ctx->palette); - tty_putn(tty, ctx->ptr, ctx->num, ctx->num); + + /* Get tty position from pane position for overlay check. */ + px = ctx->xoff + ctx->ocx - ctx->wox; + py = ctx->yoff + ctx->ocy - ctx->woy; + + tty_check_overlay_range(tty, px, py, ctx->num, &r); + for (i = 0; i < OVERLAY_MAX_RANGES; i++) { + if (r.nx[i] == 0) + continue; + /* Convert back to pane position for printing. */ + cx = r.px[i] - ctx->xoff + ctx->wox; + tty_cursor_pane_unless_wrap(tty, ctx, cx, ctx->ocy); + tty_putn(tty, cp + r.px[i] - px, r.nx[i], r.nx[i]); + } } void @@ -1907,7 +2099,8 @@ tty_set_selection(struct tty *tty, const char *buf, size_t len) size = 4 * ((len + 2) / 3) + 1; /* storage for base64 */ encoded = xmalloc(size); - b64_ntop((const u_char *)buf, len, encoded, size); + b64_ntop(buf, len, encoded, size); + tty->flags |= TTY_NOBLOCK; tty_putcode_ptr2(tty, TTYC_MS, "", encoded); free(encoded); @@ -1916,19 +2109,33 @@ tty_set_selection(struct tty *tty, const char *buf, size_t len) void tty_cmd_rawstring(struct tty *tty, const struct tty_ctx *ctx) { + tty->flags |= TTY_NOBLOCK; tty_add(tty, ctx->ptr, ctx->num); tty_invalidate(tty); } void -tty_cmd_syncstart(struct tty *tty, __unused const struct tty_ctx *ctx) +tty_cmd_syncstart(struct tty *tty, const struct tty_ctx *ctx) { - tty_sync_start(tty); + if (ctx->num == 0x11) { + /* + * This is an overlay and a command that moves the cursor so + * start synchronized updates. + */ + tty_sync_start(tty); + } else if (~ctx->num & 0x10) { + /* + * This is a pane. If there is an overlay, always start; + * otherwise, only if requested. + */ + if (ctx->num || tty->client->overlay_draw != NULL) + tty_sync_start(tty); + } } void tty_cell(struct tty *tty, const struct grid_cell *gc, - const struct grid_cell *defaults, int *palette) + const struct grid_cell *defaults, struct colour_palette *palette) { const struct grid_cell *gcp; @@ -2117,17 +2324,25 @@ tty_cursor(struct tty *tty, u_int cx, u_int cy) if (tty->flags & TTY_BLOCK) return; - if (cx > tty->sx - 1) - cx = tty->sx - 1; - thisx = tty->cx; thisy = tty->cy; + /* + * If in the automargin space, and want to be there, do not move. + * Otherwise, force the cursor to be in range (and complain). + */ + if (cx == thisx && cy == thisy && cx == tty->sx) + return; + if (cx > tty->sx - 1) { + log_debug("%s: x too big %u > %u", __func__, cx, tty->sx - 1); + cx = tty->sx - 1; + } + /* No change. */ if (cx == thisx && cy == thisy) return; - /* Very end of the line, just use absolute movement. */ + /* Currently at the very end of the line - use absolute movement. */ if (thisx > tty->sx - 1) goto absolute; @@ -2248,17 +2463,19 @@ out: void tty_attributes(struct tty *tty, const struct grid_cell *gc, - const struct grid_cell *defaults, int *palette) + const struct grid_cell *defaults, struct colour_palette *palette) { struct grid_cell *tc = &tty->cell, gc2; int changed; /* Copy cell and update default colours. */ memcpy(&gc2, gc, sizeof gc2); - if (gc2.fg == 8) - gc2.fg = defaults->fg; - if (gc2.bg == 8) - gc2.bg = defaults->bg; + if (~gc->flags & GRID_FLAG_NOPALETTE) { + if (gc2.fg == 8) + gc2.fg = defaults->fg; + if (gc2.bg == 8) + gc2.bg = defaults->bg; + } /* Ignore cell if it is the same as the last one. */ if (gc2.attr == tty->last_cell.attr && @@ -2400,13 +2617,14 @@ tty_colours(struct tty *tty, const struct grid_cell *gc) if (!COLOUR_DEFAULT(gc->bg) && gc->bg != tc->bg) tty_colours_bg(tty, gc); - /* Set the underscore color. */ + /* Set the underscore colour. */ if (gc->us != tc->us) tty_colours_us(tty, gc); } static void -tty_check_fg(struct tty *tty, int *palette, struct grid_cell *gc) +tty_check_fg(struct tty *tty, struct colour_palette *palette, + struct grid_cell *gc) { u_char r, g, b; u_int colours; @@ -2421,7 +2639,7 @@ tty_check_fg(struct tty *tty, int *palette, struct grid_cell *gc) c = gc->fg; if (c < 8 && gc->attr & GRID_ATTR_BRIGHT) c += 90; - if ((c = tty_get_palette(palette, c)) != -1) + if ((c = colour_palette_get(palette, c)) != -1) gc->fg = c; } @@ -2462,7 +2680,8 @@ tty_check_fg(struct tty *tty, int *palette, struct grid_cell *gc) } static void -tty_check_bg(struct tty *tty, int *palette, struct grid_cell *gc) +tty_check_bg(struct tty *tty, struct colour_palette *palette, + struct grid_cell *gc) { u_char r, g, b; u_int colours; @@ -2470,7 +2689,7 @@ tty_check_bg(struct tty *tty, int *palette, struct grid_cell *gc) /* Perform substitution if this pane has a palette. */ if (~gc->flags & GRID_FLAG_NOPALETTE) { - if ((c = tty_get_palette(palette, gc->bg)) != -1) + if ((c = colour_palette_get(palette, gc->bg)) != -1) gc->bg = c; } @@ -2513,13 +2732,14 @@ tty_check_bg(struct tty *tty, int *palette, struct grid_cell *gc) } static void -tty_check_us(__unused struct tty *tty, int *palette, struct grid_cell *gc) +tty_check_us(__unused struct tty *tty, struct colour_palette *palette, + struct grid_cell *gc) { int c; /* Perform substitution if this pane has a palette. */ if (~gc->flags & GRID_FLAG_NOPALETTE) { - if ((c = tty_get_palette(palette, gc->us)) != -1) + if ((c = colour_palette_get(palette, gc->us)) != -1) gc->us = c; } @@ -2660,25 +2880,30 @@ static void tty_window_default_style(struct grid_cell *gc, struct window_pane *wp) { memcpy(gc, &grid_default_cell, sizeof *gc); - gc->fg = wp->fg; - gc->bg = wp->bg; + gc->fg = wp->palette.fg; + gc->bg = wp->palette.bg; } void tty_default_colours(struct grid_cell *gc, struct window_pane *wp) { - struct options *oo = wp->options; + struct options *oo = wp->options; + struct format_tree *ft; memcpy(gc, &grid_default_cell, sizeof *gc); if (wp->flags & PANE_STYLECHANGED) { + log_debug("%%%u: style changed", wp->id); wp->flags &= ~PANE_STYLECHANGED; + ft = format_create(NULL, NULL, FORMAT_PANE|wp->id, + FORMAT_NOJOBS); + format_defaults(ft, NULL, NULL, NULL, wp); tty_window_default_style(&wp->cached_active_gc, wp); - style_add(&wp->cached_active_gc, oo, "window-active-style", - NULL); + style_add(&wp->cached_active_gc, oo, "window-active-style", ft); tty_window_default_style(&wp->cached_gc, wp); - style_add(&wp->cached_gc, oo, "window-style", NULL); + style_add(&wp->cached_gc, oo, "window-style", ft); + format_free(ft); } if (gc->fg == 8) { @@ -2698,7 +2923,7 @@ tty_default_colours(struct grid_cell *gc, struct window_pane *wp) static void tty_default_attributes(struct tty *tty, const struct grid_cell *defaults, - int *palette, u_int bg) + struct colour_palette *palette, u_int bg) { struct grid_cell gc; @@ -2706,3 +2931,31 @@ tty_default_attributes(struct tty *tty, const struct grid_cell *defaults, gc.bg = bg; tty_attributes(tty, &gc, defaults, palette); } + +static void +tty_clipboard_query_callback(__unused int fd, __unused short events, void *data) +{ + struct tty *tty = data; + struct client *c = tty->client; + + c->flags &= ~CLIENT_CLIPBOARDBUFFER; + free(c->clipboard_panes); + c->clipboard_panes = NULL; + c->clipboard_npanes = 0; + + tty->flags &= ~TTY_OSC52QUERY; +} + +void +tty_clipboard_query(struct tty *tty) +{ + struct timeval tv = { .tv_sec = TTY_QUERY_TIMEOUT }; + + if ((~tty->flags & TTY_STARTED) || (tty->flags & TTY_OSC52QUERY)) + return; + tty_putcode_ptr2(tty, TTYC_MS, "", "?"); + + tty->flags |= TTY_OSC52QUERY; + evtimer_set(&tty->clipboard_timer, tty_clipboard_query_callback, tty); + evtimer_add(&tty->clipboard_timer, &tv); +} diff --git a/external/bsd/tmux/dist/utf8.c b/external/bsd/tmux/dist/utf8.c index 2fb44eb34e2..6ec03e5dd7f 100644 --- a/external/bsd/tmux/dist/utf8.c +++ b/external/bsd/tmux/dist/utf8.c @@ -64,7 +64,7 @@ static struct utf8_index_tree utf8_index_tree = RB_INITIALIZER(utf8_index_tree); static u_int utf8_next_index; #define UTF8_GET_SIZE(uc) (((uc) >> 24) & 0x1f) -#define UTF8_GET_WIDTH(flags) (((uc) >> 29) - 1) +#define UTF8_GET_WIDTH(uc) (((uc) >> 29) - 1) #define UTF8_SET_SIZE(size) (((utf8_char)(size)) << 24) #define UTF8_SET_WIDTH(width) ((((utf8_char)(width)) + 1) << 29) @@ -237,21 +237,6 @@ utf8_width(struct utf8_data *ud, int *width) if (*width >= 0 && *width <= 0xff) return (UTF8_DONE); log_debug("UTF-8 %.*s, wcwidth() %d", (int)ud->size, ud->data, *width); - -#ifndef __OpenBSD__ - /* - * Many platforms (particularly and inevitably OS X) have no width for - * relatively common characters (wcwidth() returns -1); assume width 1 - * in this case. This will be wrong for genuinely nonprintable - * characters, but they should be rare. We may pass through stuff that - * ideally we would block, but this is no worse than sending the same - * to the terminal without tmux. - */ - if (*width < 0) { - *width = 1; - return (UTF8_DONE); - } -#endif return (UTF8_ERROR); } diff --git a/external/bsd/tmux/dist/window-buffer.c b/external/bsd/tmux/dist/window-buffer.c index 7507e2c576c..620e0cc3892 100644 --- a/external/bsd/tmux/dist/window-buffer.c +++ b/external/bsd/tmux/dist/window-buffer.c @@ -308,7 +308,7 @@ window_buffer_get_key(void *modedata, void *itemdata, u_int line) } pb = paste_get_name(item->name); if (pb == NULL) - return KEYC_NONE; + return (KEYC_NONE); ft = format_create(NULL, NULL, FORMAT_NONE, 0); format_defaults(ft, NULL, NULL, 0, NULL); @@ -321,7 +321,7 @@ window_buffer_get_key(void *modedata, void *itemdata, u_int line) key = key_string_lookup_string(expanded); free(expanded); format_free(ft); - return key; + return (key); } static struct screen * @@ -344,10 +344,10 @@ window_buffer_init(struct window_mode_entry *wme, struct cmd_find_state *fs, data->key_format = xstrdup(WINDOW_BUFFER_DEFAULT_KEY_FORMAT); else data->key_format = xstrdup(args_get(args, 'K')); - if (args == NULL || args->argc == 0) + if (args == NULL || args_count(args) == 0) data->command = xstrdup(WINDOW_BUFFER_DEFAULT_COMMAND); else - data->command = xstrdup(args->argv[0]); + data->command = xstrdup(args_string(args, 0)); data->data = mode_tree_start(wp, args, window_buffer_build, window_buffer_draw, window_buffer_search, window_buffer_menu, NULL, diff --git a/external/bsd/tmux/dist/window-client.c b/external/bsd/tmux/dist/window-client.c index b65021a0248..18a3919f87d 100644 --- a/external/bsd/tmux/dist/window-client.c +++ b/external/bsd/tmux/dist/window-client.c @@ -281,7 +281,7 @@ window_client_get_key(void *modedata, void *itemdata, u_int line) key = key_string_lookup_string(expanded); free(expanded); format_free(ft); - return key; + return (key); } static struct screen * @@ -303,10 +303,10 @@ window_client_init(struct window_mode_entry *wme, data->key_format = xstrdup(WINDOW_CLIENT_DEFAULT_KEY_FORMAT); else data->key_format = xstrdup(args_get(args, 'K')); - if (args == NULL || args->argc == 0) + if (args == NULL || args_count(args) == 0) data->command = xstrdup(WINDOW_CLIENT_DEFAULT_COMMAND); else - data->command = xstrdup(args->argv[0]); + data->command = xstrdup(args_string(args, 0)); data->data = mode_tree_start(wp, args, window_client_build, window_client_draw, NULL, window_client_menu, NULL, diff --git a/external/bsd/tmux/dist/window-copy.c b/external/bsd/tmux/dist/window-copy.c index 5065ab2373d..54ef1b9789c 100644 --- a/external/bsd/tmux/dist/window-copy.c +++ b/external/bsd/tmux/dist/window-copy.c @@ -128,7 +128,7 @@ static void window_copy_cursor_next_word_end_pos(struct window_mode_entry *, static void window_copy_cursor_next_word_end(struct window_mode_entry *, const char *, int); static void window_copy_cursor_previous_word_pos(struct window_mode_entry *, - const char *, int, u_int *, u_int *); + const char *, u_int *, u_int *); static void window_copy_cursor_previous_word(struct window_mode_entry *, const char *, int); static void window_copy_scroll_up(struct window_mode_entry *, u_int); @@ -222,6 +222,8 @@ struct window_copy_mode_data { struct screen *backing; int backing_written; /* backing display started */ + struct screen *writing; + struct input_ctx *ictx; int viewmode; /* view mode entered */ @@ -255,7 +257,7 @@ struct window_copy_mode_data { SEL_LINE, /* select one line at a time */ } selflag; - const char *ws; /* word separators */ + const char *separators; /* word separators */ u_int dx; /* drag start position */ u_int dy; @@ -467,13 +469,16 @@ window_copy_view_init(struct window_mode_entry *wme, struct window_pane *wp = wme->wp; struct window_copy_mode_data *data; struct screen *base = &wp->base; - struct screen *s; + u_int sx = screen_size_x(base); data = window_copy_common_init(wme); data->viewmode = 1; - 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, sx, screen_size_y(base), UINT_MAX); + data->writing = xmalloc(sizeof *data->writing); + screen_init(data->writing, sx, screen_size_y(base), 0); + data->ictx = input_init(NULL, NULL, NULL); data->mx = data->cx; data->my = screen_hsize(data->backing) + data->cy - data->oy; data->showmark = 0; @@ -492,6 +497,12 @@ window_copy_free(struct window_mode_entry *wme) free(data->searchstr); free(data->jumpchar); + if (data->writing != NULL) { + screen_free(data->writing); + free(data->writing); + } + if (data->ictx != NULL) + input_free(data->ictx); screen_free(data->backing); free(data->backing); @@ -500,41 +511,67 @@ window_copy_free(struct window_mode_entry *wme) } void -window_copy_add(struct window_pane *wp, const char *fmt, ...) +window_copy_add(struct window_pane *wp, int parse, const char *fmt, ...) { va_list ap; va_start(ap, fmt); - window_copy_vadd(wp, fmt, ap); + window_copy_vadd(wp, parse, fmt, ap); va_end(ap); } +static void +window_copy_init_ctx_cb(__unused struct screen_write_ctx *ctx, + struct tty_ctx *ttyctx) +{ + memcpy(&ttyctx->defaults, &grid_default_cell, sizeof ttyctx->defaults); + ttyctx->palette = NULL; + ttyctx->redraw_cb = NULL; + ttyctx->set_client_cb = NULL; + ttyctx->arg = NULL; +} + void -window_copy_vadd(struct window_pane *wp, const char *fmt, va_list ap) +window_copy_vadd(struct window_pane *wp, int parse, const char *fmt, va_list ap) { struct window_mode_entry *wme = TAILQ_FIRST(&wp->modes); struct window_copy_mode_data *data = wme->data; struct screen *backing = data->backing; - struct screen_write_ctx back_ctx, ctx; + struct screen *writing = data->writing; + struct screen_write_ctx writing_ctx, backing_ctx, ctx; struct grid_cell gc; u_int old_hsize, old_cy; + u_int sx = screen_size_x(backing); + char *text; - memcpy(&gc, &grid_default_cell, sizeof gc); + if (parse) { + vasprintf(&text, fmt, ap); + screen_write_start(&writing_ctx, writing); + screen_write_reset(&writing_ctx); + input_parse_screen(data->ictx, writing, window_copy_init_ctx_cb, + data, text, strlen(text)); + free(text); + } old_hsize = screen_hsize(data->backing); - screen_write_start(&back_ctx, backing); + screen_write_start(&backing_ctx, backing); if (data->backing_written) { /* * On the second or later line, do a CRLF before writing * (so it's on a new line). */ - screen_write_carriagereturn(&back_ctx); - screen_write_linefeed(&back_ctx, 0, 8); + screen_write_carriagereturn(&backing_ctx); + screen_write_linefeed(&backing_ctx, 0, 8); } else data->backing_written = 1; old_cy = backing->cy; - screen_write_vnputs(&back_ctx, 0, &gc, fmt, ap); - screen_write_stop(&back_ctx); + if (parse) + screen_write_fast_copy(&backing_ctx, writing, 0, 0, sx, 1); + else { + memcpy(&gc, &grid_default_cell, sizeof gc); + screen_write_vnputs(&backing_ctx, 0, &gc, fmt, ap); + } + screen_write_stop(&backing_ctx); data->oy += screen_hsize(data->backing) - old_hsize; @@ -842,26 +879,23 @@ window_copy_expand_search_string(struct window_copy_cmd_state *cs) { struct window_mode_entry *wme = cs->wme; struct window_copy_mode_data *data = wme->data; - const char *argument; + const char *ss = args_string(cs->args, 1); char *expanded; - if (cs->args->argc == 2) { - argument = cs->args->argv[1]; - if (*argument != '\0') { - if (args_has(cs->args, 'F')) { - expanded = format_single(NULL, argument, NULL, - NULL, NULL, wme->wp); - if (*expanded == '\0') { - free(expanded); - return (0); - } - free(data->searchstr); - data->searchstr = expanded; - } else { - free(data->searchstr); - data->searchstr = xstrdup(argument); - } + if (ss == NULL || *ss == '\0') + return (0); + + if (args_has(cs->args, 'F')) { + expanded = format_single(NULL, ss, NULL, NULL, NULL, wme->wp); + if (*expanded == '\0') { + free(expanded); + return (0); } + free(data->searchstr); + data->searchstr = expanded; + } else { + free(data->searchstr); + data->searchstr = xstrdup(ss); } return (1); } @@ -959,18 +993,34 @@ window_copy_cmd_clear_selection(struct window_copy_cmd_state *cs) } static enum window_copy_cmd_action -window_copy_cmd_copy_end_of_line(struct window_copy_cmd_state *cs) -{ - struct window_mode_entry *wme = cs->wme; - struct client *c = cs->c; - struct session *s = cs->s; - struct winlink *wl = cs->wl; - struct window_pane *wp = wme->wp; - u_int np = wme->prefix; - char *prefix = NULL; +window_copy_do_copy_end_of_line(struct window_copy_cmd_state *cs, int pipe, + int cancel) +{ + struct window_mode_entry *wme = cs->wme; + struct client *c = cs->c; + struct session *s = cs->s; + struct winlink *wl = cs->wl; + struct window_pane *wp = wme->wp; + u_int count = args_count(cs->args); + u_int np = wme->prefix, ocx, ocy, ooy; + struct window_copy_mode_data *data = wme->data; + char *prefix = NULL, *command = NULL; + const char *arg1 = args_string(cs->args, 1); + const char *arg2 = args_string(cs->args, 2); + + if (pipe) { + if (count == 3) + prefix = format_single(NULL, arg2, c, s, wl, wp); + if (s != NULL && count > 1 && *arg1 != '\0') + command = format_single(NULL, arg1, c, s, wl, wp); + } else { + if (count == 2) + prefix = format_single(NULL, arg1, c, s, wl, wp); + } - if (cs->args->argc == 2) - prefix = format_single(NULL, cs->args->argv[1], c, s, wl, wp); + ocx = data->cx; + ocy = data->cy; + ooy = data->oy; window_copy_start_selection(wme); for (; np > 1; np--) @@ -978,30 +1028,81 @@ window_copy_cmd_copy_end_of_line(struct window_copy_cmd_state *cs) window_copy_cursor_end_of_line(wme); if (s != NULL) { - window_copy_copy_selection(wme, prefix); + if (pipe) + window_copy_copy_pipe(wme, s, prefix, command); + else + window_copy_copy_selection(wme, prefix); - free(prefix); - return (WINDOW_COPY_CMD_CANCEL); + if (cancel) { + free(prefix); + free(command); + return (WINDOW_COPY_CMD_CANCEL); + } } + window_copy_clear_selection(wme); + + data->cx = ocx; + data->cy = ocy; + data->oy = ooy; free(prefix); + free(command); return (WINDOW_COPY_CMD_REDRAW); } static enum window_copy_cmd_action -window_copy_cmd_copy_line(struct window_copy_cmd_state *cs) +window_copy_cmd_copy_end_of_line(struct window_copy_cmd_state *cs) { - struct window_mode_entry *wme = cs->wme; - struct client *c = cs->c; - struct session *s = cs->s; - struct winlink *wl = cs->wl; - struct window_pane *wp = wme->wp; - struct window_copy_mode_data *data = wme->data; - u_int np = wme->prefix; - char *prefix = NULL; + return (window_copy_do_copy_end_of_line(cs, 0, 0)); +} + +static enum window_copy_cmd_action +window_copy_cmd_copy_end_of_line_and_cancel(struct window_copy_cmd_state *cs) +{ + return (window_copy_do_copy_end_of_line(cs, 0, 1)); +} + +static enum window_copy_cmd_action +window_copy_cmd_copy_pipe_end_of_line(struct window_copy_cmd_state *cs) +{ + return (window_copy_do_copy_end_of_line(cs, 1, 0)); +} + +static enum window_copy_cmd_action +window_copy_cmd_copy_pipe_end_of_line_and_cancel( + struct window_copy_cmd_state *cs) +{ + return (window_copy_do_copy_end_of_line(cs, 1, 1)); +} - if (cs->args->argc == 2) - prefix = format_single(NULL, cs->args->argv[1], c, s, wl, wp); +static enum window_copy_cmd_action +window_copy_do_copy_line(struct window_copy_cmd_state *cs, int pipe, int cancel) +{ + struct window_mode_entry *wme = cs->wme; + struct client *c = cs->c; + struct session *s = cs->s; + struct winlink *wl = cs->wl; + struct window_pane *wp = wme->wp; + struct window_copy_mode_data *data = wme->data; + u_int count = args_count(cs->args); + u_int np = wme->prefix, ocx, ocy, ooy; + char *prefix = NULL, *command = NULL; + const char *arg1 = args_string(cs->args, 1); + const char *arg2 = args_string(cs->args, 2); + + if (pipe) { + if (count == 3) + prefix = format_single(NULL, arg2, c, s, wl, wp); + if (s != NULL && count > 1 && *arg1 != '\0') + command = format_single(NULL, arg1, c, s, wl, wp); + } else { + if (count == 2) + prefix = format_single(NULL, arg1, c, s, wl, wp); + } + + ocx = data->cx; + ocy = data->cy; + ooy = data->oy; data->selflag = SEL_CHAR; window_copy_cursor_start_of_line(wme); @@ -1011,17 +1112,53 @@ window_copy_cmd_copy_line(struct window_copy_cmd_state *cs) window_copy_cursor_end_of_line(wme); if (s != NULL) { - window_copy_copy_selection(wme, prefix); + if (pipe) + window_copy_copy_pipe(wme, s, prefix, command); + else + window_copy_copy_selection(wme, prefix); - free(prefix); - return (WINDOW_COPY_CMD_CANCEL); + if (cancel) { + free(prefix); + free(command); + return (WINDOW_COPY_CMD_CANCEL); + } } + window_copy_clear_selection(wme); + + data->cx = ocx; + data->cy = ocy; + data->oy = ooy; free(prefix); + free(command); return (WINDOW_COPY_CMD_REDRAW); } static enum window_copy_cmd_action +window_copy_cmd_copy_line(struct window_copy_cmd_state *cs) +{ + return (window_copy_do_copy_line(cs, 0, 0)); +} + +static enum window_copy_cmd_action +window_copy_cmd_copy_line_and_cancel(struct window_copy_cmd_state *cs) +{ + return (window_copy_do_copy_line(cs, 0, 1)); +} + +static enum window_copy_cmd_action +window_copy_cmd_copy_pipe_line(struct window_copy_cmd_state *cs) +{ + return (window_copy_do_copy_line(cs, 1, 0)); +} + +static enum window_copy_cmd_action +window_copy_cmd_copy_pipe_line_and_cancel(struct window_copy_cmd_state *cs) +{ + return (window_copy_do_copy_line(cs, 1, 1)); +} + +static enum window_copy_cmd_action window_copy_cmd_copy_selection_no_clear(struct window_copy_cmd_state *cs) { struct window_mode_entry *wme = cs->wme; @@ -1030,9 +1167,10 @@ window_copy_cmd_copy_selection_no_clear(struct window_copy_cmd_state *cs) struct winlink *wl = cs->wl; struct window_pane *wp = wme->wp; char *prefix = NULL; + const char *arg1 = args_string(cs->args, 1); - if (cs->args->argc == 2) - prefix = format_single(NULL, cs->args->argv[1], c, s, wl, wp); + if (arg1 != NULL) + prefix = format_single(NULL, arg1, c, s, wl, wp); if (s != NULL) window_copy_copy_selection(wme, prefix); @@ -1172,6 +1310,16 @@ window_copy_cmd_halfpage_up(struct window_copy_cmd_state *cs) } static enum window_copy_cmd_action +window_copy_cmd_toggle_position(struct window_copy_cmd_state *cs) +{ + struct window_mode_entry *wme = cs->wme; + struct window_copy_mode_data *data = wme->data; + + data->hide_position = !data->hide_position; + return (WINDOW_COPY_CMD_REDRAW); +} + +static enum window_copy_cmd_action window_copy_cmd_history_bottom(struct window_copy_cmd_state *cs) { struct window_mode_entry *wme = cs->wme; @@ -1324,7 +1472,7 @@ window_copy_cmd_previous_matching_bracket(struct window_copy_cmd_state *cs) tried = 1; goto retry; } - window_copy_cursor_previous_word(wme, "}]) ", 1); + window_copy_cursor_previous_word(wme, close, 1); } continue; } @@ -1436,8 +1584,7 @@ window_copy_cmd_next_matching_bracket(struct window_copy_cmd_state *cs) tried = 1; goto retry; } - window_copy_cursor_next_word_end(wme, "{[( ", - 0); + window_copy_cursor_next_word_end(wme, open, 0); continue; } /* For vi, continue searching for bracket until EOL. */ @@ -1509,7 +1656,7 @@ window_copy_cmd_next_space(struct window_copy_cmd_state *cs) u_int np = wme->prefix; for (; np != 0; np--) - window_copy_cursor_next_word(wme, " "); + window_copy_cursor_next_word(wme, ""); return (WINDOW_COPY_CMD_NOTHING); } @@ -1520,7 +1667,7 @@ window_copy_cmd_next_space_end(struct window_copy_cmd_state *cs) u_int np = wme->prefix; for (; np != 0; np--) - window_copy_cursor_next_word_end(wme, " ", 0); + window_copy_cursor_next_word_end(wme, "", 0); return (WINDOW_COPY_CMD_NOTHING); } @@ -1528,13 +1675,13 @@ static enum window_copy_cmd_action window_copy_cmd_next_word(struct window_copy_cmd_state *cs) { struct window_mode_entry *wme = cs->wme; - struct session *s = cs->s; u_int np = wme->prefix; - const char *ws; + const char *separators; + + separators = options_get_string(cs->s->options, "word-separators"); - ws = options_get_string(s->options, "word-separators"); for (; np != 0; np--) - window_copy_cursor_next_word(wme, ws); + window_copy_cursor_next_word(wme, separators); return (WINDOW_COPY_CMD_NOTHING); } @@ -1542,13 +1689,13 @@ static enum window_copy_cmd_action window_copy_cmd_next_word_end(struct window_copy_cmd_state *cs) { struct window_mode_entry *wme = cs->wme; - struct session *s = cs->s; u_int np = wme->prefix; - const char *ws; + const char *separators; + + separators = options_get_string(cs->s->options, "word-separators"); - ws = options_get_string(s->options, "word-separators"); for (; np != 0; np--) - window_copy_cursor_next_word_end(wme, ws, 0); + window_copy_cursor_next_word_end(wme, separators, 0); return (WINDOW_COPY_CMD_NOTHING); } @@ -1621,7 +1768,7 @@ window_copy_cmd_previous_space(struct window_copy_cmd_state *cs) u_int np = wme->prefix; for (; np != 0; np--) - window_copy_cursor_previous_word(wme, " ", 1); + window_copy_cursor_previous_word(wme, "", 1); return (WINDOW_COPY_CMD_NOTHING); } @@ -1629,13 +1776,13 @@ static enum window_copy_cmd_action window_copy_cmd_previous_word(struct window_copy_cmd_state *cs) { struct window_mode_entry *wme = cs->wme; - struct session *s = cs->s; u_int np = wme->prefix; - const char *ws; + const char *separators; + + separators = options_get_string(cs->s->options, "word-separators"); - ws = options_get_string(s->options, "word-separators"); for (; np != 0; np--) - window_copy_cursor_previous_word(wme, ws, 1); + window_copy_cursor_previous_word(wme, separators, 1); return (WINDOW_COPY_CMD_NOTHING); } @@ -1781,7 +1928,7 @@ static enum window_copy_cmd_action window_copy_cmd_select_word(struct window_copy_cmd_state *cs) { struct window_mode_entry *wme = cs->wme; - struct session *s = cs->s; + struct options *session_options = cs->s->options; struct window_copy_mode_data *data = wme->data; u_int px, py, nextx, nexty; @@ -1791,8 +1938,9 @@ window_copy_cmd_select_word(struct window_copy_cmd_state *cs) data->dx = data->cx; data->dy = screen_hsize(data->backing) + data->cy - data->oy; - data->ws = options_get_string(s->options, "word-separators"); - window_copy_cursor_previous_word(wme, data->ws, 0); + data->separators = options_get_string(session_options, + "word-separators"); + window_copy_cursor_previous_word(wme, data->separators, 0); px = data->cx; py = screen_hsize(data->backing) + data->cy - data->oy; data->selrx = px; @@ -1808,8 +1956,8 @@ window_copy_cmd_select_word(struct window_copy_cmd_state *cs) nexty++; } if (px >= window_copy_find_length(wme, py) || - !window_copy_in_set(wme, nextx, nexty, data->ws)) - window_copy_cursor_next_word_end(wme, data->ws, 1); + !window_copy_in_set(wme, nextx, nexty, WHITESPACE)) + window_copy_cursor_next_word_end(wme, data->separators, 1); else { window_copy_update_cursor(wme, px, data->cy); if (window_copy_update_selection(wme, 1, 1)) @@ -1867,14 +2015,15 @@ window_copy_cmd_copy_pipe_no_clear(struct window_copy_cmd_state *cs) struct session *s = cs->s; struct winlink *wl = cs->wl; struct window_pane *wp = wme->wp; - char *command = NULL; - char *prefix = NULL; + char *command = NULL, *prefix = NULL; + const char *arg1 = args_string(cs->args, 1); + const char *arg2 = args_string(cs->args, 2); - if (cs->args->argc == 3) - prefix = format_single(NULL, cs->args->argv[2], c, s, wl, wp); + if (arg2 != NULL) + prefix = format_single(NULL, arg2, c, s, wl, wp); - if (s != NULL && cs->args->argc > 1 && *cs->args->argv[1] != '\0') - command = format_single(NULL, cs->args->argv[1], c, s, wl, wp); + if (s != NULL && arg1 != NULL && *arg1 != '\0') + command = format_single(NULL, arg1, c, s, wl, wp); window_copy_copy_pipe(wme, s, prefix, command); free(command); @@ -1911,9 +2060,10 @@ window_copy_cmd_pipe_no_clear(struct window_copy_cmd_state *cs) struct winlink *wl = cs->wl; struct window_pane *wp = wme->wp; char *command = NULL; + const char *arg1 = args_string(cs->args, 1); - if (s != NULL && cs->args->argc > 1 && *cs->args->argv[1] != '\0') - command = format_single(NULL, cs->args->argv[1], c, s, wl, wp); + if (s != NULL && arg1 != NULL && *arg1 != '\0') + command = format_single(NULL, arg1, c, s, wl, wp); window_copy_pipe(wme, s, command); free(command); @@ -1944,10 +2094,10 @@ static enum window_copy_cmd_action window_copy_cmd_goto_line(struct window_copy_cmd_state *cs) { struct window_mode_entry *wme = cs->wme; - const char *argument = cs->args->argv[1]; + const char *arg1 = args_string(cs->args, 1); - if (*argument != '\0') - window_copy_goto_line(wme, argument); + if (*arg1 != '\0') + window_copy_goto_line(wme, arg1); return (WINDOW_COPY_CMD_NOTHING); } @@ -1957,12 +2107,12 @@ window_copy_cmd_jump_backward(struct window_copy_cmd_state *cs) struct window_mode_entry *wme = cs->wme; struct window_copy_mode_data *data = wme->data; u_int np = wme->prefix; - const char *argument = cs->args->argv[1]; + const char *arg1 = args_string(cs->args, 1); - if (*argument != '\0') { + if (*arg1 != '\0') { data->jumptype = WINDOW_COPY_JUMPBACKWARD; free(data->jumpchar); - data->jumpchar = utf8_fromcstr(argument); + data->jumpchar = utf8_fromcstr(arg1); for (; np != 0; np--) window_copy_cursor_jump_back(wme); } @@ -1975,12 +2125,12 @@ window_copy_cmd_jump_forward(struct window_copy_cmd_state *cs) struct window_mode_entry *wme = cs->wme; struct window_copy_mode_data *data = wme->data; u_int np = wme->prefix; - const char *argument = cs->args->argv[1]; + const char *arg1 = args_string(cs->args, 1); - if (*argument != '\0') { + if (*arg1 != '\0') { data->jumptype = WINDOW_COPY_JUMPFORWARD; free(data->jumpchar); - data->jumpchar = utf8_fromcstr(argument); + data->jumpchar = utf8_fromcstr(arg1); for (; np != 0; np--) window_copy_cursor_jump(wme); } @@ -1993,12 +2143,12 @@ window_copy_cmd_jump_to_backward(struct window_copy_cmd_state *cs) struct window_mode_entry *wme = cs->wme; struct window_copy_mode_data *data = wme->data; u_int np = wme->prefix; - const char *argument = cs->args->argv[1]; + const char *arg1 = args_string(cs->args, 1); - if (*argument != '\0') { + if (*arg1 != '\0') { data->jumptype = WINDOW_COPY_JUMPTOBACKWARD; free(data->jumpchar); - data->jumpchar = utf8_fromcstr(argument); + data->jumpchar = utf8_fromcstr(arg1); for (; np != 0; np--) window_copy_cursor_jump_to_back(wme); } @@ -2011,12 +2161,12 @@ window_copy_cmd_jump_to_forward(struct window_copy_cmd_state *cs) struct window_mode_entry *wme = cs->wme; struct window_copy_mode_data *data = wme->data; u_int np = wme->prefix; - const char *argument = cs->args->argv[1]; + const char *arg1 = args_string(cs->args, 1); - if (*argument != '\0') { + if (*arg1 != '\0') { data->jumptype = WINDOW_COPY_JUMPTOFORWARD; free(data->jumpchar); - data->jumpchar = utf8_fromcstr(argument); + data->jumpchar = utf8_fromcstr(arg1); for (; np != 0; np--) window_copy_cursor_jump_to(wme); } @@ -2117,27 +2267,27 @@ window_copy_cmd_search_backward_incremental(struct window_copy_cmd_state *cs) { struct window_mode_entry *wme = cs->wme; struct window_copy_mode_data *data = wme->data; - const char *argument = cs->args->argv[1]; + const char *arg1 = args_string(cs->args, 1); const char *ss = data->searchstr; char prefix; enum window_copy_cmd_action action = WINDOW_COPY_CMD_NOTHING; data->timeout = 0; - log_debug ("%s: %s", __func__, argument); + log_debug("%s: %s", __func__, arg1); - prefix = *argument++; + prefix = *arg1++; if (data->searchx == -1 || data->searchy == -1) { data->searchx = data->cx; data->searchy = data->cy; data->searcho = data->oy; - } else if (ss != NULL && strcmp(argument, ss) != 0) { + } else if (ss != NULL && strcmp(arg1, ss) != 0) { data->cx = data->searchx; data->cy = data->searchy; data->oy = data->searcho; action = WINDOW_COPY_CMD_REDRAW; } - if (*argument == '\0') { + if (*arg1 == '\0') { window_copy_clear_marks(wme); return (WINDOW_COPY_CMD_REDRAW); } @@ -2147,7 +2297,7 @@ window_copy_cmd_search_backward_incremental(struct window_copy_cmd_state *cs) data->searchtype = WINDOW_COPY_SEARCHUP; data->searchregex = 0; free(data->searchstr); - data->searchstr = xstrdup(argument); + data->searchstr = xstrdup(arg1); if (!window_copy_search_up(wme, 0)) { window_copy_clear_marks(wme); return (WINDOW_COPY_CMD_REDRAW); @@ -2157,7 +2307,7 @@ window_copy_cmd_search_backward_incremental(struct window_copy_cmd_state *cs) data->searchtype = WINDOW_COPY_SEARCHDOWN; data->searchregex = 0; free(data->searchstr); - data->searchstr = xstrdup(argument); + data->searchstr = xstrdup(arg1); if (!window_copy_search_down(wme, 0)) { window_copy_clear_marks(wme); return (WINDOW_COPY_CMD_REDRAW); @@ -2172,27 +2322,27 @@ window_copy_cmd_search_forward_incremental(struct window_copy_cmd_state *cs) { struct window_mode_entry *wme = cs->wme; struct window_copy_mode_data *data = wme->data; - const char *argument = cs->args->argv[1]; + const char *arg1 = args_string(cs->args, 1); const char *ss = data->searchstr; char prefix; enum window_copy_cmd_action action = WINDOW_COPY_CMD_NOTHING; data->timeout = 0; - log_debug ("%s: %s", __func__, argument); + log_debug("%s: %s", __func__, arg1); - prefix = *argument++; + prefix = *arg1++; if (data->searchx == -1 || data->searchy == -1) { data->searchx = data->cx; data->searchy = data->cy; data->searcho = data->oy; - } else if (ss != NULL && strcmp(argument, ss) != 0) { + } else if (ss != NULL && strcmp(arg1, ss) != 0) { data->cx = data->searchx; data->cy = data->searchy; data->oy = data->searcho; action = WINDOW_COPY_CMD_REDRAW; } - if (*argument == '\0') { + if (*arg1 == '\0') { window_copy_clear_marks(wme); return (WINDOW_COPY_CMD_REDRAW); } @@ -2202,7 +2352,7 @@ window_copy_cmd_search_forward_incremental(struct window_copy_cmd_state *cs) data->searchtype = WINDOW_COPY_SEARCHDOWN; data->searchregex = 0; free(data->searchstr); - data->searchstr = xstrdup(argument); + data->searchstr = xstrdup(arg1); if (!window_copy_search_down(wme, 0)) { window_copy_clear_marks(wme); return (WINDOW_COPY_CMD_REDRAW); @@ -2212,7 +2362,7 @@ window_copy_cmd_search_forward_incremental(struct window_copy_cmd_state *cs) data->searchtype = WINDOW_COPY_SEARCHUP; data->searchregex = 0; free(data->searchstr); - data->searchstr = xstrdup(argument); + data->searchstr = xstrdup(arg1); if (!window_copy_search_up(wme, 0)) { window_copy_clear_marks(wme); return (WINDOW_COPY_CMD_REDRAW); @@ -2233,8 +2383,7 @@ window_copy_cmd_refresh_from_pane(struct window_copy_cmd_state *cs) screen_free(data->backing); free(data->backing); - data->backing = window_copy_clone_screen(&wp->base, &data->screen, NULL, - NULL, wme->swp != wme->wp); + data->backing = window_copy_clone_screen(&wp->base, &data->screen, NULL, NULL, wme->swp != wme->wp); window_copy_size_changed(wme); return (WINDOW_COPY_CMD_REDRAW); @@ -2242,157 +2391,491 @@ window_copy_cmd_refresh_from_pane(struct window_copy_cmd_state *cs) static const struct { const char *command; - int minargs; - int maxargs; + u_int minargs; + u_int maxargs; enum window_copy_cmd_clear clear; enum window_copy_cmd_action (*f)(struct window_copy_cmd_state *); } window_copy_cmd_table[] = { - { "append-selection", 0, 0, WINDOW_COPY_CMD_CLEAR_ALWAYS, - window_copy_cmd_append_selection }, - { "append-selection-and-cancel", 0, 0, WINDOW_COPY_CMD_CLEAR_ALWAYS, - window_copy_cmd_append_selection_and_cancel }, - { "back-to-indentation", 0, 0, WINDOW_COPY_CMD_CLEAR_ALWAYS, - window_copy_cmd_back_to_indentation }, - { "begin-selection", 0, 0, WINDOW_COPY_CMD_CLEAR_ALWAYS, - window_copy_cmd_begin_selection }, - { "bottom-line", 0, 0, WINDOW_COPY_CMD_CLEAR_EMACS_ONLY, - window_copy_cmd_bottom_line }, - { "cancel", 0, 0, WINDOW_COPY_CMD_CLEAR_ALWAYS, - window_copy_cmd_cancel }, - { "clear-selection", 0, 0, WINDOW_COPY_CMD_CLEAR_ALWAYS, - window_copy_cmd_clear_selection }, - { "copy-end-of-line", 0, 1, WINDOW_COPY_CMD_CLEAR_ALWAYS, - window_copy_cmd_copy_end_of_line }, - { "copy-line", 0, 1, WINDOW_COPY_CMD_CLEAR_ALWAYS, - window_copy_cmd_copy_line }, - { "copy-pipe-no-clear", 0, 2, WINDOW_COPY_CMD_CLEAR_NEVER, - window_copy_cmd_copy_pipe_no_clear }, - { "copy-pipe", 0, 2, WINDOW_COPY_CMD_CLEAR_ALWAYS, - window_copy_cmd_copy_pipe }, - { "copy-pipe-and-cancel", 0, 2, WINDOW_COPY_CMD_CLEAR_ALWAYS, - window_copy_cmd_copy_pipe_and_cancel }, - { "copy-selection-no-clear", 0, 1, WINDOW_COPY_CMD_CLEAR_NEVER, - window_copy_cmd_copy_selection_no_clear }, - { "copy-selection", 0, 1, WINDOW_COPY_CMD_CLEAR_ALWAYS, - window_copy_cmd_copy_selection }, - { "copy-selection-and-cancel", 0, 1, WINDOW_COPY_CMD_CLEAR_ALWAYS, - window_copy_cmd_copy_selection_and_cancel }, - { "cursor-down", 0, 0, WINDOW_COPY_CMD_CLEAR_EMACS_ONLY, - window_copy_cmd_cursor_down }, - { "cursor-down-and-cancel", 0, 0, WINDOW_COPY_CMD_CLEAR_ALWAYS, - window_copy_cmd_cursor_down_and_cancel }, - { "cursor-left", 0, 0, WINDOW_COPY_CMD_CLEAR_EMACS_ONLY, - window_copy_cmd_cursor_left }, - { "cursor-right", 0, 0, WINDOW_COPY_CMD_CLEAR_EMACS_ONLY, - window_copy_cmd_cursor_right }, - { "cursor-up", 0, 0, WINDOW_COPY_CMD_CLEAR_EMACS_ONLY, - window_copy_cmd_cursor_up }, - { "end-of-line", 0, 0, WINDOW_COPY_CMD_CLEAR_EMACS_ONLY, - window_copy_cmd_end_of_line }, - { "goto-line", 1, 1, WINDOW_COPY_CMD_CLEAR_EMACS_ONLY, - window_copy_cmd_goto_line }, - { "halfpage-down", 0, 0, WINDOW_COPY_CMD_CLEAR_EMACS_ONLY, - window_copy_cmd_halfpage_down }, - { "halfpage-down-and-cancel", 0, 0, WINDOW_COPY_CMD_CLEAR_ALWAYS, - window_copy_cmd_halfpage_down_and_cancel }, - { "halfpage-up", 0, 0, WINDOW_COPY_CMD_CLEAR_EMACS_ONLY, - window_copy_cmd_halfpage_up }, - { "history-bottom", 0, 0, WINDOW_COPY_CMD_CLEAR_EMACS_ONLY, - window_copy_cmd_history_bottom }, - { "history-top", 0, 0, WINDOW_COPY_CMD_CLEAR_EMACS_ONLY, - window_copy_cmd_history_top }, - { "jump-again", 0, 0, WINDOW_COPY_CMD_CLEAR_EMACS_ONLY, - window_copy_cmd_jump_again }, - { "jump-backward", 1, 1, WINDOW_COPY_CMD_CLEAR_EMACS_ONLY, - window_copy_cmd_jump_backward }, - { "jump-forward", 1, 1, WINDOW_COPY_CMD_CLEAR_EMACS_ONLY, - window_copy_cmd_jump_forward }, - { "jump-reverse", 0, 0, WINDOW_COPY_CMD_CLEAR_EMACS_ONLY, - window_copy_cmd_jump_reverse }, - { "jump-to-backward", 1, 1, WINDOW_COPY_CMD_CLEAR_EMACS_ONLY, - window_copy_cmd_jump_to_backward }, - { "jump-to-forward", 1, 1, WINDOW_COPY_CMD_CLEAR_EMACS_ONLY, - window_copy_cmd_jump_to_forward }, - { "jump-to-mark", 0, 0, WINDOW_COPY_CMD_CLEAR_ALWAYS, - window_copy_cmd_jump_to_mark }, - { "middle-line", 0, 0, WINDOW_COPY_CMD_CLEAR_EMACS_ONLY, - window_copy_cmd_middle_line }, - { "next-matching-bracket", 0, 0, WINDOW_COPY_CMD_CLEAR_ALWAYS, - window_copy_cmd_next_matching_bracket }, - { "next-paragraph", 0, 0, WINDOW_COPY_CMD_CLEAR_EMACS_ONLY, - window_copy_cmd_next_paragraph }, - { "next-space", 0, 0, WINDOW_COPY_CMD_CLEAR_EMACS_ONLY, - window_copy_cmd_next_space }, - { "next-space-end", 0, 0, WINDOW_COPY_CMD_CLEAR_EMACS_ONLY, - window_copy_cmd_next_space_end }, - { "next-word", 0, 0, WINDOW_COPY_CMD_CLEAR_EMACS_ONLY, - window_copy_cmd_next_word }, - { "next-word-end", 0, 0, WINDOW_COPY_CMD_CLEAR_EMACS_ONLY, - window_copy_cmd_next_word_end }, - { "other-end", 0, 0, WINDOW_COPY_CMD_CLEAR_EMACS_ONLY, - window_copy_cmd_other_end }, - { "page-down", 0, 0, WINDOW_COPY_CMD_CLEAR_EMACS_ONLY, - window_copy_cmd_page_down }, - { "page-down-and-cancel", 0, 0, WINDOW_COPY_CMD_CLEAR_ALWAYS, - window_copy_cmd_page_down_and_cancel }, - { "page-up", 0, 0, WINDOW_COPY_CMD_CLEAR_EMACS_ONLY, - window_copy_cmd_page_up }, - { "pipe-no-clear", 0, 1, WINDOW_COPY_CMD_CLEAR_NEVER, - window_copy_cmd_pipe_no_clear }, - { "pipe", 0, 1, WINDOW_COPY_CMD_CLEAR_ALWAYS, - window_copy_cmd_pipe }, - { "pipe-and-cancel", 0, 1, WINDOW_COPY_CMD_CLEAR_ALWAYS, - window_copy_cmd_pipe_and_cancel }, - { "previous-matching-bracket", 0, 0, WINDOW_COPY_CMD_CLEAR_ALWAYS, - window_copy_cmd_previous_matching_bracket }, - { "previous-paragraph", 0, 0, WINDOW_COPY_CMD_CLEAR_EMACS_ONLY, - window_copy_cmd_previous_paragraph }, - { "previous-space", 0, 0, WINDOW_COPY_CMD_CLEAR_EMACS_ONLY, - window_copy_cmd_previous_space }, - { "previous-word", 0, 0, WINDOW_COPY_CMD_CLEAR_EMACS_ONLY, - window_copy_cmd_previous_word }, - { "rectangle-on", 0, 0, WINDOW_COPY_CMD_CLEAR_ALWAYS, - window_copy_cmd_rectangle_on }, - { "rectangle-off", 0, 0, WINDOW_COPY_CMD_CLEAR_ALWAYS, - window_copy_cmd_rectangle_off }, - { "rectangle-toggle", 0, 0, WINDOW_COPY_CMD_CLEAR_ALWAYS, - window_copy_cmd_rectangle_toggle }, - { "refresh-from-pane", 0, 0, WINDOW_COPY_CMD_CLEAR_ALWAYS, - window_copy_cmd_refresh_from_pane }, - { "scroll-down", 0, 0, WINDOW_COPY_CMD_CLEAR_EMACS_ONLY, - window_copy_cmd_scroll_down }, - { "scroll-down-and-cancel", 0, 0, WINDOW_COPY_CMD_CLEAR_ALWAYS, - window_copy_cmd_scroll_down_and_cancel }, - { "scroll-up", 0, 0, WINDOW_COPY_CMD_CLEAR_EMACS_ONLY, - window_copy_cmd_scroll_up }, - { "search-again", 0, 0, WINDOW_COPY_CMD_CLEAR_ALWAYS, - window_copy_cmd_search_again }, - { "search-backward", 0, 1, WINDOW_COPY_CMD_CLEAR_ALWAYS, - window_copy_cmd_search_backward }, - { "search-backward-text", 0, 1, WINDOW_COPY_CMD_CLEAR_ALWAYS, - window_copy_cmd_search_backward_text }, - { "search-backward-incremental", 1, 1, WINDOW_COPY_CMD_CLEAR_ALWAYS, - window_copy_cmd_search_backward_incremental }, - { "search-forward", 0, 1, WINDOW_COPY_CMD_CLEAR_ALWAYS, - window_copy_cmd_search_forward }, - { "search-forward-text", 0, 1, WINDOW_COPY_CMD_CLEAR_ALWAYS, - window_copy_cmd_search_forward_text }, - { "search-forward-incremental", 1, 1, WINDOW_COPY_CMD_CLEAR_ALWAYS, - window_copy_cmd_search_forward_incremental }, - { "search-reverse", 0, 0, WINDOW_COPY_CMD_CLEAR_ALWAYS, - window_copy_cmd_search_reverse }, - { "select-line", 0, 0, WINDOW_COPY_CMD_CLEAR_ALWAYS, - window_copy_cmd_select_line }, - { "select-word", 0, 0, WINDOW_COPY_CMD_CLEAR_ALWAYS, - window_copy_cmd_select_word }, - { "set-mark", 0, 0, WINDOW_COPY_CMD_CLEAR_ALWAYS, - window_copy_cmd_set_mark }, - { "start-of-line", 0, 0, WINDOW_COPY_CMD_CLEAR_EMACS_ONLY, - window_copy_cmd_start_of_line }, - { "stop-selection", 0, 0, WINDOW_COPY_CMD_CLEAR_ALWAYS, - window_copy_cmd_stop_selection }, - { "top-line", 0, 0, WINDOW_COPY_CMD_CLEAR_EMACS_ONLY, - window_copy_cmd_top_line }, + { .command = "append-selection", + .minargs = 0, + .maxargs = 0, + .clear = WINDOW_COPY_CMD_CLEAR_ALWAYS, + .f = window_copy_cmd_append_selection + }, + { .command = "append-selection-and-cancel", + .minargs = 0, + .maxargs = 0, + .clear = WINDOW_COPY_CMD_CLEAR_ALWAYS, + .f = window_copy_cmd_append_selection_and_cancel + }, + { .command = "back-to-indentation", + .minargs = 0, + .maxargs = 0, + .clear = WINDOW_COPY_CMD_CLEAR_ALWAYS, + .f = window_copy_cmd_back_to_indentation + }, + { .command = "begin-selection", + .minargs = 0, + .maxargs = 0, + .clear = WINDOW_COPY_CMD_CLEAR_ALWAYS, + .f = window_copy_cmd_begin_selection + }, + { .command = "bottom-line", + .minargs = 0, + .maxargs = 0, + .clear = WINDOW_COPY_CMD_CLEAR_EMACS_ONLY, + .f = window_copy_cmd_bottom_line + }, + { .command = "cancel", + .minargs = 0, + .maxargs = 0, + .clear = WINDOW_COPY_CMD_CLEAR_ALWAYS, + .f = window_copy_cmd_cancel + }, + { .command = "clear-selection", + .minargs = 0, + .maxargs = 0, + .clear = WINDOW_COPY_CMD_CLEAR_ALWAYS, + .f = window_copy_cmd_clear_selection + }, + { .command = "copy-end-of-line", + .minargs = 0, + .maxargs = 1, + .clear = WINDOW_COPY_CMD_CLEAR_ALWAYS, + .f = window_copy_cmd_copy_end_of_line + }, + { .command = "copy-end-of-line-and-cancel", + .minargs = 0, + .maxargs = 1, + .clear = WINDOW_COPY_CMD_CLEAR_ALWAYS, + .f = window_copy_cmd_copy_end_of_line_and_cancel + }, + { .command = "copy-pipe-end-of-line", + .minargs = 0, + .maxargs = 2, + .clear = WINDOW_COPY_CMD_CLEAR_ALWAYS, + .f = window_copy_cmd_copy_pipe_end_of_line + }, + { .command = "copy-pipe-end-of-line-and-cancel", + .minargs = 0, + .maxargs = 2, + .clear = WINDOW_COPY_CMD_CLEAR_ALWAYS, + .f = window_copy_cmd_copy_pipe_end_of_line_and_cancel + }, + { .command = "copy-line", + .minargs = 0, + .maxargs = 1, + .clear = WINDOW_COPY_CMD_CLEAR_ALWAYS, + .f = window_copy_cmd_copy_line + }, + { .command = "copy-line-and-cancel", + .minargs = 0, + .maxargs = 1, + .clear = WINDOW_COPY_CMD_CLEAR_ALWAYS, + .f = window_copy_cmd_copy_line_and_cancel + }, + { .command = "copy-pipe-line", + .minargs = 0, + .maxargs = 2, + .clear = WINDOW_COPY_CMD_CLEAR_ALWAYS, + .f = window_copy_cmd_copy_pipe_line + }, + { .command = "copy-pipe-line-and-cancel", + .minargs = 0, + .maxargs = 2, + .clear = WINDOW_COPY_CMD_CLEAR_ALWAYS, + .f = window_copy_cmd_copy_pipe_line_and_cancel + }, + { .command = "copy-pipe-no-clear", + .minargs = 0, + .maxargs = 2, + .clear = WINDOW_COPY_CMD_CLEAR_NEVER, + .f = window_copy_cmd_copy_pipe_no_clear + }, + { .command = "copy-pipe", + .minargs = 0, + .maxargs = 2, + .clear = WINDOW_COPY_CMD_CLEAR_ALWAYS, + .f = window_copy_cmd_copy_pipe + }, + { .command = "copy-pipe-and-cancel", + .minargs = 0, + .maxargs = 2, + .clear = WINDOW_COPY_CMD_CLEAR_ALWAYS, + .f = window_copy_cmd_copy_pipe_and_cancel + }, + { .command = "copy-selection-no-clear", + .minargs = 0, + .maxargs = 1, + .clear = WINDOW_COPY_CMD_CLEAR_NEVER, + .f = window_copy_cmd_copy_selection_no_clear + }, + { .command = "copy-selection", + .minargs = 0, + .maxargs = 1, + .clear = WINDOW_COPY_CMD_CLEAR_ALWAYS, + .f = window_copy_cmd_copy_selection + }, + { .command = "copy-selection-and-cancel", + .minargs = 0, + .maxargs = 1, + .clear = WINDOW_COPY_CMD_CLEAR_ALWAYS, + .f = window_copy_cmd_copy_selection_and_cancel + }, + { .command = "cursor-down", + .minargs = 0, + .maxargs = 0, + .clear = WINDOW_COPY_CMD_CLEAR_EMACS_ONLY, + .f = window_copy_cmd_cursor_down + }, + { .command = "cursor-down-and-cancel", + .minargs = 0, + .maxargs = 0, + .clear = WINDOW_COPY_CMD_CLEAR_ALWAYS, + .f = window_copy_cmd_cursor_down_and_cancel + }, + { .command = "cursor-left", + .minargs = 0, + .maxargs = 0, + .clear = WINDOW_COPY_CMD_CLEAR_EMACS_ONLY, + .f = window_copy_cmd_cursor_left + }, + { .command = "cursor-right", + .minargs = 0, + .maxargs = 0, + .clear = WINDOW_COPY_CMD_CLEAR_EMACS_ONLY, + .f = window_copy_cmd_cursor_right + }, + { .command = "cursor-up", + .minargs = 0, + .maxargs = 0, + .clear = WINDOW_COPY_CMD_CLEAR_EMACS_ONLY, + .f = window_copy_cmd_cursor_up + }, + { .command = "end-of-line", + .minargs = 0, + .maxargs = 0, + .clear = WINDOW_COPY_CMD_CLEAR_EMACS_ONLY, + .f = window_copy_cmd_end_of_line + }, + { .command = "goto-line", + .minargs = 1, + .maxargs = 1, + .clear = WINDOW_COPY_CMD_CLEAR_EMACS_ONLY, + .f = window_copy_cmd_goto_line + }, + { .command = "halfpage-down", + .minargs = 0, + .maxargs = 0, + .clear = WINDOW_COPY_CMD_CLEAR_EMACS_ONLY, + .f = window_copy_cmd_halfpage_down + }, + { .command = "halfpage-down-and-cancel", + .minargs = 0, + .maxargs = 0, + .clear = WINDOW_COPY_CMD_CLEAR_ALWAYS, + .f = window_copy_cmd_halfpage_down_and_cancel + }, + { .command = "halfpage-up", + .minargs = 0, + .maxargs = 0, + .clear = WINDOW_COPY_CMD_CLEAR_EMACS_ONLY, + .f = window_copy_cmd_halfpage_up + }, + { .command = "history-bottom", + .minargs = 0, + .maxargs = 0, + .clear = WINDOW_COPY_CMD_CLEAR_EMACS_ONLY, + .f = window_copy_cmd_history_bottom + }, + { .command = "history-top", + .minargs = 0, + .maxargs = 0, + .clear = WINDOW_COPY_CMD_CLEAR_EMACS_ONLY, + .f = window_copy_cmd_history_top + }, + { .command = "jump-again", + .minargs = 0, + .maxargs = 0, + .clear = WINDOW_COPY_CMD_CLEAR_EMACS_ONLY, + .f = window_copy_cmd_jump_again + }, + { .command = "jump-backward", + .minargs = 1, + .maxargs = 1, + .clear = WINDOW_COPY_CMD_CLEAR_EMACS_ONLY, + .f = window_copy_cmd_jump_backward + }, + { .command = "jump-forward", + .minargs = 1, + .maxargs = 1, + .clear = WINDOW_COPY_CMD_CLEAR_EMACS_ONLY, + .f = window_copy_cmd_jump_forward + }, + { .command = "jump-reverse", + .minargs = 0, + .maxargs = 0, + .clear = WINDOW_COPY_CMD_CLEAR_EMACS_ONLY, + .f = window_copy_cmd_jump_reverse + }, + { .command = "jump-to-backward", + .minargs = 1, + .maxargs = 1, + .clear = WINDOW_COPY_CMD_CLEAR_EMACS_ONLY, + .f = window_copy_cmd_jump_to_backward + }, + { .command = "jump-to-forward", + .minargs = 1, + .maxargs = 1, + .clear = WINDOW_COPY_CMD_CLEAR_EMACS_ONLY, + .f = window_copy_cmd_jump_to_forward + }, + { .command = "jump-to-mark", + .minargs = 0, + .maxargs = 0, + .clear = WINDOW_COPY_CMD_CLEAR_ALWAYS, + .f = window_copy_cmd_jump_to_mark + }, + { .command = "middle-line", + .minargs = 0, + .maxargs = 0, + .clear = WINDOW_COPY_CMD_CLEAR_EMACS_ONLY, + .f = window_copy_cmd_middle_line + }, + { .command = "next-matching-bracket", + .minargs = 0, + .maxargs = 0, + .clear = WINDOW_COPY_CMD_CLEAR_ALWAYS, + .f = window_copy_cmd_next_matching_bracket + }, + { .command = "next-paragraph", + .minargs = 0, + .maxargs = 0, + .clear = WINDOW_COPY_CMD_CLEAR_EMACS_ONLY, + .f = window_copy_cmd_next_paragraph + }, + { .command = "next-space", + .minargs = 0, + .maxargs = 0, + .clear = WINDOW_COPY_CMD_CLEAR_EMACS_ONLY, + .f = window_copy_cmd_next_space + }, + { .command = "next-space-end", + .minargs = 0, + .maxargs = 0, + .clear = WINDOW_COPY_CMD_CLEAR_EMACS_ONLY, + .f = window_copy_cmd_next_space_end + }, + { .command = "next-word", + .minargs = 0, + .maxargs = 0, + .clear = WINDOW_COPY_CMD_CLEAR_EMACS_ONLY, + .f = window_copy_cmd_next_word + }, + { .command = "next-word-end", + .minargs = 0, + .maxargs = 0, + .clear = WINDOW_COPY_CMD_CLEAR_EMACS_ONLY, + .f = window_copy_cmd_next_word_end + }, + { .command = "other-end", + .minargs = 0, + .maxargs = 0, + .clear = WINDOW_COPY_CMD_CLEAR_EMACS_ONLY, + .f = window_copy_cmd_other_end + }, + { .command = "page-down", + .minargs = 0, + .maxargs = 0, + .clear = WINDOW_COPY_CMD_CLEAR_EMACS_ONLY, + .f = window_copy_cmd_page_down + }, + { .command = "page-down-and-cancel", + .minargs = 0, + .maxargs = 0, + .clear = WINDOW_COPY_CMD_CLEAR_ALWAYS, + .f = window_copy_cmd_page_down_and_cancel + }, + { .command = "page-up", + .minargs = 0, + .maxargs = 0, + .clear = WINDOW_COPY_CMD_CLEAR_EMACS_ONLY, + .f = window_copy_cmd_page_up + }, + { .command = "pipe-no-clear", + .minargs = 0, + .maxargs = 1, + .clear = WINDOW_COPY_CMD_CLEAR_NEVER, + .f = window_copy_cmd_pipe_no_clear + }, + { .command = "pipe", + .minargs = 0, + .maxargs = 1, + .clear = WINDOW_COPY_CMD_CLEAR_ALWAYS, + .f = window_copy_cmd_pipe + }, + { .command = "pipe-and-cancel", + .minargs = 0, + .maxargs = 1, + .clear = WINDOW_COPY_CMD_CLEAR_ALWAYS, + .f = window_copy_cmd_pipe_and_cancel + }, + { .command = "previous-matching-bracket", + .minargs = 0, + .maxargs = 0, + .clear = WINDOW_COPY_CMD_CLEAR_ALWAYS, + .f = window_copy_cmd_previous_matching_bracket + }, + { .command = "previous-paragraph", + .minargs = 0, + .maxargs = 0, + .clear = WINDOW_COPY_CMD_CLEAR_EMACS_ONLY, + .f = window_copy_cmd_previous_paragraph + }, + { .command = "previous-space", + .minargs = 0, + .maxargs = 0, + .clear = WINDOW_COPY_CMD_CLEAR_EMACS_ONLY, + .f = window_copy_cmd_previous_space + }, + { .command = "previous-word", + .minargs = 0, + .maxargs = 0, + .clear = WINDOW_COPY_CMD_CLEAR_EMACS_ONLY, + .f = window_copy_cmd_previous_word + }, + { .command = "rectangle-on", + .minargs = 0, + .maxargs = 0, + .clear = WINDOW_COPY_CMD_CLEAR_ALWAYS, + .f = window_copy_cmd_rectangle_on + }, + { .command = "rectangle-off", + .minargs = 0, + .maxargs = 0, + .clear = WINDOW_COPY_CMD_CLEAR_ALWAYS, + .f = window_copy_cmd_rectangle_off + }, + { .command = "rectangle-toggle", + .minargs = 0, + .maxargs = 0, + .clear = WINDOW_COPY_CMD_CLEAR_ALWAYS, + .f = window_copy_cmd_rectangle_toggle + }, + { .command = "refresh-from-pane", + .minargs = 0, + .maxargs = 0, + .clear = WINDOW_COPY_CMD_CLEAR_ALWAYS, + .f = window_copy_cmd_refresh_from_pane + }, + { .command = "scroll-down", + .minargs = 0, + .maxargs = 0, + .clear = WINDOW_COPY_CMD_CLEAR_EMACS_ONLY, + .f = window_copy_cmd_scroll_down + }, + { .command = "scroll-down-and-cancel", + .minargs = 0, + .maxargs = 0, + .clear = WINDOW_COPY_CMD_CLEAR_ALWAYS, + .f = window_copy_cmd_scroll_down_and_cancel + }, + { .command = "scroll-up", + .minargs = 0, + .maxargs = 0, + .clear = WINDOW_COPY_CMD_CLEAR_EMACS_ONLY, + .f = window_copy_cmd_scroll_up + }, + { .command = "search-again", + .minargs = 0, + .maxargs = 0, + .clear = WINDOW_COPY_CMD_CLEAR_ALWAYS, + .f = window_copy_cmd_search_again + }, + { .command = "search-backward", + .minargs = 0, + .maxargs = 1, + .clear = WINDOW_COPY_CMD_CLEAR_ALWAYS, + .f = window_copy_cmd_search_backward + }, + { .command = "search-backward-text", + .minargs = 0, + .maxargs = 1, + .clear = WINDOW_COPY_CMD_CLEAR_ALWAYS, + .f = window_copy_cmd_search_backward_text + }, + { .command = "search-backward-incremental", + .minargs = 1, + .maxargs = 1, + .clear = WINDOW_COPY_CMD_CLEAR_ALWAYS, + .f = window_copy_cmd_search_backward_incremental + }, + { .command = "search-forward", + .minargs = 0, + .maxargs = 1, + .clear = WINDOW_COPY_CMD_CLEAR_ALWAYS, + .f = window_copy_cmd_search_forward + }, + { .command = "search-forward-text", + .minargs = 0, + .maxargs = 1, + .clear = WINDOW_COPY_CMD_CLEAR_ALWAYS, + .f = window_copy_cmd_search_forward_text + }, + { .command = "search-forward-incremental", + .minargs = 1, + .maxargs = 1, + .clear = WINDOW_COPY_CMD_CLEAR_ALWAYS, + .f = window_copy_cmd_search_forward_incremental + }, + { .command = "search-reverse", + .minargs = 0, + .maxargs = 0, + .clear = WINDOW_COPY_CMD_CLEAR_ALWAYS, + .f = window_copy_cmd_search_reverse + }, + { .command = "select-line", + .minargs = 0, + .maxargs = 0, + .clear = WINDOW_COPY_CMD_CLEAR_ALWAYS, + .f = window_copy_cmd_select_line + }, + { .command = "select-word", + .minargs = 0, + .maxargs = 0, + .clear = WINDOW_COPY_CMD_CLEAR_ALWAYS, + .f = window_copy_cmd_select_word + }, + { .command = "set-mark", + .minargs = 0, + .maxargs = 0, + .clear = WINDOW_COPY_CMD_CLEAR_ALWAYS, + .f = window_copy_cmd_set_mark + }, + { .command = "start-of-line", + .minargs = 0, + .maxargs = 0, + .clear = WINDOW_COPY_CMD_CLEAR_EMACS_ONLY, + .f = window_copy_cmd_start_of_line + }, + { .command = "stop-selection", + .minargs = 0, + .maxargs = 0, + .clear = WINDOW_COPY_CMD_CLEAR_ALWAYS, + .f = window_copy_cmd_stop_selection + }, + { .command = "toggle-position", + .minargs = 0, + .maxargs = 0, + .clear = WINDOW_COPY_CMD_CLEAR_NEVER, + .f = window_copy_cmd_toggle_position + }, + { .command = "top-line", + .minargs = 0, + .maxargs = 0, + .clear = WINDOW_COPY_CMD_CLEAR_EMACS_ONLY, + .f = window_copy_cmd_top_line + } }; static void @@ -2405,12 +2888,12 @@ window_copy_command(struct window_mode_entry *wme, struct client *c, enum window_copy_cmd_action action; enum window_copy_cmd_clear clear = WINDOW_COPY_CMD_CLEAR_NEVER; const char *command; - u_int i; + u_int i, count = args_count(args); int keys; - if (args->argc == 0) + if (count == 0) return; - command = args->argv[0]; + command = args_string(args, 0); if (m != NULL && m->valid && !MOUSE_WHEEL(m->b)) window_copy_move_mouse(m); @@ -2426,11 +2909,11 @@ window_copy_command(struct window_mode_entry *wme, struct client *c, action = WINDOW_COPY_CMD_NOTHING; for (i = 0; i < nitems(window_copy_cmd_table); i++) { if (strcmp(window_copy_cmd_table[i].command, command) == 0) { - if (args->argc - 1 < window_copy_cmd_table[i].minargs || - args->argc - 1 > window_copy_cmd_table[i].maxargs) + if (count - 1 < window_copy_cmd_table[i].minargs || + count - 1 > window_copy_cmd_table[i].maxargs) break; clear = window_copy_cmd_table[i].clear; - action = window_copy_cmd_table[i].f (&cs); + action = window_copy_cmd_table[i].f(&cs); break; } } @@ -2718,6 +3201,11 @@ window_copy_cellstring(const struct grid_line *gl, u_int px, size_t *size, } utf8_to_data(gl->extddata[gce->offset].data, &ud); + if (ud.size == 0) { + *size = 0; + *allocated = 0; + return (NULL); + } *size = ud.size; *allocated = 1; @@ -3733,8 +4221,8 @@ window_copy_synchronize_cursor_end(struct window_mode_entry *wme, int begin, begin = 0; if (data->dy > yy || (data->dy == yy && data->dx > xx)) { /* Right to left selection. */ - window_copy_cursor_previous_word_pos(wme, data->ws, 0, - &xx, &yy); + window_copy_cursor_previous_word_pos(wme, + data->separators, &xx, &yy); begin = 1; /* Reset the end. */ @@ -3743,9 +4231,10 @@ window_copy_synchronize_cursor_end(struct window_mode_entry *wme, int begin, } else { /* Left to right selection. */ if (xx >= window_copy_find_length(wme, yy) || - !window_copy_in_set(wme, xx + 1, yy, data->ws)) + !window_copy_in_set(wme, xx + 1, yy, WHITESPACE)) { window_copy_cursor_next_word_end_pos(wme, - data->ws, &xx, &yy); + data->separators, &xx, &yy); + } /* Reset the start. */ data->selx = data->selrx; @@ -4100,8 +4589,8 @@ window_copy_pipe_run(struct window_mode_entry *wme, struct session *s, if (cmd == NULL || *cmd == '\0') cmd = options_get_string(global_options, "copy-command"); if (cmd != NULL && *cmd != '\0') { - job = job_run(cmd, 0, NULL, s, NULL, NULL, NULL, NULL, NULL, - JOB_NOWAIT, -1, -1); + job = job_run(cmd, 0, NULL, NULL, s, NULL, NULL, NULL, NULL, + NULL, JOB_NOWAIT, -1, -1); bufferevent_write(job_get_event(job), buf, *len); } return (buf); @@ -4683,19 +5172,19 @@ window_copy_cursor_next_word_end_pos(struct window_mode_entry *wme, struct screen *back_s = data->backing; struct grid_reader gr; u_int px, py, hsize; - int keys; px = data->cx; hsize = screen_hsize(back_s); py = hsize + data->cy - data->oy; grid_reader_start(&gr, back_s->grid, px, py); - keys = options_get_number(oo, "mode-keys"); - if (keys == MODEKEY_VI && !grid_reader_in_set(&gr, separators)) - grid_reader_cursor_right(&gr, 0, 0); - grid_reader_cursor_next_word_end(&gr, separators); - if (keys == MODEKEY_VI) + if (options_get_number(oo, "mode-keys") == MODEKEY_VI) { + if (!grid_reader_in_set(&gr, WHITESPACE)) + grid_reader_cursor_right(&gr, 0, 0); + grid_reader_cursor_next_word_end(&gr, separators); grid_reader_cursor_left(&gr, 1); + } else + grid_reader_cursor_next_word_end(&gr, separators); grid_reader_get_cursor(&gr, &px, &py); *ppx = px; *ppy = py; @@ -4712,7 +5201,6 @@ window_copy_cursor_next_word_end(struct window_mode_entry *wme, struct screen *back_s = data->backing; struct grid_reader gr; u_int px, py, oldy, hsize; - int keys; px = data->cx; hsize = screen_hsize(back_s); @@ -4720,12 +5208,13 @@ window_copy_cursor_next_word_end(struct window_mode_entry *wme, oldy = data->cy; grid_reader_start(&gr, back_s->grid, px, py); - keys = options_get_number(oo, "mode-keys"); - if (keys == MODEKEY_VI && !grid_reader_in_set(&gr, separators)) - grid_reader_cursor_right(&gr, 0, 0); - grid_reader_cursor_next_word_end(&gr, separators); - if (keys == MODEKEY_VI) + if (options_get_number(oo, "mode-keys") == MODEKEY_VI) { + if (!grid_reader_in_set(&gr, WHITESPACE)) + grid_reader_cursor_right(&gr, 0, 0); + grid_reader_cursor_next_word_end(&gr, separators); grid_reader_cursor_left(&gr, 1); + } else + grid_reader_cursor_next_word_end(&gr, separators); grid_reader_get_cursor(&gr, &px, &py); window_copy_acquire_cursor_down(wme, hsize, screen_size_y(back_s), data->oy, oldy, px, py, no_reset); @@ -4734,7 +5223,7 @@ window_copy_cursor_next_word_end(struct window_mode_entry *wme, /* Compute the previous place where a word begins. */ static void window_copy_cursor_previous_word_pos(struct window_mode_entry *wme, - const char *separators, int already, u_int *ppx, u_int *ppy) + const char *separators, u_int *ppx, u_int *ppy) { struct window_copy_mode_data *data = wme->data; struct screen *back_s = data->backing; @@ -4746,7 +5235,8 @@ window_copy_cursor_previous_word_pos(struct window_mode_entry *wme, py = hsize + data->cy - data->oy; grid_reader_start(&gr, back_s->grid, px, py); - grid_reader_cursor_previous_word(&gr, separators, already); + grid_reader_cursor_previous_word(&gr, separators, /* already= */ 0, + /* stop_at_eol= */ 1); grid_reader_get_cursor(&gr, &px, &py); *ppx = px; *ppy = py; @@ -4758,9 +5248,16 @@ window_copy_cursor_previous_word(struct window_mode_entry *wme, const char *separators, int already) { struct window_copy_mode_data *data = wme->data; + struct window *w = wme->wp->window; struct screen *back_s = data->backing; struct grid_reader gr; u_int px, py, oldy, hsize; + int stop_at_eol; + + if (options_get_number(w->options, "mode-keys") == MODEKEY_EMACS) + stop_at_eol = 1; + else + stop_at_eol = 0; px = data->cx; hsize = screen_hsize(back_s); @@ -4768,7 +5265,7 @@ window_copy_cursor_previous_word(struct window_mode_entry *wme, oldy = data->cy; grid_reader_start(&gr, back_s->grid, px, py); - grid_reader_cursor_previous_word(&gr, separators, already); + grid_reader_cursor_previous_word(&gr, separators, already, stop_at_eol); grid_reader_get_cursor(&gr, &px, &py); window_copy_acquire_cursor_up(wme, hsize, data->oy, oldy, px, py); } @@ -4910,10 +5407,10 @@ window_copy_start_drag(struct client *c, struct mouse_event *m) data->selflag = SEL_CHAR; switch (data->selflag) { case SEL_WORD: - if (data->ws != NULL) { + if (data->separators != NULL) { window_copy_update_cursor(wme, x, y); - window_copy_cursor_previous_word_pos(wme, data->ws, 0, - &x, &y); + window_copy_cursor_previous_word_pos(wme, + data->separators, &x, &y); y -= screen_hsize(data->backing) - data->oy; } window_copy_update_cursor(wme, x, y); diff --git a/external/bsd/tmux/dist/window-customize.c b/external/bsd/tmux/dist/window-customize.c index d90d7a677bf..7dddff356f4 100644 --- a/external/bsd/tmux/dist/window-customize.c +++ b/external/bsd/tmux/dist/window-customize.c @@ -398,11 +398,11 @@ window_customize_build_options(struct window_customize_modedata *data, for (i = 0; i < size; i++) { if (oo2 != NULL) - o = options_get(oo0, list[i]); + o = options_get(oo2, list[i]); if (o == NULL && oo1 != NULL) o = options_get(oo1, list[i]); if (o == NULL) - o = options_get(oo2, list[i]); + o = options_get(oo0, list[i]); if (options_owner(o) == oo2) scope = scope2; else if (options_owner(o) == oo1) @@ -680,9 +680,7 @@ window_customize_draw_option(struct window_customize_modedata *data, } ft = format_create_from_state(NULL, NULL, &fs); - if (oe == NULL) - text = "This is a user option."; - else if (oe->text == NULL) + if (oe == NULL || oe->text == NULL) text = "This option doesn't have a description."; else text = oe->text; @@ -1123,7 +1121,7 @@ window_customize_set_option(struct client *c, status_prompt_set(c, NULL, prompt, value, window_customize_set_option_callback, window_customize_free_item_callback, new_item, - PROMPT_NOFORMAT); + PROMPT_NOFORMAT, PROMPT_TYPE_COMMAND); free(prompt); free(value); @@ -1185,9 +1183,6 @@ window_customize_set_command_callback(struct client *c, void *itemdata, pr = cmd_parse_from_string(s, NULL); switch (pr->status) { - case CMD_PARSE_EMPTY: - error = xstrdup("empty command"); - goto fail; case CMD_PARSE_ERROR: error = pr->error; goto fail; @@ -1264,7 +1259,7 @@ window_customize_set_key(struct client *c, status_prompt_set(c, NULL, prompt, value, window_customize_set_command_callback, window_customize_free_item_callback, new_item, - PROMPT_NOFORMAT); + PROMPT_NOFORMAT, PROMPT_TYPE_COMMAND); free(prompt); free(value); } else if (strcmp(s, "Note") == 0) { @@ -1281,7 +1276,7 @@ window_customize_set_key(struct client *c, (bd->note == NULL ? "" : bd->note), window_customize_set_note_callback, window_customize_free_item_callback, new_item, - PROMPT_NOFORMAT); + PROMPT_NOFORMAT, PROMPT_TYPE_COMMAND); free(prompt); } } @@ -1458,7 +1453,7 @@ window_customize_key(struct window_mode_entry *wme, struct client *c, status_prompt_set(c, NULL, prompt, "", window_customize_change_current_callback, window_customize_free_callback, data, - PROMPT_SINGLE|PROMPT_NOFORMAT); + PROMPT_SINGLE|PROMPT_NOFORMAT, PROMPT_TYPE_COMMAND); free(prompt); break; case 'D': @@ -1471,7 +1466,7 @@ window_customize_key(struct window_mode_entry *wme, struct client *c, status_prompt_set(c, NULL, prompt, "", window_customize_change_tagged_callback, window_customize_free_callback, data, - PROMPT_SINGLE|PROMPT_NOFORMAT); + PROMPT_SINGLE|PROMPT_NOFORMAT, PROMPT_TYPE_COMMAND); free(prompt); break; case 'u': @@ -1487,7 +1482,7 @@ window_customize_key(struct window_mode_entry *wme, struct client *c, status_prompt_set(c, NULL, prompt, "", window_customize_change_current_callback, window_customize_free_callback, data, - PROMPT_SINGLE|PROMPT_NOFORMAT); + PROMPT_SINGLE|PROMPT_NOFORMAT, PROMPT_TYPE_COMMAND); free(prompt); break; case 'U': @@ -1500,7 +1495,7 @@ window_customize_key(struct window_mode_entry *wme, struct client *c, status_prompt_set(c, NULL, prompt, "", window_customize_change_tagged_callback, window_customize_free_callback, data, - PROMPT_SINGLE|PROMPT_NOFORMAT); + PROMPT_SINGLE|PROMPT_NOFORMAT, PROMPT_TYPE_COMMAND); free(prompt); break; case 'H': diff --git a/external/bsd/tmux/dist/window-tree.c b/external/bsd/tmux/dist/window-tree.c index 7057693f3ec..e299633c9e8 100644 --- a/external/bsd/tmux/dist/window-tree.c +++ b/external/bsd/tmux/dist/window-tree.c @@ -519,7 +519,8 @@ window_tree_draw_label(struct screen_write_ctx *ctx, u_int px, u_int py, if (ox > 1 && ox + len < sx - 1 && sy >= 3) { screen_write_cursormove(ctx, px + ox - 1, py + oy - 1, 0); - screen_write_box(ctx, len + 2, 3); + screen_write_box(ctx, len + 2, 3, BOX_LINES_DEFAULT, NULL, + NULL); } screen_write_cursormove(ctx, px + ox, py + oy, 0); screen_write_puts(ctx, gc, "%s", label); @@ -895,7 +896,7 @@ window_tree_get_key(void *modedata, void *itemdata, u_int line) key = key_string_lookup_string(expanded); free(expanded); format_free(ft); - return key; + return (key); } static struct screen * @@ -926,10 +927,10 @@ window_tree_init(struct window_mode_entry *wme, struct cmd_find_state *fs, data->key_format = xstrdup(WINDOW_TREE_DEFAULT_KEY_FORMAT); else data->key_format = xstrdup(args_get(args, 'K')); - if (args == NULL || args->argc == 0) + if (args == NULL || args_count(args) == 0) data->command = xstrdup(WINDOW_TREE_DEFAULT_COMMAND); else - data->command = xstrdup(args->argv[0]); + data->command = xstrdup(args_string(args, 0)); data->squash_groups = !args_has(args, 'G'); data->data = mode_tree_start(wp, args, window_tree_build, @@ -1297,7 +1298,7 @@ window_tree_key(struct window_mode_entry *wme, struct client *c, data->references++; status_prompt_set(c, NULL, prompt, "", window_tree_kill_current_callback, window_tree_command_free, - data, PROMPT_SINGLE|PROMPT_NOFORMAT); + data, PROMPT_SINGLE|PROMPT_NOFORMAT, PROMPT_TYPE_COMMAND); free(prompt); break; case 'X': @@ -1308,7 +1309,7 @@ window_tree_key(struct window_mode_entry *wme, struct client *c, data->references++; status_prompt_set(c, NULL, prompt, "", window_tree_kill_tagged_callback, window_tree_command_free, - data, PROMPT_SINGLE|PROMPT_NOFORMAT); + data, PROMPT_SINGLE|PROMPT_NOFORMAT, PROMPT_TYPE_COMMAND); free(prompt); break; case ':': @@ -1320,7 +1321,7 @@ window_tree_key(struct window_mode_entry *wme, struct client *c, data->references++; status_prompt_set(c, NULL, prompt, "", window_tree_command_callback, window_tree_command_free, - data, PROMPT_NOFORMAT); + data, PROMPT_NOFORMAT, PROMPT_TYPE_COMMAND); free(prompt); break; case '\r': diff --git a/external/bsd/tmux/dist/window.c b/external/bsd/tmux/dist/window.c index 01273bc3300..683dd8473ba 100644 --- a/external/bsd/tmux/dist/window.c +++ b/external/bsd/tmux/dist/window.c @@ -316,6 +316,8 @@ window_create(u_int sx, u_int sy, u_int xpixel, u_int ypixel) w->sx = sx; w->sy = sy; + w->manual_sx = sx; + w->manual_sy = sy; w->xpixel = xpixel; w->ypixel = ypixel; @@ -327,6 +329,7 @@ window_create(u_int sx, u_int sy, u_int xpixel, u_int ypixel) w->id = next_window_id++; RB_INSERT(windows, &windows, w); + window_set_fill_character(w); window_update_activity(w); log_debug("%s: @%u create %ux%u (%ux%u)", __func__, w->id, sx, sy, @@ -358,6 +361,7 @@ window_destroy(struct window *w) event_del(&w->offset_timer); options_free(w->options); + free(w->fill_character); free(w->name); free(w); @@ -465,6 +469,52 @@ window_has_pane(struct window *w, struct window_pane *wp) return (0); } +void +window_update_focus(struct window *w) +{ + if (w != NULL) { + log_debug("%s: @%u", __func__, w->id); + window_pane_update_focus(w->active); + } +} + +void +window_pane_update_focus(struct window_pane *wp) +{ + struct client *c; + int focused = 0; + + if (wp != NULL) { + if (wp != wp->window->active) + focused = 0; + else { + TAILQ_FOREACH(c, &clients, entry) { + if (c->session != NULL && + c->session->attached != 0 && + (c->flags & CLIENT_FOCUSED) && + c->session->curw->window == wp->window) { + focused = 1; + break; + } + } + } + if (!focused && (wp->flags & PANE_FOCUSED)) { + log_debug("%s: %%%u focus out", __func__, wp->id); + if (wp->base.mode & MODE_FOCUSON) + bufferevent_write(wp->event, "\033[O", 3); + notify_pane("pane-focus-out", wp); + wp->flags &= ~PANE_FOCUSED; + } else if (focused && (~wp->flags & PANE_FOCUSED)) { + log_debug("%s: %%%u focus in", __func__, wp->id); + if (wp->base.mode & MODE_FOCUSON) + bufferevent_write(wp->event, "\033[I", 3); + notify_pane("pane-focus-in", wp); + wp->flags |= PANE_FOCUSED; + } else + log_debug("%s: %%%u focus unchanged", __func__, wp->id); + } +} + int window_set_active_pane(struct window *w, struct window_pane *wp, int notify) { @@ -478,6 +528,11 @@ window_set_active_pane(struct window *w, struct window_pane *wp, int notify) w->active->active_point = next_active_point++; w->active->flags |= PANE_CHANGED; + if (options_get_number(global_options, "focus-events")) { + window_pane_update_focus(w->last); + window_pane_update_focus(w->active); + } + tty_update_window_offset(w); if (notify) @@ -485,6 +540,14 @@ window_set_active_pane(struct window *w, struct window_pane *wp, int notify) return (1); } +static int +window_pane_get_palette(struct window_pane *wp, int c) +{ + if (wp == NULL) + return (-1); + return (colour_palette_get(&wp->palette, c)); +} + void window_redraw_active_switch(struct window *w, struct window_pane *wp) { @@ -700,6 +763,7 @@ window_lost_pane(struct window *w, struct window_pane *wp) if (w->active != NULL) { w->active->flags |= PANE_CHANGED; notify_window("window-pane-changed", w); + window_update_focus(w); } } else if (wp == w->last) w->last = NULL; @@ -862,9 +926,6 @@ window_pane_create(struct window *w, u_int sx, u_int sy, u_int hlimit) wp->fd = -1; - wp->fg = 8; - wp->bg = 8; - TAILQ_INIT(&wp->modes); TAILQ_INIT (&wp->resize_queue); @@ -874,6 +935,9 @@ window_pane_create(struct window *w, u_int sx, u_int sy, u_int hlimit) wp->pipe_fd = -1; + colour_palette_init(&wp->palette); + colour_palette_from_option(&wp->palette, wp->options); + screen_init(&wp->base, sx, sy, hlimit); wp->screen = &wp->base; @@ -926,7 +990,7 @@ window_pane_destroy(struct window_pane *wp) free(__UNCONST(wp->cwd)); free(wp->shell); cmd_free_argv(wp->argc, wp->argv); - free(wp->palette); + colour_palette_free(&wp->palette); free(wp); } @@ -978,7 +1042,7 @@ window_pane_set_event(struct window_pane *wp) wp->event = bufferevent_new(wp->fd, window_pane_read_callback, NULL, window_pane_error_callback, wp); - wp->ictx = input_init(wp, wp->event); + wp->ictx = input_init(wp, wp->event, &wp->palette); bufferevent_enable(wp->event, EV_READ|EV_WRITE); } @@ -992,7 +1056,7 @@ window_pane_resize(struct window_pane *wp, u_int sx, u_int sy) if (sx == wp->sx && sy == wp->sy) return; - r = xmalloc (sizeof *r); + r = xmalloc(sizeof *r); r->sx = sx; r->sy = sy; r->osx = wp->sx; @@ -1010,60 +1074,6 @@ window_pane_resize(struct window_pane *wp, u_int sx, u_int sy) wme->mode->resize(wme, sx, sy); } -void -window_pane_set_palette(struct window_pane *wp, u_int n, int colour) -{ - if (n > 0xff) - return; - - if (wp->palette == NULL) - wp->palette = xcalloc(0x100, sizeof *wp->palette); - - wp->palette[n] = colour; - wp->flags |= PANE_REDRAW; -} - -void -window_pane_unset_palette(struct window_pane *wp, u_int n) -{ - if (n > 0xff || wp->palette == NULL) - return; - - wp->palette[n] = 0; - wp->flags |= PANE_REDRAW; -} - -void -window_pane_reset_palette(struct window_pane *wp) -{ - if (wp->palette == NULL) - return; - - free(wp->palette); - wp->palette = NULL; - wp->flags |= PANE_REDRAW; -} - -int -window_pane_get_palette(struct window_pane *wp, int c) -{ - int new; - - if (wp == NULL || wp->palette == NULL) - return (-1); - - new = -1; - if (c < 8) - new = wp->palette[c]; - else if (c >= 90 && c <= 97) - new = wp->palette[8 + c - 90]; - else if (c & COLOUR_FLAG_256) - new = wp->palette[c & ~COLOUR_FLAG_256]; - if (new == 0) - return (-1); - return (new); -} - int window_pane_set_mode(struct window_pane *wp, struct window_pane *swp, const struct window_mode *mode, struct cmd_find_state *fs, @@ -1530,7 +1540,7 @@ window_pane_input_callback(struct client *c, __unused const char *path, size_t len = EVBUFFER_LENGTH(buffer); wp = window_pane_find_by_id(cdata->wp); - if (wp == NULL || closed || error != 0 || c->flags & CLIENT_DEAD) { + if (wp == NULL || closed || error != 0 || (c->flags & CLIENT_DEAD)) { if (wp == NULL) c->flags |= CLIENT_EXIT; @@ -1556,6 +1566,10 @@ window_pane_start_input(struct window_pane *wp, struct cmdq_item *item, *cause = xstrdup("pane is not empty"); return (-1); } + if (c->flags & (CLIENT_DEAD|CLIENT_EXITED)) + return (1); + if (c->session != NULL) + return (1); cdata = xmalloc(sizeof *cdata); cdata->item = item; @@ -1587,3 +1601,20 @@ window_pane_update_used_data(struct window_pane *wp, size = EVBUFFER_LENGTH(wp->event->input) - used; wpo->used += size; } + +void +window_set_fill_character(struct window *w) +{ + const char *value; + struct utf8_data *ud; + + free(w->fill_character); + w->fill_character = NULL; + + value = options_get_string(w->options, "fill-character"); + if (*value != '\0' && utf8_isvalid(value)) { + ud = utf8_fromcstr(value); + if (ud != NULL && ud[0].width == 1) + w->fill_character = ud; + } +} diff --git a/external/bsd/tmux/dist/xmalloc.h b/external/bsd/tmux/dist/xmalloc.h index f6454b9728e..903ee29a503 100644 --- a/external/bsd/tmux/dist/xmalloc.h +++ b/external/bsd/tmux/dist/xmalloc.h @@ -34,14 +34,14 @@ int xasprintf(char **, const char *, ...) __attribute__((__format__ (__printf__, 2, 3))) __attribute__((__nonnull__ (2))); int xvasprintf(char **, const char *, va_list) - __attribute__((__format__ (__printf__, 2, 0))) + __attribute__((__format__ (printf, 2, 0))) __attribute__((__nonnull__ (2))); int xsnprintf(char *, size_t, const char *, ...) __attribute__((__format__ (__printf__, 3, 4))) __attribute__((__nonnull__ (3))) __attribute__((__bounded__ (__string__, 1, 2))); int xvsnprintf(char *, size_t, const char *, va_list) - __attribute__((__format__ (__printf__, 3, 0))) + __attribute__((__format__ (printf, 3, 0))) __attribute__((__nonnull__ (3))) __attribute__((__bounded__ (__string__, 1, 2))); |
