1/* $OpenBSD$ */
2
3/*
4 * Copyright (c) 2009 Nicholas Marriott <[email protected]>
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 <string.h>
23
24#include "tmux.h"
25
26/*
27 * Select pane.
28 */
29
30static enum cmd_retval cmd_select_pane_exec(struct cmd *, struct cmdq_item *);
31
32const struct cmd_entry cmd_select_pane_entry = {
33 .name = "select-pane",
34 .alias = "selectp",
35
36 .args = { "DdegLlMmP:RT:t:UZ", 0, 0 }, /* -P and -g deprecated */
37 .usage = "[-DdeLlMmRUZ] [-T title] " CMD_TARGET_PANE_USAGE,
38
39 .target = { 't', CMD_FIND_PANE, 0 },
40
41 .flags = 0,
42 .exec = cmd_select_pane_exec
43};
44
45const struct cmd_entry cmd_last_pane_entry = {
46 .name = "last-pane",
47 .alias = "lastp",
48
49 .args = { "det:Z", 0, 0 },
50 .usage = "[-deZ] " CMD_TARGET_WINDOW_USAGE,
51
52 .target = { 't', CMD_FIND_WINDOW, 0 },
53
54 .flags = 0,
55 .exec = cmd_select_pane_exec
56};
57
58static void
59cmd_select_pane_redraw(struct window *w)
60{
61 struct client *c;
62
63 /*
64 * Redraw entire window if it is bigger than the client (the
65 * offset may change), otherwise just draw borders.
66 */
67
68 TAILQ_FOREACH(c, &clients, entry) {
69 if (c->session == NULL || (c->flags & CLIENT_CONTROL))
70 continue;
71 if (c->session->curw->window == w && tty_window_bigger(&c->tty))
72 server_redraw_client(c);
73 else {
74 if (c->session->curw->window == w)
75 c->flags |= CLIENT_REDRAWBORDERS;
76 if (session_has(c->session, w))
77 c->flags |= CLIENT_REDRAWSTATUS;
78 }
79
80 }
81}
82
83static enum cmd_retval
84cmd_select_pane_exec(struct cmd *self, struct cmdq_item *item)
85{
86 struct args *args = self->args;
87 struct cmd_find_state *current = &item->shared->current;
88 struct client *c = cmd_find_client(item, NULL, 1);
89 struct winlink *wl = item->target.wl;
90 struct window *w = wl->window;
91 struct session *s = item->target.s;
92 struct window_pane *wp = item->target.wp, *lastwp, *markedwp;
93 char *pane_title;
94 const char *style;
95 struct style *sy;
96 struct options_entry *o;
97
98 if (self->entry == &cmd_last_pane_entry || args_has(args, 'l')) {
99 lastwp = w->last;
100 if (lastwp == NULL && window_count_panes(w) == 2) {
101 lastwp = TAILQ_PREV(w->active, window_panes, entry);
102 if (lastwp == NULL)
103 lastwp = TAILQ_NEXT(w->active, entry);
104 }
105 if (lastwp == NULL) {
106 cmdq_error(item, "no last pane");
107 return (CMD_RETURN_ERROR);
108 }
109 if (args_has(self->args, 'e'))
110 lastwp->flags &= ~PANE_INPUTOFF;
111 else if (args_has(self->args, 'd'))
112 lastwp->flags |= PANE_INPUTOFF;
113 else {
114 if (window_push_zoom(w, args_has(self->args, 'Z')))
115 server_redraw_window(w);
116 window_redraw_active_switch(w, lastwp);
117 if (window_set_active_pane(w, lastwp, 1)) {
118 cmd_find_from_winlink(current, wl, 0);
119 cmd_select_pane_redraw(w);
120 }
121 if (window_pop_zoom(w))
122 server_redraw_window(w);
123 }
124 return (CMD_RETURN_NORMAL);
125 }
126
127 if (args_has(args, 'm') || args_has(args, 'M')) {
128 if (args_has(args, 'm') && !window_pane_visible(wp))
129 return (CMD_RETURN_NORMAL);
130 lastwp = marked_pane.wp;
131
132 if (args_has(args, 'M') || server_is_marked(s, wl, wp))
133 server_clear_marked();
134 else
135 server_set_marked(s, wl, wp);
136 markedwp = marked_pane.wp;
137
138 if (lastwp != NULL) {
139 server_redraw_window_borders(lastwp->window);
140 server_status_window(lastwp->window);
141 }
142 if (markedwp != NULL) {
143 server_redraw_window_borders(markedwp->window);
144 server_status_window(markedwp->window);
145 }
146 return (CMD_RETURN_NORMAL);
147 }
148
149 if (args_has(self->args, 'P') || args_has(self->args, 'g')) {
150 if ((style = args_get(args, 'P')) != NULL) {
151 o = options_set_style(wp->options, "window-style", 0,
152 style);
153 if (o == NULL) {
154 cmdq_error(item, "bad style: %s", style);
155 return (CMD_RETURN_ERROR);
156 }
157 options_set_style(wp->options, "window-active-style", 0,
158 style);
159 wp->flags |= (PANE_REDRAW|PANE_STYLECHANGED);
160 }
161 if (args_has(self->args, 'g')) {
162 sy = options_get_style(wp->options, "window-style");
163 cmdq_print(item, "%s", style_tostring(sy));
164 }
165 return (CMD_RETURN_NORMAL);
166 }
167
168 if (args_has(self->args, 'L')) {
169 window_push_zoom(w, 1);
170 wp = window_pane_find_left(wp);
171 window_pop_zoom(w);
172 } else if (args_has(self->args, 'R')) {
173 window_push_zoom(w, 1);
174 wp = window_pane_find_right(wp);
175 window_pop_zoom(w);
176 } else if (args_has(self->args, 'U')) {
177 window_push_zoom(w, 1);
178 wp = window_pane_find_up(wp);
179 window_pop_zoom(w);
180 } else if (args_has(self->args, 'D')) {
181 window_push_zoom(w, 1);
182 wp = window_pane_find_down(wp);
183 window_pop_zoom(w);
184 }
185 if (wp == NULL)
186 return (CMD_RETURN_NORMAL);
187
188 if (args_has(self->args, 'e')) {
189 wp->flags &= ~PANE_INPUTOFF;
190 return (CMD_RETURN_NORMAL);
191 }
192 if (args_has(self->args, 'd')) {
193 wp->flags |= PANE_INPUTOFF;
194 return (CMD_RETURN_NORMAL);
195 }
196
197 if (args_has(self->args, 'T')) {
198 pane_title = format_single(item, args_get(self->args, 'T'),
199 c, s, wl, wp);
200 if (screen_set_title(&wp->base, pane_title))
201 server_status_window(wp->window);
202 free(pane_title);
203 return (CMD_RETURN_NORMAL);
204 }
205
206 if (wp == w->active)
207 return (CMD_RETURN_NORMAL);
208 if (window_push_zoom(w, args_has(self->args, 'Z')))
209 server_redraw_window(w);
210 window_redraw_active_switch(w, wp);
211 if (window_set_active_pane(w, wp, 1)) {
212 cmd_find_from_winlink_pane(current, wl, wp, 0);
213 cmdq_insert_hook(s, item, current, "after-select-pane");
214 cmd_select_pane_redraw(w);
215 }
216 if (window_pop_zoom(w))
217 server_redraw_window(w);
218
219 return (CMD_RETURN_NORMAL);
220}
221