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