Annotation of src/usr.bin/tmux/cmd-swap-pane.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:
! 23: #include "tmux.h"
! 24:
! 25: /*
! 26: * Swap two panes.
! 27: */
! 28:
! 29: int cmd_swap_pane_parse(struct cmd *, int, char **, char **);
! 30: int cmd_swap_pane_exec(struct cmd *, struct cmd_ctx *);
! 31: void cmd_swap_pane_send(struct cmd *, struct buffer *);
! 32: void cmd_swap_pane_recv(struct cmd *, struct buffer *);
! 33: void cmd_swap_pane_free(struct cmd *);
! 34: void cmd_swap_pane_init(struct cmd *, int);
! 35: size_t cmd_swap_pane_print(struct cmd *, char *, size_t);
! 36:
! 37: struct cmd_swap_pane_data {
! 38: char *target;
! 39: int src;
! 40: int dst;
! 41: int flag_detached;
! 42: int flag_up;
! 43: int flag_down;
! 44: };
! 45:
! 46: const struct cmd_entry cmd_swap_pane_entry = {
! 47: "swap-pane", "swapp",
! 48: "[-dDU] [-t target-window] [-p src-index] [-q dst-index]",
! 49: 0,
! 50: cmd_swap_pane_init,
! 51: cmd_swap_pane_parse,
! 52: cmd_swap_pane_exec,
! 53: cmd_swap_pane_send,
! 54: cmd_swap_pane_recv,
! 55: cmd_swap_pane_free,
! 56: cmd_swap_pane_print
! 57: };
! 58:
! 59: void
! 60: cmd_swap_pane_init(struct cmd *self, int key)
! 61: {
! 62: struct cmd_swap_pane_data *data;
! 63:
! 64: self->data = data = xmalloc(sizeof *data);
! 65: data->target = NULL;
! 66: data->src = -1;
! 67: data->dst = -1;
! 68: data->flag_detached = 0;
! 69: data->flag_up = 0;
! 70: data->flag_down = 0;
! 71:
! 72: switch (key) {
! 73: case '{':
! 74: data->flag_up = 1;
! 75: break;
! 76: case '}':
! 77: data->flag_down = 1;
! 78: break;
! 79: }
! 80: }
! 81:
! 82: int
! 83: cmd_swap_pane_parse(struct cmd *self, int argc, char **argv, char **cause)
! 84: {
! 85: struct cmd_swap_pane_data *data;
! 86: int opt, n;
! 87: const char *errstr;
! 88:
! 89: self->entry->init(self, 0);
! 90: data = self->data;
! 91:
! 92: while ((opt = getopt(argc, argv, "dDt:p:q:U")) != -1) {
! 93: switch (opt) {
! 94: case 'd':
! 95: data->flag_detached = 1;
! 96: break;
! 97: case 'D':
! 98: data->flag_up = 0;
! 99: data->flag_down = 1;
! 100: data->dst = -1;
! 101: break;
! 102: case 't':
! 103: if (data->target == NULL)
! 104: data->target = xstrdup(optarg);
! 105: break;
! 106: case 'p':
! 107: if (data->src == -1) {
! 108: n = strtonum(optarg, 0, INT_MAX, &errstr);
! 109: if (errstr != NULL) {
! 110: xasprintf(cause, "src %s", errstr);
! 111: goto error;
! 112: }
! 113: data->src = n;
! 114: }
! 115: break;
! 116: case 'q':
! 117: if (data->dst == -1) {
! 118: n = strtonum(optarg, 0, INT_MAX, &errstr);
! 119: if (errstr != NULL) {
! 120: xasprintf(cause, "dst %s", errstr);
! 121: goto error;
! 122: }
! 123: data->dst = n;
! 124: }
! 125: data->flag_up = 0;
! 126: data->flag_down = 0;
! 127: break;
! 128: case 'U':
! 129: data->flag_up = 1;
! 130: data->flag_down = 0;
! 131: data->dst = -1;
! 132: break;
! 133:
! 134: default:
! 135: goto usage;
! 136: }
! 137: }
! 138: argc -= optind;
! 139: argv += optind;
! 140: if (argc != 0)
! 141: goto usage;
! 142:
! 143: return (0);
! 144:
! 145: usage:
! 146: xasprintf(cause, "usage: %s %s", self->entry->name, self->entry->usage);
! 147:
! 148: error:
! 149: self->entry->free(self);
! 150: return (-1);
! 151: }
! 152:
! 153: int
! 154: cmd_swap_pane_exec(struct cmd *self, struct cmd_ctx *ctx)
! 155: {
! 156: struct cmd_swap_pane_data *data = self->data;
! 157: struct winlink *wl;
! 158: struct window *w;
! 159: struct window_pane *tmp_wp, *src_wp, *dst_wp;
! 160: u_int xx, yy;
! 161:
! 162: if (data == NULL)
! 163: return (0);
! 164:
! 165: if ((wl = cmd_find_window(ctx, data->target, NULL)) == NULL)
! 166: return (-1);
! 167: w = wl->window;
! 168:
! 169: if (data->src == -1)
! 170: src_wp = w->active;
! 171: else {
! 172: src_wp = window_pane_at_index(w, data->src);
! 173: if (src_wp == NULL) {
! 174: ctx->error(ctx, "no pane: %d", data->src);
! 175: return (-1);
! 176: }
! 177: }
! 178: if (data->dst == -1)
! 179: dst_wp = w->active;
! 180: else {
! 181: dst_wp = window_pane_at_index(w, data->dst);
! 182: if (dst_wp == NULL) {
! 183: ctx->error(ctx, "no pane: %d", data->dst);
! 184: return (-1);
! 185: }
! 186: }
! 187:
! 188: if (data->dst == -1 && data->flag_up) {
! 189: if ((dst_wp = TAILQ_PREV(src_wp, window_panes, entry)) == NULL)
! 190: dst_wp = TAILQ_LAST(&w->panes, window_panes);
! 191: }
! 192: if (data->dst == -1 && data->flag_down) {
! 193: if ((dst_wp = TAILQ_NEXT(src_wp, entry)) == NULL)
! 194: dst_wp = TAILQ_FIRST(&w->panes);
! 195: }
! 196:
! 197: if (src_wp == dst_wp)
! 198: return (0);
! 199:
! 200: tmp_wp = TAILQ_PREV(dst_wp, window_panes, entry);
! 201: TAILQ_REMOVE(&w->panes, dst_wp, entry);
! 202: TAILQ_REPLACE(&w->panes, src_wp, dst_wp, entry);
! 203: if (tmp_wp == src_wp)
! 204: tmp_wp = dst_wp;
! 205: if (tmp_wp == NULL)
! 206: TAILQ_INSERT_HEAD(&w->panes, src_wp, entry);
! 207: else
! 208: TAILQ_INSERT_AFTER(&w->panes, tmp_wp, src_wp, entry);
! 209:
! 210: xx = src_wp->xoff;
! 211: yy = src_wp->yoff;
! 212: src_wp->xoff = dst_wp->xoff;
! 213: src_wp->yoff = dst_wp->yoff;
! 214: dst_wp->xoff = xx;
! 215: dst_wp->yoff = yy;
! 216:
! 217: xx = src_wp->sx;
! 218: yy = src_wp->sy;
! 219: window_pane_resize(src_wp, dst_wp->sx, dst_wp->sy);
! 220: window_pane_resize(dst_wp, xx, yy);
! 221:
! 222: if (!data->flag_detached) {
! 223: window_set_active_pane(w, dst_wp);
! 224: layout_refresh(w, 0);
! 225: }
! 226:
! 227: return (0);
! 228: }
! 229:
! 230: void
! 231: cmd_swap_pane_send(struct cmd *self, struct buffer *b)
! 232: {
! 233: struct cmd_swap_pane_data *data = self->data;
! 234:
! 235: buffer_write(b, data, sizeof *data);
! 236: cmd_send_string(b, data->target);
! 237: }
! 238:
! 239: void
! 240: cmd_swap_pane_recv(struct cmd *self, struct buffer *b)
! 241: {
! 242: struct cmd_swap_pane_data *data;
! 243:
! 244: self->data = data = xmalloc(sizeof *data);
! 245: buffer_read(b, data, sizeof *data);
! 246: data->target = cmd_recv_string(b);
! 247: }
! 248:
! 249: void
! 250: cmd_swap_pane_free(struct cmd *self)
! 251: {
! 252: struct cmd_swap_pane_data *data = self->data;
! 253:
! 254: if (data->target != NULL)
! 255: xfree(data->target);
! 256: xfree(data);
! 257: }
! 258:
! 259: size_t
! 260: cmd_swap_pane_print(struct cmd *self, char *buf, size_t len)
! 261: {
! 262: struct cmd_swap_pane_data *data = self->data;
! 263: size_t off = 0;
! 264:
! 265: off += xsnprintf(buf, len, "%s", self->entry->name);
! 266: if (data == NULL)
! 267: return (off);
! 268: if (off < len &&
! 269: (data->flag_down || data->flag_up || data->flag_detached)) {
! 270: off += xsnprintf(buf + off, len - off, " -");
! 271: if (off < len && data->flag_detached)
! 272: off += xsnprintf(buf + off, len - off, "d");
! 273: if (off < len && data->flag_up)
! 274: off += xsnprintf(buf + off, len - off, "D");
! 275: if (off < len && data->flag_down)
! 276: off += xsnprintf(buf + off, len - off, "U");
! 277: }
! 278: if (off < len && data->target != NULL)
! 279: off += cmd_prarg(buf + off, len - off, " -t ", data->target);
! 280: if (off < len && data->src != -1)
! 281: off += xsnprintf(buf + off, len - off, " -p %d", data->src);
! 282: if (off < len && data->dst != -1)
! 283: off += xsnprintf(buf + off, len - off, " -q %d", data->dst);
! 284: return (off);
! 285: }