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