1/* $Id: cmd-new-window.c,v 1.1.1.2 2011/08/17 18:40:04 jmmv 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
29int	cmd_new_window_exec(struct cmd *, struct cmd_ctx *);
30
31const 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
41int
42cmd_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