xref: /netbsd-src/external/bsd/tmux/dist/cmd-display-panes.c (revision f8cf1a9151c7af1cb0bd8b09c13c66bca599c027)
15494e770Schristos /* $OpenBSD$ */
2698d5317Sjmmv 
3698d5317Sjmmv /*
4ed4e6cd4Schristos  * Copyright (c) 2009 Nicholas Marriott <nicholas.marriott@gmail.com>
5698d5317Sjmmv  *
6698d5317Sjmmv  * Permission to use, copy, modify, and distribute this software for any
7698d5317Sjmmv  * purpose with or without fee is hereby granted, provided that the above
8698d5317Sjmmv  * copyright notice and this permission notice appear in all copies.
9698d5317Sjmmv  *
10698d5317Sjmmv  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11698d5317Sjmmv  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12698d5317Sjmmv  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13698d5317Sjmmv  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14698d5317Sjmmv  * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
15698d5317Sjmmv  * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
16698d5317Sjmmv  * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17698d5317Sjmmv  */
18698d5317Sjmmv 
19698d5317Sjmmv #include <sys/types.h>
20698d5317Sjmmv 
214e179ddaSchristos #include <stdlib.h>
226483eba0Schristos #include <string.h>
234e179ddaSchristos 
24698d5317Sjmmv #include "tmux.h"
25698d5317Sjmmv 
26698d5317Sjmmv /*
27698d5317Sjmmv  * Display panes on a client.
28698d5317Sjmmv  */
29698d5317Sjmmv 
306db26757Swiz static enum args_parse_type	cmd_display_panes_args_parse(struct args *,
316db26757Swiz 				    u_int, char **);
324e179ddaSchristos static enum cmd_retval		cmd_display_panes_exec(struct cmd *,
334e179ddaSchristos 				    struct cmdq_item *);
344e179ddaSchristos 
35698d5317Sjmmv const struct cmd_entry cmd_display_panes_entry = {
36ed4e6cd4Schristos 	.name = "display-panes",
37ed4e6cd4Schristos 	.alias = "displayp",
38ed4e6cd4Schristos 
396db26757Swiz 	.args = { "bd:Nt:", 0, 1, cmd_display_panes_args_parse },
409fb66d81Schristos 	.usage = "[-bN] [-d duration] " CMD_TARGET_CLIENT_USAGE " [template]",
41ed4e6cd4Schristos 
429fb66d81Schristos 	.flags = CMD_AFTERHOOK|CMD_CLIENT_TFLAG,
43ed4e6cd4Schristos 	.exec = cmd_display_panes_exec
44698d5317Sjmmv };
45698d5317Sjmmv 
466483eba0Schristos struct cmd_display_panes_data {
476483eba0Schristos 	struct cmdq_item		*item;
486db26757Swiz 	struct args_command_state	*state;
496483eba0Schristos };
506483eba0Schristos 
516db26757Swiz static enum args_parse_type
526db26757Swiz cmd_display_panes_args_parse(__unused struct args *args, __unused u_int idx,
536db26757Swiz     __unused char **cause)
546db26757Swiz {
556db26757Swiz 	return (ARGS_PARSE_COMMANDS_OR_STRING);
566db26757Swiz }
576db26757Swiz 
586483eba0Schristos static void
596483eba0Schristos cmd_display_panes_draw_pane(struct screen_redraw_ctx *ctx,
606483eba0Schristos     struct window_pane *wp)
616483eba0Schristos {
626483eba0Schristos 	struct client		*c = ctx->c;
636483eba0Schristos 	struct tty		*tty = &c->tty;
646483eba0Schristos 	struct session		*s = c->session;
656483eba0Schristos 	struct options		*oo = s->options;
666483eba0Schristos 	struct window		*w = wp->window;
679fb66d81Schristos 	struct grid_cell	 fgc, bgc;
689fb66d81Schristos 	u_int			 pane, idx, px, py, i, j, xoff, yoff, sx, sy;
696483eba0Schristos 	int			 colour, active_colour;
709fb66d81Schristos 	char			 buf[16], lbuf[16], rbuf[16], *ptr;
719fb66d81Schristos 	size_t			 len, llen, rlen;
726483eba0Schristos 
736483eba0Schristos 	if (wp->xoff + wp->sx <= ctx->ox ||
746483eba0Schristos 	    wp->xoff >= ctx->ox + ctx->sx ||
756483eba0Schristos 	    wp->yoff + wp->sy <= ctx->oy ||
766483eba0Schristos 	    wp->yoff >= ctx->oy + ctx->sy)
776483eba0Schristos 		return;
786483eba0Schristos 
796483eba0Schristos 	if (wp->xoff >= ctx->ox && wp->xoff + wp->sx <= ctx->ox + ctx->sx) {
806483eba0Schristos 		/* All visible. */
816483eba0Schristos 		xoff = wp->xoff - ctx->ox;
826483eba0Schristos 		sx = wp->sx;
836483eba0Schristos 	} else if (wp->xoff < ctx->ox &&
846483eba0Schristos 	    wp->xoff + wp->sx > ctx->ox + ctx->sx) {
856483eba0Schristos 		/* Both left and right not visible. */
866483eba0Schristos 		xoff = 0;
876483eba0Schristos 		sx = ctx->sx;
886483eba0Schristos 	} else if (wp->xoff < ctx->ox) {
896483eba0Schristos 		/* Left not visible. */
906483eba0Schristos 		xoff = 0;
916483eba0Schristos 		sx = wp->sx - (ctx->ox - wp->xoff);
926483eba0Schristos 	} else {
936483eba0Schristos 		/* Right not visible. */
946483eba0Schristos 		xoff = wp->xoff - ctx->ox;
956483eba0Schristos 		sx = wp->sx - xoff;
966483eba0Schristos 	}
976483eba0Schristos 	if (wp->yoff >= ctx->oy && wp->yoff + wp->sy <= ctx->oy + ctx->sy) {
986483eba0Schristos 		/* All visible. */
996483eba0Schristos 		yoff = wp->yoff - ctx->oy;
1006483eba0Schristos 		sy = wp->sy;
1016483eba0Schristos 	} else if (wp->yoff < ctx->oy &&
1026483eba0Schristos 	    wp->yoff + wp->sy > ctx->oy + ctx->sy) {
1036483eba0Schristos 		/* Both top and bottom not visible. */
1046483eba0Schristos 		yoff = 0;
1056483eba0Schristos 		sy = ctx->sy;
1066483eba0Schristos 	} else if (wp->yoff < ctx->oy) {
1076483eba0Schristos 		/* Top not visible. */
1086483eba0Schristos 		yoff = 0;
1096483eba0Schristos 		sy = wp->sy - (ctx->oy - wp->yoff);
1106483eba0Schristos 	} else {
1116483eba0Schristos 		/* Bottom not visible. */
1126483eba0Schristos 		yoff = wp->yoff - ctx->oy;
1136483eba0Schristos 		sy = wp->sy - yoff;
1146483eba0Schristos 	}
1156483eba0Schristos 
1166483eba0Schristos 	if (ctx->statustop)
1176483eba0Schristos 		yoff += ctx->statuslines;
1186483eba0Schristos 	px = sx / 2;
1196483eba0Schristos 	py = sy / 2;
1206483eba0Schristos 
1219fb66d81Schristos 	if (window_pane_index(wp, &pane) != 0)
1226483eba0Schristos 		fatalx("index not found");
1239fb66d81Schristos 	len = xsnprintf(buf, sizeof buf, "%u", pane);
1246483eba0Schristos 
1256483eba0Schristos 	if (sx < len)
1266483eba0Schristos 		return;
1276483eba0Schristos 	colour = options_get_number(oo, "display-panes-colour");
1286483eba0Schristos 	active_colour = options_get_number(oo, "display-panes-active-colour");
1296483eba0Schristos 
1309fb66d81Schristos 	memcpy(&fgc, &grid_default_cell, sizeof fgc);
1319fb66d81Schristos 	memcpy(&bgc, &grid_default_cell, sizeof bgc);
1329fb66d81Schristos 	if (w->active == wp) {
1339fb66d81Schristos 		fgc.fg = active_colour;
1349fb66d81Schristos 		bgc.bg = active_colour;
1359fb66d81Schristos 	} else {
1369fb66d81Schristos 		fgc.fg = colour;
1379fb66d81Schristos 		bgc.bg = colour;
1389fb66d81Schristos 	}
1399fb66d81Schristos 
1409fb66d81Schristos 	rlen = xsnprintf(rbuf, sizeof rbuf, "%ux%u", wp->sx, wp->sy);
1419fb66d81Schristos 	if (pane > 9 && pane < 35)
1429fb66d81Schristos 		llen = xsnprintf(lbuf, sizeof lbuf, "%c", 'a' + (pane - 10));
1439fb66d81Schristos 	else
1449fb66d81Schristos 		llen = 0;
1459fb66d81Schristos 
1466483eba0Schristos 	if (sx < len * 6 || sy < 5) {
147c23f9150Swiz 		tty_attributes(tty, &fgc, &grid_default_cell, NULL, NULL);
1489fb66d81Schristos 		if (sx >= len + llen + 1) {
1499fb66d81Schristos 			len += llen + 1;
1506483eba0Schristos 			tty_cursor(tty, xoff + px - len / 2, yoff + py);
1519fb66d81Schristos 			tty_putn(tty, buf, len,	 len);
1529fb66d81Schristos 			tty_putn(tty, " ", 1, 1);
1539fb66d81Schristos 			tty_putn(tty, lbuf, llen, llen);
1549fb66d81Schristos 		} else {
1559fb66d81Schristos 			tty_cursor(tty, xoff + px - len / 2, yoff + py);
1569fb66d81Schristos 			tty_putn(tty, buf, len, len);
1579fb66d81Schristos 		}
1589fb66d81Schristos 		goto out;
1596483eba0Schristos 	}
1606483eba0Schristos 
1616483eba0Schristos 	px -= len * 3;
1626483eba0Schristos 	py -= 2;
1636483eba0Schristos 
164c23f9150Swiz 	tty_attributes(tty, &bgc, &grid_default_cell, NULL, NULL);
1656483eba0Schristos 	for (ptr = buf; *ptr != '\0'; ptr++) {
1666483eba0Schristos 		if (*ptr < '0' || *ptr > '9')
1676483eba0Schristos 			continue;
1686483eba0Schristos 		idx = *ptr - '0';
1696483eba0Schristos 
1706483eba0Schristos 		for (j = 0; j < 5; j++) {
1716483eba0Schristos 			for (i = px; i < px + 5; i++) {
1726483eba0Schristos 				tty_cursor(tty, xoff + i, yoff + py + j);
1736483eba0Schristos 				if (window_clock_table[idx][j][i - px])
1746483eba0Schristos 					tty_putc(tty, ' ');
1756483eba0Schristos 			}
1766483eba0Schristos 		}
1776483eba0Schristos 		px += 6;
1786483eba0Schristos 	}
1796483eba0Schristos 
1809fb66d81Schristos 	if (sy <= 6)
1819fb66d81Schristos 		goto out;
182c23f9150Swiz 	tty_attributes(tty, &fgc, &grid_default_cell, NULL, NULL);
1839fb66d81Schristos 	if (rlen != 0 && sx >= rlen) {
1849fb66d81Schristos 		tty_cursor(tty, xoff + sx - rlen, yoff);
1859fb66d81Schristos 		tty_putn(tty, rbuf, rlen, rlen);
1869fb66d81Schristos 	}
1879fb66d81Schristos 	if (llen != 0) {
1889fb66d81Schristos 		tty_cursor(tty, xoff + sx / 2 + len * 3 - llen - 1,
1899fb66d81Schristos 		    yoff + py + 5);
1909fb66d81Schristos 		tty_putn(tty, lbuf, llen, llen);
1919fb66d81Schristos 	}
1926483eba0Schristos 
1939fb66d81Schristos out:
1946483eba0Schristos 	tty_cursor(tty, 0, 0);
1956483eba0Schristos }
1966483eba0Schristos 
1976483eba0Schristos static void
1986db26757Swiz cmd_display_panes_draw(struct client *c, __unused void *data,
1996db26757Swiz     struct screen_redraw_ctx *ctx)
2006483eba0Schristos {
2016483eba0Schristos 	struct window		*w = c->session->curw->window;
2026483eba0Schristos 	struct window_pane	*wp;
2036483eba0Schristos 
2046483eba0Schristos 	log_debug("%s: %s @%u", __func__, c->name, w->id);
2056483eba0Schristos 
2066483eba0Schristos 	TAILQ_FOREACH(wp, &w->panes, entry) {
2076483eba0Schristos 		if (window_pane_visible(wp))
2086483eba0Schristos 			cmd_display_panes_draw_pane(ctx, wp);
2096483eba0Schristos 	}
2106483eba0Schristos }
2116483eba0Schristos 
2126483eba0Schristos static void
2136db26757Swiz cmd_display_panes_free(__unused struct client *c, void *data)
2146483eba0Schristos {
2156db26757Swiz 	struct cmd_display_panes_data	*cdata = data;
2166483eba0Schristos 
2176483eba0Schristos 	if (cdata->item != NULL)
2186483eba0Schristos 		cmdq_continue(cdata->item);
2196db26757Swiz 	args_make_commands_free(cdata->state);
2206483eba0Schristos 	free(cdata);
2216483eba0Schristos }
2226483eba0Schristos 
2236483eba0Schristos static int
2246db26757Swiz cmd_display_panes_key(struct client *c, void *data, struct key_event *event)
2256483eba0Schristos {
2266db26757Swiz 	struct cmd_display_panes_data	*cdata = data;
2276db26757Swiz 	char				*expanded, *error;
2286db26757Swiz 	struct cmdq_item		*item = cdata->item, *new_item;
2296db26757Swiz 	struct cmd_list			*cmdlist;
2306483eba0Schristos 	struct window			*w = c->session->curw->window;
2316483eba0Schristos 	struct window_pane		*wp;
2329fb66d81Schristos 	u_int				 index;
2339fb66d81Schristos 	key_code			 key;
2346483eba0Schristos 
2359fb66d81Schristos 	if (event->key >= '0' && event->key <= '9')
2369fb66d81Schristos 		index = event->key - '0';
2379fb66d81Schristos 	else if ((event->key & KEYC_MASK_MODIFIERS) == 0) {
2389fb66d81Schristos 		key = (event->key & KEYC_MASK_KEY);
2399fb66d81Schristos 		if (key >= 'a' && key <= 'z')
2409fb66d81Schristos 			index = 10 + (key - 'a');
2419fb66d81Schristos 		else
2429fb66d81Schristos 			return (-1);
2439fb66d81Schristos 	} else
2446483eba0Schristos 		return (-1);
2456483eba0Schristos 
2469fb66d81Schristos 	wp = window_pane_at_index(w, index);
2476483eba0Schristos 	if (wp == NULL)
2486483eba0Schristos 		return (1);
249*f8cf1a91Swiz 	window_unzoom(w, 1);
2506483eba0Schristos 
2516483eba0Schristos 	xasprintf(&expanded, "%%%u", wp->id);
2526483eba0Schristos 
2536db26757Swiz 	cmdlist = args_make_commands(cdata->state, 1, &expanded, &error);
2546db26757Swiz 	if (cmdlist == NULL) {
2559fb66d81Schristos 		cmdq_append(c, cmdq_get_error(error));
2569fb66d81Schristos 		free(error);
2576db26757Swiz 	} else if (item == NULL) {
2586db26757Swiz 		new_item = cmdq_get_command(cmdlist, NULL);
2596db26757Swiz 		cmdq_append(c, new_item);
2606db26757Swiz 	} else {
2616db26757Swiz 		new_item = cmdq_get_command(cmdlist, cmdq_get_state(item));
2626db26757Swiz 		cmdq_insert_after(item, new_item);
2636483eba0Schristos 	}
2646483eba0Schristos 
2656483eba0Schristos 	free(expanded);
2666483eba0Schristos 	return (1);
2676483eba0Schristos }
2686483eba0Schristos 
2694e179ddaSchristos static enum cmd_retval
2704e179ddaSchristos cmd_display_panes_exec(struct cmd *self, struct cmdq_item *item)
271698d5317Sjmmv {
2729fb66d81Schristos 	struct args			*args = cmd_get_args(self);
2739fb66d81Schristos 	struct client			*tc = cmdq_get_target_client(item);
2749fb66d81Schristos 	struct session			*s = tc->session;
275c9ad075bSchristos 	u_int				 delay;
276c9ad075bSchristos 	char				*cause;
2776483eba0Schristos 	struct cmd_display_panes_data	*cdata;
2786db26757Swiz 	int				 wait = !args_has(args, 'b');
279c9ad075bSchristos 
2809fb66d81Schristos 	if (tc->overlay_draw != NULL)
2814e179ddaSchristos 		return (CMD_RETURN_NORMAL);
2824e179ddaSchristos 
283c9ad075bSchristos 	if (args_has(args, 'd')) {
284c9ad075bSchristos 		delay = args_strtonum(args, 'd', 0, UINT_MAX, &cause);
285c9ad075bSchristos 		if (cause != NULL) {
286c9ad075bSchristos 			cmdq_error(item, "delay %s", cause);
287c9ad075bSchristos 			free(cause);
288c9ad075bSchristos 			return (CMD_RETURN_ERROR);
289c9ad075bSchristos 		}
290c9ad075bSchristos 	} else
291c9ad075bSchristos 		delay = options_get_number(s->options, "display-panes-time");
2926483eba0Schristos 
2936db26757Swiz 	cdata = xcalloc(1, sizeof *cdata);
2946db26757Swiz 	if (wait)
2956483eba0Schristos 		cdata->item = item;
2966db26757Swiz 	cdata->state = args_make_commands_prepare(self, item, 0,
2976db26757Swiz 	    "select-pane -t \"%%%\"", wait, 0);
2986483eba0Schristos 
2999fb66d81Schristos 	if (args_has(args, 'N')) {
3009fb66d81Schristos 		server_client_set_overlay(tc, delay, NULL, NULL,
3016db26757Swiz 		    cmd_display_panes_draw, NULL, cmd_display_panes_free, NULL,
3029fb66d81Schristos 		    cdata);
3039fb66d81Schristos 	} else {
3049fb66d81Schristos 		server_client_set_overlay(tc, delay, NULL, NULL,
3059fb66d81Schristos 		    cmd_display_panes_draw, cmd_display_panes_key,
3066db26757Swiz 		    cmd_display_panes_free, NULL, cdata);
3079fb66d81Schristos 	}
308698d5317Sjmmv 
3096db26757Swiz 	if (!wait)
310ef36e747Schristos 		return (CMD_RETURN_NORMAL);
3118f3b9483Schristos 	return (CMD_RETURN_WAIT);
312698d5317Sjmmv }
313