blob: 82e390cda2c6a7f08f6be8066938aa9d5b0142a5 [file] [log] [blame] [raw]
Nicholas Marriott35876ea2009-06-01 22:58:49 +00001/* $OpenBSD$ */
2
3/*
nicm995af0e2016-01-19 15:59:12 +00004 * Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
Nicholas Marriott35876ea2009-06-01 22:58:49 +00005 *
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
nicmc363c232017-12-22 23:16:41 +000021#include <stdlib.h>
Nicholas Marriott35876ea2009-06-01 22:58:49 +000022#include <string.h>
23
24#include "tmux.h"
25
nicmd0a600c2018-08-14 11:31:34 +000026static void screen_redraw_draw_borders(struct screen_redraw_ctx *);
27static void screen_redraw_draw_panes(struct screen_redraw_ctx *);
28static void screen_redraw_draw_status(struct screen_redraw_ctx *);
nicm64699532018-10-18 08:38:01 +000029static void screen_redraw_draw_pane(struct screen_redraw_ctx *,
nicmd0a600c2018-08-14 11:31:34 +000030 struct window_pane *);
nicm5340bf52020-06-23 14:10:43 +000031static void screen_redraw_set_context(struct client *,
32 struct screen_redraw_ctx *);
Nicholas Marriott35876ea2009-06-01 22:58:49 +000033
Nicholas Marriott029599c2009-07-24 16:21:42 +000034#define CELL_INSIDE 0
nicm3dddc112021-02-05 12:29:18 +000035#define CELL_TOPBOTTOM 1
36#define CELL_LEFTRIGHT 2
Nicholas Marriott13317382009-07-24 19:14:38 +000037#define CELL_TOPLEFT 3
38#define CELL_TOPRIGHT 4
39#define CELL_BOTTOMLEFT 5
40#define CELL_BOTTOMRIGHT 6
41#define CELL_TOPJOIN 7
42#define CELL_BOTTOMJOIN 8
43#define CELL_LEFTJOIN 9
44#define CELL_RIGHTJOIN 10
45#define CELL_JOIN 11
46#define CELL_OUTSIDE 12
47
Nicholas Marriottcb564bb2010-09-11 16:19:22 +000048#define CELL_BORDERS " xqlkmjwvtun~"
nicm3dddc112021-02-05 12:29:18 +000049
50#define START_ISOLATE "\342\201\246"
51#define END_ISOLATE "\342\201\251"
Nicholas Marriottcb564bb2010-09-11 16:19:22 +000052
nicme2a26742020-05-16 16:26:34 +000053static const struct utf8_data screen_redraw_double_borders[] = {
54 { "", 0, 0, 0 },
55 { "\342\225\221", 0, 3, 1 }, /* U+2551 */
56 { "\342\225\220", 0, 3, 1 }, /* U+2550 */
57 { "\342\225\224", 0, 3, 1 }, /* U+2554 */
58 { "\342\225\227", 0, 3, 1 }, /* U+2557 */
59 { "\342\225\232", 0, 3, 1 }, /* U+255A */
60 { "\342\225\235", 0, 3, 1 }, /* U+255D */
61 { "\342\225\246", 0, 3, 1 }, /* U+2566 */
62 { "\342\225\251", 0, 3, 1 }, /* U+2569 */
63 { "\342\225\240", 0, 3, 1 }, /* U+2560 */
64 { "\342\225\243", 0, 3, 1 }, /* U+2563 */
65 { "\342\225\254", 0, 3, 1 }, /* U+256C */
66 { "\302\267", 0, 2, 1 } /* U+00B7 */
67};
68
69static const struct utf8_data screen_redraw_heavy_borders[] = {
70 { "", 0, 0, 0 },
71 { "\342\224\203", 0, 3, 1 }, /* U+2503 */
72 { "\342\224\201", 0, 3, 1 }, /* U+2501 */
73 { "\342\224\223", 0, 3, 1 }, /* U+2513 */
74 { "\342\224\217", 0, 3, 1 }, /* U+250F */
75 { "\342\224\227", 0, 3, 1 }, /* U+2517 */
76 { "\342\224\233", 0, 3, 1 }, /* U+251B */
77 { "\342\224\263", 0, 3, 1 }, /* U+2533 */
78 { "\342\224\273", 0, 3, 1 }, /* U+253B */
79 { "\342\224\243", 0, 3, 1 }, /* U+2523 */
80 { "\342\224\253", 0, 3, 1 }, /* U+252B */
81 { "\342\225\213", 0, 3, 1 }, /* U+254B */
82 { "\302\267", 0, 2, 1 } /* U+00B7 */
nicmf03b6112020-05-16 15:01:30 +000083};
84
85enum screen_redraw_border_type {
86 SCREEN_REDRAW_OUTSIDE,
87 SCREEN_REDRAW_INSIDE,
88 SCREEN_REDRAW_BORDER
89};
nicme2a26742020-05-16 16:26:34 +000090
91/* Get cell border character. */
92static void
93screen_redraw_border_set(struct window_pane *wp, int pane_lines, int cell_type,
94 struct grid_cell *gc)
95{
96 u_int idx;
97
98 switch (pane_lines) {
99 case PANE_LINES_NUMBER:
100 if (cell_type == CELL_OUTSIDE) {
101 gc->attr |= GRID_ATTR_CHARSET;
102 utf8_set(&gc->data, CELL_BORDERS[CELL_OUTSIDE]);
103 break;
104 }
105 gc->attr &= ~GRID_ATTR_CHARSET;
106 if (wp != NULL && window_pane_index(wp, &idx) == 0)
107 utf8_set(&gc->data, '0' + (idx % 10));
108 else
109 utf8_set(&gc->data, '*');
110 break;
111 case PANE_LINES_DOUBLE:
112 gc->attr &= ~GRID_ATTR_CHARSET;
113 utf8_copy(&gc->data, &screen_redraw_double_borders[cell_type]);
114 break;
115 case PANE_LINES_HEAVY:
116 gc->attr &= ~GRID_ATTR_CHARSET;
117 utf8_copy(&gc->data, &screen_redraw_heavy_borders[cell_type]);
118 break;
119 case PANE_LINES_SIMPLE:
120 gc->attr &= ~GRID_ATTR_CHARSET;
121 utf8_set(&gc->data, " |-+++++++++."[cell_type]);
122 break;
123 default:
124 gc->attr |= GRID_ATTR_CHARSET;
125 utf8_set(&gc->data, CELL_BORDERS[cell_type]);
126 break;
127 }
128}
nicmf03b6112020-05-16 15:01:30 +0000129
130/* Return if window has only two panes. */
nicmc426e482016-10-10 21:29:23 +0000131static int
nicmf03b6112020-05-16 15:01:30 +0000132screen_redraw_two_panes(struct window *w, int direction)
Nicholas Marriott7e4f8b42010-01-03 12:51:05 +0000133{
nicmf03b6112020-05-16 15:01:30 +0000134 struct window_pane *wp;
135
136 wp = TAILQ_NEXT(TAILQ_FIRST(&w->panes), entry);
137 if (wp == NULL)
138 return (0); /* one pane */
139 if (TAILQ_NEXT(wp, entry) != NULL)
140 return (0); /* more than two panes */
141 if (direction == 0 && wp->xoff == 0)
Nicholas Marriott7e4f8b42010-01-03 12:51:05 +0000142 return (0);
nicmf03b6112020-05-16 15:01:30 +0000143 if (direction == 1 && wp->yoff == 0)
144 return (0);
145 return (1);
146}
147
148/* Check if cell is on the border of a pane. */
149static enum screen_redraw_border_type
150screen_redraw_pane_border(struct window_pane *wp, u_int px, u_int py,
151 int pane_status)
152{
153 u_int ex = wp->xoff + wp->sx, ey = wp->yoff + wp->sy;
154
155 /* Inside pane. */
156 if (px >= wp->xoff && px < ex && py >= wp->yoff && py < ey)
157 return (SCREEN_REDRAW_INSIDE);
Nicholas Marriott7e4f8b42010-01-03 12:51:05 +0000158
159 /* Left/right borders. */
nicmf03b6112020-05-16 15:01:30 +0000160 if (pane_status == PANE_STATUS_OFF) {
161 if (screen_redraw_two_panes(wp->window, 0)) {
162 if (wp->xoff == 0 && px == wp->sx && py <= wp->sy / 2)
163 return (SCREEN_REDRAW_BORDER);
164 if (wp->xoff != 0 &&
165 px == wp->xoff - 1 &&
166 py > wp->sy / 2)
167 return (SCREEN_REDRAW_BORDER);
168 } else {
169 if ((wp->yoff == 0 || py >= wp->yoff - 1) && py <= ey) {
170 if (wp->xoff != 0 && px == wp->xoff - 1)
171 return (SCREEN_REDRAW_BORDER);
172 if (px == ex)
173 return (SCREEN_REDRAW_BORDER);
174 }
175 }
176 } else {
177 if ((wp->yoff == 0 || py >= wp->yoff - 1) && py <= ey) {
178 if (wp->xoff != 0 && px == wp->xoff - 1)
179 return (SCREEN_REDRAW_BORDER);
180 if (px == ex)
181 return (SCREEN_REDRAW_BORDER);
182 }
Nicholas Marriott7e4f8b42010-01-03 12:51:05 +0000183 }
184
185 /* Top/bottom borders. */
nicmf03b6112020-05-16 15:01:30 +0000186 if (pane_status == PANE_STATUS_OFF) {
187 if (screen_redraw_two_panes(wp->window, 1)) {
188 if (wp->yoff == 0 && py == wp->sy && px <= wp->sx / 2)
189 return (SCREEN_REDRAW_BORDER);
190 if (wp->yoff != 0 &&
191 py == wp->yoff - 1 &&
192 px > wp->sx / 2)
193 return (SCREEN_REDRAW_BORDER);
194 } else {
195 if ((wp->xoff == 0 || px >= wp->xoff - 1) && px <= ex) {
196 if (wp->yoff != 0 && py == wp->yoff - 1)
197 return (SCREEN_REDRAW_BORDER);
198 if (py == ey)
199 return (SCREEN_REDRAW_BORDER);
200 }
201 }
202 } else if (pane_status == PANE_STATUS_TOP) {
203 if ((wp->xoff == 0 || px >= wp->xoff - 1) && px <= ex) {
204 if (wp->yoff != 0 && py == wp->yoff - 1)
205 return (SCREEN_REDRAW_BORDER);
206 }
207 } else {
208 if ((wp->xoff == 0 || px >= wp->xoff - 1) && px <= ex) {
209 if (py == ey)
210 return (SCREEN_REDRAW_BORDER);
211 }
Nicholas Marriott7e4f8b42010-01-03 12:51:05 +0000212 }
213
214 /* Outside pane. */
nicmf03b6112020-05-16 15:01:30 +0000215 return (SCREEN_REDRAW_OUTSIDE);
Nicholas Marriott7e4f8b42010-01-03 12:51:05 +0000216}
217
nicmf03b6112020-05-16 15:01:30 +0000218/* Check if a cell is on a border. */
nicmc426e482016-10-10 21:29:23 +0000219static int
nicmf03b6112020-05-16 15:01:30 +0000220screen_redraw_cell_border(struct client *c, u_int px, u_int py, int pane_status)
Nicholas Marriott13317382009-07-24 19:14:38 +0000221{
222 struct window *w = c->session->curw->window;
223 struct window_pane *wp;
nicmf03b6112020-05-16 15:01:30 +0000224
225 /* Outside the window? */
226 if (px > w->sx || py > w->sy)
227 return (0);
228
229 /* On the window border? */
230 if (px == w->sx || py == w->sy)
231 return (1);
Nicholas Marriott13317382009-07-24 19:14:38 +0000232
233 /* Check all the panes. */
234 TAILQ_FOREACH(wp, &w->panes, entry) {
235 if (!window_pane_visible(wp))
236 continue;
nicmf03b6112020-05-16 15:01:30 +0000237 switch (screen_redraw_pane_border(wp, px, py, pane_status)) {
238 case SCREEN_REDRAW_INSIDE:
239 return (0);
240 case SCREEN_REDRAW_BORDER:
241 return (1);
242 case SCREEN_REDRAW_OUTSIDE:
243 break;
244 }
Nicholas Marriott13317382009-07-24 19:14:38 +0000245 }
246
247 return (0);
nicmf03b6112020-05-16 15:01:30 +0000248}
249
250/* Work out type of border cell from surrounding cells. */
251static int
252screen_redraw_type_of_cell(struct client *c, u_int px, u_int py,
253 int pane_status)
254{
255 struct window *w = c->session->curw->window;
256 u_int sx = w->sx, sy = w->sy;
257 int borders = 0;
258
nicm5340bf52020-06-23 14:10:43 +0000259 /* Is this outside the window? */
nicm1f5e5202020-07-22 06:21:46 +0000260 if (px > sx || py > sy)
nicm5340bf52020-06-23 14:10:43 +0000261 return (CELL_OUTSIDE);
262
nicmf03b6112020-05-16 15:01:30 +0000263 /*
264 * Construct a bitmask of whether the cells to the left (bit 4), right,
265 * top, and bottom (bit 1) of this cell are borders.
266 */
267 if (px == 0 || screen_redraw_cell_border(c, px - 1, py, pane_status))
268 borders |= 8;
269 if (px <= sx && screen_redraw_cell_border(c, px + 1, py, pane_status))
270 borders |= 4;
271 if (pane_status == PANE_STATUS_TOP) {
272 if (py != 0 &&
273 screen_redraw_cell_border(c, px, py - 1, pane_status))
274 borders |= 2;
nicm5340bf52020-06-23 14:10:43 +0000275 if (screen_redraw_cell_border(c, px, py + 1, pane_status))
276 borders |= 1;
nicmb6aeb862020-06-27 10:23:10 +0000277 } else if (pane_status == PANE_STATUS_BOTTOM) {
nicmf03b6112020-05-16 15:01:30 +0000278 if (py == 0 ||
279 screen_redraw_cell_border(c, px, py - 1, pane_status))
nicm5340bf52020-06-23 14:10:43 +0000280 borders |= 2;
281 if (py != sy - 1 &&
282 screen_redraw_cell_border(c, px, py + 1, pane_status))
283 borders |= 1;
nicmb6aeb862020-06-27 10:23:10 +0000284 } else {
285 if (py == 0 ||
286 screen_redraw_cell_border(c, px, py - 1, pane_status))
287 borders |= 2;
288 if (screen_redraw_cell_border(c, px, py + 1, pane_status))
289 borders |= 1;
nicmf03b6112020-05-16 15:01:30 +0000290 }
nicmf03b6112020-05-16 15:01:30 +0000291
292 /*
293 * Figure out what kind of border this cell is. Only one bit set
294 * doesn't make sense (can't have a border cell with no others
295 * connected).
296 */
297 switch (borders) {
298 case 15: /* 1111, left right top bottom */
299 return (CELL_JOIN);
300 case 14: /* 1110, left right top */
301 return (CELL_BOTTOMJOIN);
302 case 13: /* 1101, left right bottom */
303 return (CELL_TOPJOIN);
304 case 12: /* 1100, left right */
nicm3dddc112021-02-05 12:29:18 +0000305 return (CELL_LEFTRIGHT);
nicmf03b6112020-05-16 15:01:30 +0000306 case 11: /* 1011, left top bottom */
307 return (CELL_RIGHTJOIN);
308 case 10: /* 1010, left top */
309 return (CELL_BOTTOMRIGHT);
310 case 9: /* 1001, left bottom */
311 return (CELL_TOPRIGHT);
312 case 7: /* 0111, right top bottom */
313 return (CELL_LEFTJOIN);
314 case 6: /* 0110, right top */
315 return (CELL_BOTTOMLEFT);
316 case 5: /* 0101, right bottom */
317 return (CELL_TOPLEFT);
318 case 3: /* 0011, top bottom */
nicm3dddc112021-02-05 12:29:18 +0000319 return (CELL_TOPBOTTOM);
nicmf03b6112020-05-16 15:01:30 +0000320 }
321 return (CELL_OUTSIDE);
Nicholas Marriott13317382009-07-24 19:14:38 +0000322}
Nicholas Marriott029599c2009-07-24 16:21:42 +0000323
Nicholas Marriott35876ea2009-06-01 22:58:49 +0000324/* Check if cell inside a pane. */
nicmc426e482016-10-10 21:29:23 +0000325static int
nicm0509be02016-04-29 15:00:48 +0000326screen_redraw_check_cell(struct client *c, u_int px, u_int py, int pane_status,
Nicholas Marriott111d9932013-03-25 11:41:49 +0000327 struct window_pane **wpp)
Nicholas Marriott35876ea2009-06-01 22:58:49 +0000328{
329 struct window *w = c->session->curw->window;
nicm303d3422020-05-16 16:20:59 +0000330 struct window_pane *wp, *active;
nicmf03b6112020-05-16 15:01:30 +0000331 int border;
nicm0509be02016-04-29 15:00:48 +0000332 u_int right, line;
nicmc426e482016-10-10 21:29:23 +0000333
334 *wpp = NULL;
Nicholas Marriott35876ea2009-06-01 22:58:49 +0000335
nicm1f5e5202020-07-22 06:21:46 +0000336 if (px > w->sx || py > w->sy)
Nicholas Marriott029599c2009-07-24 16:21:42 +0000337 return (CELL_OUTSIDE);
nicmf03b6112020-05-16 15:01:30 +0000338 if (px == w->sx || py == w->sy) /* window border */
339 return (screen_redraw_type_of_cell(c, px, py, pane_status));
nicm0509be02016-04-29 15:00:48 +0000340
nicmd83f3562019-06-26 13:03:47 +0000341 if (pane_status != PANE_STATUS_OFF) {
nicm303d3422020-05-16 16:20:59 +0000342 active = wp = server_client_get_pane(c);
nicmf03b6112020-05-16 15:01:30 +0000343 do {
nicm0509be02016-04-29 15:00:48 +0000344 if (!window_pane_visible(wp))
nicmf03b6112020-05-16 15:01:30 +0000345 goto next1;
nicm0509be02016-04-29 15:00:48 +0000346
nicmd83f3562019-06-26 13:03:47 +0000347 if (pane_status == PANE_STATUS_TOP)
nicm0509be02016-04-29 15:00:48 +0000348 line = wp->yoff - 1;
349 else
350 line = wp->yoff + wp->sy;
351 right = wp->xoff + 2 + wp->status_size - 1;
352
353 if (py == line && px >= wp->xoff + 2 && px <= right)
354 return (CELL_INSIDE);
nicmf03b6112020-05-16 15:01:30 +0000355
356 next1:
357 wp = TAILQ_NEXT(wp, entry);
358 if (wp == NULL)
359 wp = TAILQ_FIRST(&w->panes);
nicm303d3422020-05-16 16:20:59 +0000360 } while (wp != active);
nicm0509be02016-04-29 15:00:48 +0000361 }
Nicholas Marriott35876ea2009-06-01 22:58:49 +0000362
nicm303d3422020-05-16 16:20:59 +0000363 active = wp = server_client_get_pane(c);
nicmf03b6112020-05-16 15:01:30 +0000364 do {
Nicholas Marriottfe20c0d2009-07-14 07:23:36 +0000365 if (!window_pane_visible(wp))
nicmf03b6112020-05-16 15:01:30 +0000366 goto next2;
Nicholas Marriott111d9932013-03-25 11:41:49 +0000367 *wpp = wp;
Nicholas Marriottfe20c0d2009-07-14 07:23:36 +0000368
nicmf03b6112020-05-16 15:01:30 +0000369 /*
370 * If definitely inside, return. If not on border, skip.
371 * Otherwise work out the cell.
372 */
373 border = screen_redraw_pane_border(wp, px, py, pane_status);
374 if (border == SCREEN_REDRAW_INSIDE)
Nicholas Marriott029599c2009-07-24 16:21:42 +0000375 return (CELL_INSIDE);
nicmf03b6112020-05-16 15:01:30 +0000376 if (border == SCREEN_REDRAW_OUTSIDE)
377 goto next2;
378 return (screen_redraw_type_of_cell(c, px, py, pane_status));
Nicholas Marriott35876ea2009-06-01 22:58:49 +0000379
nicmf03b6112020-05-16 15:01:30 +0000380 next2:
381 wp = TAILQ_NEXT(wp, entry);
382 if (wp == NULL)
383 wp = TAILQ_FIRST(&w->panes);
nicm303d3422020-05-16 16:20:59 +0000384 } while (wp != active);
Nicholas Marriott35876ea2009-06-01 22:58:49 +0000385
Nicholas Marriott029599c2009-07-24 16:21:42 +0000386 return (CELL_OUTSIDE);
Nicholas Marriott111d9932013-03-25 11:41:49 +0000387}
388
nicma8638342015-06-04 11:43:51 +0000389/* Check if the border of a particular pane. */
nicmc426e482016-10-10 21:29:23 +0000390static int
nicmf03b6112020-05-16 15:01:30 +0000391screen_redraw_check_is(u_int px, u_int py, int pane_status,
392 struct window_pane *wp)
Nicholas Marriott111d9932013-03-25 11:41:49 +0000393{
nicmf03b6112020-05-16 15:01:30 +0000394 enum screen_redraw_border_type border;
nicm0509be02016-04-29 15:00:48 +0000395
nicmf03b6112020-05-16 15:01:30 +0000396 border = screen_redraw_pane_border(wp, px, py, pane_status);
397 if (border == SCREEN_REDRAW_BORDER)
Nicholas Marriott111d9932013-03-25 11:41:49 +0000398 return (1);
nicmf03b6112020-05-16 15:01:30 +0000399 return (0);
nicm0509be02016-04-29 15:00:48 +0000400}
401
402/* Update pane status. */
nicmc426e482016-10-10 21:29:23 +0000403static int
nicm5340bf52020-06-23 14:10:43 +0000404screen_redraw_make_pane_status(struct client *c, struct window_pane *wp,
405 struct screen_redraw_ctx *rctx, int pane_lines)
nicm0509be02016-04-29 15:00:48 +0000406{
nicm5340bf52020-06-23 14:10:43 +0000407 struct window *w = wp->window;
nicm0509be02016-04-29 15:00:48 +0000408 struct grid_cell gc;
409 const char *fmt;
410 struct format_tree *ft;
nicm97931382019-03-18 20:53:33 +0000411 char *expanded;
nicm5340bf52020-06-23 14:10:43 +0000412 int pane_status = rctx->pane_status;
nicmf6095ca2020-12-07 09:46:58 +0000413 u_int width, i, cell_type, px, py;
nicm0509be02016-04-29 15:00:48 +0000414 struct screen_write_ctx ctx;
nicme0add112016-10-12 17:36:52 +0000415 struct screen old;
nicm0509be02016-04-29 15:00:48 +0000416
nicm90dba3e2019-07-24 21:16:17 +0000417 ft = format_create(c, NULL, FORMAT_PANE|wp->id, FORMAT_STATUS);
nicmf03b6112020-05-16 15:01:30 +0000418 format_defaults(ft, c, c->session, c->session->curw, wp);
419
nicm303d3422020-05-16 16:20:59 +0000420 if (wp == server_client_get_pane(c))
nicmf03b6112020-05-16 15:01:30 +0000421 style_apply(&gc, w->options, "pane-active-border-style", ft);
422 else
423 style_apply(&gc, w->options, "pane-border-style", ft);
424 fmt = options_get_string(w->options, "pane-border-format");
nicm0509be02016-04-29 15:00:48 +0000425
nicm97931382019-03-18 20:53:33 +0000426 expanded = format_expand_time(ft, fmt);
nicme3b13582019-04-17 14:41:08 +0000427 if (wp->sx < 4)
428 wp->status_size = width = 0;
429 else
430 wp->status_size = width = wp->sx - 4;
nicm97931382019-03-18 20:53:33 +0000431
nicme0add112016-10-12 17:36:52 +0000432 memcpy(&old, &wp->status_screen, sizeof old);
nicm97931382019-03-18 20:53:33 +0000433 screen_init(&wp->status_screen, width, 1, 0);
nicm0509be02016-04-29 15:00:48 +0000434 wp->status_screen.mode = 0;
435
nicm9605b082020-05-16 15:34:08 +0000436 screen_write_start(&ctx, &wp->status_screen);
nicm97931382019-03-18 20:53:33 +0000437
nicm5340bf52020-06-23 14:10:43 +0000438 for (i = 0; i < width; i++) {
439 px = wp->xoff + 2 + i;
440 if (rctx->pane_status == PANE_STATUS_TOP)
nicmf6095ca2020-12-07 09:46:58 +0000441 py = wp->yoff - 1;
nicm5340bf52020-06-23 14:10:43 +0000442 else
nicmf6095ca2020-12-07 09:46:58 +0000443 py = wp->yoff + wp->sy;
nicm5340bf52020-06-23 14:10:43 +0000444 cell_type = screen_redraw_type_of_cell(c, px, py, pane_status);
445 screen_redraw_border_set(wp, pane_lines, cell_type, &gc);
nicme2a26742020-05-16 16:26:34 +0000446 screen_write_cell(&ctx, &gc);
nicm5340bf52020-06-23 14:10:43 +0000447 }
nicm97931382019-03-18 20:53:33 +0000448 gc.attr &= ~GRID_ATTR_CHARSET;
449
nicm938156d2019-03-12 20:02:47 +0000450 screen_write_cursormove(&ctx, 0, 0, 0);
nicm97931382019-03-18 20:53:33 +0000451 format_draw(&ctx, &gc, width, expanded, NULL);
nicm0509be02016-04-29 15:00:48 +0000452 screen_write_stop(&ctx);
453
nicm97931382019-03-18 20:53:33 +0000454 free(expanded);
nicm0509be02016-04-29 15:00:48 +0000455 format_free(ft);
nicme0add112016-10-12 17:36:52 +0000456
457 if (grid_compare(wp->status_screen.grid, old.grid) == 0) {
458 screen_free(&old);
459 return (0);
460 }
461 screen_free(&old);
462 return (1);
nicm0509be02016-04-29 15:00:48 +0000463}
464
465/* Draw pane status. */
nicmc426e482016-10-10 21:29:23 +0000466static void
nicm3bc08b02018-08-18 16:14:03 +0000467screen_redraw_draw_pane_status(struct screen_redraw_ctx *ctx)
nicm0509be02016-04-29 15:00:48 +0000468{
nicm88327c72018-08-19 16:45:03 +0000469 struct client *c = ctx->c;
nicm0509be02016-04-29 15:00:48 +0000470 struct window *w = c->session->curw->window;
nicm0509be02016-04-29 15:00:48 +0000471 struct tty *tty = &c->tty;
472 struct window_pane *wp;
nicm64699532018-10-18 08:38:01 +0000473 struct screen *s;
474 u_int i, x, width, xoff, yoff, size;
nicm0509be02016-04-29 15:00:48 +0000475
nicm64699532018-10-18 08:38:01 +0000476 log_debug("%s: %s @%u", __func__, c->name, w->id);
477
nicm0509be02016-04-29 15:00:48 +0000478 TAILQ_FOREACH(wp, &w->panes, entry) {
nicme0add112016-10-12 17:36:52 +0000479 if (!window_pane_visible(wp))
480 continue;
nicm64699532018-10-18 08:38:01 +0000481 s = &wp->status_screen;
482
483 size = wp->status_size;
nicmd83f3562019-06-26 13:03:47 +0000484 if (ctx->pane_status == PANE_STATUS_TOP)
nicm0509be02016-04-29 15:00:48 +0000485 yoff = wp->yoff - 1;
486 else
487 yoff = wp->yoff + wp->sy;
nicm64699532018-10-18 08:38:01 +0000488 xoff = wp->xoff + 2;
nicm0509be02016-04-29 15:00:48 +0000489
nicm64699532018-10-18 08:38:01 +0000490 if (xoff + size <= ctx->ox ||
491 xoff >= ctx->ox + ctx->sx ||
492 yoff < ctx->oy ||
493 yoff >= ctx->oy + ctx->sy)
494 continue;
495
496 if (xoff >= ctx->ox && xoff + size <= ctx->ox + ctx->sx) {
497 /* All visible. */
498 i = 0;
499 x = xoff - ctx->ox;
500 width = size;
501 } else if (xoff < ctx->ox && xoff + size > ctx->ox + ctx->sx) {
502 /* Both left and right not visible. */
503 i = ctx->ox;
504 x = 0;
505 width = ctx->sx;
506 } else if (xoff < ctx->ox) {
507 /* Left not visible. */
508 i = ctx->ox - xoff;
509 x = 0;
510 width = size - i;
511 } else {
512 /* Right not visible. */
513 i = 0;
514 x = xoff - ctx->ox;
515 width = size - x;
516 }
517
nicm89db3092019-05-07 20:01:41 +0000518 if (ctx->statustop)
519 yoff += ctx->statuslines;
nicm9605b082020-05-16 15:34:08 +0000520 tty_draw_line(tty, s, i, 0, width, x, yoff - ctx->oy,
521 &grid_default_cell, NULL);
nicm0509be02016-04-29 15:00:48 +0000522 }
523 tty_cursor(tty, 0, 0);
Nicholas Marriott35876ea2009-06-01 22:58:49 +0000524}
525
nicmb8f2dd82016-10-09 16:24:34 +0000526/* Update status line and change flags if unchanged. */
nicmcac4ead2018-08-19 20:13:07 +0000527static int
528screen_redraw_update(struct client *c, int flags)
nicmb8f2dd82016-10-09 16:24:34 +0000529{
530 struct window *w = c->session->curw->window;
531 struct window_pane *wp;
532 struct options *wo = w->options;
nicme2a26742020-05-16 16:26:34 +0000533 int redraw, lines;
nicm5340bf52020-06-23 14:10:43 +0000534 struct screen_redraw_ctx ctx;
nicmb8f2dd82016-10-09 16:24:34 +0000535
536 if (c->message_string != NULL)
537 redraw = status_message_redraw(c);
538 else if (c->prompt_string != NULL)
539 redraw = status_prompt_redraw(c);
540 else
541 redraw = status_redraw(c);
nicmcac4ead2018-08-19 20:13:07 +0000542 if (!redraw && (~flags & CLIENT_REDRAWSTATUSALWAYS))
543 flags &= ~CLIENT_REDRAWSTATUS;
nicmb8f2dd82016-10-09 16:24:34 +0000544
nicm5fef9462019-05-26 18:27:52 +0000545 if (c->overlay_draw != NULL)
546 flags |= CLIENT_REDRAWOVERLAY;
547
nicmd83f3562019-06-26 13:03:47 +0000548 if (options_get_number(wo, "pane-border-status") != PANE_STATUS_OFF) {
nicm5340bf52020-06-23 14:10:43 +0000549 screen_redraw_set_context(c, &ctx);
nicme2a26742020-05-16 16:26:34 +0000550 lines = options_get_number(wo, "pane-border-lines");
nicmb8f2dd82016-10-09 16:24:34 +0000551 redraw = 0;
552 TAILQ_FOREACH(wp, &w->panes, entry) {
nicm5340bf52020-06-23 14:10:43 +0000553 if (screen_redraw_make_pane_status(c, wp, &ctx, lines))
nicmb8f2dd82016-10-09 16:24:34 +0000554 redraw = 1;
555 }
556 if (redraw)
nicmcac4ead2018-08-19 20:13:07 +0000557 flags |= CLIENT_REDRAWBORDERS;
nicmb8f2dd82016-10-09 16:24:34 +0000558 }
nicmcac4ead2018-08-19 20:13:07 +0000559 return (flags);
nicmb8f2dd82016-10-09 16:24:34 +0000560}
561
nicm3bc08b02018-08-18 16:14:03 +0000562/* Set up redraw context. */
563static void
564screen_redraw_set_context(struct client *c, struct screen_redraw_ctx *ctx)
565{
nicm88327c72018-08-19 16:45:03 +0000566 struct session *s = c->session;
567 struct options *oo = s->options;
568 struct window *w = s->curw->window;
569 struct options *wo = w->options;
nicm89db3092019-05-07 20:01:41 +0000570 u_int lines;
nicm3bc08b02018-08-18 16:14:03 +0000571
572 memset(ctx, 0, sizeof *ctx);
573 ctx->c = c;
574
nicm89db3092019-05-07 20:01:41 +0000575 lines = status_line_size(c);
nicm64699532018-10-18 08:38:01 +0000576 if (c->message_string != NULL || c->prompt_string != NULL)
nicm89db3092019-05-07 20:01:41 +0000577 lines = (lines == 0) ? 1 : lines;
578 if (lines != 0 && options_get_number(oo, "status-position") == 0)
579 ctx->statustop = 1;
580 ctx->statuslines = lines;
581
nicm3bc08b02018-08-18 16:14:03 +0000582 ctx->pane_status = options_get_number(wo, "pane-border-status");
nicme2a26742020-05-16 16:26:34 +0000583 ctx->pane_lines = options_get_number(wo, "pane-border-lines");
nicm3bc08b02018-08-18 16:14:03 +0000584
nicm64699532018-10-18 08:38:01 +0000585 tty_window_offset(&c->tty, &ctx->ox, &ctx->oy, &ctx->sx, &ctx->sy);
586
587 log_debug("%s: %s @%u ox=%u oy=%u sx=%u sy=%u %u/%d", __func__, c->name,
nicm89db3092019-05-07 20:01:41 +0000588 w->id, ctx->ox, ctx->oy, ctx->sx, ctx->sy, ctx->statuslines,
589 ctx->statustop);
nicm3bc08b02018-08-18 16:14:03 +0000590}
591
Nicholas Marriottae2ea522009-07-14 19:03:16 +0000592/* Redraw entire screen. */
Nicholas Marriott35876ea2009-06-01 22:58:49 +0000593void
nicm88327c72018-08-19 16:45:03 +0000594screen_redraw_screen(struct client *c)
Nicholas Marriott35876ea2009-06-01 22:58:49 +0000595{
nicm88327c72018-08-19 16:45:03 +0000596 struct screen_redraw_ctx ctx;
nicmcac4ead2018-08-19 20:13:07 +0000597 int flags;
Nicholas Marriott35876ea2009-06-01 22:58:49 +0000598
Nicholas Marriottd5269a22011-07-08 21:51:40 +0000599 if (c->flags & CLIENT_SUSPENDED)
600 return;
601
nicmcac4ead2018-08-19 20:13:07 +0000602 flags = screen_redraw_update(c, c->flags);
nicm21a39c92020-05-16 14:42:06 +0000603 if ((flags & CLIENT_ALLREDRAWFLAGS) == 0)
604 return;
605
nicm3bc08b02018-08-18 16:14:03 +0000606 screen_redraw_set_context(c, &ctx);
nicmb2443aa2020-04-16 13:35:24 +0000607 tty_sync_start(&c->tty);
nicmff860e52021-04-13 05:25:05 +0000608 tty_update_mode(&c->tty, c->tty.mode, NULL);
nicm2f6935a2017-10-16 19:30:53 +0000609
nicmcac4ead2018-08-19 20:13:07 +0000610 if (flags & (CLIENT_REDRAWWINDOW|CLIENT_REDRAWBORDERS)) {
nicm1d2bd862020-04-18 06:20:50 +0000611 log_debug("%s: redrawing borders", c->name);
nicmd83f3562019-06-26 13:03:47 +0000612 if (ctx.pane_status != PANE_STATUS_OFF)
nicm88327c72018-08-19 16:45:03 +0000613 screen_redraw_draw_pane_status(&ctx);
nicmd0a600c2018-08-14 11:31:34 +0000614 screen_redraw_draw_borders(&ctx);
nicm88327c72018-08-19 16:45:03 +0000615 }
nicm1d2bd862020-04-18 06:20:50 +0000616 if (flags & CLIENT_REDRAWWINDOW) {
617 log_debug("%s: redrawing panes", c->name);
nicmd0a600c2018-08-14 11:31:34 +0000618 screen_redraw_draw_panes(&ctx);
nicm1d2bd862020-04-18 06:20:50 +0000619 }
nicm89db3092019-05-07 20:01:41 +0000620 if (ctx.statuslines != 0 &&
nicm1d2bd862020-04-18 06:20:50 +0000621 (flags & (CLIENT_REDRAWSTATUS|CLIENT_REDRAWSTATUSALWAYS))) {
622 log_debug("%s: redrawing status", c->name);
nicmd0a600c2018-08-14 11:31:34 +0000623 screen_redraw_draw_status(&ctx);
nicm1d2bd862020-04-18 06:20:50 +0000624 }
625 if (c->overlay_draw != NULL && (flags & CLIENT_REDRAWOVERLAY)) {
626 log_debug("%s: redrawing overlay", c->name);
nicm77896392021-08-13 18:54:54 +0000627 c->overlay_draw(c, c->overlay_data, &ctx);
nicm1d2bd862020-04-18 06:20:50 +0000628 }
nicmb2443aa2020-04-16 13:35:24 +0000629
nicm3bc08b02018-08-18 16:14:03 +0000630 tty_reset(&c->tty);
Nicholas Marriott35876ea2009-06-01 22:58:49 +0000631}
632
nicm64699532018-10-18 08:38:01 +0000633/* Redraw a single pane. */
Nicholas Marriott35876ea2009-06-01 22:58:49 +0000634void
635screen_redraw_pane(struct client *c, struct window_pane *wp)
636{
nicm64699532018-10-18 08:38:01 +0000637 struct screen_redraw_ctx ctx;
Nicholas Marriott230d0fb2012-01-29 09:37:02 +0000638
nicm93cc8df2021-08-05 09:43:51 +0000639 if (!window_pane_visible(wp))
Nicholas Marriott446fb0c2013-03-25 10:12:01 +0000640 return;
641
nicm64699532018-10-18 08:38:01 +0000642 screen_redraw_set_context(c, &ctx);
nicmb2443aa2020-04-16 13:35:24 +0000643 tty_sync_start(&c->tty);
nicmff860e52021-04-13 05:25:05 +0000644 tty_update_mode(&c->tty, c->tty.mode, NULL);
Nicholas Marriott35876ea2009-06-01 22:58:49 +0000645
nicm64699532018-10-18 08:38:01 +0000646 screen_redraw_draw_pane(&ctx, wp);
nicmb2443aa2020-04-16 13:35:24 +0000647
Nicholas Marriott181e1bc2009-08-10 19:42:03 +0000648 tty_reset(&c->tty);
Nicholas Marriott35876ea2009-06-01 22:58:49 +0000649}
Nicholas Marriott04319962009-08-31 20:46:19 +0000650
nicmf03b6112020-05-16 15:01:30 +0000651/* Get border cell style. */
652static const struct grid_cell *
653screen_redraw_draw_borders_style(struct screen_redraw_ctx *ctx, u_int x,
654 u_int y, struct window_pane *wp)
nicmd0a600c2018-08-14 11:31:34 +0000655{
nicm88327c72018-08-19 16:45:03 +0000656 struct client *c = ctx->c;
657 struct session *s = c->session;
658 struct window *w = s->curw->window;
nicm303d3422020-05-16 16:20:59 +0000659 struct window_pane *active = server_client_get_pane(c);
nicmf03b6112020-05-16 15:01:30 +0000660 struct options *oo = w->options;
nicmf03b6112020-05-16 15:01:30 +0000661 struct format_tree *ft;
662
663 if (wp->border_gc_set)
664 return (&wp->border_gc);
665 wp->border_gc_set = 1;
666
667 ft = format_create_defaults(NULL, c, s, s->curw, wp);
nicme2a26742020-05-16 16:26:34 +0000668 if (screen_redraw_check_is(x, y, ctx->pane_status, active))
669 style_apply(&wp->border_gc, oo, "pane-active-border-style", ft);
670 else
671 style_apply(&wp->border_gc, oo, "pane-border-style", ft);
nicmf03b6112020-05-16 15:01:30 +0000672 format_free(ft);
nicme2a26742020-05-16 16:26:34 +0000673
674 return (&wp->border_gc);
nicmf03b6112020-05-16 15:01:30 +0000675}
676
677/* Draw a border cell. */
678static void
679screen_redraw_draw_borders_cell(struct screen_redraw_ctx *ctx, u_int i, u_int j)
680{
681 struct client *c = ctx->c;
682 struct session *s = c->session;
nicm90136002021-08-11 09:05:21 +0000683 struct window *w = s->curw->window;
684 struct options *oo = w->options;
nicm88327c72018-08-19 16:45:03 +0000685 struct tty *tty = &c->tty;
nicm90136002021-08-11 09:05:21 +0000686 struct format_tree *ft;
nicm88327c72018-08-19 16:45:03 +0000687 struct window_pane *wp;
nicme2a26742020-05-16 16:26:34 +0000688 u_int cell_type, x = ctx->ox + i, y = ctx->oy + j;
nicm3dddc112021-02-05 12:29:18 +0000689 int pane_status = ctx->pane_status, isolates;
nicme2a26742020-05-16 16:26:34 +0000690 struct grid_cell gc;
691 const struct grid_cell *tmp;
nicmd0a600c2018-08-14 11:31:34 +0000692
nicm77896392021-08-13 18:54:54 +0000693 if (c->overlay_check != NULL &&
694 !c->overlay_check(c, c->overlay_data, x, y))
nicm8a838b02020-03-24 08:09:43 +0000695 return;
nicmf03b6112020-05-16 15:01:30 +0000696
nicme2a26742020-05-16 16:26:34 +0000697 cell_type = screen_redraw_check_cell(c, x, y, pane_status, &wp);
698 if (cell_type == CELL_INSIDE)
nicmd0a600c2018-08-14 11:31:34 +0000699 return;
nicmd0a600c2018-08-14 11:31:34 +0000700
nicm90136002021-08-11 09:05:21 +0000701 if (wp == NULL) {
702 if (!ctx->no_pane_gc_set) {
703 ft = format_create_defaults(NULL, c, s, s->curw, NULL);
704 memcpy(&ctx->no_pane_gc, &grid_default_cell, sizeof gc);
705 style_add(&ctx->no_pane_gc, oo, "pane-border-style",
706 ft);
707 format_free(ft);
708 ctx->no_pane_gc_set = 1;
709 }
710 memcpy(&gc, &ctx->no_pane_gc, sizeof gc);
711 } else {
nicme2a26742020-05-16 16:26:34 +0000712 tmp = screen_redraw_draw_borders_style(ctx, x, y, wp);
713 if (tmp == NULL)
nicmf03b6112020-05-16 15:01:30 +0000714 return;
nicme2a26742020-05-16 16:26:34 +0000715 memcpy(&gc, tmp, sizeof gc);
nicmf03b6112020-05-16 15:01:30 +0000716
717 if (server_is_marked(s, s->curw, marked_pane.wp) &&
nicme2a26742020-05-16 16:26:34 +0000718 screen_redraw_check_is(x, y, pane_status, marked_pane.wp))
719 gc.attr ^= GRID_ATTR_REVERSE;
nicmf03b6112020-05-16 15:01:30 +0000720 }
nicme2a26742020-05-16 16:26:34 +0000721 screen_redraw_border_set(wp, ctx->pane_lines, cell_type, &gc);
nicmf03b6112020-05-16 15:01:30 +0000722
nicm3dddc112021-02-05 12:29:18 +0000723 if (cell_type == CELL_TOPBOTTOM &&
724 (c->flags & CLIENT_UTF8) &&
725 tty_term_has(tty->term, TTYC_BIDI))
726 isolates = 1;
727 else
728 isolates = 0;
729
nicm89db3092019-05-07 20:01:41 +0000730 if (ctx->statustop)
731 tty_cursor(tty, i, ctx->statuslines + j);
nicmd0a600c2018-08-14 11:31:34 +0000732 else
nicm64699532018-10-18 08:38:01 +0000733 tty_cursor(tty, i, j);
nicm3dddc112021-02-05 12:29:18 +0000734 if (isolates)
735 tty_puts(tty, END_ISOLATE);
nicme2a26742020-05-16 16:26:34 +0000736 tty_cell(tty, &gc, &grid_default_cell, NULL);
nicm3dddc112021-02-05 12:29:18 +0000737 if (isolates)
738 tty_puts(tty, START_ISOLATE);
nicmd0a600c2018-08-14 11:31:34 +0000739}
740
nicm9f02feb2014-01-31 14:19:24 +0000741/* Draw the borders. */
nicmc426e482016-10-10 21:29:23 +0000742static void
nicmd0a600c2018-08-14 11:31:34 +0000743screen_redraw_draw_borders(struct screen_redraw_ctx *ctx)
nicm9f02feb2014-01-31 14:19:24 +0000744{
nicmd0a600c2018-08-14 11:31:34 +0000745 struct client *c = ctx->c;
nicma8638342015-06-04 11:43:51 +0000746 struct session *s = c->session;
747 struct window *w = s->curw->window;
nicmf03b6112020-05-16 15:01:30 +0000748 struct window_pane *wp;
nicm64699532018-10-18 08:38:01 +0000749 u_int i, j;
nicme0929262014-11-14 02:19:47 +0000750
nicm64699532018-10-18 08:38:01 +0000751 log_debug("%s: %s @%u", __func__, c->name, w->id);
nicm9f02feb2014-01-31 14:19:24 +0000752
nicmf03b6112020-05-16 15:01:30 +0000753 TAILQ_FOREACH(wp, &w->panes, entry)
754 wp->border_gc_set = 0;
nicm9f02feb2014-01-31 14:19:24 +0000755
nicmf03b6112020-05-16 15:01:30 +0000756 for (j = 0; j < c->tty.sy - ctx->statuslines; j++) {
757 for (i = 0; i < c->tty.sx; i++)
758 screen_redraw_draw_borders_cell(ctx, i, j);
nicme0929262014-11-14 02:19:47 +0000759 }
nicm9f02feb2014-01-31 14:19:24 +0000760}
761
762/* Draw the panes. */
nicmc426e482016-10-10 21:29:23 +0000763static void
nicmd0a600c2018-08-14 11:31:34 +0000764screen_redraw_draw_panes(struct screen_redraw_ctx *ctx)
nicm9f02feb2014-01-31 14:19:24 +0000765{
nicmd0a600c2018-08-14 11:31:34 +0000766 struct client *c = ctx->c;
nicm9f02feb2014-01-31 14:19:24 +0000767 struct window *w = c->session->curw->window;
nicm9f02feb2014-01-31 14:19:24 +0000768 struct window_pane *wp;
nicm2f6935a2017-10-16 19:30:53 +0000769
nicm64699532018-10-18 08:38:01 +0000770 log_debug("%s: %s @%u", __func__, c->name, w->id);
771
nicm9f02feb2014-01-31 14:19:24 +0000772 TAILQ_FOREACH(wp, &w->panes, entry) {
nicm89db3092019-05-07 20:01:41 +0000773 if (window_pane_visible(wp))
774 screen_redraw_draw_pane(ctx, wp);
nicm9f02feb2014-01-31 14:19:24 +0000775 }
776}
777
778/* Draw the status line. */
nicmc426e482016-10-10 21:29:23 +0000779static void
nicmd0a600c2018-08-14 11:31:34 +0000780screen_redraw_draw_status(struct screen_redraw_ctx *ctx)
nicm9f02feb2014-01-31 14:19:24 +0000781{
nicmd0a600c2018-08-14 11:31:34 +0000782 struct client *c = ctx->c;
nicm64699532018-10-18 08:38:01 +0000783 struct window *w = c->session->curw->window;
nicm9f02feb2014-01-31 14:19:24 +0000784 struct tty *tty = &c->tty;
nicmb588b172019-03-16 19:12:13 +0000785 struct screen *s = c->status.active;
nicm2f6935a2017-10-16 19:30:53 +0000786 u_int i, y;
nicm64699532018-10-18 08:38:01 +0000787
788 log_debug("%s: %s @%u", __func__, c->name, w->id);
nicm9f02feb2014-01-31 14:19:24 +0000789
nicm89db3092019-05-07 20:01:41 +0000790 if (ctx->statustop)
nicm2f6935a2017-10-16 19:30:53 +0000791 y = 0;
nicm9f02feb2014-01-31 14:19:24 +0000792 else
nicm89db3092019-05-07 20:01:41 +0000793 y = c->tty.sy - ctx->statuslines;
nicm9605b082020-05-16 15:34:08 +0000794 for (i = 0; i < ctx->statuslines; i++) {
795 tty_draw_line(tty, s, 0, i, UINT_MAX, 0, y + i,
796 &grid_default_cell, NULL);
797 }
nicm64699532018-10-18 08:38:01 +0000798}
799
800/* Draw one pane. */
801static void
802screen_redraw_draw_pane(struct screen_redraw_ctx *ctx, struct window_pane *wp)
803{
nicm7eea3d72021-08-11 20:49:55 +0000804 struct client *c = ctx->c;
805 struct window *w = c->session->curw->window;
806 struct tty *tty = &c->tty;
807 struct screen *s = wp->screen;
808 struct colour_palette *palette = &wp->palette;
809 struct grid_cell defaults;
810 u_int i, j, top, x, y, width;
nicm64699532018-10-18 08:38:01 +0000811
812 log_debug("%s: %s @%u %%%u", __func__, c->name, w->id, wp->id);
813
814 if (wp->xoff + wp->sx <= ctx->ox || wp->xoff >= ctx->ox + ctx->sx)
815 return;
nicm89db3092019-05-07 20:01:41 +0000816 if (ctx->statustop)
817 top = ctx->statuslines;
nicm64699532018-10-18 08:38:01 +0000818 else
819 top = 0;
nicm64699532018-10-18 08:38:01 +0000820 for (j = 0; j < wp->sy; j++) {
821 if (wp->yoff + j < ctx->oy || wp->yoff + j >= ctx->oy + ctx->sy)
822 continue;
823 y = top + wp->yoff + j - ctx->oy;
824
825 if (wp->xoff >= ctx->ox &&
826 wp->xoff + wp->sx <= ctx->ox + ctx->sx) {
827 /* All visible. */
828 i = 0;
829 x = wp->xoff - ctx->ox;
830 width = wp->sx;
831 } else if (wp->xoff < ctx->ox &&
832 wp->xoff + wp->sx > ctx->ox + ctx->sx) {
833 /* Both left and right not visible. */
834 i = ctx->ox;
835 x = 0;
836 width = ctx->sx;
837 } else if (wp->xoff < ctx->ox) {
838 /* Left not visible. */
839 i = ctx->ox - wp->xoff;
840 x = 0;
841 width = wp->sx - i;
842 } else {
843 /* Right not visible. */
844 i = 0;
845 x = wp->xoff - ctx->ox;
846 width = ctx->sx - x;
847 }
848 log_debug("%s: %s %%%u line %u,%u at %u,%u, width %u",
849 __func__, c->name, wp->id, i, j, x, y, width);
850
nicm9605b082020-05-16 15:34:08 +0000851 tty_default_colours(&defaults, wp);
nicm7eea3d72021-08-11 20:49:55 +0000852 tty_draw_line(tty, s, i, j, width, x, y, &defaults, palette);
nicm64699532018-10-18 08:38:01 +0000853 }
Nicholas Marriott04319962009-08-31 20:46:19 +0000854}