cmd-display-panes.c revision 1.1.1.12
1/* $OpenBSD$ */ 2 3/* 4 * Copyright (c) 2009 Nicholas Marriott <nicholas.marriott@gmail.com> 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 * Display panes on a client. 28 */ 29 30static enum cmd_retval cmd_display_panes_exec(struct cmd *, 31 struct cmdq_item *); 32 33const struct cmd_entry cmd_display_panes_entry = { 34 .name = "display-panes", 35 .alias = "displayp", 36 37 .args = { "bd:Nt:", 0, 1 }, 38 .usage = "[-bN] [-d duration] " CMD_TARGET_CLIENT_USAGE " [template]", 39 40 .flags = CMD_AFTERHOOK|CMD_CLIENT_TFLAG, 41 .exec = cmd_display_panes_exec 42}; 43 44struct cmd_display_panes_data { 45 struct cmdq_item *item; 46 char *command; 47}; 48 49static void 50cmd_display_panes_draw_pane(struct screen_redraw_ctx *ctx, 51 struct window_pane *wp) 52{ 53 struct client *c = ctx->c; 54 struct tty *tty = &c->tty; 55 struct session *s = c->session; 56 struct options *oo = s->options; 57 struct window *w = wp->window; 58 struct grid_cell fgc, bgc; 59 u_int pane, idx, px, py, i, j, xoff, yoff, sx, sy; 60 int colour, active_colour; 61 char buf[16], lbuf[16], rbuf[16], *ptr; 62 size_t len, llen, rlen; 63 64 if (wp->xoff + wp->sx <= ctx->ox || 65 wp->xoff >= ctx->ox + ctx->sx || 66 wp->yoff + wp->sy <= ctx->oy || 67 wp->yoff >= ctx->oy + ctx->sy) 68 return; 69 70 if (wp->xoff >= ctx->ox && wp->xoff + wp->sx <= ctx->ox + ctx->sx) { 71 /* All visible. */ 72 xoff = wp->xoff - ctx->ox; 73 sx = wp->sx; 74 } else if (wp->xoff < ctx->ox && 75 wp->xoff + wp->sx > ctx->ox + ctx->sx) { 76 /* Both left and right not visible. */ 77 xoff = 0; 78 sx = ctx->sx; 79 } else if (wp->xoff < ctx->ox) { 80 /* Left not visible. */ 81 xoff = 0; 82 sx = wp->sx - (ctx->ox - wp->xoff); 83 } else { 84 /* Right not visible. */ 85 xoff = wp->xoff - ctx->ox; 86 sx = wp->sx - xoff; 87 } 88 if (wp->yoff >= ctx->oy && wp->yoff + wp->sy <= ctx->oy + ctx->sy) { 89 /* All visible. */ 90 yoff = wp->yoff - ctx->oy; 91 sy = wp->sy; 92 } else if (wp->yoff < ctx->oy && 93 wp->yoff + wp->sy > ctx->oy + ctx->sy) { 94 /* Both top and bottom not visible. */ 95 yoff = 0; 96 sy = ctx->sy; 97 } else if (wp->yoff < ctx->oy) { 98 /* Top not visible. */ 99 yoff = 0; 100 sy = wp->sy - (ctx->oy - wp->yoff); 101 } else { 102 /* Bottom not visible. */ 103 yoff = wp->yoff - ctx->oy; 104 sy = wp->sy - yoff; 105 } 106 107 if (ctx->statustop) 108 yoff += ctx->statuslines; 109 px = sx / 2; 110 py = sy / 2; 111 112 if (window_pane_index(wp, &pane) != 0) 113 fatalx("index not found"); 114 len = xsnprintf(buf, sizeof buf, "%u", pane); 115 116 if (sx < len) 117 return; 118 colour = options_get_number(oo, "display-panes-colour"); 119 active_colour = options_get_number(oo, "display-panes-active-colour"); 120 121 memcpy(&fgc, &grid_default_cell, sizeof fgc); 122 memcpy(&bgc, &grid_default_cell, sizeof bgc); 123 if (w->active == wp) { 124 fgc.fg = active_colour; 125 bgc.bg = active_colour; 126 } else { 127 fgc.fg = colour; 128 bgc.bg = colour; 129 } 130 131 rlen = xsnprintf(rbuf, sizeof rbuf, "%ux%u", wp->sx, wp->sy); 132 if (pane > 9 && pane < 35) 133 llen = xsnprintf(lbuf, sizeof lbuf, "%c", 'a' + (pane - 10)); 134 else 135 llen = 0; 136 137 if (sx < len * 6 || sy < 5) { 138 tty_attributes(tty, &fgc, &grid_default_cell, NULL); 139 if (sx >= len + llen + 1) { 140 len += llen + 1; 141 tty_cursor(tty, xoff + px - len / 2, yoff + py); 142 tty_putn(tty, buf, len, len); 143 tty_putn(tty, " ", 1, 1); 144 tty_putn(tty, lbuf, llen, llen); 145 } else { 146 tty_cursor(tty, xoff + px - len / 2, yoff + py); 147 tty_putn(tty, buf, len, len); 148 } 149 goto out; 150 } 151 152 px -= len * 3; 153 py -= 2; 154 155 tty_attributes(tty, &bgc, &grid_default_cell, NULL); 156 for (ptr = buf; *ptr != '\0'; ptr++) { 157 if (*ptr < '0' || *ptr > '9') 158 continue; 159 idx = *ptr - '0'; 160 161 for (j = 0; j < 5; j++) { 162 for (i = px; i < px + 5; i++) { 163 tty_cursor(tty, xoff + i, yoff + py + j); 164 if (window_clock_table[idx][j][i - px]) 165 tty_putc(tty, ' '); 166 } 167 } 168 px += 6; 169 } 170 171 if (sy <= 6) 172 goto out; 173 tty_attributes(tty, &fgc, &grid_default_cell, NULL); 174 if (rlen != 0 && sx >= rlen) { 175 tty_cursor(tty, xoff + sx - rlen, yoff); 176 tty_putn(tty, rbuf, rlen, rlen); 177 } 178 if (llen != 0) { 179 tty_cursor(tty, xoff + sx / 2 + len * 3 - llen - 1, 180 yoff + py + 5); 181 tty_putn(tty, lbuf, llen, llen); 182 } 183 184out: 185 tty_cursor(tty, 0, 0); 186} 187 188static void 189cmd_display_panes_draw(struct client *c, struct screen_redraw_ctx *ctx) 190{ 191 struct window *w = c->session->curw->window; 192 struct window_pane *wp; 193 194 log_debug("%s: %s @%u", __func__, c->name, w->id); 195 196 TAILQ_FOREACH(wp, &w->panes, entry) { 197 if (window_pane_visible(wp)) 198 cmd_display_panes_draw_pane(ctx, wp); 199 } 200} 201 202static void 203cmd_display_panes_free(struct client *c) 204{ 205 struct cmd_display_panes_data *cdata = c->overlay_data; 206 207 if (cdata->item != NULL) 208 cmdq_continue(cdata->item); 209 free(cdata->command); 210 free(cdata); 211} 212 213static int 214cmd_display_panes_key(struct client *c, struct key_event *event) 215{ 216 struct cmd_display_panes_data *cdata = c->overlay_data; 217 char *cmd, *expanded, *error; 218 struct window *w = c->session->curw->window; 219 struct window_pane *wp; 220 enum cmd_parse_status status; 221 u_int index; 222 key_code key; 223 224 if (event->key >= '0' && event->key <= '9') 225 index = event->key - '0'; 226 else if ((event->key & KEYC_MASK_MODIFIERS) == 0) { 227 key = (event->key & KEYC_MASK_KEY); 228 if (key >= 'a' && key <= 'z') 229 index = 10 + (key - 'a'); 230 else 231 return (-1); 232 } else 233 return (-1); 234 235 wp = window_pane_at_index(w, index); 236 if (wp == NULL) 237 return (1); 238 window_unzoom(w); 239 240 xasprintf(&expanded, "%%%u", wp->id); 241 cmd = cmd_template_replace(cdata->command, expanded, 1); 242 243 status = cmd_parse_and_append(cmd, NULL, c, NULL, &error); 244 if (status == CMD_PARSE_ERROR) { 245 cmdq_append(c, cmdq_get_error(error)); 246 free(error); 247 } 248 249 free(cmd); 250 free(expanded); 251 return (1); 252} 253 254static enum cmd_retval 255cmd_display_panes_exec(struct cmd *self, struct cmdq_item *item) 256{ 257 struct args *args = cmd_get_args(self); 258 struct client *tc = cmdq_get_target_client(item); 259 struct session *s = tc->session; 260 u_int delay; 261 char *cause; 262 struct cmd_display_panes_data *cdata; 263 264 if (tc->overlay_draw != NULL) 265 return (CMD_RETURN_NORMAL); 266 267 if (args_has(args, 'd')) { 268 delay = args_strtonum(args, 'd', 0, UINT_MAX, &cause); 269 if (cause != NULL) { 270 cmdq_error(item, "delay %s", cause); 271 free(cause); 272 return (CMD_RETURN_ERROR); 273 } 274 } else 275 delay = options_get_number(s->options, "display-panes-time"); 276 277 cdata = xmalloc(sizeof *cdata); 278 if (args->argc != 0) 279 cdata->command = xstrdup(args->argv[0]); 280 else 281 cdata->command = xstrdup("select-pane -t '%%'"); 282 if (args_has(args, 'b')) 283 cdata->item = NULL; 284 else 285 cdata->item = item; 286 287 if (args_has(args, 'N')) { 288 server_client_set_overlay(tc, delay, NULL, NULL, 289 cmd_display_panes_draw, NULL, cmd_display_panes_free, 290 cdata); 291 } else { 292 server_client_set_overlay(tc, delay, NULL, NULL, 293 cmd_display_panes_draw, cmd_display_panes_key, 294 cmd_display_panes_free, cdata); 295 } 296 297 if (args_has(args, 'b')) 298 return (CMD_RETURN_NORMAL); 299 return (CMD_RETURN_WAIT); 300} 301