diff --git a/client.c b/client.c index 8e55640f..6ab53e4f 100644 --- a/client.c +++ b/client.c @@ -315,7 +315,7 @@ client_main(int argc, char **argv, int flags) /* Prepare command for server. */ data->argc = argc; - if (cmd_pack_argv(argc, argv, (char*)(data + 1), size) != 0) { + if (cmd_pack_argv(argc, argv, (char *)(data + 1), size) != 0) { fprintf(stderr, "command too long\n"); free(data); return (1); @@ -397,7 +397,7 @@ client_write_one(enum msgtype type, int fd, const void *buf, size_t len) int retval; retval = imsg_compose(&client_ibuf, type, PROTOCOL_VERSION, -1, fd, - (void*)buf, len); + (void *)buf, len); if (retval != 1) return (-1); return (0); diff --git a/cmd-list.c b/cmd-list.c index 7ef8d1c5..5687f324 100644 --- a/cmd-list.c +++ b/cmd-list.c @@ -24,7 +24,7 @@ #include "tmux.h" struct cmd_list * -cmd_list_parse(int argc, char **argv, const char* file, u_int line, +cmd_list_parse(int argc, char **argv, const char *file, u_int line, char **cause) { struct cmd_list *cmdlist; diff --git a/cmd-load-buffer.c b/cmd-load-buffer.c index d2e1cc6b..d6df1f60 100644 --- a/cmd-load-buffer.c +++ b/cmd-load-buffer.c @@ -62,7 +62,7 @@ cmd_load_buffer_exec(struct cmd *self, struct cmd_q *cmdq) path = args->argv[0]; if (strcmp(path, "-") == 0) { error = server_set_stdin_callback(c, cmd_load_buffer_callback, - (void*)bufname, &cause); + (void *)bufname, &cause); if (error != 0) { cmdq_error(cmdq, "%s: %s", path, cause); free(cause); diff --git a/cmd-new-window.c b/cmd-new-window.c index cd0042ee..efbcbbf1 100644 --- a/cmd-new-window.c +++ b/cmd-new-window.c @@ -88,7 +88,7 @@ cmd_new_window_exec(struct cmd *self, struct cmd_q *cmdq) cmd = options_get_string(&s->options, "default-command"); if (cmd != NULL && *cmd != '\0') { argc = 1; - argv = (char**)&cmd; + argv = (char **)&cmd; } else { argc = 0; argv = NULL; diff --git a/cmd-queue.c b/cmd-queue.c index f4b3b97c..ca9d16e2 100644 --- a/cmd-queue.c +++ b/cmd-queue.c @@ -124,14 +124,14 @@ cmdq_guard(struct cmd_q *cmdq, const char *guard, int flags) struct client *c = cmdq->client; if (c == NULL) - return 0; + return (0); if (!(c->flags & CLIENT_CONTROL)) - return 0; + return (0); evbuffer_add_printf(c->stdout_data, "%%%s %ld %u %d\n", guard, (long) cmdq->time, cmdq->number, flags); server_push_stdout(c); - return 1; + return (1); } /* Add command list to queue and begin processing if needed. */ diff --git a/cmd-select-pane.c b/cmd-select-pane.c index c342fef3..639adf52 100644 --- a/cmd-select-pane.c +++ b/cmd-select-pane.c @@ -29,8 +29,8 @@ enum cmd_retval cmd_select_pane_exec(struct cmd *, struct cmd_q *); const struct cmd_entry cmd_select_pane_entry = { "select-pane", "selectp", - "lDLRt:U", 0, 0, - "[-lDLRU] " CMD_TARGET_PANE_USAGE, + "DdeLlRt:U", 0, 0, + "[-DdeLlRU] " CMD_TARGET_PANE_USAGE, 0, cmd_select_pane_key_binding, cmd_select_pane_exec @@ -38,8 +38,8 @@ const struct cmd_entry cmd_select_pane_entry = { const struct cmd_entry cmd_last_pane_entry = { "last-pane", "lastp", - "t:", 0, 0, - CMD_TARGET_WINDOW_USAGE, + "det:", 0, 0, + "[-de] " CMD_TARGET_WINDOW_USAGE, 0, NULL, cmd_select_pane_exec @@ -78,10 +78,16 @@ cmd_select_pane_exec(struct cmd *self, struct cmd_q *cmdq) return (CMD_RETURN_ERROR); } - server_unzoom_window(wl->window); - window_set_active_pane(wl->window, wl->window->last); - server_status_window(wl->window); - server_redraw_window_borders(wl->window); + if (args_has(self->args, 'e')) + wl->window->last->flags &= ~PANE_INPUTOFF; + else if (args_has(self->args, 'd')) + wl->window->last->flags |= PANE_INPUTOFF; + else { + server_unzoom_window(wl->window); + window_set_active_pane(wl->window, wl->window->last); + server_status_window(wl->window); + server_redraw_window_borders(wl->window); + } return (CMD_RETURN_NORMAL); } @@ -108,9 +114,15 @@ cmd_select_pane_exec(struct cmd *self, struct cmd_q *cmdq) return (CMD_RETURN_ERROR); } - window_set_active_pane(wl->window, wp); - server_status_window(wl->window); - server_redraw_window_borders(wl->window); + if (args_has(self->args, 'e')) + wp->flags &= ~PANE_INPUTOFF; + else if (args_has(self->args, 'd')) + wp->flags |= PANE_INPUTOFF; + else { + window_set_active_pane(wl->window, wp); + server_status_window(wl->window); + server_redraw_window_borders(wl->window); + } return (CMD_RETURN_NORMAL); } diff --git a/cmd-set-option.c b/cmd-set-option.c index f55b0d30..22432b7d 100644 --- a/cmd-set-option.c +++ b/cmd-set-option.c @@ -201,7 +201,7 @@ cmd_set_option_exec(struct cmd *self, struct cmd_q *cmdq) /* Set user option. */ enum cmd_retval -cmd_set_option_user(struct cmd *self, struct cmd_q *cmdq, const char* optstr, +cmd_set_option_user(struct cmd *self, struct cmd_q *cmdq, const char *optstr, const char *valstr) { struct args *args = self->args; @@ -254,7 +254,7 @@ cmd_set_option_user(struct cmd *self, struct cmd_q *cmdq, const char* optstr, if (args_has(args, 'o') && options_find1(oo, optstr) != NULL) { if (!args_has(args, 'q')) { cmdq_error(cmdq, "already set: %s", optstr); - return CMD_RETURN_ERROR; + return (CMD_RETURN_ERROR); } return (CMD_RETURN_NORMAL); } diff --git a/cmd-split-window.c b/cmd-split-window.c index ea047a3f..f086a4ce 100644 --- a/cmd-split-window.c +++ b/cmd-split-window.c @@ -84,7 +84,7 @@ cmd_split_window_exec(struct cmd *self, struct cmd_q *cmdq) cmd = options_get_string(&s->options, "default-command"); if (cmd != NULL && *cmd != '\0') { argc = 1; - argv = (char**)&cmd; + argv = (char **)&cmd; } else { argc = 0; argv = NULL; diff --git a/cmd-wait-for.c b/cmd-wait-for.c index e251863d..1deb2da9 100644 --- a/cmd-wait-for.c +++ b/cmd-wait-for.c @@ -108,7 +108,7 @@ cmd_wait_for_signal(struct cmd_q *cmdq, const char *name, if (!wc->locked) { RB_REMOVE(wait_channels, &wait_channels, wc); - free((void*) wc->name); + free((void *)wc->name); free(wc); } @@ -186,7 +186,7 @@ cmd_wait_for_unlock(struct cmd_q *cmdq, const char *name, wc->locked = 0; if (TAILQ_EMPTY(&wc->waiters)) { RB_REMOVE(wait_channels, &wait_channels, wc); - free((void*) wc->name); + free((void *)wc->name); free(wc); } } @@ -194,3 +194,25 @@ cmd_wait_for_unlock(struct cmd_q *cmdq, const char *name, return (CMD_RETURN_NORMAL); } +void +cmd_wait_for_flush(void) +{ + struct wait_channel *wc, *wc1; + struct cmd_q *wq, *wq1; + + RB_FOREACH_SAFE(wc, wait_channels, &wait_channels, wc1) { + TAILQ_FOREACH_SAFE(wq, &wc->waiters, waitentry, wq1) { + TAILQ_REMOVE(&wc->waiters, wq, waitentry); + if (!cmdq_free(wq)) + cmdq_continue(wq); + } + while ((wq = TAILQ_FIRST(&wc->lockers)) != NULL) { + TAILQ_REMOVE(&wc->lockers, wq, waitentry); + if (!cmdq_free(wq)) + cmdq_continue(wq); + } + RB_REMOVE(wait_channels, &wait_channels, wc); + free((void *)wc->name); + free(wc); + } +} diff --git a/format.c b/format.c index 66795d50..baf23ec1 100644 --- a/format.c +++ b/format.c @@ -494,7 +494,10 @@ format_winlink(struct format_tree *ft, struct session *s, struct winlink *wl) !!(wl->flags & WINLINK_ACTIVITY)); format_add(ft, "window_silence_flag", "%u", !!(wl->flags & WINLINK_SILENCE)); - + format_add(ft, "window_last_flag", "%u", + !!(wl == TAILQ_FIRST(&s->lastw))); + format_add(ft, "window_zoomed_flag", "%u", + !!(wl->flags & WINDOW_ZOOMED)); free(flags); } diff --git a/grid.c b/grid.c index a84a58b5..6b8cfcb7 100644 --- a/grid.c +++ b/grid.c @@ -514,20 +514,18 @@ grid_string_cells_code(const struct grid_cell *lastgc, s[n++] = attrs[i].code; } - /* If the foreground c changed, append its parameters. */ + /* If the foreground colour changed, append 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) { + if (nnewc != noldc || memcmp(newc, oldc, nnewc * sizeof newc[0]) != 0) { for (i = 0; i < nnewc; i++) s[n++] = newc[i]; } - /* If the background c changed, append its parameters. */ + /* 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) { + if (nnewc != noldc || memcmp(newc, oldc, nnewc * sizeof newc[0]) != 0) { for (i = 0; i < nnewc; i++) s[n++] = newc[i]; } @@ -572,7 +570,7 @@ grid_string_cells(struct grid *gd, u_int px, u_int py, u_int nx, const struct grid_cell *gc; static struct grid_cell lastgc1; struct utf8_data ud; - const char* data; + const char *data; char *buf, code[128]; size_t len, off, size, codelen; u_int xx; diff --git a/mode-key.c b/mode-key.c index 8bb83cb9..678114e5 100644 --- a/mode-key.c +++ b/mode-key.c @@ -130,6 +130,7 @@ const struct mode_key_cmdstr mode_key_cmdstr_copy[] = { { MODEKEYCOPY_NEXTSPACEEND, "next-space-end" }, { MODEKEYCOPY_NEXTWORD, "next-word" }, { MODEKEYCOPY_NEXTWORDEND, "next-word-end" }, + { MODEKEYCOPY_OTHEREND, "other-end" }, { MODEKEYCOPY_PREVIOUSPAGE, "page-up" }, { MODEKEYCOPY_PREVIOUSSPACE, "previous-space" }, { MODEKEYCOPY_PREVIOUSWORD, "previous-word" }, diff --git a/paste.c b/paste.c index b05cf025..4af8cccf 100644 --- a/paste.c +++ b/paste.c @@ -101,7 +101,7 @@ paste_get_name(const char *name) if (name == NULL || *name == '\0') return (NULL); - pbfind.name = (char*)name; + pbfind.name = (char *)name; return (RB_FIND(paste_name_tree, &paste_by_name, &pbfind)); } @@ -114,7 +114,7 @@ paste_free_name(const char *name) if (name == NULL || *name == '\0') return (-1); - pbfind.name = (char*)name; + pbfind.name = (char *)name; pb = RB_FIND(paste_name_tree, &paste_by_name, &pbfind); if (pb == NULL) return (-1); @@ -297,6 +297,9 @@ paste_send_pane(struct paste_buffer *pb, struct window_pane *wp, const char *data = pb->data, *end = data + pb->size, *lf; size_t seplen; + if (wp->flags & PANE_INPUTOFF) + return; + if (bracket) bufferevent_write(wp->event, "\033[200~", 6); diff --git a/screen.c b/screen.c index 7bfc0154..014e4f31 100644 --- a/screen.c +++ b/screen.c @@ -277,6 +277,7 @@ int screen_check_selection(struct screen *s, u_int px, u_int py) { struct screen_sel *sel = &s->sel; + u_int xx; if (!sel->flag) return (0); @@ -326,16 +327,24 @@ screen_check_selection(struct screen *s, u_int px, u_int py) if (py < sel->sy || py > sel->ey) return (0); - if ((py == sel->sy && px < sel->sx) - || (py == sel->ey && px > sel->ex)) + if (py == sel->sy && px < sel->sx) + return (0); + + if (py == sel->ey && px > sel->ex) return (0); } else if (sel->sy > sel->ey) { /* starting line > ending line -- upward selection. */ if (py > sel->sy || py < sel->ey) return (0); - if ((py == sel->sy && px >= sel->sx) - || (py == sel->ey && px < sel->ex)) + if (py == sel->ey && px < sel->ex) + return (0); + + if (sel->modekeys == MODEKEY_EMACS) + xx = sel->sx - 1; + else + xx = sel->sx; + if (py == sel->sy && px > xx) return (0); } else { /* starting line == ending line. */ @@ -344,7 +353,11 @@ screen_check_selection(struct screen *s, u_int px, u_int py) if (sel->ex < sel->sx) { /* cursor (ex) is on the left */ - if (px > sel->sx || px < sel->ex) + if (sel->modekeys == MODEKEY_EMACS) + xx = sel->sx - 1; + else + xx = sel->sx; + if (px > xx || px < sel->ex) return (0); } else { /* selection start (sx) is on the left */ diff --git a/server-client.c b/server-client.c index 6d5d0833..08085f75 100644 --- a/server-client.c +++ b/server-client.c @@ -923,7 +923,7 @@ server_client_msg_command(struct client *c, struct imsg *imsg) fatalx("bad MSG_COMMAND size"); memcpy(&data, imsg->data, sizeof data); - buf = (char*)imsg->data + sizeof data; + buf = (char *)imsg->data + sizeof data; len = imsg->hdr.len - IMSG_HEADER_SIZE - sizeof data; if (len > 0 && buf[len - 1] != '\0') fatalx("bad MSG_COMMAND string"); diff --git a/server.c b/server.c index 6cded12a..94c928db 100644 --- a/server.c +++ b/server.c @@ -218,16 +218,30 @@ server_loop(void) int server_should_shutdown(void) { - u_int i; + struct client *c; + u_int i; if (!options_get_number(&global_options, "exit-unattached")) { if (!RB_EMPTY(&sessions)) return (0); } + + for (i = 0; i < ARRAY_LENGTH(&clients); i++) { + c = ARRAY_ITEM(&clients, i); + if (c != NULL && c->session != NULL) + return (0); + } + + /* + * No attached clients therefore want to exit - flush any waiting + * clients but don't actually exit until they've gone. + */ + cmd_wait_for_flush(); for (i = 0; i < ARRAY_LENGTH(&clients); i++) { if (ARRAY_ITEM(&clients, i) != NULL) return (0); } + return (1); } @@ -239,6 +253,8 @@ server_send_shutdown(void) struct session *s, *next_s; u_int i; + cmd_wait_for_flush(); + for (i = 0; i < ARRAY_LENGTH(&clients); i++) { c = ARRAY_ITEM(&clients, i); if (c != NULL) { diff --git a/tmux.1 b/tmux.1 index 924157d3..8afc3c5e 100644 --- a/tmux.1 +++ b/tmux.1 @@ -1296,7 +1296,7 @@ flag, see the section. This command works only if at least one client is attached. .It Ic display-panes Op Fl t Ar target-client -.D1 (alias: Ic displayp) +.D1 (alias: Ic displayp ) Display a visible indicator of each pane shown by .Ar target-client . See the @@ -1386,9 +1386,16 @@ The .Fl a option kills all but the window given with .Fl t . -.It Ic last-pane Op Fl t Ar target-window +.It Xo Ic last-pane +.Op Fl de +.Op Fl t Ar target-window +.Xc .D1 (alias: Ic lastp ) Select the last (previously selected) pane. +.Fl e +enables or +.Fl d +disables input to the pane. .It Ic last-window Op Fl t Ar target-session .D1 (alias: Ic last ) Select the last (previously selected) window. @@ -1705,7 +1712,7 @@ and .Ic previous-layout commands. .It Xo Ic select-pane -.Op Fl lDLRU +.Op Fl DdeLlRU .Op Fl t Ar target-pane .Xc .D1 (alias: Ic selectp ) @@ -1725,6 +1732,10 @@ target pane is used. is the same as using the .Ic last-pane command. +.Fl e +enables or +.Fl d +disables input to the pane. .It Xo Ic select-window .Op Fl lnpT .Op Fl t Ar target-window @@ -2429,7 +2440,7 @@ see the option. Attributes are ignored. .It Ic pane-border-style Ar style -Set the pane border style for paneas aside from the active pane. +Set the pane border style for panes aside from the active pane. For how to specify .Ar style , see the @@ -3126,11 +3137,13 @@ The following variables are available, where appropriate: .It Li "window_height" Ta "" Ta "Height of window" .It Li "window_id" Ta "" Ta "Unique window ID" .It Li "window_index" Ta "#I" Ta "Index of window" +.It Li "window_last_flag" Ta "" Ta "1 if window is the last used" .It Li "window_layout" Ta "" Ta "Window layout description" .It Li "window_name" Ta "#W" Ta "Name of window" .It Li "window_panes" Ta "" Ta "Number of panes in window" .It Li "window_silence_flag" Ta "" Ta "1 if window has silence alert" .It Li "window_width" Ta "" Ta "Width of window" +.It Li "window_zoomed_flag" Ta "" Ta "1 if window is zoomed" .It Li "wrap_flag" Ta "" Ta "Pane wrap flag" .El .Sh NAMES AND TITLES diff --git a/tmux.h b/tmux.h index ef1943a1..5ffc07cd 100644 --- a/tmux.h +++ b/tmux.h @@ -791,6 +791,7 @@ LIST_HEAD(joblist, job); struct screen_sel { int flag; int rectflag; + int modekeys; u_int sx; u_int sy; @@ -953,6 +954,7 @@ struct window_pane { #define PANE_FOCUSED 0x4 #define PANE_RESIZE 0x8 #define PANE_FOCUSPUSH 0x10 +#define PANE_INPUTOFF 0x20 int argc; char **argv; @@ -1919,6 +1921,9 @@ void cmdq_flush(struct cmd_q *); int cmd_string_parse(const char *, struct cmd_list **, const char *, u_int, char **); +/* cmd-wait-for.c */ +void cmd_wait_for_flush(void); + /* client.c */ int client_main(int, char **, int); @@ -2320,7 +2325,7 @@ void set_signals(void(*)(int, short, void *)); void clear_signals(int); /* control.c */ -void control_callback(struct client *, int, void*); +void control_callback(struct client *, int, void *); void printflike2 control_write(struct client *, const char *, ...); void control_write_buffer(struct client *, struct evbuffer *); diff --git a/window-copy.c b/window-copy.c index 0775bcb9..3ac994d3 100644 --- a/window-copy.c +++ b/window-copy.c @@ -199,6 +199,7 @@ window_copy_init(struct window_pane *wp) mode_key_init(&data->mdata, &mode_key_tree_emacs_copy); else mode_key_init(&data->mdata, &mode_key_tree_vi_copy); + s->sel.modekeys = keys; data->backing = NULL; @@ -428,7 +429,7 @@ window_copy_key(struct window_pane *wp, struct session *sess, int key) window_pane_reset_mode(wp); return; case MODEKEYCOPY_OTHEREND: - for (; np != 0; np--) + if (np % 2) window_copy_other_end(wp); break; case MODEKEYCOPY_LEFT: @@ -1497,8 +1498,8 @@ window_copy_copy_pipe(struct window_pane *wp, struct session *sess, void window_copy_copy_selection(struct window_pane *wp, const char *bufname) { - void* buf; - size_t len; + void *buf; + size_t len; buf = window_copy_get_selection(wp, &len); if (buf == NULL) diff --git a/window.c b/window.c index e9ec7eaf..d3c41154 100644 --- a/window.c +++ b/window.c @@ -1071,8 +1071,9 @@ window_pane_key(struct window_pane *wp, struct session *sess, int key) return; } - if (wp->fd == -1) + if (wp->fd == -1 || wp->flags & PANE_INPUTOFF) return; + input_key(wp, key); if (options_get_number(&wp->window->options, "synchronize-panes")) { TAILQ_FOREACH(wp2, &wp->window->panes, entry) { @@ -1085,8 +1086,8 @@ window_pane_key(struct window_pane *wp, struct session *sess, int key) } void -window_pane_mouse( - struct window_pane *wp, struct session *sess, struct mouse_event *m) +window_pane_mouse(struct window_pane *wp, struct session *sess, + struct mouse_event *m) { if (!window_pane_visible(wp)) return;