Annotation of src/usr.bin/tmux/cmd-split-window.c, Revision 1.1
1.1 ! nicm 1: /* $OpenBSD$ */
! 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;
! 42: int percentage;
! 43: int lines;
! 44: };
! 45:
! 46: const 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:
! 59: void
! 60: cmd_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:
! 72: int
! 73: cmd_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:
! 126: usage:
! 127: xasprintf(cause, "usage: %s %s", self->entry->name, self->entry->usage);
! 128:
! 129: error:
! 130: self->entry->free(self);
! 131: return (-1);
! 132: }
! 133:
! 134: int
! 135: cmd_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, lines;
! 145:
! 146: if ((wl = cmd_find_window(ctx, data->target, &s)) == NULL)
! 147: return (-1);
! 148: w = wl->window;
! 149:
! 150: env = server_fill_environ(s);
! 151:
! 152: cmd = data->cmd;
! 153: if (cmd == NULL)
! 154: cmd = options_get_string(&s->options, "default-command");
! 155: if (ctx->cmdclient == NULL || ctx->cmdclient->cwd == NULL)
! 156: cwd = options_get_string(&global_options, "default-path");
! 157: else
! 158: cwd = ctx->cmdclient->cwd;
! 159:
! 160: lines = -1;
! 161: if (data->lines != -1)
! 162: lines = data->lines;
! 163: else if (data->percentage != -1)
! 164: lines = (w->active->sy * data->percentage) / 100;
! 165:
! 166: hlimit = options_get_number(&s->options, "history-limit");
! 167: wp = window_add_pane(w, lines, cmd, cwd, env, hlimit, &cause);
! 168: if (wp == NULL) {
! 169: ctx->error(ctx, "create pane failed: %s", cause);
! 170: xfree(cause);
! 171: return (-1);
! 172: }
! 173: server_redraw_window(w);
! 174:
! 175: if (!data->flag_detached) {
! 176: window_set_active_pane(w, wp);
! 177: session_select(s, wl->idx);
! 178: server_redraw_session(s);
! 179: } else
! 180: server_status_session(s);
! 181: layout_refresh(w, 0);
! 182:
! 183: return (0);
! 184: }
! 185:
! 186: void
! 187: cmd_split_window_send(struct cmd *self, struct buffer *b)
! 188: {
! 189: struct cmd_split_window_data *data = self->data;
! 190:
! 191: buffer_write(b, data, sizeof *data);
! 192: cmd_send_string(b, data->target);
! 193: cmd_send_string(b, data->cmd);
! 194: }
! 195:
! 196: void
! 197: cmd_split_window_recv(struct cmd *self, struct buffer *b)
! 198: {
! 199: struct cmd_split_window_data *data;
! 200:
! 201: self->data = data = xmalloc(sizeof *data);
! 202: buffer_read(b, data, sizeof *data);
! 203: data->target = cmd_recv_string(b);
! 204: data->cmd = cmd_recv_string(b);
! 205: }
! 206:
! 207: void
! 208: cmd_split_window_free(struct cmd *self)
! 209: {
! 210: struct cmd_split_window_data *data = self->data;
! 211:
! 212: if (data->target != NULL)
! 213: xfree(data->target);
! 214: if (data->cmd != NULL)
! 215: xfree(data->cmd);
! 216: xfree(data);
! 217: }
! 218:
! 219: size_t
! 220: cmd_split_window_print(struct cmd *self, char *buf, size_t len)
! 221: {
! 222: struct cmd_split_window_data *data = self->data;
! 223: size_t off = 0;
! 224:
! 225: off += xsnprintf(buf, len, "%s", self->entry->name);
! 226: if (data == NULL)
! 227: return (off);
! 228: if (off < len && data->flag_detached)
! 229: off += xsnprintf(buf + off, len - off, " -d");
! 230: if (off < len && data->target != NULL)
! 231: off += cmd_prarg(buf + off, len - off, " -t ", data->target);
! 232: if (off < len && data->cmd != NULL)
! 233: off += cmd_prarg(buf + off, len - off, " ", data->cmd);
! 234: return (off);
! 235: }