4 * Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
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.
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.
19 #include <sys/types.h>
26 static void screen_redraw_draw_borders(struct screen_redraw_ctx
*);
27 static void screen_redraw_draw_panes(struct screen_redraw_ctx
*);
28 static void screen_redraw_draw_status(struct screen_redraw_ctx
*);
29 static void screen_redraw_draw_pane(struct screen_redraw_ctx
*,
30 struct window_pane
*);
31 static void screen_redraw_set_context(struct client
*,
32 struct screen_redraw_ctx
*);
34 #define START_ISOLATE "\342\201\246"
35 #define END_ISOLATE "\342\201\251"
37 enum screen_redraw_border_type
{
38 SCREEN_REDRAW_OUTSIDE
,
43 /* Get cell border character. */
45 screen_redraw_border_set(struct window_pane
*wp
, enum pane_lines pane_lines
,
46 int cell_type
, struct grid_cell
*gc
)
51 case PANE_LINES_NUMBER
:
52 if (cell_type
== CELL_OUTSIDE
) {
53 gc
->attr
|= GRID_ATTR_CHARSET
;
54 utf8_set(&gc
->data
, CELL_BORDERS
[CELL_OUTSIDE
]);
57 gc
->attr
&= ~GRID_ATTR_CHARSET
;
58 if (wp
!= NULL
&& window_pane_index(wp
, &idx
) == 0)
59 utf8_set(&gc
->data
, '0' + (idx
% 10));
61 utf8_set(&gc
->data
, '*');
63 case PANE_LINES_DOUBLE
:
64 gc
->attr
&= ~GRID_ATTR_CHARSET
;
65 utf8_copy(&gc
->data
, tty_acs_double_borders(cell_type
));
67 case PANE_LINES_HEAVY
:
68 gc
->attr
&= ~GRID_ATTR_CHARSET
;
69 utf8_copy(&gc
->data
, tty_acs_heavy_borders(cell_type
));
71 case PANE_LINES_SIMPLE
:
72 gc
->attr
&= ~GRID_ATTR_CHARSET
;
73 utf8_set(&gc
->data
, SIMPLE_BORDERS
[cell_type
]);
76 gc
->attr
|= GRID_ATTR_CHARSET
;
77 utf8_set(&gc
->data
, CELL_BORDERS
[cell_type
]);
82 /* Return if window has only two panes. */
84 screen_redraw_two_panes(struct window
*w
, int direction
)
86 struct window_pane
*wp
;
88 wp
= TAILQ_NEXT(TAILQ_FIRST(&w
->panes
), entry
);
90 return (0); /* one pane */
91 if (TAILQ_NEXT(wp
, entry
) != NULL
)
92 return (0); /* more than two panes */
93 if (direction
== 0 && wp
->xoff
== 0)
95 if (direction
== 1 && wp
->yoff
== 0)
100 /* Check if cell is on the border of a pane. */
101 static enum screen_redraw_border_type
102 screen_redraw_pane_border(struct window_pane
*wp
, u_int px
, u_int py
,
105 u_int ex
= wp
->xoff
+ wp
->sx
, ey
= wp
->yoff
+ wp
->sy
;
108 if (px
>= wp
->xoff
&& px
< ex
&& py
>= wp
->yoff
&& py
< ey
)
109 return (SCREEN_REDRAW_INSIDE
);
111 /* Left/right borders. */
112 if (pane_status
== PANE_STATUS_OFF
) {
113 if (screen_redraw_two_panes(wp
->window
, 0)) {
114 if (wp
->xoff
== 0 && px
== wp
->sx
&& py
<= wp
->sy
/ 2)
115 return (SCREEN_REDRAW_BORDER
);
117 px
== wp
->xoff
- 1 &&
119 return (SCREEN_REDRAW_BORDER
);
121 if ((wp
->yoff
== 0 || py
>= wp
->yoff
- 1) && py
<= ey
) {
122 if (wp
->xoff
!= 0 && px
== wp
->xoff
- 1)
123 return (SCREEN_REDRAW_BORDER
);
125 return (SCREEN_REDRAW_BORDER
);
129 if ((wp
->yoff
== 0 || py
>= wp
->yoff
- 1) && py
<= ey
) {
130 if (wp
->xoff
!= 0 && px
== wp
->xoff
- 1)
131 return (SCREEN_REDRAW_BORDER
);
133 return (SCREEN_REDRAW_BORDER
);
137 /* Top/bottom borders. */
138 if (pane_status
== PANE_STATUS_OFF
) {
139 if (screen_redraw_two_panes(wp
->window
, 1)) {
140 if (wp
->yoff
== 0 && py
== wp
->sy
&& px
<= wp
->sx
/ 2)
141 return (SCREEN_REDRAW_BORDER
);
143 py
== wp
->yoff
- 1 &&
145 return (SCREEN_REDRAW_BORDER
);
147 if ((wp
->xoff
== 0 || px
>= wp
->xoff
- 1) && px
<= ex
) {
148 if (wp
->yoff
!= 0 && py
== wp
->yoff
- 1)
149 return (SCREEN_REDRAW_BORDER
);
151 return (SCREEN_REDRAW_BORDER
);
154 } else if (pane_status
== PANE_STATUS_TOP
) {
155 if ((wp
->xoff
== 0 || px
>= wp
->xoff
- 1) && px
<= ex
) {
156 if (wp
->yoff
!= 0 && py
== wp
->yoff
- 1)
157 return (SCREEN_REDRAW_BORDER
);
160 if ((wp
->xoff
== 0 || px
>= wp
->xoff
- 1) && px
<= ex
) {
162 return (SCREEN_REDRAW_BORDER
);
167 return (SCREEN_REDRAW_OUTSIDE
);
170 /* Check if a cell is on a border. */
172 screen_redraw_cell_border(struct client
*c
, u_int px
, u_int py
, int pane_status
)
174 struct window
*w
= c
->session
->curw
->window
;
175 struct window_pane
*wp
;
177 /* Outside the window? */
178 if (px
> w
->sx
|| py
> w
->sy
)
181 /* On the window border? */
182 if (px
== w
->sx
|| py
== w
->sy
)
185 /* Check all the panes. */
186 TAILQ_FOREACH(wp
, &w
->panes
, entry
) {
187 if (!window_pane_visible(wp
))
189 switch (screen_redraw_pane_border(wp
, px
, py
, pane_status
)) {
190 case SCREEN_REDRAW_INSIDE
:
192 case SCREEN_REDRAW_BORDER
:
194 case SCREEN_REDRAW_OUTSIDE
:
202 /* Work out type of border cell from surrounding cells. */
204 screen_redraw_type_of_cell(struct client
*c
, u_int px
, u_int py
,
207 struct window
*w
= c
->session
->curw
->window
;
208 u_int sx
= w
->sx
, sy
= w
->sy
;
211 /* Is this outside the window? */
212 if (px
> sx
|| py
> sy
)
213 return (CELL_OUTSIDE
);
216 * Construct a bitmask of whether the cells to the left (bit 4), right,
217 * top, and bottom (bit 1) of this cell are borders.
219 if (px
== 0 || screen_redraw_cell_border(c
, px
- 1, py
, pane_status
))
221 if (px
<= sx
&& screen_redraw_cell_border(c
, px
+ 1, py
, pane_status
))
223 if (pane_status
== PANE_STATUS_TOP
) {
225 screen_redraw_cell_border(c
, px
, py
- 1, pane_status
))
227 if (screen_redraw_cell_border(c
, px
, py
+ 1, pane_status
))
229 } else if (pane_status
== PANE_STATUS_BOTTOM
) {
231 screen_redraw_cell_border(c
, px
, py
- 1, pane_status
))
234 screen_redraw_cell_border(c
, px
, py
+ 1, pane_status
))
238 screen_redraw_cell_border(c
, px
, py
- 1, pane_status
))
240 if (screen_redraw_cell_border(c
, px
, py
+ 1, pane_status
))
245 * Figure out what kind of border this cell is. Only one bit set
246 * doesn't make sense (can't have a border cell with no others
250 case 15: /* 1111, left right top bottom */
252 case 14: /* 1110, left right top */
253 return (CELL_BOTTOMJOIN
);
254 case 13: /* 1101, left right bottom */
255 return (CELL_TOPJOIN
);
256 case 12: /* 1100, left right */
257 return (CELL_LEFTRIGHT
);
258 case 11: /* 1011, left top bottom */
259 return (CELL_RIGHTJOIN
);
260 case 10: /* 1010, left top */
261 return (CELL_BOTTOMRIGHT
);
262 case 9: /* 1001, left bottom */
263 return (CELL_TOPRIGHT
);
264 case 7: /* 0111, right top bottom */
265 return (CELL_LEFTJOIN
);
266 case 6: /* 0110, right top */
267 return (CELL_BOTTOMLEFT
);
268 case 5: /* 0101, right bottom */
269 return (CELL_TOPLEFT
);
270 case 3: /* 0011, top bottom */
271 return (CELL_TOPBOTTOM
);
273 return (CELL_OUTSIDE
);
276 /* Check if cell inside a pane. */
278 screen_redraw_check_cell(struct client
*c
, u_int px
, u_int py
, int pane_status
,
279 struct window_pane
**wpp
)
281 struct window
*w
= c
->session
->curw
->window
;
282 struct window_pane
*wp
, *active
;
288 if (px
> w
->sx
|| py
> w
->sy
)
289 return (CELL_OUTSIDE
);
290 if (px
== w
->sx
|| py
== w
->sy
) /* window border */
291 return (screen_redraw_type_of_cell(c
, px
, py
, pane_status
));
293 if (pane_status
!= PANE_STATUS_OFF
) {
294 active
= wp
= server_client_get_pane(c
);
296 if (!window_pane_visible(wp
))
299 if (pane_status
== PANE_STATUS_TOP
)
302 line
= wp
->yoff
+ wp
->sy
;
303 right
= wp
->xoff
+ 2 + wp
->status_size
- 1;
305 if (py
== line
&& px
>= wp
->xoff
+ 2 && px
<= right
)
306 return (CELL_INSIDE
);
309 wp
= TAILQ_NEXT(wp
, entry
);
311 wp
= TAILQ_FIRST(&w
->panes
);
312 } while (wp
!= active
);
315 active
= wp
= server_client_get_pane(c
);
317 if (!window_pane_visible(wp
))
322 * If definitely inside, return. If not on border, skip.
323 * Otherwise work out the cell.
325 border
= screen_redraw_pane_border(wp
, px
, py
, pane_status
);
326 if (border
== SCREEN_REDRAW_INSIDE
)
327 return (CELL_INSIDE
);
328 if (border
== SCREEN_REDRAW_OUTSIDE
)
330 return (screen_redraw_type_of_cell(c
, px
, py
, pane_status
));
333 wp
= TAILQ_NEXT(wp
, entry
);
335 wp
= TAILQ_FIRST(&w
->panes
);
336 } while (wp
!= active
);
338 return (CELL_OUTSIDE
);
341 /* Check if the border of a particular pane. */
343 screen_redraw_check_is(u_int px
, u_int py
, int pane_status
,
344 struct window_pane
*wp
)
346 enum screen_redraw_border_type border
;
348 border
= screen_redraw_pane_border(wp
, px
, py
, pane_status
);
349 if (border
== SCREEN_REDRAW_BORDER
)
354 /* Update pane status. */
356 screen_redraw_make_pane_status(struct client
*c
, struct window_pane
*wp
,
357 struct screen_redraw_ctx
*rctx
, enum pane_lines pane_lines
)
359 struct window
*w
= wp
->window
;
362 struct format_tree
*ft
;
364 int pane_status
= rctx
->pane_status
;
365 u_int width
, i
, cell_type
, px
, py
;
366 struct screen_write_ctx ctx
;
369 ft
= format_create(c
, NULL
, FORMAT_PANE
|wp
->id
, FORMAT_STATUS
);
370 format_defaults(ft
, c
, c
->session
, c
->session
->curw
, wp
);
372 if (wp
== server_client_get_pane(c
))
373 style_apply(&gc
, w
->options
, "pane-active-border-style", ft
);
375 style_apply(&gc
, w
->options
, "pane-border-style", ft
);
376 fmt
= options_get_string(wp
->options
, "pane-border-format");
378 expanded
= format_expand_time(ft
, fmt
);
380 wp
->status_size
= width
= 0;
382 wp
->status_size
= width
= wp
->sx
- 4;
384 memcpy(&old
, &wp
->status_screen
, sizeof old
);
385 screen_init(&wp
->status_screen
, width
, 1, 0);
386 wp
->status_screen
.mode
= 0;
388 screen_write_start(&ctx
, &wp
->status_screen
);
390 for (i
= 0; i
< width
; i
++) {
391 px
= wp
->xoff
+ 2 + i
;
392 if (rctx
->pane_status
== PANE_STATUS_TOP
)
395 py
= wp
->yoff
+ wp
->sy
;
396 cell_type
= screen_redraw_type_of_cell(c
, px
, py
, pane_status
);
397 screen_redraw_border_set(wp
, pane_lines
, cell_type
, &gc
);
398 screen_write_cell(&ctx
, &gc
);
400 gc
.attr
&= ~GRID_ATTR_CHARSET
;
402 screen_write_cursormove(&ctx
, 0, 0, 0);
403 format_draw(&ctx
, &gc
, width
, expanded
, NULL
, 0);
404 screen_write_stop(&ctx
);
409 if (grid_compare(wp
->status_screen
.grid
, old
.grid
) == 0) {
417 /* Draw pane status. */
419 screen_redraw_draw_pane_status(struct screen_redraw_ctx
*ctx
)
421 struct client
*c
= ctx
->c
;
422 struct window
*w
= c
->session
->curw
->window
;
423 struct tty
*tty
= &c
->tty
;
424 struct window_pane
*wp
;
426 u_int i
, x
, width
, xoff
, yoff
, size
;
428 log_debug("%s: %s @%u", __func__
, c
->name
, w
->id
);
430 TAILQ_FOREACH(wp
, &w
->panes
, entry
) {
431 if (!window_pane_visible(wp
))
433 s
= &wp
->status_screen
;
435 size
= wp
->status_size
;
436 if (ctx
->pane_status
== PANE_STATUS_TOP
)
439 yoff
= wp
->yoff
+ wp
->sy
;
442 if (xoff
+ size
<= ctx
->ox
||
443 xoff
>= ctx
->ox
+ ctx
->sx
||
445 yoff
>= ctx
->oy
+ ctx
->sy
)
448 if (xoff
>= ctx
->ox
&& xoff
+ size
<= ctx
->ox
+ ctx
->sx
) {
453 } else if (xoff
< ctx
->ox
&& xoff
+ size
> ctx
->ox
+ ctx
->sx
) {
454 /* Both left and right not visible. */
458 } else if (xoff
< ctx
->ox
) {
459 /* Left not visible. */
464 /* Right not visible. */
471 yoff
+= ctx
->statuslines
;
472 tty_draw_line(tty
, s
, i
, 0, width
, x
, yoff
- ctx
->oy
,
473 &grid_default_cell
, NULL
);
475 tty_cursor(tty
, 0, 0);
478 /* Update status line and change flags if unchanged. */
480 screen_redraw_update(struct client
*c
, int flags
)
482 struct window
*w
= c
->session
->curw
->window
;
483 struct window_pane
*wp
;
484 struct options
*wo
= w
->options
;
486 enum pane_lines lines
;
487 struct screen_redraw_ctx ctx
;
489 if (c
->message_string
!= NULL
)
490 redraw
= status_message_redraw(c
);
491 else if (c
->prompt_string
!= NULL
)
492 redraw
= status_prompt_redraw(c
);
494 redraw
= status_redraw(c
);
495 if (!redraw
&& (~flags
& CLIENT_REDRAWSTATUSALWAYS
))
496 flags
&= ~CLIENT_REDRAWSTATUS
;
498 if (c
->overlay_draw
!= NULL
)
499 flags
|= CLIENT_REDRAWOVERLAY
;
501 if (options_get_number(wo
, "pane-border-status") != PANE_STATUS_OFF
) {
502 screen_redraw_set_context(c
, &ctx
);
503 lines
= options_get_number(wo
, "pane-border-lines");
505 TAILQ_FOREACH(wp
, &w
->panes
, entry
) {
506 if (screen_redraw_make_pane_status(c
, wp
, &ctx
, lines
))
510 flags
|= CLIENT_REDRAWBORDERS
;
515 /* Set up redraw context. */
517 screen_redraw_set_context(struct client
*c
, struct screen_redraw_ctx
*ctx
)
519 struct session
*s
= c
->session
;
520 struct options
*oo
= s
->options
;
521 struct window
*w
= s
->curw
->window
;
522 struct options
*wo
= w
->options
;
525 memset(ctx
, 0, sizeof *ctx
);
528 lines
= status_line_size(c
);
529 if (c
->message_string
!= NULL
|| c
->prompt_string
!= NULL
)
530 lines
= (lines
== 0) ? 1 : lines
;
531 if (lines
!= 0 && options_get_number(oo
, "status-position") == 0)
533 ctx
->statuslines
= lines
;
535 ctx
->pane_status
= options_get_number(wo
, "pane-border-status");
536 ctx
->pane_lines
= options_get_number(wo
, "pane-border-lines");
538 tty_window_offset(&c
->tty
, &ctx
->ox
, &ctx
->oy
, &ctx
->sx
, &ctx
->sy
);
540 log_debug("%s: %s @%u ox=%u oy=%u sx=%u sy=%u %u/%d", __func__
, c
->name
,
541 w
->id
, ctx
->ox
, ctx
->oy
, ctx
->sx
, ctx
->sy
, ctx
->statuslines
,
545 /* Redraw entire screen. */
547 screen_redraw_screen(struct client
*c
)
549 struct screen_redraw_ctx ctx
;
552 if (c
->flags
& CLIENT_SUSPENDED
)
555 flags
= screen_redraw_update(c
, c
->flags
);
556 if ((flags
& CLIENT_ALLREDRAWFLAGS
) == 0)
559 screen_redraw_set_context(c
, &ctx
);
560 tty_sync_start(&c
->tty
);
561 tty_update_mode(&c
->tty
, c
->tty
.mode
, NULL
);
563 if (flags
& (CLIENT_REDRAWWINDOW
|CLIENT_REDRAWBORDERS
)) {
564 log_debug("%s: redrawing borders", c
->name
);
565 if (ctx
.pane_status
!= PANE_STATUS_OFF
)
566 screen_redraw_draw_pane_status(&ctx
);
567 screen_redraw_draw_borders(&ctx
);
569 if (flags
& CLIENT_REDRAWWINDOW
) {
570 log_debug("%s: redrawing panes", c
->name
);
571 screen_redraw_draw_panes(&ctx
);
573 if (ctx
.statuslines
!= 0 &&
574 (flags
& (CLIENT_REDRAWSTATUS
|CLIENT_REDRAWSTATUSALWAYS
))) {
575 log_debug("%s: redrawing status", c
->name
);
576 screen_redraw_draw_status(&ctx
);
578 if (c
->overlay_draw
!= NULL
&& (flags
& CLIENT_REDRAWOVERLAY
)) {
579 log_debug("%s: redrawing overlay", c
->name
);
580 c
->overlay_draw(c
, c
->overlay_data
, &ctx
);
586 /* Redraw a single pane. */
588 screen_redraw_pane(struct client
*c
, struct window_pane
*wp
)
590 struct screen_redraw_ctx ctx
;
592 if (!window_pane_visible(wp
))
595 screen_redraw_set_context(c
, &ctx
);
596 tty_sync_start(&c
->tty
);
597 tty_update_mode(&c
->tty
, c
->tty
.mode
, NULL
);
599 screen_redraw_draw_pane(&ctx
, wp
);
604 /* Get border cell style. */
605 static const struct grid_cell
*
606 screen_redraw_draw_borders_style(struct screen_redraw_ctx
*ctx
, u_int x
,
607 u_int y
, struct window_pane
*wp
)
609 struct client
*c
= ctx
->c
;
610 struct session
*s
= c
->session
;
611 struct window
*w
= s
->curw
->window
;
612 struct window_pane
*active
= server_client_get_pane(c
);
613 struct options
*oo
= w
->options
;
614 struct format_tree
*ft
;
616 if (wp
->border_gc_set
)
617 return (&wp
->border_gc
);
618 wp
->border_gc_set
= 1;
620 ft
= format_create_defaults(NULL
, c
, s
, s
->curw
, wp
);
621 if (screen_redraw_check_is(x
, y
, ctx
->pane_status
, active
))
622 style_apply(&wp
->border_gc
, oo
, "pane-active-border-style", ft
);
624 style_apply(&wp
->border_gc
, oo
, "pane-border-style", ft
);
627 return (&wp
->border_gc
);
630 /* Draw a border cell. */
632 screen_redraw_draw_borders_cell(struct screen_redraw_ctx
*ctx
, u_int i
, u_int j
)
634 struct client
*c
= ctx
->c
;
635 struct session
*s
= c
->session
;
636 struct window
*w
= s
->curw
->window
;
637 struct options
*oo
= w
->options
;
638 struct tty
*tty
= &c
->tty
;
639 struct format_tree
*ft
;
640 struct window_pane
*wp
;
642 const struct grid_cell
*tmp
;
643 struct overlay_ranges r
;
644 u_int cell_type
, x
= ctx
->ox
+ i
, y
= ctx
->oy
+ j
;
645 int pane_status
= ctx
->pane_status
, isolates
;
647 if (c
->overlay_check
!= NULL
) {
648 c
->overlay_check(c
, c
->overlay_data
, x
, y
, 1, &r
);
649 if (r
.nx
[0] + r
.nx
[1] == 0)
653 cell_type
= screen_redraw_check_cell(c
, x
, y
, pane_status
, &wp
);
654 if (cell_type
== CELL_INSIDE
)
658 if (!ctx
->no_pane_gc_set
) {
659 ft
= format_create_defaults(NULL
, c
, s
, s
->curw
, NULL
);
660 memcpy(&ctx
->no_pane_gc
, &grid_default_cell
, sizeof gc
);
661 style_add(&ctx
->no_pane_gc
, oo
, "pane-border-style",
664 ctx
->no_pane_gc_set
= 1;
666 memcpy(&gc
, &ctx
->no_pane_gc
, sizeof gc
);
668 tmp
= screen_redraw_draw_borders_style(ctx
, x
, y
, wp
);
671 memcpy(&gc
, tmp
, sizeof gc
);
673 if (server_is_marked(s
, s
->curw
, marked_pane
.wp
) &&
674 screen_redraw_check_is(x
, y
, pane_status
, marked_pane
.wp
))
675 gc
.attr
^= GRID_ATTR_REVERSE
;
677 screen_redraw_border_set(wp
, ctx
->pane_lines
, cell_type
, &gc
);
679 if (cell_type
== CELL_TOPBOTTOM
&&
680 (c
->flags
& CLIENT_UTF8
) &&
681 tty_term_has(tty
->term
, TTYC_BIDI
))
687 tty_cursor(tty
, i
, ctx
->statuslines
+ j
);
689 tty_cursor(tty
, i
, j
);
691 tty_puts(tty
, END_ISOLATE
);
692 tty_cell(tty
, &gc
, &grid_default_cell
, NULL
);
694 tty_puts(tty
, START_ISOLATE
);
697 /* Draw the borders. */
699 screen_redraw_draw_borders(struct screen_redraw_ctx
*ctx
)
701 struct client
*c
= ctx
->c
;
702 struct session
*s
= c
->session
;
703 struct window
*w
= s
->curw
->window
;
704 struct window_pane
*wp
;
707 log_debug("%s: %s @%u", __func__
, c
->name
, w
->id
);
709 TAILQ_FOREACH(wp
, &w
->panes
, entry
)
710 wp
->border_gc_set
= 0;
712 for (j
= 0; j
< c
->tty
.sy
- ctx
->statuslines
; j
++) {
713 for (i
= 0; i
< c
->tty
.sx
; i
++)
714 screen_redraw_draw_borders_cell(ctx
, i
, j
);
718 /* Draw the panes. */
720 screen_redraw_draw_panes(struct screen_redraw_ctx
*ctx
)
722 struct client
*c
= ctx
->c
;
723 struct window
*w
= c
->session
->curw
->window
;
724 struct window_pane
*wp
;
726 log_debug("%s: %s @%u", __func__
, c
->name
, w
->id
);
728 TAILQ_FOREACH(wp
, &w
->panes
, entry
) {
729 if (window_pane_visible(wp
))
730 screen_redraw_draw_pane(ctx
, wp
);
734 /* Draw the status line. */
736 screen_redraw_draw_status(struct screen_redraw_ctx
*ctx
)
738 struct client
*c
= ctx
->c
;
739 struct window
*w
= c
->session
->curw
->window
;
740 struct tty
*tty
= &c
->tty
;
741 struct screen
*s
= c
->status
.active
;
744 log_debug("%s: %s @%u", __func__
, c
->name
, w
->id
);
749 y
= c
->tty
.sy
- ctx
->statuslines
;
750 for (i
= 0; i
< ctx
->statuslines
; i
++) {
751 tty_draw_line(tty
, s
, 0, i
, UINT_MAX
, 0, y
+ i
,
752 &grid_default_cell
, NULL
);
758 screen_redraw_draw_pane(struct screen_redraw_ctx
*ctx
, struct window_pane
*wp
)
760 struct client
*c
= ctx
->c
;
761 struct window
*w
= c
->session
->curw
->window
;
762 struct tty
*tty
= &c
->tty
;
763 struct screen
*s
= wp
->screen
;
764 struct colour_palette
*palette
= &wp
->palette
;
765 struct grid_cell defaults
;
766 u_int i
, j
, top
, x
, y
, width
;
768 log_debug("%s: %s @%u %%%u", __func__
, c
->name
, w
->id
, wp
->id
);
770 if (wp
->xoff
+ wp
->sx
<= ctx
->ox
|| wp
->xoff
>= ctx
->ox
+ ctx
->sx
)
773 top
= ctx
->statuslines
;
776 for (j
= 0; j
< wp
->sy
; j
++) {
777 if (wp
->yoff
+ j
< ctx
->oy
|| wp
->yoff
+ j
>= ctx
->oy
+ ctx
->sy
)
779 y
= top
+ wp
->yoff
+ j
- ctx
->oy
;
781 if (wp
->xoff
>= ctx
->ox
&&
782 wp
->xoff
+ wp
->sx
<= ctx
->ox
+ ctx
->sx
) {
785 x
= wp
->xoff
- ctx
->ox
;
787 } else if (wp
->xoff
< ctx
->ox
&&
788 wp
->xoff
+ wp
->sx
> ctx
->ox
+ ctx
->sx
) {
789 /* Both left and right not visible. */
793 } else if (wp
->xoff
< ctx
->ox
) {
794 /* Left not visible. */
795 i
= ctx
->ox
- wp
->xoff
;
799 /* Right not visible. */
801 x
= wp
->xoff
- ctx
->ox
;
804 log_debug("%s: %s %%%u line %u,%u at %u,%u, width %u",
805 __func__
, c
->name
, wp
->id
, i
, j
, x
, y
, width
);
807 tty_default_colours(&defaults
, wp
);
808 tty_draw_line(tty
, s
, i
, j
, width
, x
, y
, &defaults
, palette
);