4 * Copyright (c) 2009 Nicholas Marriott <nicholas.marriott@gmail.com>
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.
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.
19 #include <sys/types.h>
27 * Display panes on a client.
30 static enum args_parse_type
cmd_display_panes_args_parse(struct args
*,
32 static enum cmd_retval
cmd_display_panes_exec(struct cmd
*,
35 const struct cmd_entry cmd_display_panes_entry
= {
36 .name
= "display-panes",
39 .args
= { "bd:Nt:", 0, 1, cmd_display_panes_args_parse
},
40 .usage
= "[-bN] [-d duration] " CMD_TARGET_CLIENT_USAGE
" [template]",
42 .flags
= CMD_AFTERHOOK
|CMD_CLIENT_TFLAG
,
43 .exec
= cmd_display_panes_exec
46 struct cmd_display_panes_data
{
47 struct cmdq_item
*item
;
48 struct args_command_state
*state
;
51 static enum args_parse_type
52 cmd_display_panes_args_parse(__unused
struct args
*args
, __unused u_int idx
,
53 __unused
char **cause
)
55 return (ARGS_PARSE_COMMANDS_OR_STRING
);
59 cmd_display_panes_draw_pane(struct screen_redraw_ctx
*ctx
,
60 struct window_pane
*wp
)
62 struct client
*c
= ctx
->c
;
63 struct tty
*tty
= &c
->tty
;
64 struct session
*s
= c
->session
;
65 struct options
*oo
= s
->options
;
66 struct window
*w
= wp
->window
;
67 struct grid_cell fgc
, bgc
;
68 u_int pane
, idx
, px
, py
, i
, j
, xoff
, yoff
, sx
, sy
;
69 int colour
, active_colour
;
70 char buf
[16], lbuf
[16], rbuf
[16], *ptr
;
71 size_t len
, llen
, rlen
;
73 if (wp
->xoff
+ wp
->sx
<= ctx
->ox
||
74 wp
->xoff
>= ctx
->ox
+ ctx
->sx
||
75 wp
->yoff
+ wp
->sy
<= ctx
->oy
||
76 wp
->yoff
>= ctx
->oy
+ ctx
->sy
)
79 if (wp
->xoff
>= ctx
->ox
&& wp
->xoff
+ wp
->sx
<= ctx
->ox
+ ctx
->sx
) {
81 xoff
= wp
->xoff
- ctx
->ox
;
83 } else if (wp
->xoff
< ctx
->ox
&&
84 wp
->xoff
+ wp
->sx
> ctx
->ox
+ ctx
->sx
) {
85 /* Both left and right not visible. */
88 } else if (wp
->xoff
< ctx
->ox
) {
89 /* Left not visible. */
91 sx
= wp
->sx
- (ctx
->ox
- wp
->xoff
);
93 /* Right not visible. */
94 xoff
= wp
->xoff
- ctx
->ox
;
97 if (wp
->yoff
>= ctx
->oy
&& wp
->yoff
+ wp
->sy
<= ctx
->oy
+ ctx
->sy
) {
99 yoff
= wp
->yoff
- ctx
->oy
;
101 } else if (wp
->yoff
< ctx
->oy
&&
102 wp
->yoff
+ wp
->sy
> ctx
->oy
+ ctx
->sy
) {
103 /* Both top and bottom not visible. */
106 } else if (wp
->yoff
< ctx
->oy
) {
107 /* Top not visible. */
109 sy
= wp
->sy
- (ctx
->oy
- wp
->yoff
);
111 /* Bottom not visible. */
112 yoff
= wp
->yoff
- ctx
->oy
;
117 yoff
+= ctx
->statuslines
;
121 if (window_pane_index(wp
, &pane
) != 0)
122 fatalx("index not found");
123 len
= xsnprintf(buf
, sizeof buf
, "%u", pane
);
127 colour
= options_get_number(oo
, "display-panes-colour");
128 active_colour
= options_get_number(oo
, "display-panes-active-colour");
130 memcpy(&fgc
, &grid_default_cell
, sizeof fgc
);
131 memcpy(&bgc
, &grid_default_cell
, sizeof bgc
);
132 if (w
->active
== wp
) {
133 fgc
.fg
= active_colour
;
134 bgc
.bg
= active_colour
;
140 rlen
= xsnprintf(rbuf
, sizeof rbuf
, "%ux%u", wp
->sx
, wp
->sy
);
141 if (pane
> 9 && pane
< 35)
142 llen
= xsnprintf(lbuf
, sizeof lbuf
, "%c", 'a' + (pane
- 10));
146 if (sx
< len
* 6 || sy
< 5) {
147 tty_attributes(tty
, &fgc
, &grid_default_cell
, NULL
, NULL
);
148 if (sx
>= len
+ llen
+ 1) {
150 tty_cursor(tty
, xoff
+ px
- len
/ 2, yoff
+ py
);
151 tty_putn(tty
, buf
, len
, len
);
152 tty_putn(tty
, " ", 1, 1);
153 tty_putn(tty
, lbuf
, llen
, llen
);
155 tty_cursor(tty
, xoff
+ px
- len
/ 2, yoff
+ py
);
156 tty_putn(tty
, buf
, len
, len
);
164 tty_attributes(tty
, &bgc
, &grid_default_cell
, NULL
, NULL
);
165 for (ptr
= buf
; *ptr
!= '\0'; ptr
++) {
166 if (*ptr
< '0' || *ptr
> '9')
170 for (j
= 0; j
< 5; j
++) {
171 for (i
= px
; i
< px
+ 5; i
++) {
172 tty_cursor(tty
, xoff
+ i
, yoff
+ py
+ j
);
173 if (window_clock_table
[idx
][j
][i
- px
])
182 tty_attributes(tty
, &fgc
, &grid_default_cell
, NULL
, NULL
);
183 if (rlen
!= 0 && sx
>= rlen
) {
184 tty_cursor(tty
, xoff
+ sx
- rlen
, yoff
);
185 tty_putn(tty
, rbuf
, rlen
, rlen
);
188 tty_cursor(tty
, xoff
+ sx
/ 2 + len
* 3 - llen
- 1,
190 tty_putn(tty
, lbuf
, llen
, llen
);
194 tty_cursor(tty
, 0, 0);
198 cmd_display_panes_draw(struct client
*c
, __unused
void *data
,
199 struct screen_redraw_ctx
*ctx
)
201 struct window
*w
= c
->session
->curw
->window
;
202 struct window_pane
*wp
;
204 log_debug("%s: %s @%u", __func__
, c
->name
, w
->id
);
206 TAILQ_FOREACH(wp
, &w
->panes
, entry
) {
207 if (window_pane_visible(wp
))
208 cmd_display_panes_draw_pane(ctx
, wp
);
213 cmd_display_panes_free(__unused
struct client
*c
, void *data
)
215 struct cmd_display_panes_data
*cdata
= data
;
217 if (cdata
->item
!= NULL
)
218 cmdq_continue(cdata
->item
);
219 args_make_commands_free(cdata
->state
);
224 cmd_display_panes_key(struct client
*c
, void *data
, struct key_event
*event
)
226 struct cmd_display_panes_data
*cdata
= data
;
227 char *expanded
, *error
;
228 struct cmdq_item
*item
= cdata
->item
, *new_item
;
229 struct cmd_list
*cmdlist
;
230 struct window
*w
= c
->session
->curw
->window
;
231 struct window_pane
*wp
;
235 if (event
->key
>= '0' && event
->key
<= '9')
236 index
= event
->key
- '0';
237 else if ((event
->key
& KEYC_MASK_MODIFIERS
) == 0) {
238 key
= (event
->key
& KEYC_MASK_KEY
);
239 if (key
>= 'a' && key
<= 'z')
240 index
= 10 + (key
- 'a');
246 wp
= window_pane_at_index(w
, index
);
251 xasprintf(&expanded
, "%%%u", wp
->id
);
253 cmdlist
= args_make_commands(cdata
->state
, 1, &expanded
, &error
);
254 if (cmdlist
== NULL
) {
255 cmdq_append(c
, cmdq_get_error(error
));
257 } else if (item
== NULL
) {
258 new_item
= cmdq_get_command(cmdlist
, NULL
);
259 cmdq_append(c
, new_item
);
261 new_item
= cmdq_get_command(cmdlist
, cmdq_get_state(item
));
262 cmdq_insert_after(item
, new_item
);
269 static enum cmd_retval
270 cmd_display_panes_exec(struct cmd
*self
, struct cmdq_item
*item
)
272 struct args
*args
= cmd_get_args(self
);
273 struct client
*tc
= cmdq_get_target_client(item
);
274 struct session
*s
= tc
->session
;
277 struct cmd_display_panes_data
*cdata
;
278 int wait
= !args_has(args
, 'b');
280 if (tc
->overlay_draw
!= NULL
)
281 return (CMD_RETURN_NORMAL
);
283 if (args_has(args
, 'd')) {
284 delay
= args_strtonum(args
, 'd', 0, UINT_MAX
, &cause
);
286 cmdq_error(item
, "delay %s", cause
);
288 return (CMD_RETURN_ERROR
);
291 delay
= options_get_number(s
->options
, "display-panes-time");
293 cdata
= xcalloc(1, sizeof *cdata
);
296 cdata
->state
= args_make_commands_prepare(self
, item
, 0,
297 "select-pane -t \"%%%\"", wait
, 0);
299 if (args_has(args
, 'N')) {
300 server_client_set_overlay(tc
, delay
, NULL
, NULL
,
301 cmd_display_panes_draw
, NULL
, cmd_display_panes_free
, NULL
,
304 server_client_set_overlay(tc
, delay
, NULL
, NULL
,
305 cmd_display_panes_draw
, cmd_display_panes_key
,
306 cmd_display_panes_free
, NULL
, cdata
);
310 return (CMD_RETURN_NORMAL
);
311 return (CMD_RETURN_WAIT
);