1 /* $OpenBSD: cmd-new-window.c,v 1.27 2012/08/14 08:51:53 nicm Exp $ */ 2 3 /* 4 * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> 5 * 6 * Permission to use, copy, modify, and distribute this software for any 7 * purpose with or without fee is hereby granted, provided that the above 8 * copyright notice and this permission notice appear in all copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER 15 * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING 16 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19 #include <sys/types.h> 20 21 #include <stdlib.h> 22 23 #include "tmux.h" 24 25 /* 26 * Create a new window. 27 */ 28 29 int cmd_new_window_exec(struct cmd *, struct cmd_ctx *); 30 31 const struct cmd_entry cmd_new_window_entry = { 32 "new-window", "neww", 33 "ac:dF:kn:Pt:", 0, 1, 34 "[-adkP] [-c start-directory] [-F format] [-n window-name] " 35 "[-t target-window] [command]", 36 0, 37 NULL, 38 NULL, 39 cmd_new_window_exec 40 }; 41 42 enum cmd_retval 43 cmd_new_window_exec(struct cmd *self, struct cmd_ctx *ctx) 44 { 45 struct args *args = self->args; 46 struct session *s; 47 struct winlink *wl; 48 struct client *c; 49 const char *cmd, *cwd; 50 const char *template; 51 char *cause; 52 int idx, last, detached; 53 struct format_tree *ft; 54 char *cp; 55 56 if (args_has(args, 'a')) { 57 wl = cmd_find_window(ctx, args_get(args, 't'), &s); 58 if (wl == NULL) 59 return (CMD_RETURN_ERROR); 60 idx = wl->idx + 1; 61 62 /* Find the next free index. */ 63 for (last = idx; last < INT_MAX; last++) { 64 if (winlink_find_by_index(&s->windows, last) == NULL) 65 break; 66 } 67 if (last == INT_MAX) { 68 ctx->error(ctx, "no free window indexes"); 69 return (CMD_RETURN_ERROR); 70 } 71 72 /* Move everything from last - 1 to idx up a bit. */ 73 for (; last > idx; last--) { 74 wl = winlink_find_by_index(&s->windows, last - 1); 75 server_link_window(s, wl, s, last, 0, 0, NULL); 76 server_unlink_window(s, wl); 77 } 78 } else { 79 if ((idx = cmd_find_index(ctx, args_get(args, 't'), &s)) == -2) 80 return (CMD_RETURN_ERROR); 81 } 82 detached = args_has(args, 'd'); 83 84 wl = NULL; 85 if (idx != -1) 86 wl = winlink_find_by_index(&s->windows, idx); 87 if (wl != NULL && args_has(args, 'k')) { 88 /* 89 * Can't use session_detach as it will destroy session if this 90 * makes it empty. 91 */ 92 notify_window_unlinked(s, wl->window); 93 wl->flags &= ~WINLINK_ALERTFLAGS; 94 winlink_stack_remove(&s->lastw, wl); 95 winlink_remove(&s->windows, wl); 96 97 /* Force select/redraw if current. */ 98 if (wl == s->curw) { 99 detached = 0; 100 s->curw = NULL; 101 } 102 } 103 104 if (args->argc == 0) 105 cmd = options_get_string(&s->options, "default-command"); 106 else 107 cmd = args->argv[0]; 108 cwd = cmd_get_default_path(ctx, args_get(args, 'c')); 109 110 if (idx == -1) 111 idx = -1 - options_get_number(&s->options, "base-index"); 112 wl = session_new(s, args_get(args, 'n'), cmd, cwd, idx, &cause); 113 if (wl == NULL) { 114 ctx->error(ctx, "create window failed: %s", cause); 115 free(cause); 116 return (CMD_RETURN_ERROR); 117 } 118 if (!detached) { 119 session_select(s, wl->idx); 120 server_redraw_session_group(s); 121 } else 122 server_status_session_group(s); 123 124 if (args_has(args, 'P')) { 125 if ((template = args_get(args, 'F')) == NULL) 126 template = NEW_WINDOW_TEMPLATE; 127 128 ft = format_create(); 129 if ((c = cmd_find_client(ctx, NULL)) != NULL) 130 format_client(ft, c); 131 format_session(ft, s); 132 format_winlink(ft, s, wl); 133 format_window_pane(ft, wl->window->active); 134 135 cp = format_expand(ft, template); 136 ctx->print(ctx, "%s", cp); 137 free(cp); 138 139 format_free(ft); 140 } 141 142 return (CMD_RETURN_NORMAL); 143 } 144