Annotation of src/usr.bin/tmux/cmd-swap-pane.c, Revision 1.4
1.4 ! nicm 1: /* $OpenBSD: cmd-swap-pane.c,v 1.3 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:
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;
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) {
1.2 nicm 223: tmp_wp = dst_wp;
1.4 ! nicm 224: if (!window_pane_visible(tmp_wp))
1.2 nicm 225: tmp_wp = src_wp;
226: window_set_active_pane(w, tmp_wp);
1.1 nicm 227: layout_refresh(w, 0);
228: }
229:
230: return (0);
231: }
232:
233: void
234: cmd_swap_pane_send(struct cmd *self, struct buffer *b)
235: {
236: struct cmd_swap_pane_data *data = self->data;
237:
238: buffer_write(b, data, sizeof *data);
239: cmd_send_string(b, data->target);
240: }
241:
242: void
243: cmd_swap_pane_recv(struct cmd *self, struct buffer *b)
244: {
245: struct cmd_swap_pane_data *data;
246:
247: self->data = data = xmalloc(sizeof *data);
248: buffer_read(b, data, sizeof *data);
249: data->target = cmd_recv_string(b);
250: }
251:
252: void
253: cmd_swap_pane_free(struct cmd *self)
254: {
255: struct cmd_swap_pane_data *data = self->data;
256:
257: if (data->target != NULL)
258: xfree(data->target);
259: xfree(data);
260: }
261:
262: size_t
263: cmd_swap_pane_print(struct cmd *self, char *buf, size_t len)
264: {
265: struct cmd_swap_pane_data *data = self->data;
266: size_t off = 0;
267:
268: off += xsnprintf(buf, len, "%s", self->entry->name);
269: if (data == NULL)
270: return (off);
271: if (off < len &&
272: (data->flag_down || data->flag_up || data->flag_detached)) {
273: off += xsnprintf(buf + off, len - off, " -");
274: if (off < len && data->flag_detached)
275: off += xsnprintf(buf + off, len - off, "d");
276: if (off < len && data->flag_up)
277: off += xsnprintf(buf + off, len - off, "D");
278: if (off < len && data->flag_down)
279: off += xsnprintf(buf + off, len - off, "U");
280: }
281: if (off < len && data->target != NULL)
282: off += cmd_prarg(buf + off, len - off, " -t ", data->target);
283: if (off < len && data->src != -1)
284: off += xsnprintf(buf + off, len - off, " -p %d", data->src);
285: if (off < len && data->dst != -1)
286: off += xsnprintf(buf + off, len - off, " -q %d", data->dst);
287: return (off);
288: }