Annotation of src/usr.bin/tmux/cmd-display-panes.c, Revision 1.44
1.44 ! nicm 1: /* $OpenBSD: cmd-display-panes.c,v 1.43 2021/08/23 12:33:55 nicm Exp $ */
1.1 nicm 2:
3: /*
1.12 nicm 4: * Copyright (c) 2009 Nicholas Marriott <nicholas.marriott@gmail.com>
1.1 nicm 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:
1.13 nicm 21: #include <stdlib.h>
1.24 nicm 22: #include <string.h>
1.13 nicm 23:
1.1 nicm 24: #include "tmux.h"
25:
26: /*
27: * Display panes on a client.
28: */
29:
1.44 ! nicm 30: static enum args_parse_type cmd_display_panes_args_parse(struct args *,
! 31: u_int, char **);
! 32: static enum cmd_retval cmd_display_panes_exec(struct cmd *,
! 33: struct cmdq_item *);
1.13 nicm 34:
1.1 nicm 35: const struct cmd_entry cmd_display_panes_entry = {
1.10 nicm 36: .name = "display-panes",
37: .alias = "displayp",
38:
1.44 ! nicm 39: .args = { "bd:Nt:", 0, 1, cmd_display_panes_args_parse },
1.38 nicm 40: .usage = "[-bN] [-d duration] " CMD_TARGET_CLIENT_USAGE " [template]",
1.10 nicm 41:
1.34 nicm 42: .flags = CMD_AFTERHOOK|CMD_CLIENT_TFLAG,
1.10 nicm 43: .exec = cmd_display_panes_exec
1.1 nicm 44: };
45:
1.24 nicm 46: struct cmd_display_panes_data {
1.43 nicm 47: struct cmdq_item *item;
48: struct args_command_state *state;
1.24 nicm 49: };
50:
1.44 ! nicm 51: static enum args_parse_type
! 52: cmd_display_panes_args_parse(__unused struct args *args, __unused u_int idx,
! 53: __unused char **cause)
! 54: {
! 55: return (ARGS_PARSE_COMMANDS_OR_STRING);
! 56: }
! 57:
1.24 nicm 58: static void
59: cmd_display_panes_draw_pane(struct screen_redraw_ctx *ctx,
60: struct window_pane *wp)
1.1 nicm 61: {
1.24 nicm 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;
1.36 nicm 67: struct grid_cell fgc, bgc;
68: u_int pane, idx, px, py, i, j, xoff, yoff, sx, sy;
1.24 nicm 69: int colour, active_colour;
1.36 nicm 70: char buf[16], lbuf[16], rbuf[16], *ptr;
71: size_t len, llen, rlen;
1.24 nicm 72:
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)
77: return;
78:
79: if (wp->xoff >= ctx->ox && wp->xoff + wp->sx <= ctx->ox + ctx->sx) {
80: /* All visible. */
81: xoff = wp->xoff - ctx->ox;
82: sx = wp->sx;
83: } else if (wp->xoff < ctx->ox &&
84: wp->xoff + wp->sx > ctx->ox + ctx->sx) {
85: /* Both left and right not visible. */
86: xoff = 0;
87: sx = ctx->sx;
88: } else if (wp->xoff < ctx->ox) {
89: /* Left not visible. */
90: xoff = 0;
91: sx = wp->sx - (ctx->ox - wp->xoff);
92: } else {
93: /* Right not visible. */
94: xoff = wp->xoff - ctx->ox;
95: sx = wp->sx - xoff;
96: }
97: if (wp->yoff >= ctx->oy && wp->yoff + wp->sy <= ctx->oy + ctx->sy) {
98: /* All visible. */
99: yoff = wp->yoff - ctx->oy;
100: sy = wp->sy;
101: } else if (wp->yoff < ctx->oy &&
102: wp->yoff + wp->sy > ctx->oy + ctx->sy) {
103: /* Both top and bottom not visible. */
104: yoff = 0;
105: sy = ctx->sy;
106: } else if (wp->yoff < ctx->oy) {
107: /* Top not visible. */
108: yoff = 0;
109: sy = wp->sy - (ctx->oy - wp->yoff);
110: } else {
111: /* Bottom not visible. */
112: yoff = wp->yoff - ctx->oy;
113: sy = wp->sy - yoff;
114: }
1.19 nicm 115:
1.24 nicm 116: if (ctx->statustop)
117: yoff += ctx->statuslines;
118: px = sx / 2;
119: py = sy / 2;
120:
1.36 nicm 121: if (window_pane_index(wp, &pane) != 0)
1.24 nicm 122: fatalx("index not found");
1.36 nicm 123: len = xsnprintf(buf, sizeof buf, "%u", pane);
1.24 nicm 124:
125: if (sx < len)
126: return;
127: colour = options_get_number(oo, "display-panes-colour");
128: active_colour = options_get_number(oo, "display-panes-active-colour");
129:
1.36 nicm 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;
135: } else {
136: fgc.fg = colour;
137: bgc.bg = colour;
138: }
139:
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));
143: else
144: llen = 0;
145:
1.24 nicm 146: if (sx < len * 6 || sy < 5) {
1.36 nicm 147: tty_attributes(tty, &fgc, &grid_default_cell, NULL);
148: if (sx >= len + llen + 1) {
149: len += llen + 1;
150: tty_cursor(tty, xoff + px - len / 2, yoff + py);
1.44 ! nicm 151: tty_putn(tty, buf, len, len);
1.36 nicm 152: tty_putn(tty, " ", 1, 1);
153: tty_putn(tty, lbuf, llen, llen);
154: } else {
155: tty_cursor(tty, xoff + px - len / 2, yoff + py);
156: tty_putn(tty, buf, len, len);
157: }
158: goto out;
1.24 nicm 159: }
1.13 nicm 160:
1.24 nicm 161: px -= len * 3;
162: py -= 2;
1.13 nicm 163:
1.36 nicm 164: tty_attributes(tty, &bgc, &grid_default_cell, NULL);
1.24 nicm 165: for (ptr = buf; *ptr != '\0'; ptr++) {
166: if (*ptr < '0' || *ptr > '9')
167: continue;
168: idx = *ptr - '0';
169:
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])
174: tty_putc(tty, ' ');
175: }
176: }
177: px += 6;
178: }
179:
1.37 nicm 180: if (sy <= 6)
1.36 nicm 181: goto out;
182: tty_attributes(tty, &fgc, &grid_default_cell, NULL);
183: if (rlen != 0 && sx >= rlen) {
184: tty_cursor(tty, xoff + sx - rlen, yoff);
185: tty_putn(tty, rbuf, rlen, rlen);
186: }
187: if (llen != 0) {
188: tty_cursor(tty, xoff + sx / 2 + len * 3 - llen - 1,
189: yoff + py + 5);
190: tty_putn(tty, lbuf, llen, llen);
191: }
1.24 nicm 192:
1.36 nicm 193: out:
1.24 nicm 194: tty_cursor(tty, 0, 0);
195: }
196:
197: static void
1.40 nicm 198: cmd_display_panes_draw(struct client *c, __unused void *data,
199: struct screen_redraw_ctx *ctx)
1.24 nicm 200: {
201: struct window *w = c->session->curw->window;
202: struct window_pane *wp;
203:
204: log_debug("%s: %s @%u", __func__, c->name, w->id);
1.1 nicm 205:
1.24 nicm 206: TAILQ_FOREACH(wp, &w->panes, entry) {
207: if (window_pane_visible(wp))
208: cmd_display_panes_draw_pane(ctx, wp);
209: }
1.13 nicm 210: }
211:
212: static void
1.40 nicm 213: cmd_display_panes_free(__unused struct client *c, void *data)
1.24 nicm 214: {
1.40 nicm 215: struct cmd_display_panes_data *cdata = data;
1.24 nicm 216:
217: if (cdata->item != NULL)
1.28 nicm 218: cmdq_continue(cdata->item);
1.43 nicm 219: args_make_commands_free(cdata->state);
1.24 nicm 220: free(cdata);
221: }
222:
223: static int
1.40 nicm 224: cmd_display_panes_key(struct client *c, void *data, struct key_event *event)
1.13 nicm 225: {
1.40 nicm 226: struct cmd_display_panes_data *cdata = data;
1.43 nicm 227: char *expanded, *error;
228: struct cmdq_item *item = cdata->item, *new_item;
229: struct cmd_list *cmdlist;
1.24 nicm 230: struct window *w = c->session->curw->window;
231: struct window_pane *wp;
1.36 nicm 232: u_int index;
233: key_code key;
1.13 nicm 234:
1.36 nicm 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');
241: else
242: return (-1);
243: } else
1.29 nicm 244: return (-1);
1.24 nicm 245:
1.36 nicm 246: wp = window_pane_at_index(w, index);
1.15 nicm 247: if (wp == NULL)
1.24 nicm 248: return (1);
249: window_unzoom(w);
1.21 nicm 250:
1.15 nicm 251: xasprintf(&expanded, "%%%u", wp->id);
252:
1.43 nicm 253: cmdlist = args_make_commands(cdata->state, 1, &expanded, &error);
254: if (cmdlist == NULL) {
1.33 nicm 255: cmdq_append(c, cmdq_get_error(error));
256: free(error);
1.43 nicm 257: } else if (item == NULL) {
258: new_item = cmdq_get_command(cmdlist, NULL);
259: cmdq_append(c, new_item);
260: } else {
261: new_item = cmdq_get_command(cmdlist, cmdq_get_state(item));
262: cmdq_insert_after(item, new_item);
1.23 nicm 263: }
1.15 nicm 264:
265: free(expanded);
1.24 nicm 266: return (1);
267: }
268:
269: static enum cmd_retval
270: cmd_display_panes_exec(struct cmd *self, struct cmdq_item *item)
271: {
1.31 nicm 272: struct args *args = cmd_get_args(self);
1.34 nicm 273: struct client *tc = cmdq_get_target_client(item);
274: struct session *s = tc->session;
1.44 ! nicm 275: u_int delay;
1.24 nicm 276: char *cause;
277: struct cmd_display_panes_data *cdata;
1.43 nicm 278: int wait = !args_has(args, 'b');
1.24 nicm 279:
1.34 nicm 280: if (tc->overlay_draw != NULL)
1.24 nicm 281: return (CMD_RETURN_NORMAL);
1.13 nicm 282:
1.24 nicm 283: if (args_has(args, 'd')) {
284: delay = args_strtonum(args, 'd', 0, UINT_MAX, &cause);
285: if (cause != NULL) {
286: cmdq_error(item, "delay %s", cause);
287: free(cause);
288: return (CMD_RETURN_ERROR);
289: }
290: } else
291: delay = options_get_number(s->options, "display-panes-time");
292:
1.43 nicm 293: cdata = xcalloc(1, sizeof *cdata);
294: if (wait)
1.24 nicm 295: cdata->item = item;
1.43 nicm 296: cdata->state = args_make_commands_prepare(self, item, 0,
297: "select-pane -t \"%%%\"", wait, 0);
1.21 nicm 298:
1.38 nicm 299: if (args_has(args, 'N')) {
300: server_client_set_overlay(tc, delay, NULL, NULL,
1.39 nicm 301: cmd_display_panes_draw, NULL, cmd_display_panes_free, NULL,
1.38 nicm 302: cdata);
303: } else {
304: server_client_set_overlay(tc, delay, NULL, NULL,
305: cmd_display_panes_draw, cmd_display_panes_key,
1.39 nicm 306: cmd_display_panes_free, NULL, cdata);
1.38 nicm 307: }
1.21 nicm 308:
1.43 nicm 309: if (!wait)
1.24 nicm 310: return (CMD_RETURN_NORMAL);
311: return (CMD_RETURN_WAIT);
1.1 nicm 312: }