Make the prompt history global for all clients which is much more useful than per...
[tmux-openbsd.git] / cmd-new-window.c
blobb44be0b21965b2919fb993ae3a4abf1699b36efb
1 /* $OpenBSD$ */
3 /*
4 * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
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.
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.
19 #include <sys/types.h>
21 #include <stdlib.h>
23 #include "tmux.h"
26 * Create a new window.
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);
35 struct cmd_new_window_data {
36 char *target;
37 char *name;
38 char *cmd;
39 int flag_insert_after;
40 int flag_detached;
41 int flag_kill;
44 const struct cmd_entry cmd_new_window_entry = {
45 "new-window", "neww",
46 "[-adk] [-n window-name] [-t target-window] [command]",
47 0, "",
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
55 /* ARGSUSED */
56 void
57 cmd_new_window_init(struct cmd *self, unused int arg)
59 struct cmd_new_window_data *data;
61 self->data = data = xmalloc(sizeof *data);
62 data->target = NULL;
63 data->name = NULL;
64 data->cmd = NULL;
65 data->flag_insert_after = 0;
66 data->flag_detached = 0;
67 data->flag_kill = 0;
70 int
71 cmd_new_window_parse(struct cmd *self, int argc, char **argv, char **cause)
73 struct cmd_new_window_data *data;
74 int opt;
76 self->entry->init(self, KEYC_NONE);
77 data = self->data;
79 while ((opt = getopt(argc, argv, "adkt:n:")) != -1) {
80 switch (opt) {
81 case 'a':
82 data->flag_insert_after = 1;
83 break;
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;
102 argc -= optind;
103 argv += optind;
104 if (argc != 0 && argc != 1)
105 goto usage;
107 if (argc == 1)
108 data->cmd = xstrdup(argv[0]);
110 return (0);
112 usage:
113 xasprintf(cause, "usage: %s %s", self->entry->name, self->entry->usage);
115 self->entry->free(self);
116 return (-1);
120 cmd_new_window_exec(struct cmd *self, struct cmd_ctx *ctx)
122 struct cmd_new_window_data *data = self->data;
123 struct session *s;
124 struct winlink *wl;
125 char *cmd, *cwd, *cause;
126 int idx, last;
128 if (data == NULL)
129 return (0);
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;
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;
141 if (last == INT_MAX) {
142 ctx->error(ctx, "no free window indexes");
143 return (-1);
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);
152 } else {
153 if ((idx = cmd_find_index(ctx, data->target, &s)) == -2)
154 return (-1);
157 wl = NULL;
158 if (idx != -1)
159 wl = winlink_find_by_index(&s->windows, idx);
160 if (wl != NULL && data->flag_kill) {
162 * Can't use session_detach as it will destroy session if this
163 * makes it empty.
165 wl->flags &= ~WINLINK_ALERTFLAGS;
166 winlink_stack_remove(&s->lastw, wl);
167 winlink_remove(&s->windows, wl);
169 /* Force select/redraw if current. */
170 if (wl == s->curw) {
171 data->flag_detached = 0;
172 s->curw = NULL;
176 cmd = data->cmd;
177 if (cmd == NULL)
178 cmd = options_get_string(&s->options, "default-command");
179 cwd = options_get_string(&s->options, "default-path");
180 if (*cwd == '\0') {
181 if (ctx->cmdclient != NULL && ctx->cmdclient->cwd != NULL)
182 cwd = ctx->cmdclient->cwd;
183 else
184 cwd = s->cwd;
187 if (idx == -1)
188 idx = -1 - options_get_number(&s->options, "base-index");
189 wl = session_new(s, data->name, cmd, cwd, idx, &cause);
190 if (wl == NULL) {
191 ctx->error(ctx, "create window failed: %s", cause);
192 xfree(cause);
193 return (-1);
195 if (!data->flag_detached) {
196 session_select(s, wl->idx);
197 server_redraw_session_group(s);
198 } else
199 server_status_session_group(s);
201 return (0);
204 void
205 cmd_new_window_free(struct cmd *self)
207 struct cmd_new_window_data *data = self->data;
209 if (data->target != NULL)
210 xfree(data->target);
211 if (data->name != NULL)
212 xfree(data->name);
213 if (data->cmd != NULL)
214 xfree(data->cmd);
215 xfree(data);
218 size_t
219 cmd_new_window_print(struct cmd *self, char *buf, size_t len)
221 struct cmd_new_window_data *data = self->data;
222 size_t off = 0;
224 off += xsnprintf(buf, len, "%s", self->entry->name);
225 if (data == NULL)
226 return (off);
227 if (off < len && data->flag_detached)
228 off += xsnprintf(buf + off, len - off, " -d");
229 if (off < len && data->target != NULL)
230 off += cmd_prarg(buf + off, len - off, " -t ", data->target);
231 if (off < len && data->name != NULL)
232 off += cmd_prarg(buf + off, len - off, " -n ", data->name);
233 if (off < len && data->cmd != NULL)
234 off += cmd_prarg(buf + off, len - off, " ", data->cmd);
235 return (off);