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