xref: /minix3/external/bsd/tmux/dist/screen-redraw.c (revision e1cdaee10649323af446eb1a74571984b2ab3181)
10a6a1f1dSLionel Sambuc /* Id */
2eda6f593SDavid van Moolenbroek 
3eda6f593SDavid van Moolenbroek /*
4eda6f593SDavid van Moolenbroek  * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
5eda6f593SDavid van Moolenbroek  *
6eda6f593SDavid van Moolenbroek  * Permission to use, copy, modify, and distribute this software for any
7eda6f593SDavid van Moolenbroek  * purpose with or without fee is hereby granted, provided that the above
8eda6f593SDavid van Moolenbroek  * copyright notice and this permission notice appear in all copies.
9eda6f593SDavid van Moolenbroek  *
10eda6f593SDavid van Moolenbroek  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11eda6f593SDavid van Moolenbroek  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12eda6f593SDavid van Moolenbroek  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13eda6f593SDavid van Moolenbroek  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14eda6f593SDavid van Moolenbroek  * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
15eda6f593SDavid van Moolenbroek  * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
16eda6f593SDavid van Moolenbroek  * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17eda6f593SDavid van Moolenbroek  */
18eda6f593SDavid van Moolenbroek 
19eda6f593SDavid van Moolenbroek #include <sys/types.h>
20eda6f593SDavid van Moolenbroek 
21eda6f593SDavid van Moolenbroek #include <string.h>
22eda6f593SDavid van Moolenbroek 
23eda6f593SDavid van Moolenbroek #include "tmux.h"
24eda6f593SDavid van Moolenbroek 
25eda6f593SDavid van Moolenbroek int	screen_redraw_cell_border1(struct window_pane *, u_int, u_int);
26eda6f593SDavid van Moolenbroek int	screen_redraw_cell_border(struct client *, u_int, u_int);
270a6a1f1dSLionel Sambuc int	screen_redraw_check_cell(struct client *, u_int, u_int,
280a6a1f1dSLionel Sambuc 	    struct window_pane **);
290a6a1f1dSLionel Sambuc int	screen_redraw_check_active(u_int, u_int, int, struct window *,
300a6a1f1dSLionel Sambuc 	    struct window_pane *);
310a6a1f1dSLionel Sambuc 
320a6a1f1dSLionel Sambuc void	screen_redraw_draw_borders(struct client *, int, u_int);
330a6a1f1dSLionel Sambuc void	screen_redraw_draw_panes(struct client *, u_int);
340a6a1f1dSLionel Sambuc void	screen_redraw_draw_status(struct client *, u_int);
35eda6f593SDavid van Moolenbroek void	screen_redraw_draw_number(struct client *, struct window_pane *);
36eda6f593SDavid van Moolenbroek 
37eda6f593SDavid van Moolenbroek #define CELL_INSIDE 0
38eda6f593SDavid van Moolenbroek #define CELL_LEFTRIGHT 1
39eda6f593SDavid van Moolenbroek #define CELL_TOPBOTTOM 2
40eda6f593SDavid van Moolenbroek #define CELL_TOPLEFT 3
41eda6f593SDavid van Moolenbroek #define CELL_TOPRIGHT 4
42eda6f593SDavid van Moolenbroek #define CELL_BOTTOMLEFT 5
43eda6f593SDavid van Moolenbroek #define CELL_BOTTOMRIGHT 6
44eda6f593SDavid van Moolenbroek #define CELL_TOPJOIN 7
45eda6f593SDavid van Moolenbroek #define CELL_BOTTOMJOIN 8
46eda6f593SDavid van Moolenbroek #define CELL_LEFTJOIN 9
47eda6f593SDavid van Moolenbroek #define CELL_RIGHTJOIN 10
48eda6f593SDavid van Moolenbroek #define CELL_JOIN 11
49eda6f593SDavid van Moolenbroek #define CELL_OUTSIDE 12
50eda6f593SDavid van Moolenbroek 
51eda6f593SDavid van Moolenbroek #define CELL_BORDERS " xqlkmjwvtun~"
52eda6f593SDavid van Moolenbroek 
53eda6f593SDavid van Moolenbroek /* Check if cell is on the border of a particular pane. */
54eda6f593SDavid van Moolenbroek int
screen_redraw_cell_border1(struct window_pane * wp,u_int px,u_int py)55eda6f593SDavid van Moolenbroek screen_redraw_cell_border1(struct window_pane *wp, u_int px, u_int py)
56eda6f593SDavid van Moolenbroek {
57eda6f593SDavid van Moolenbroek 	/* Inside pane. */
58eda6f593SDavid van Moolenbroek 	if (px >= wp->xoff && px < wp->xoff + wp->sx &&
59eda6f593SDavid van Moolenbroek 	    py >= wp->yoff && py < wp->yoff + wp->sy)
60eda6f593SDavid van Moolenbroek 		return (0);
61eda6f593SDavid van Moolenbroek 
62eda6f593SDavid van Moolenbroek 	/* Left/right borders. */
63eda6f593SDavid van Moolenbroek 	if ((wp->yoff == 0 || py >= wp->yoff - 1) && py <= wp->yoff + wp->sy) {
64eda6f593SDavid van Moolenbroek 		if (wp->xoff != 0 && px == wp->xoff - 1)
65eda6f593SDavid van Moolenbroek 			return (1);
66eda6f593SDavid van Moolenbroek 		if (px == wp->xoff + wp->sx)
67eda6f593SDavid van Moolenbroek 			return (1);
68eda6f593SDavid van Moolenbroek 	}
69eda6f593SDavid van Moolenbroek 
70eda6f593SDavid van Moolenbroek 	/* Top/bottom borders. */
71eda6f593SDavid van Moolenbroek 	if ((wp->xoff == 0 || px >= wp->xoff - 1) && px <= wp->xoff + wp->sx) {
72eda6f593SDavid van Moolenbroek 		if (wp->yoff != 0 && py == wp->yoff - 1)
73eda6f593SDavid van Moolenbroek 			return (1);
74eda6f593SDavid van Moolenbroek 		if (py == wp->yoff + wp->sy)
75eda6f593SDavid van Moolenbroek 			return (1);
76eda6f593SDavid van Moolenbroek 	}
77eda6f593SDavid van Moolenbroek 
78eda6f593SDavid van Moolenbroek 	/* Outside pane. */
79eda6f593SDavid van Moolenbroek 	return (-1);
80eda6f593SDavid van Moolenbroek }
81eda6f593SDavid van Moolenbroek 
82eda6f593SDavid van Moolenbroek /* Check if a cell is on the pane border. */
83eda6f593SDavid van Moolenbroek int
screen_redraw_cell_border(struct client * c,u_int px,u_int py)84eda6f593SDavid van Moolenbroek screen_redraw_cell_border(struct client *c, u_int px, u_int py)
85eda6f593SDavid van Moolenbroek {
86eda6f593SDavid van Moolenbroek 	struct window		*w = c->session->curw->window;
87eda6f593SDavid van Moolenbroek 	struct window_pane	*wp;
88eda6f593SDavid van Moolenbroek 	int			 retval;
89eda6f593SDavid van Moolenbroek 
90eda6f593SDavid van Moolenbroek 	/* Check all the panes. */
91eda6f593SDavid van Moolenbroek 	TAILQ_FOREACH(wp, &w->panes, entry) {
92eda6f593SDavid van Moolenbroek 		if (!window_pane_visible(wp))
93eda6f593SDavid van Moolenbroek 			continue;
94eda6f593SDavid van Moolenbroek 		if ((retval = screen_redraw_cell_border1(wp, px, py)) != -1)
95eda6f593SDavid van Moolenbroek 			return (retval);
96eda6f593SDavid van Moolenbroek 	}
97eda6f593SDavid van Moolenbroek 
98eda6f593SDavid van Moolenbroek 	return (0);
99eda6f593SDavid van Moolenbroek }
100eda6f593SDavid van Moolenbroek 
101eda6f593SDavid van Moolenbroek /* Check if cell inside a pane. */
102eda6f593SDavid van Moolenbroek int
screen_redraw_check_cell(struct client * c,u_int px,u_int py,struct window_pane ** wpp)1030a6a1f1dSLionel Sambuc screen_redraw_check_cell(struct client *c, u_int px, u_int py,
1040a6a1f1dSLionel Sambuc     struct window_pane **wpp)
105eda6f593SDavid van Moolenbroek {
106eda6f593SDavid van Moolenbroek 	struct window		*w = c->session->curw->window;
107eda6f593SDavid van Moolenbroek 	struct window_pane	*wp;
108eda6f593SDavid van Moolenbroek 	int			 borders;
109eda6f593SDavid van Moolenbroek 
110eda6f593SDavid van Moolenbroek 	if (px > w->sx || py > w->sy)
111eda6f593SDavid van Moolenbroek 		return (CELL_OUTSIDE);
112eda6f593SDavid van Moolenbroek 
113eda6f593SDavid van Moolenbroek 	TAILQ_FOREACH(wp, &w->panes, entry) {
114eda6f593SDavid van Moolenbroek 		if (!window_pane_visible(wp))
115eda6f593SDavid van Moolenbroek 			continue;
1160a6a1f1dSLionel Sambuc 		*wpp = wp;
117eda6f593SDavid van Moolenbroek 
118eda6f593SDavid van Moolenbroek 		/* If outside the pane and its border, skip it. */
119eda6f593SDavid van Moolenbroek 		if ((wp->xoff != 0 && px < wp->xoff - 1) ||
120eda6f593SDavid van Moolenbroek 		    px > wp->xoff + wp->sx ||
121eda6f593SDavid van Moolenbroek 		    (wp->yoff != 0 && py < wp->yoff - 1) ||
122eda6f593SDavid van Moolenbroek 		    py > wp->yoff + wp->sy)
123eda6f593SDavid van Moolenbroek 			continue;
124eda6f593SDavid van Moolenbroek 
125eda6f593SDavid van Moolenbroek 		/* If definitely inside, return so. */
126eda6f593SDavid van Moolenbroek 		if (!screen_redraw_cell_border(c, px, py))
127eda6f593SDavid van Moolenbroek 			return (CELL_INSIDE);
128eda6f593SDavid van Moolenbroek 
129eda6f593SDavid van Moolenbroek 		/*
130eda6f593SDavid van Moolenbroek 		 * Construct a bitmask of whether the cells to the left (bit
131eda6f593SDavid van Moolenbroek 		 * 4), right, top, and bottom (bit 1) of this cell are borders.
132eda6f593SDavid van Moolenbroek 		 */
133eda6f593SDavid van Moolenbroek 		borders = 0;
134eda6f593SDavid van Moolenbroek 		if (px == 0 || screen_redraw_cell_border(c, px - 1, py))
135eda6f593SDavid van Moolenbroek 			borders |= 8;
136eda6f593SDavid van Moolenbroek 		if (px <= w->sx && screen_redraw_cell_border(c, px + 1, py))
137eda6f593SDavid van Moolenbroek 			borders |= 4;
138eda6f593SDavid van Moolenbroek 		if (py == 0 || screen_redraw_cell_border(c, px, py - 1))
139eda6f593SDavid van Moolenbroek 			borders |= 2;
140eda6f593SDavid van Moolenbroek 		if (py <= w->sy && screen_redraw_cell_border(c, px, py + 1))
141eda6f593SDavid van Moolenbroek 			borders |= 1;
142eda6f593SDavid van Moolenbroek 
143eda6f593SDavid van Moolenbroek 		/*
144eda6f593SDavid van Moolenbroek 		 * Figure out what kind of border this cell is. Only one bit
145eda6f593SDavid van Moolenbroek 		 * set doesn't make sense (can't have a border cell with no
146eda6f593SDavid van Moolenbroek 		 * others connected).
147eda6f593SDavid van Moolenbroek 		 */
148eda6f593SDavid van Moolenbroek 		switch (borders) {
149eda6f593SDavid van Moolenbroek 		case 15:	/* 1111, left right top bottom */
150eda6f593SDavid van Moolenbroek 			return (CELL_JOIN);
151eda6f593SDavid van Moolenbroek 		case 14:	/* 1110, left right top */
152eda6f593SDavid van Moolenbroek 			return (CELL_BOTTOMJOIN);
153eda6f593SDavid van Moolenbroek 		case 13:	/* 1101, left right bottom */
154eda6f593SDavid van Moolenbroek 			return (CELL_TOPJOIN);
155eda6f593SDavid van Moolenbroek 		case 12:	/* 1100, left right */
156eda6f593SDavid van Moolenbroek 			return (CELL_TOPBOTTOM);
157eda6f593SDavid van Moolenbroek 		case 11:	/* 1011, left top bottom */
158eda6f593SDavid van Moolenbroek 			return (CELL_RIGHTJOIN);
159eda6f593SDavid van Moolenbroek 		case 10:	/* 1010, left top */
160eda6f593SDavid van Moolenbroek 			return (CELL_BOTTOMRIGHT);
161eda6f593SDavid van Moolenbroek 		case 9:		/* 1001, left bottom */
162eda6f593SDavid van Moolenbroek 			return (CELL_TOPRIGHT);
163eda6f593SDavid van Moolenbroek 		case 7:		/* 0111, right top bottom */
164eda6f593SDavid van Moolenbroek 			return (CELL_LEFTJOIN);
165eda6f593SDavid van Moolenbroek 		case 6:		/* 0110, right top */
166eda6f593SDavid van Moolenbroek 			return (CELL_BOTTOMLEFT);
167eda6f593SDavid van Moolenbroek 		case 5:		/* 0101, right bottom */
168eda6f593SDavid van Moolenbroek 			return (CELL_TOPLEFT);
169eda6f593SDavid van Moolenbroek 		case 3:		/* 0011, top bottom */
170eda6f593SDavid van Moolenbroek 			return (CELL_LEFTRIGHT);
171eda6f593SDavid van Moolenbroek 		}
172eda6f593SDavid van Moolenbroek 	}
173eda6f593SDavid van Moolenbroek 
1740a6a1f1dSLionel Sambuc 	*wpp = NULL;
175eda6f593SDavid van Moolenbroek 	return (CELL_OUTSIDE);
176eda6f593SDavid van Moolenbroek }
177eda6f593SDavid van Moolenbroek 
1780a6a1f1dSLionel Sambuc /* Check active pane indicator. */
1790a6a1f1dSLionel Sambuc int
screen_redraw_check_active(u_int px,u_int py,int type,struct window * w,struct window_pane * wp)1800a6a1f1dSLionel Sambuc screen_redraw_check_active(u_int px, u_int py, int type, struct window *w,
1810a6a1f1dSLionel Sambuc     struct window_pane *wp)
1820a6a1f1dSLionel Sambuc {
1830a6a1f1dSLionel Sambuc 	/* Is this off the active pane border? */
1840a6a1f1dSLionel Sambuc 	if (screen_redraw_cell_border1(w->active, px, py) != 1)
1850a6a1f1dSLionel Sambuc 		return (0);
1860a6a1f1dSLionel Sambuc 
1870a6a1f1dSLionel Sambuc 	/* If there are more than two panes, that's enough. */
1880a6a1f1dSLionel Sambuc 	if (window_count_panes(w) != 2)
1890a6a1f1dSLionel Sambuc 		return (1);
1900a6a1f1dSLionel Sambuc 
1910a6a1f1dSLionel Sambuc 	/* Else if the cell is not a border cell, forget it. */
1920a6a1f1dSLionel Sambuc 	if (wp == NULL || (type == CELL_OUTSIDE || type == CELL_INSIDE))
1930a6a1f1dSLionel Sambuc 		return (1);
1940a6a1f1dSLionel Sambuc 
1950a6a1f1dSLionel Sambuc 	/* Check if the pane covers the whole width. */
1960a6a1f1dSLionel Sambuc 	if (wp->xoff == 0 && wp->sx == w->sx) {
1970a6a1f1dSLionel Sambuc 		/* This can either be the top pane or the bottom pane. */
1980a6a1f1dSLionel Sambuc 		if (wp->yoff == 0) { /* top pane */
1990a6a1f1dSLionel Sambuc 			if (wp == w->active)
2000a6a1f1dSLionel Sambuc 				return (px <= wp->sx / 2);
2010a6a1f1dSLionel Sambuc 			return (px > wp->sx / 2);
2020a6a1f1dSLionel Sambuc 		}
2030a6a1f1dSLionel Sambuc 		return (0);
2040a6a1f1dSLionel Sambuc 	}
2050a6a1f1dSLionel Sambuc 
2060a6a1f1dSLionel Sambuc 	/* Check if the pane covers the whole height. */
2070a6a1f1dSLionel Sambuc 	if (wp->yoff == 0 && wp->sy == w->sy) {
2080a6a1f1dSLionel Sambuc 		/* This can either be the left pane or the right pane. */
2090a6a1f1dSLionel Sambuc 		if (wp->xoff == 0) { /* left pane */
2100a6a1f1dSLionel Sambuc 			if (wp == w->active)
2110a6a1f1dSLionel Sambuc 				return (py <= wp->sy / 2);
2120a6a1f1dSLionel Sambuc 			return (py > wp->sy / 2);
2130a6a1f1dSLionel Sambuc 		}
2140a6a1f1dSLionel Sambuc 		return (0);
2150a6a1f1dSLionel Sambuc 	}
2160a6a1f1dSLionel Sambuc 
2170a6a1f1dSLionel Sambuc 	return (type);
2180a6a1f1dSLionel Sambuc }
2190a6a1f1dSLionel Sambuc 
220eda6f593SDavid van Moolenbroek /* Redraw entire screen. */
221eda6f593SDavid van Moolenbroek void
screen_redraw_screen(struct client * c,int draw_panes,int draw_status,int draw_borders)2220a6a1f1dSLionel Sambuc screen_redraw_screen(struct client *c, int draw_panes, int draw_status,
2230a6a1f1dSLionel Sambuc     int draw_borders)
224eda6f593SDavid van Moolenbroek {
2250a6a1f1dSLionel Sambuc 	struct options	*oo = &c->session->options;
226eda6f593SDavid van Moolenbroek 	struct tty	*tty = &c->tty;
2270a6a1f1dSLionel Sambuc 	u_int		 top;
2280a6a1f1dSLionel Sambuc 	int	 	 status, spos;
229eda6f593SDavid van Moolenbroek 
230eda6f593SDavid van Moolenbroek 	/* Suspended clients should not be updated. */
231eda6f593SDavid van Moolenbroek 	if (c->flags & CLIENT_SUSPENDED)
232eda6f593SDavid van Moolenbroek 		return;
233eda6f593SDavid van Moolenbroek 
234eda6f593SDavid van Moolenbroek 	/* Get status line, er, status. */
2350a6a1f1dSLionel Sambuc 	spos = options_get_number(oo, "status-position");
236eda6f593SDavid van Moolenbroek 	if (c->message_string != NULL || c->prompt_string != NULL)
237eda6f593SDavid van Moolenbroek 		status = 1;
238eda6f593SDavid van Moolenbroek 	else
2390a6a1f1dSLionel Sambuc 		status = options_get_number(oo, "status");
2400a6a1f1dSLionel Sambuc 	top = 0;
2410a6a1f1dSLionel Sambuc 	if (status && spos == 0)
2420a6a1f1dSLionel Sambuc 		top = 1;
2430a6a1f1dSLionel Sambuc 	if (!status)
2440a6a1f1dSLionel Sambuc 		draw_status = 0;
245eda6f593SDavid van Moolenbroek 
2460a6a1f1dSLionel Sambuc 	if (draw_borders)
2470a6a1f1dSLionel Sambuc 		screen_redraw_draw_borders(c, status, top);
2480a6a1f1dSLionel Sambuc 	if (draw_panes)
2490a6a1f1dSLionel Sambuc 		screen_redraw_draw_panes(c, top);
2500a6a1f1dSLionel Sambuc 	if (draw_status)
2510a6a1f1dSLionel Sambuc 		screen_redraw_draw_status(c, top);
252eda6f593SDavid van Moolenbroek 	tty_reset(tty);
253eda6f593SDavid van Moolenbroek }
254eda6f593SDavid van Moolenbroek 
255eda6f593SDavid van Moolenbroek /* Draw a single pane. */
256eda6f593SDavid van Moolenbroek void
screen_redraw_pane(struct client * c,struct window_pane * wp)257eda6f593SDavid van Moolenbroek screen_redraw_pane(struct client *c, struct window_pane *wp)
258eda6f593SDavid van Moolenbroek {
2590a6a1f1dSLionel Sambuc 	u_int	i, yoff;
2600a6a1f1dSLionel Sambuc 
2610a6a1f1dSLionel Sambuc 	if (!window_pane_visible(wp))
2620a6a1f1dSLionel Sambuc 		return;
2630a6a1f1dSLionel Sambuc 
2640a6a1f1dSLionel Sambuc 	yoff = wp->yoff;
2650a6a1f1dSLionel Sambuc 	if (status_at_line(c) == 0)
2660a6a1f1dSLionel Sambuc 		yoff++;
267eda6f593SDavid van Moolenbroek 
268eda6f593SDavid van Moolenbroek 	for (i = 0; i < wp->sy; i++)
2690a6a1f1dSLionel Sambuc 		tty_draw_line(&c->tty, wp->screen, i, wp->xoff, yoff);
270eda6f593SDavid van Moolenbroek 	tty_reset(&c->tty);
271eda6f593SDavid van Moolenbroek }
272eda6f593SDavid van Moolenbroek 
2730a6a1f1dSLionel Sambuc /* Draw the borders. */
2740a6a1f1dSLionel Sambuc void
screen_redraw_draw_borders(struct client * c,int status,u_int top)2750a6a1f1dSLionel Sambuc screen_redraw_draw_borders(struct client *c, int status, u_int top)
2760a6a1f1dSLionel Sambuc {
2770a6a1f1dSLionel Sambuc 	struct window		*w = c->session->curw->window;
2780a6a1f1dSLionel Sambuc 	struct options		*oo = &c->session->options;
2790a6a1f1dSLionel Sambuc 	struct tty		*tty = &c->tty;
2800a6a1f1dSLionel Sambuc 	struct window_pane	*wp;
2810a6a1f1dSLionel Sambuc 	struct grid_cell	 active_gc, other_gc;
2820a6a1f1dSLionel Sambuc 	u_int		 	 i, j, type;
2830a6a1f1dSLionel Sambuc 
284*e1cdaee1SLionel Sambuc #if defined(__minix)
285*e1cdaee1SLionel Sambuc 	/* LSC: -Werror=maybe-uninitialized while compiling with -O3 */
286*e1cdaee1SLionel Sambuc 	wp = NULL;
287*e1cdaee1SLionel Sambuc #endif /* defined(__minix) */
2880a6a1f1dSLionel Sambuc 	style_apply(&other_gc, oo, "pane-border-style");
2890a6a1f1dSLionel Sambuc 	style_apply(&active_gc, oo, "pane-active-border-style");
2900a6a1f1dSLionel Sambuc 	active_gc.attr = other_gc.attr = GRID_ATTR_CHARSET;
2910a6a1f1dSLionel Sambuc 
2920a6a1f1dSLionel Sambuc 	for (j = 0; j < tty->sy - status; j++) {
2930a6a1f1dSLionel Sambuc 		for (i = 0; i < tty->sx; i++) {
2940a6a1f1dSLionel Sambuc 			type = screen_redraw_check_cell(c, i, j, &wp);
2950a6a1f1dSLionel Sambuc 			if (type == CELL_INSIDE)
2960a6a1f1dSLionel Sambuc 				continue;
2970a6a1f1dSLionel Sambuc 			if (screen_redraw_check_active(i, j, type, w, wp))
2980a6a1f1dSLionel Sambuc 				tty_attributes(tty, &active_gc);
2990a6a1f1dSLionel Sambuc 			else
3000a6a1f1dSLionel Sambuc 				tty_attributes(tty, &other_gc);
3010a6a1f1dSLionel Sambuc 			tty_cursor(tty, i, top + j);
3020a6a1f1dSLionel Sambuc 			tty_putc(tty, CELL_BORDERS[type]);
3030a6a1f1dSLionel Sambuc 		}
3040a6a1f1dSLionel Sambuc 	}
3050a6a1f1dSLionel Sambuc }
3060a6a1f1dSLionel Sambuc 
3070a6a1f1dSLionel Sambuc /* Draw the panes. */
3080a6a1f1dSLionel Sambuc void
screen_redraw_draw_panes(struct client * c,u_int top)3090a6a1f1dSLionel Sambuc screen_redraw_draw_panes(struct client *c, u_int top)
3100a6a1f1dSLionel Sambuc {
3110a6a1f1dSLionel Sambuc 	struct window		*w = c->session->curw->window;
3120a6a1f1dSLionel Sambuc 	struct tty		*tty = &c->tty;
3130a6a1f1dSLionel Sambuc 	struct window_pane	*wp;
3140a6a1f1dSLionel Sambuc 	struct screen		*s;
3150a6a1f1dSLionel Sambuc 	u_int		 	 i;
3160a6a1f1dSLionel Sambuc 
3170a6a1f1dSLionel Sambuc 	TAILQ_FOREACH(wp, &w->panes, entry) {
3180a6a1f1dSLionel Sambuc 		if (!window_pane_visible(wp))
3190a6a1f1dSLionel Sambuc 			continue;
3200a6a1f1dSLionel Sambuc 		s = wp->screen;
3210a6a1f1dSLionel Sambuc 		for (i = 0; i < wp->sy; i++)
3220a6a1f1dSLionel Sambuc 			tty_draw_line(tty, s, i, wp->xoff, top + wp->yoff);
3230a6a1f1dSLionel Sambuc 		if (c->flags & CLIENT_IDENTIFY)
3240a6a1f1dSLionel Sambuc 			screen_redraw_draw_number(c, wp);
3250a6a1f1dSLionel Sambuc 	}
3260a6a1f1dSLionel Sambuc }
3270a6a1f1dSLionel Sambuc 
3280a6a1f1dSLionel Sambuc /* Draw the status line. */
3290a6a1f1dSLionel Sambuc void
screen_redraw_draw_status(struct client * c,u_int top)3300a6a1f1dSLionel Sambuc screen_redraw_draw_status(struct client *c, u_int top)
3310a6a1f1dSLionel Sambuc {
3320a6a1f1dSLionel Sambuc 	struct tty	*tty = &c->tty;
3330a6a1f1dSLionel Sambuc 
3340a6a1f1dSLionel Sambuc 	if (top)
3350a6a1f1dSLionel Sambuc 		tty_draw_line(tty, &c->status, 0, 0, 0);
3360a6a1f1dSLionel Sambuc 	else
3370a6a1f1dSLionel Sambuc 		tty_draw_line(tty, &c->status, 0, 0, tty->sy - 1);
3380a6a1f1dSLionel Sambuc }
3390a6a1f1dSLionel Sambuc 
340eda6f593SDavid van Moolenbroek /* Draw number on a pane. */
341eda6f593SDavid van Moolenbroek void
screen_redraw_draw_number(struct client * c,struct window_pane * wp)342eda6f593SDavid van Moolenbroek screen_redraw_draw_number(struct client *c, struct window_pane *wp)
343eda6f593SDavid van Moolenbroek {
344eda6f593SDavid van Moolenbroek 	struct tty		*tty = &c->tty;
345eda6f593SDavid van Moolenbroek 	struct session		*s = c->session;
346eda6f593SDavid van Moolenbroek 	struct options		*oo = &s->options;
347eda6f593SDavid van Moolenbroek 	struct window		*w = wp->window;
348eda6f593SDavid van Moolenbroek 	struct grid_cell	 gc;
349eda6f593SDavid van Moolenbroek 	u_int			 idx, px, py, i, j, xoff, yoff;
350eda6f593SDavid van Moolenbroek 	int			 colour, active_colour;
351eda6f593SDavid van Moolenbroek 	char			 buf[16], *ptr;
352eda6f593SDavid van Moolenbroek 	size_t			 len;
353eda6f593SDavid van Moolenbroek 
3540a6a1f1dSLionel Sambuc 	if (window_pane_index(wp, &idx) != 0)
3550a6a1f1dSLionel Sambuc 		fatalx("index not found");
356eda6f593SDavid van Moolenbroek 	len = xsnprintf(buf, sizeof buf, "%u", idx);
357eda6f593SDavid van Moolenbroek 
358eda6f593SDavid van Moolenbroek 	if (wp->sx < len)
359eda6f593SDavid van Moolenbroek 		return;
360eda6f593SDavid van Moolenbroek 	colour = options_get_number(oo, "display-panes-colour");
361eda6f593SDavid van Moolenbroek 	active_colour = options_get_number(oo, "display-panes-active-colour");
362eda6f593SDavid van Moolenbroek 
363eda6f593SDavid van Moolenbroek 	px = wp->sx / 2; py = wp->sy / 2;
364eda6f593SDavid van Moolenbroek 	xoff = wp->xoff; yoff = wp->yoff;
365eda6f593SDavid van Moolenbroek 
366eda6f593SDavid van Moolenbroek 	if (wp->sx < len * 6 || wp->sy < 5) {
367eda6f593SDavid van Moolenbroek 		tty_cursor(tty, xoff + px - len / 2, yoff + py);
3680a6a1f1dSLionel Sambuc 		goto draw_text;
369eda6f593SDavid van Moolenbroek 	}
370eda6f593SDavid van Moolenbroek 
371eda6f593SDavid van Moolenbroek 	px -= len * 3;
372eda6f593SDavid van Moolenbroek 	py -= 2;
373eda6f593SDavid van Moolenbroek 
374eda6f593SDavid van Moolenbroek 	memcpy(&gc, &grid_default_cell, sizeof gc);
375eda6f593SDavid van Moolenbroek 	if (w->active == wp)
376eda6f593SDavid van Moolenbroek 		colour_set_bg(&gc, active_colour);
377eda6f593SDavid van Moolenbroek 	else
378eda6f593SDavid van Moolenbroek 		colour_set_bg(&gc, colour);
379eda6f593SDavid van Moolenbroek 	tty_attributes(tty, &gc);
380eda6f593SDavid van Moolenbroek 	for (ptr = buf; *ptr != '\0'; ptr++) {
381eda6f593SDavid van Moolenbroek 		if (*ptr < '0' || *ptr > '9')
382eda6f593SDavid van Moolenbroek 			continue;
383eda6f593SDavid van Moolenbroek 		idx = *ptr - '0';
384eda6f593SDavid van Moolenbroek 
385eda6f593SDavid van Moolenbroek 		for (j = 0; j < 5; j++) {
386eda6f593SDavid van Moolenbroek 			for (i = px; i < px + 5; i++) {
387eda6f593SDavid van Moolenbroek 				tty_cursor(tty, xoff + i, yoff + py + j);
388eda6f593SDavid van Moolenbroek 				if (clock_table[idx][j][i - px])
389eda6f593SDavid van Moolenbroek 					tty_putc(tty, ' ');
390eda6f593SDavid van Moolenbroek 			}
391eda6f593SDavid van Moolenbroek 		}
392eda6f593SDavid van Moolenbroek 		px += 6;
393eda6f593SDavid van Moolenbroek 	}
3940a6a1f1dSLionel Sambuc 
3950a6a1f1dSLionel Sambuc 	len = xsnprintf(buf, sizeof buf, "%ux%u", wp->sx, wp->sy);
3960a6a1f1dSLionel Sambuc 	if (wp->sx < len || wp->sy < 6)
3970a6a1f1dSLionel Sambuc 		return;
3980a6a1f1dSLionel Sambuc 	tty_cursor(tty, xoff + wp->sx - len, yoff);
3990a6a1f1dSLionel Sambuc 
4000a6a1f1dSLionel Sambuc draw_text:
4010a6a1f1dSLionel Sambuc 	memcpy(&gc, &grid_default_cell, sizeof gc);
4020a6a1f1dSLionel Sambuc 	if (w->active == wp)
4030a6a1f1dSLionel Sambuc 		colour_set_fg(&gc, active_colour);
4040a6a1f1dSLionel Sambuc 	else
4050a6a1f1dSLionel Sambuc 		colour_set_fg(&gc, colour);
4060a6a1f1dSLionel Sambuc 	tty_attributes(tty, &gc);
4070a6a1f1dSLionel Sambuc 	tty_puts(tty, buf);
4080a6a1f1dSLionel Sambuc 
4090a6a1f1dSLionel Sambuc 	tty_cursor(tty, 0, 0);
410eda6f593SDavid van Moolenbroek }
411