=================================================================== RCS file: /cvsrepo/anoncvs/cvs/src/usr.bin/tmux/window-tree.c,v retrieving revision 1.29 retrieving revision 1.30 diff -u -r1.29 -r1.30 --- src/usr.bin/tmux/window-tree.c 2018/03/29 08:03:51 1.29 +++ src/usr.bin/tmux/window-tree.c 2018/04/10 10:48:44 1.30 @@ -1,4 +1,4 @@ -/* $OpenBSD: window-tree.c,v 1.29 2018/03/29 08:03:51 nicm Exp $ */ +/* $OpenBSD: window-tree.c,v 1.30 2018/04/10 10:48:44 nicm Exp $ */ /* * Copyright (c) 2017 Nicholas Marriott @@ -18,6 +18,7 @@ #include +#include #include #include @@ -860,8 +861,6 @@ if (--data->references != 0) return; - mode_tree_free(data->data); - for (i = 0; i < data->item_size; i++) window_tree_free_item(data->item_list[i]); free(data->item_list); @@ -881,6 +880,7 @@ return; data->dead = 1; + mode_tree_free(data->data); window_tree_destroy(data); } @@ -965,7 +965,7 @@ { struct window_tree_modedata *data = modedata; - if (s == NULL || data->dead) + if (s == NULL || *s == '\0' || data->dead) return (0); data->entered = s; @@ -987,6 +987,77 @@ window_tree_destroy(data); } +static void +window_tree_kill_each(__unused void* modedata, void* itemdata, + __unused struct client *c, __unused key_code key) +{ + struct window_tree_itemdata *item = itemdata; + struct session *s; + struct winlink *wl; + struct window_pane *wp; + + window_tree_pull_item(item, &s, &wl, &wp); + + switch (item->type) { + case WINDOW_TREE_NONE: + break; + case WINDOW_TREE_SESSION: + if (s != NULL) { + server_destroy_session(s); + session_destroy(s, __func__); + } + break; + case WINDOW_TREE_WINDOW: + if (wl != NULL) + server_kill_window(wl->window); + break; + case WINDOW_TREE_PANE: + if (wp != NULL) + server_kill_pane(wp); + break; + } +} + +static int +window_tree_kill_current_callback(struct client *c, void *modedata, + const char *s, __unused int done) +{ + struct window_tree_modedata *data = modedata; + struct mode_tree_data *mtd = data->data; + + if (s == NULL || *s == '\0' || data->dead) + return (0); + if (tolower((u_char) s[0]) != 'y' || s[1] != '\0') + return (0); + + window_tree_kill_each(data, mode_tree_get_current(mtd), c, KEYC_NONE); + + data->references++; + cmdq_append(c, cmdq_get_callback(window_tree_command_done, data)); + + return (0); +} + +static int +window_tree_kill_tagged_callback(struct client *c, void *modedata, + const char *s, __unused int done) +{ + struct window_tree_modedata *data = modedata; + struct mode_tree_data *mtd = data->data; + + if (s == NULL || *s == '\0' || data->dead) + return (0); + if (tolower((u_char) s[0]) != 'y' || s[1] != '\0') + return (0); + + mode_tree_each_tagged(mtd, window_tree_kill_each, c, KEYC_NONE, 1); + + data->references++; + cmdq_append(c, cmdq_get_callback(window_tree_command_done, data)); + + return (0); +} + static key_code window_tree_mouse(struct window_tree_modedata *data, key_code key, u_int x, struct window_tree_itemdata *item) @@ -1054,10 +1125,13 @@ { struct window_tree_modedata *data = wp->modedata; struct window_tree_itemdata *item, *new_item; - char *name, *prompt; + char *name, *prompt = NULL; struct cmd_find_state fs; int finished; - u_int tagged, x, y; + u_int tagged, x, y, idx; + struct session *ns; + struct winlink *nwl; + struct window_pane *nwp; item = mode_tree_get_current(data->data); finished = mode_tree_key(data->data, c, &key, m, &x, &y); @@ -1073,6 +1147,46 @@ break; case '>': data->offset++; + break; + case 'x': + window_tree_pull_item(item, &ns, &nwl, &nwp); + switch (item->type) { + case WINDOW_TREE_NONE: + break; + case WINDOW_TREE_SESSION: + if (ns == NULL) + break; + xasprintf(&prompt, "Kill session %s? ", ns->name); + break; + case WINDOW_TREE_WINDOW: + if (nwl == NULL) + break; + xasprintf(&prompt, "Kill window %u? ", nwl->idx); + break; + case WINDOW_TREE_PANE: + if (nwp == NULL || window_pane_index(nwp, &idx) != 0) + break; + xasprintf(&prompt, "Kill pane %u? ", idx); + break; + } + if (prompt == NULL) + break; + data->references++; + status_prompt_set(c, prompt, "", + window_tree_kill_current_callback, window_tree_command_free, + data, PROMPT_SINGLE|PROMPT_NOFORMAT); + free(prompt); + break; + case 'X': + tagged = mode_tree_count_tagged(data->data); + if (tagged == 0) + break; + xasprintf(&prompt, "Kill %u tagged? ", tagged); + data->references++; + status_prompt_set(c, prompt, "", + window_tree_kill_tagged_callback, window_tree_command_free, + data, PROMPT_SINGLE|PROMPT_NOFORMAT); + free(prompt); break; case ':': tagged = mode_tree_count_tagged(data->data);