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