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