Annotation of src/usr.bin/tmux/cmd-split-window.c, Revision 1.21
1.21 ! nicm 1: /* $OpenBSD: cmd-split-window.c,v 1.20 2010/06/27 02:56:59 nicm Exp $ */
1.1 nicm 2:
3: /*
4: * Copyright (c) 2009 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:
1.11 nicm 21: #include <paths.h>
1.1 nicm 22: #include <stdlib.h>
23: #include <unistd.h>
24:
25: #include "tmux.h"
26:
27: /*
28: * Split a window (add a new pane).
29: */
30:
31: int cmd_split_window_parse(struct cmd *, int, char **, char **);
32: int cmd_split_window_exec(struct cmd *, struct cmd_ctx *);
33: void cmd_split_window_free(struct cmd *);
34: void cmd_split_window_init(struct cmd *, int);
35: size_t cmd_split_window_print(struct cmd *, char *, size_t);
36:
37: struct cmd_split_window_data {
38: char *target;
39: char *cmd;
40: int flag_detached;
1.5 nicm 41: int flag_horizontal;
1.21 ! nicm 42: int flag_print;
1.1 nicm 43: int percentage;
1.5 nicm 44: int size;
1.1 nicm 45: };
46:
47: const struct cmd_entry cmd_split_window_entry = {
48: "split-window", "splitw",
1.21 ! nicm 49: "[-dhvP] [-p percentage|-l size] [-t target-pane] [command]",
1.14 nicm 50: 0, "",
1.1 nicm 51: cmd_split_window_init,
52: cmd_split_window_parse,
53: cmd_split_window_exec,
54: cmd_split_window_free,
55: cmd_split_window_print
56: };
57:
58: void
1.5 nicm 59: cmd_split_window_init(struct cmd *self, int key)
1.1 nicm 60: {
61: struct cmd_split_window_data *data;
62:
63: self->data = data = xmalloc(sizeof *data);
64: data->target = NULL;
65: data->cmd = NULL;
66: data->flag_detached = 0;
1.5 nicm 67: data->flag_horizontal = 0;
1.21 ! nicm 68: data->flag_print = 0;
1.1 nicm 69: data->percentage = -1;
1.5 nicm 70: data->size = -1;
71:
72: switch (key) {
73: case '%':
74: data->flag_horizontal = 1;
1.16 nicm 75: break;
1.5 nicm 76: case '"':
77: data->flag_horizontal = 0;
78: break;
79: }
1.1 nicm 80: }
81:
82: int
83: cmd_split_window_parse(struct cmd *self, int argc, char **argv, char **cause)
84: {
85: struct cmd_split_window_data *data;
1.5 nicm 86: int opt;
1.1 nicm 87: const char *errstr;
88:
1.13 nicm 89: self->entry->init(self, KEYC_NONE);
1.1 nicm 90: data = self->data;
91:
1.21 ! nicm 92: while ((opt = getopt(argc, argv, "dhl:p:Pt:v")) != -1) {
1.1 nicm 93: switch (opt) {
94: case 'd':
95: data->flag_detached = 1;
96: break;
1.5 nicm 97: case 'h':
98: data->flag_horizontal = 1;
99: break;
1.1 nicm 100: case 't':
101: if (data->target == NULL)
102: data->target = xstrdup(optarg);
103: break;
104: case 'l':
1.5 nicm 105: if (data->percentage != -1 || data->size != -1)
106: break;
107: data->size = strtonum(optarg, 1, INT_MAX, &errstr);
108: if (errstr != NULL) {
109: xasprintf(cause, "size %s", errstr);
110: goto error;
1.1 nicm 111: }
112: break;
113: case 'p':
1.5 nicm 114: if (data->size != -1 || data->percentage != -1)
115: break;
116: data->percentage = strtonum(optarg, 1, 100, &errstr);
117: if (errstr != NULL) {
118: xasprintf(cause, "percentage %s", errstr);
119: goto error;
1.1 nicm 120: }
121: break;
1.21 ! nicm 122: case 'P':
! 123: data->flag_print = 1;
! 124: break;
1.5 nicm 125: case 'v':
126: data->flag_horizontal = 0;
127: break;
1.1 nicm 128: default:
129: goto usage;
130: }
131: }
132: argc -= optind;
133: argv += optind;
134: if (argc != 0 && argc != 1)
135: goto usage;
136:
137: if (argc == 1)
138: data->cmd = xstrdup(argv[0]);
139:
140: return (0);
141:
142: usage:
143: xasprintf(cause, "usage: %s %s", self->entry->name, self->entry->usage);
144:
145: error:
146: self->entry->free(self);
147: return (-1);
148: }
149:
150: int
151: cmd_split_window_exec(struct cmd *self, struct cmd_ctx *ctx)
152: {
153: struct cmd_split_window_data *data = self->data;
154: struct session *s;
155: struct winlink *wl;
156: struct window *w;
1.19 nicm 157: struct window_pane *wp, *new_wp = NULL;
1.8 nicm 158: struct environ env;
1.1 nicm 159: char *cmd, *cwd, *cause;
1.11 nicm 160: const char *shell;
1.21 ! nicm 161: u_int hlimit, paneidx;
1.5 nicm 162: int size;
163: enum layout_type type;
1.19 nicm 164: struct layout_cell *lc;
1.1 nicm 165:
1.17 nicm 166: if ((wl = cmd_find_pane(ctx, data->target, &s, &wp)) == NULL)
1.1 nicm 167: return (-1);
168: w = wl->window;
169:
1.8 nicm 170: environ_init(&env);
171: environ_copy(&global_environ, &env);
172: environ_copy(&s->environ, &env);
173: server_fill_environ(s, &env);
1.1 nicm 174:
175: cmd = data->cmd;
176: if (cmd == NULL)
177: cmd = options_get_string(&s->options, "default-command");
1.20 nicm 178: cwd = options_get_string(&s->options, "default-path");
179: if (*cwd == '\0') {
180: if (ctx->cmdclient != NULL && ctx->cmdclient->cwd != NULL)
181: cwd = ctx->cmdclient->cwd;
182: else
183: cwd = s->cwd;
184: }
1.1 nicm 185:
1.15 nicm 186: type = LAYOUT_TOPBOTTOM;
187: if (data->flag_horizontal)
188: type = LAYOUT_LEFTRIGHT;
189:
1.5 nicm 190: size = -1;
191: if (data->size != -1)
192: size = data->size;
1.15 nicm 193: else if (data->percentage != -1) {
194: if (type == LAYOUT_TOPBOTTOM)
1.18 nicm 195: size = (wp->sy * data->percentage) / 100;
1.15 nicm 196: else
1.18 nicm 197: size = (wp->sx * data->percentage) / 100;
1.15 nicm 198: }
1.5 nicm 199: hlimit = options_get_number(&s->options, "history-limit");
200:
1.11 nicm 201: shell = options_get_string(&s->options, "default-shell");
202: if (*shell == '\0' || areshell(shell))
203: shell = _PATH_BSHELL;
204:
1.19 nicm 205: if ((lc = layout_split_pane(wp, type, size)) == NULL) {
1.5 nicm 206: cause = xstrdup("pane too small");
207: goto error;
1.1 nicm 208: }
1.19 nicm 209: new_wp = window_add_pane(w, hlimit);
210: if (window_pane_spawn(
211: new_wp, cmd, shell, cwd, &env, s->tio, &cause) != 0)
212: goto error;
213: layout_assign_pane(lc, new_wp);
1.5 nicm 214:
1.1 nicm 215: server_redraw_window(w);
216:
217: if (!data->flag_detached) {
1.17 nicm 218: window_set_active_pane(w, new_wp);
1.1 nicm 219: session_select(s, wl->idx);
220: server_redraw_session(s);
221: } else
222: server_status_session(s);
223:
1.8 nicm 224: environ_free(&env);
1.21 ! nicm 225:
! 226: if (data->flag_print) {
! 227: paneidx = window_pane_index(wl->window, new_wp);
! 228: ctx->print(ctx, "%s:%u.%u", s->name, wl->idx, paneidx);
! 229: }
1.1 nicm 230: return (0);
1.5 nicm 231:
232: error:
1.8 nicm 233: environ_free(&env);
1.17 nicm 234: if (new_wp != NULL)
235: window_remove_pane(w, new_wp);
1.5 nicm 236: ctx->error(ctx, "create pane failed: %s", cause);
237: xfree(cause);
238: return (-1);
1.1 nicm 239: }
240:
241: void
242: cmd_split_window_free(struct cmd *self)
243: {
244: struct cmd_split_window_data *data = self->data;
245:
246: if (data->target != NULL)
247: xfree(data->target);
248: if (data->cmd != NULL)
249: xfree(data->cmd);
250: xfree(data);
251: }
252:
253: size_t
254: cmd_split_window_print(struct cmd *self, char *buf, size_t len)
255: {
256: struct cmd_split_window_data *data = self->data;
257: size_t off = 0;
258:
259: off += xsnprintf(buf, len, "%s", self->entry->name);
260: if (data == NULL)
261: return (off);
262: if (off < len && data->flag_detached)
263: off += xsnprintf(buf + off, len - off, " -d");
1.5 nicm 264: if (off < len && data->flag_horizontal)
265: off += xsnprintf(buf + off, len - off, " -h");
1.21 ! nicm 266: if (off < len && data->flag_print)
! 267: off += xsnprintf(buf + off, len - off, " -P");
1.10 nicm 268: if (off < len && data->size > 0)
269: off += xsnprintf(buf + off, len - off, " -l %d", data->size);
270: if (off < len && data->percentage > 0) {
271: off += xsnprintf(
272: buf + off, len - off, " -p %d", data->percentage);
273: }
1.1 nicm 274: if (off < len && data->target != NULL)
275: off += cmd_prarg(buf + off, len - off, " -t ", data->target);
276: if (off < len && data->cmd != NULL)
277: off += cmd_prarg(buf + off, len - off, " ", data->cmd);
278: return (off);
279: }