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