1 /* $OpenBSD: cmd-new-window.c,v 1.17 2011/01/04 00:42:47 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 "adkn:Pt:", 0, 1, 34 "[-adk] [-n window-name] [-t target-window] [command]", 35 0, 36 NULL, 37 NULL, 38 cmd_new_window_exec 39 }; 40 41 int 42 cmd_new_window_exec(struct cmd *self, struct cmd_ctx *ctx) 43 { 44 struct args *args = self->args; 45 struct session *s; 46 struct winlink *wl; 47 char *cmd, *cwd, *cause; 48 int idx, last, detached; 49 50 if (args_has(args, 'a')) { 51 wl = cmd_find_window(ctx, args_get(args, 't'), &s); 52 if (wl == NULL) 53 return (-1); 54 idx = wl->idx + 1; 55 56 /* Find the next free index. */ 57 for (last = idx; last < INT_MAX; last++) { 58 if (winlink_find_by_index(&s->windows, last) == NULL) 59 break; 60 } 61 if (last == INT_MAX) { 62 ctx->error(ctx, "no free window indexes"); 63 return (-1); 64 } 65 66 /* Move everything from last - 1 to idx up a bit. */ 67 for (; last > idx; last--) { 68 wl = winlink_find_by_index(&s->windows, last - 1); 69 server_link_window(s, wl, s, last, 0, 0, NULL); 70 server_unlink_window(s, wl); 71 } 72 } else { 73 if ((idx = cmd_find_index(ctx, args_get(args, 't'), &s)) == -2) 74 return (-1); 75 } 76 detached = args_has(args, 'd'); 77 78 wl = NULL; 79 if (idx != -1) 80 wl = winlink_find_by_index(&s->windows, idx); 81 if (wl != NULL && args_has(args, 'k')) { 82 /* 83 * Can't use session_detach as it will destroy session if this 84 * makes it empty. 85 */ 86 wl->flags &= ~WINLINK_ALERTFLAGS; 87 winlink_stack_remove(&s->lastw, wl); 88 winlink_remove(&s->windows, wl); 89 90 /* Force select/redraw if current. */ 91 if (wl == s->curw) { 92 detached = 0; 93 s->curw = NULL; 94 } 95 } 96 97 if (args->argc == 0) 98 cmd = options_get_string(&s->options, "default-command"); 99 else 100 cmd = args->argv[0]; 101 cwd = options_get_string(&s->options, "default-path"); 102 if (*cwd == '\0') { 103 if (ctx->cmdclient != NULL && ctx->cmdclient->cwd != NULL) 104 cwd = ctx->cmdclient->cwd; 105 else 106 cwd = s->cwd; 107 } 108 109 if (idx == -1) 110 idx = -1 - options_get_number(&s->options, "base-index"); 111 wl = session_new(s, args_get(args, 'n'), cmd, cwd, idx, &cause); 112 if (wl == NULL) { 113 ctx->error(ctx, "create window failed: %s", cause); 114 xfree(cause); 115 return (-1); 116 } 117 if (!detached) { 118 session_select(s, wl->idx); 119 server_redraw_session_group(s); 120 } else 121 server_status_session_group(s); 122 123 if (args_has(args, 'P')) 124 ctx->print(ctx, "%s:%u", s->name, wl->idx); 125 return (0); 126 } 127