Annotation of src/usr.bin/tmux/cmd-swap-pane.c, Revision 1.3
1.3 ! nicm 1: /* $OpenBSD: cmd-swap-pane.c,v 1.2 2009/06/03 07:51:24 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:
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]",
1.3 ! nicm 49: 0, 0,
1.1 nicm 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;
1.2 nicm 161: int flags;
1.1 nicm 162:
163: if (data == NULL)
164: return (0);
165:
166: if ((wl = cmd_find_window(ctx, data->target, NULL)) == NULL)
167: return (-1);
168: w = wl->window;
169:
170: if (data->src == -1)
171: src_wp = w->active;
172: else {
173: src_wp = window_pane_at_index(w, data->src);
174: if (src_wp == NULL) {
175: ctx->error(ctx, "no pane: %d", data->src);
176: return (-1);
177: }
178: }
179: if (data->dst == -1)
180: dst_wp = w->active;
181: else {
182: dst_wp = window_pane_at_index(w, data->dst);
183: if (dst_wp == NULL) {
184: ctx->error(ctx, "no pane: %d", data->dst);
185: return (-1);
186: }
187: }
188:
189: if (data->dst == -1 && data->flag_up) {
190: if ((dst_wp = TAILQ_PREV(src_wp, window_panes, entry)) == NULL)
191: dst_wp = TAILQ_LAST(&w->panes, window_panes);
192: }
193: if (data->dst == -1 && data->flag_down) {
194: if ((dst_wp = TAILQ_NEXT(src_wp, entry)) == NULL)
195: dst_wp = TAILQ_FIRST(&w->panes);
196: }
197:
198: if (src_wp == dst_wp)
199: return (0);
200:
201: tmp_wp = TAILQ_PREV(dst_wp, window_panes, entry);
202: TAILQ_REMOVE(&w->panes, dst_wp, entry);
203: TAILQ_REPLACE(&w->panes, src_wp, dst_wp, entry);
204: if (tmp_wp == src_wp)
205: tmp_wp = dst_wp;
206: if (tmp_wp == NULL)
207: TAILQ_INSERT_HEAD(&w->panes, src_wp, entry);
208: else
209: TAILQ_INSERT_AFTER(&w->panes, tmp_wp, src_wp, entry);
210:
211: xx = src_wp->xoff;
212: yy = src_wp->yoff;
1.2 nicm 213: flags = src_wp->flags;
1.1 nicm 214: src_wp->xoff = dst_wp->xoff;
215: src_wp->yoff = dst_wp->yoff;
1.2 nicm 216: src_wp->flags &= ~PANE_HIDDEN;
217: src_wp->flags |= dst_wp->flags & PANE_HIDDEN;
1.1 nicm 218: dst_wp->xoff = xx;
219: dst_wp->yoff = yy;
1.2 nicm 220: dst_wp->flags &= ~PANE_HIDDEN;
221: dst_wp->flags |= flags & PANE_HIDDEN;
1.1 nicm 222:
223: xx = src_wp->sx;
224: yy = src_wp->sy;
225: window_pane_resize(src_wp, dst_wp->sx, dst_wp->sy);
226: window_pane_resize(dst_wp, xx, yy);
227:
228: if (!data->flag_detached) {
1.2 nicm 229: tmp_wp = dst_wp;
230: if (tmp_wp->flags & PANE_HIDDEN)
231: tmp_wp = src_wp;
232: window_set_active_pane(w, tmp_wp);
1.1 nicm 233: layout_refresh(w, 0);
234: }
235:
236: return (0);
237: }
238:
239: void
240: cmd_swap_pane_send(struct cmd *self, struct buffer *b)
241: {
242: struct cmd_swap_pane_data *data = self->data;
243:
244: buffer_write(b, data, sizeof *data);
245: cmd_send_string(b, data->target);
246: }
247:
248: void
249: cmd_swap_pane_recv(struct cmd *self, struct buffer *b)
250: {
251: struct cmd_swap_pane_data *data;
252:
253: self->data = data = xmalloc(sizeof *data);
254: buffer_read(b, data, sizeof *data);
255: data->target = cmd_recv_string(b);
256: }
257:
258: void
259: cmd_swap_pane_free(struct cmd *self)
260: {
261: struct cmd_swap_pane_data *data = self->data;
262:
263: if (data->target != NULL)
264: xfree(data->target);
265: xfree(data);
266: }
267:
268: size_t
269: cmd_swap_pane_print(struct cmd *self, char *buf, size_t len)
270: {
271: struct cmd_swap_pane_data *data = self->data;
272: size_t off = 0;
273:
274: off += xsnprintf(buf, len, "%s", self->entry->name);
275: if (data == NULL)
276: return (off);
277: if (off < len &&
278: (data->flag_down || data->flag_up || data->flag_detached)) {
279: off += xsnprintf(buf + off, len - off, " -");
280: if (off < len && data->flag_detached)
281: off += xsnprintf(buf + off, len - off, "d");
282: if (off < len && data->flag_up)
283: off += xsnprintf(buf + off, len - off, "D");
284: if (off < len && data->flag_down)
285: off += xsnprintf(buf + off, len - off, "U");
286: }
287: if (off < len && data->target != NULL)
288: off += cmd_prarg(buf + off, len - off, " -t ", data->target);
289: if (off < len && data->src != -1)
290: off += xsnprintf(buf + off, len - off, " -p %d", data->src);
291: if (off < len && data->dst != -1)
292: off += xsnprintf(buf + off, len - off, " -q %d", data->dst);
293: return (off);
294: }