Annotation of src/usr.bin/tmux/cmd-new-window.c, Revision 1.14
1.14 ! nicm 1: /* $OpenBSD: cmd-new-window.c,v 1.13 2010/03/27 11:46:58 nicm Exp $ */
1.1 nicm 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;
1.13 nicm 39: int flag_insert_after;
1.1 nicm 40: int flag_detached;
41: int flag_kill;
42: };
43:
44: const struct cmd_entry cmd_new_window_entry = {
45: "new-window", "neww",
1.13 nicm 46: "[-adk] [-n window-name] [-t target-window] [command]",
1.9 nicm 47: 0, "",
1.1 nicm 48: cmd_new_window_init,
49: cmd_new_window_parse,
50: cmd_new_window_exec,
51: cmd_new_window_free,
52: cmd_new_window_print
53: };
54:
1.10 nicm 55: /* ARGSUSED */
1.1 nicm 56: void
57: cmd_new_window_init(struct cmd *self, unused int arg)
58: {
59: struct cmd_new_window_data *data;
60:
61: self->data = data = xmalloc(sizeof *data);
62: data->target = NULL;
63: data->name = NULL;
64: data->cmd = NULL;
1.13 nicm 65: data->flag_insert_after = 0;
1.1 nicm 66: data->flag_detached = 0;
67: data->flag_kill = 0;
68: }
69:
70: int
71: cmd_new_window_parse(struct cmd *self, int argc, char **argv, char **cause)
72: {
73: struct cmd_new_window_data *data;
74: int opt;
75:
1.7 nicm 76: self->entry->init(self, KEYC_NONE);
1.1 nicm 77: data = self->data;
78:
1.13 nicm 79: while ((opt = getopt(argc, argv, "adkt:n:")) != -1) {
1.1 nicm 80: switch (opt) {
1.13 nicm 81: case 'a':
82: data->flag_insert_after = 1;
83: break;
1.1 nicm 84: case 'd':
85: data->flag_detached = 1;
86: break;
87: case 'k':
88: data->flag_kill = 1;
89: break;
90: case 't':
91: if (data->target == NULL)
92: data->target = xstrdup(optarg);
93: break;
94: case 'n':
95: if (data->name == NULL)
96: data->name = xstrdup(optarg);
97: break;
98: default:
99: goto usage;
100: }
101: }
102: argc -= optind;
103: argv += optind;
104: if (argc != 0 && argc != 1)
105: goto usage;
106:
107: if (argc == 1)
108: data->cmd = xstrdup(argv[0]);
109:
110: return (0);
111:
112: usage:
113: xasprintf(cause, "usage: %s %s", self->entry->name, self->entry->usage);
114:
115: self->entry->free(self);
116: return (-1);
117: }
118:
119: int
120: cmd_new_window_exec(struct cmd *self, struct cmd_ctx *ctx)
121: {
122: struct cmd_new_window_data *data = self->data;
123: struct session *s;
124: struct winlink *wl;
125: char *cmd, *cwd, *cause;
1.13 nicm 126: int idx, last;
1.1 nicm 127:
128: if (data == NULL)
129: return (0);
130:
1.13 nicm 131: if (data->flag_insert_after) {
132: if ((wl = cmd_find_window(ctx, data->target, &s)) == NULL)
133: return (-1);
134: idx = wl->idx + 1;
135:
136: /* Find the next free index. */
137: for (last = idx; last < INT_MAX; last++) {
138: if (winlink_find_by_index(&s->windows, last) == NULL)
139: break;
140: }
141: if (last == INT_MAX) {
142: ctx->error(ctx, "no free window indexes");
143: return (-1);
144: }
145:
146: /* Move everything from last - 1 to idx up a bit. */
147: for (; last > idx; last--) {
148: wl = winlink_find_by_index(&s->windows, last - 1);
149: server_link_window(s, wl, s, last, 0, 0, NULL);
150: server_unlink_window(s, wl);
151: }
152: } else {
153: if ((idx = cmd_find_index(ctx, data->target, &s)) == -2)
154: return (-1);
155: }
1.1 nicm 156:
157: wl = NULL;
158: if (idx != -1)
159: wl = winlink_find_by_index(&s->windows, idx);
1.12 nicm 160: if (wl != NULL && data->flag_kill) {
161: /*
162: * Can't use session_detach as it will destroy session if this
163: * makes it empty.
164: */
1.14 ! nicm 165: wl->flags &= ~WINLINK_ALERTFLAGS;
1.12 nicm 166: winlink_stack_remove(&s->lastw, wl);
167: winlink_remove(&s->windows, wl);
168:
169: /* Force select/redraw if current. */
170: if (wl == s->curw) {
171: data->flag_detached = 0;
172: s->curw = NULL;
1.1 nicm 173: }
174: }
175:
176: cmd = data->cmd;
177: if (cmd == NULL)
178: cmd = options_get_string(&s->options, "default-command");
179: if (ctx->cmdclient == NULL || ctx->cmdclient->cwd == NULL)
1.2 nicm 180: cwd = options_get_string(&s->options, "default-path");
1.1 nicm 181: else
182: cwd = ctx->cmdclient->cwd;
183:
1.6 nicm 184: if (idx == -1)
185: idx = -1 - options_get_number(&s->options, "base-index");
1.1 nicm 186: wl = session_new(s, data->name, cmd, cwd, idx, &cause);
187: if (wl == NULL) {
188: ctx->error(ctx, "create window failed: %s", cause);
189: xfree(cause);
190: return (-1);
191: }
192: if (!data->flag_detached) {
193: session_select(s, wl->idx);
1.8 nicm 194: server_redraw_session_group(s);
1.11 nicm 195: } else
1.8 nicm 196: server_status_session_group(s);
1.1 nicm 197:
198: return (0);
199: }
200:
201: void
202: cmd_new_window_free(struct cmd *self)
203: {
204: struct cmd_new_window_data *data = self->data;
205:
206: if (data->target != NULL)
207: xfree(data->target);
208: if (data->name != NULL)
209: xfree(data->name);
210: if (data->cmd != NULL)
211: xfree(data->cmd);
212: xfree(data);
213: }
214:
215: size_t
216: cmd_new_window_print(struct cmd *self, char *buf, size_t len)
217: {
218: struct cmd_new_window_data *data = self->data;
219: size_t off = 0;
220:
221: off += xsnprintf(buf, len, "%s", self->entry->name);
222: if (data == NULL)
223: return (off);
224: if (off < len && data->flag_detached)
225: off += xsnprintf(buf + off, len - off, " -d");
226: if (off < len && data->target != NULL)
227: off += cmd_prarg(buf + off, len - off, " -t ", data->target);
228: if (off < len && data->name != NULL)
229: off += cmd_prarg(buf + off, len - off, " -n ", data->name);
230: if (off < len && data->cmd != NULL)
231: off += cmd_prarg(buf + off, len - off, " ", data->cmd);
232: return (off);
233: }