1 /* $OpenBSD: cmd-new-window.c,v 1.8 2009/10/10 10:02:48 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_parse(struct cmd *, int, char **, char **); 30 int cmd_new_window_exec(struct cmd *, struct cmd_ctx *); 31 void cmd_new_window_free(struct cmd *); 32 void cmd_new_window_init(struct cmd *, int); 33 size_t cmd_new_window_print(struct cmd *, char *, size_t); 34 35 struct cmd_new_window_data { 36 char *target; 37 char *name; 38 char *cmd; 39 int flag_detached; 40 int flag_kill; 41 }; 42 43 const struct cmd_entry cmd_new_window_entry = { 44 "new-window", "neww", 45 "[-dk] [-n window-name] [-t target-window] [command]", 46 0, 0, 47 cmd_new_window_init, 48 cmd_new_window_parse, 49 cmd_new_window_exec, 50 cmd_new_window_free, 51 cmd_new_window_print 52 }; 53 54 void 55 cmd_new_window_init(struct cmd *self, unused int arg) 56 { 57 struct cmd_new_window_data *data; 58 59 self->data = data = xmalloc(sizeof *data); 60 data->target = NULL; 61 data->name = NULL; 62 data->cmd = NULL; 63 data->flag_detached = 0; 64 data->flag_kill = 0; 65 } 66 67 int 68 cmd_new_window_parse(struct cmd *self, int argc, char **argv, char **cause) 69 { 70 struct cmd_new_window_data *data; 71 int opt; 72 73 self->entry->init(self, KEYC_NONE); 74 data = self->data; 75 76 while ((opt = getopt(argc, argv, "dkt:n:")) != -1) { 77 switch (opt) { 78 case 'd': 79 data->flag_detached = 1; 80 break; 81 case 'k': 82 data->flag_kill = 1; 83 break; 84 case 't': 85 if (data->target == NULL) 86 data->target = xstrdup(optarg); 87 break; 88 case 'n': 89 if (data->name == NULL) 90 data->name = xstrdup(optarg); 91 break; 92 default: 93 goto usage; 94 } 95 } 96 argc -= optind; 97 argv += optind; 98 if (argc != 0 && argc != 1) 99 goto usage; 100 101 if (argc == 1) 102 data->cmd = xstrdup(argv[0]); 103 104 return (0); 105 106 usage: 107 xasprintf(cause, "usage: %s %s", self->entry->name, self->entry->usage); 108 109 self->entry->free(self); 110 return (-1); 111 } 112 113 int 114 cmd_new_window_exec(struct cmd *self, struct cmd_ctx *ctx) 115 { 116 struct cmd_new_window_data *data = self->data; 117 struct session *s; 118 struct winlink *wl; 119 char *cmd, *cwd, *cause; 120 int idx; 121 122 if (data == NULL) 123 return (0); 124 125 if ((idx = cmd_find_index(ctx, data->target, &s)) == -2) 126 return (-1); 127 128 wl = NULL; 129 if (idx != -1) 130 wl = winlink_find_by_index(&s->windows, idx); 131 if (wl != NULL) { 132 if (data->flag_kill) { 133 /* 134 * Can't use session_detach as it will destroy session 135 * if this makes it empty. 136 */ 137 session_alert_cancel(s, wl); 138 winlink_stack_remove(&s->lastw, wl); 139 winlink_remove(&s->windows, wl); 140 141 /* Force select/redraw if current. */ 142 if (wl == s->curw) { 143 data->flag_detached = 0; 144 s->curw = NULL; 145 } 146 } 147 } 148 149 cmd = data->cmd; 150 if (cmd == NULL) 151 cmd = options_get_string(&s->options, "default-command"); 152 if (ctx->cmdclient == NULL || ctx->cmdclient->cwd == NULL) 153 cwd = options_get_string(&s->options, "default-path"); 154 else 155 cwd = ctx->cmdclient->cwd; 156 157 if (idx == -1) 158 idx = -1 - options_get_number(&s->options, "base-index"); 159 wl = session_new(s, data->name, cmd, cwd, idx, &cause); 160 if (wl == NULL) { 161 ctx->error(ctx, "create window failed: %s", cause); 162 xfree(cause); 163 return (-1); 164 } 165 if (!data->flag_detached) { 166 session_select(s, wl->idx); 167 server_redraw_session_group(s); 168 } else 169 server_status_session_group(s); 170 171 return (0); 172 } 173 174 void 175 cmd_new_window_free(struct cmd *self) 176 { 177 struct cmd_new_window_data *data = self->data; 178 179 if (data->target != NULL) 180 xfree(data->target); 181 if (data->name != NULL) 182 xfree(data->name); 183 if (data->cmd != NULL) 184 xfree(data->cmd); 185 xfree(data); 186 } 187 188 size_t 189 cmd_new_window_print(struct cmd *self, char *buf, size_t len) 190 { 191 struct cmd_new_window_data *data = self->data; 192 size_t off = 0; 193 194 off += xsnprintf(buf, len, "%s", self->entry->name); 195 if (data == NULL) 196 return (off); 197 if (off < len && data->flag_detached) 198 off += xsnprintf(buf + off, len - off, " -d"); 199 if (off < len && data->target != NULL) 200 off += cmd_prarg(buf + off, len - off, " -t ", data->target); 201 if (off < len && data->name != NULL) 202 off += cmd_prarg(buf + off, len - off, " -n ", data->name); 203 if (off < len && data->cmd != NULL) 204 off += cmd_prarg(buf + off, len - off, " ", data->cmd); 205 return (off); 206 } 207