summaryrefslogtreecommitdiffstats
path: root/cmd-kill-window.c
diff options
context:
space:
mode:
authornicm <nicm>2020-07-04 14:24:02 +0000
committernicm <nicm>2020-07-04 14:24:02 +0000
commit1e426896611f81dd6306263cb337e7ea7d80238e (patch)
treee5ee781e439c507a1b92c6ec8f38d48fb4f71364 /cmd-kill-window.c
parent43e1577b5d6c40369eb353322f68a12b36d609b0 (diff)
kill-window -a cannot just walk the list of windows because if
renumber-windows is on, the window it wants to keep could be moved. Change to renumber afterwards and also behave better if the window is linked into the session twice. GitHub issue 2287.
Diffstat (limited to 'cmd-kill-window.c')
-rw-r--r--cmd-kill-window.c46
1 files changed, 37 insertions, 9 deletions
diff --git a/cmd-kill-window.c b/cmd-kill-window.c
index 68139faa..430f667e 100644
--- a/cmd-kill-window.c
+++ b/cmd-kill-window.c
@@ -57,9 +57,10 @@ cmd_kill_window_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 winlink *wl = target->wl, *wl2, *wl3;
+ struct winlink *wl = target->wl, *loop;
struct window *w = wl->window;
struct session *s = target->s;
+ u_int found;
if (cmd_get_entry(self) == &cmd_unlink_window_entry) {
if (!args_has(args, 'k') && !session_is_linked(s, w)) {
@@ -67,16 +68,43 @@ cmd_kill_window_exec(struct cmd *self, struct cmdq_item *item)
return (CMD_RETURN_ERROR);
}
server_unlink_window(s, wl);
- } else {
- if (args_has(args, 'a')) {
- RB_FOREACH_SAFE(wl2, winlinks, &s->windows, wl3) {
- if (wl != wl2)
- server_kill_window(wl2->window);
+ recalculate_sizes();
+ return (CMD_RETURN_NORMAL);
+ }
+
+ if (args_has(args, 'a')) {
+ if (RB_PREV(winlinks, &s->windows, wl) == NULL &&
+ RB_NEXT(winlinks, &s->windows, wl) == NULL)
+ return (CMD_RETURN_NORMAL);
+
+ /* Kill all windows except the current one. */
+ do {
+ found = 0;
+ RB_FOREACH(loop, winlinks, &s->windows) {
+ if (loop->window != wl->window) {
+ server_kill_window(loop->window, 0);
+ found++;
+ break;
+ }
}
- } else
- server_kill_window(wl->window);
+ } while (found != 0);
+
+ /*
+ * If the current window appears in the session more than once,
+ * kill it as well.
+ */
+ found = 0;
+ RB_FOREACH(loop, winlinks, &s->windows) {
+ if (loop->window == wl->window)
+ found++;
+ }
+ if (found > 1)
+ server_kill_window(wl->window, 0);
+
+ server_renumber_all();
+ return (CMD_RETURN_NORMAL);
}
- recalculate_sizes();
+ server_kill_window(wl->window, 1);
return (CMD_RETURN_NORMAL);
}