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 /* Border in relation to a pane. */
38 enum screen_redraw_border_type
{
39 SCREEN_REDRAW_OUTSIDE
,
41 SCREEN_REDRAW_BORDER_LEFT
,
42 SCREEN_REDRAW_BORDER_RIGHT
,
43 SCREEN_REDRAW_BORDER_TOP
,
44 SCREEN_REDRAW_BORDER_BOTTOM
46 #define BORDER_MARKERS " +,.-"
48 /* Get cell border character. */
50 screen_redraw_border_set(struct window
*w
, struct window_pane
*wp
,
51 enum pane_lines pane_lines
, int cell_type
, struct grid_cell
*gc
)
55 if (cell_type
== CELL_OUTSIDE
&& w
->fill_character
!= NULL
) {
56 utf8_copy(&gc
->data
, &w
->fill_character
[0]);
61 case PANE_LINES_NUMBER
:
62 if (cell_type
== CELL_OUTSIDE
) {
63 gc
->attr
|= GRID_ATTR_CHARSET
;
64 utf8_set(&gc
->data
, CELL_BORDERS
[CELL_OUTSIDE
]);
67 gc
->attr
&= ~GRID_ATTR_CHARSET
;
68 if (wp
!= NULL
&& window_pane_index(wp
, &idx
) == 0)
69 utf8_set(&gc
->data
, '0' + (idx
% 10));
71 utf8_set(&gc
->data
, '*');
73 case PANE_LINES_DOUBLE
:
74 gc
->attr
&= ~GRID_ATTR_CHARSET
;
75 utf8_copy(&gc
->data
, tty_acs_double_borders(cell_type
));
77 case PANE_LINES_HEAVY
:
78 gc
->attr
&= ~GRID_ATTR_CHARSET
;
79 utf8_copy(&gc
->data
, tty_acs_heavy_borders(cell_type
));
81 case PANE_LINES_SIMPLE
:
82 gc
->attr
&= ~GRID_ATTR_CHARSET
;
83 utf8_set(&gc
->data
, SIMPLE_BORDERS
[cell_type
]);
86 gc
->attr
|= GRID_ATTR_CHARSET
;
87 utf8_set(&gc
->data
, CELL_BORDERS
[cell_type
]);
92 /* Return if window has only two panes. */
94 screen_redraw_two_panes(struct window
*w
, int direction
)
96 struct window_pane
*wp
;
98 wp
= TAILQ_NEXT(TAILQ_FIRST(&w
->panes
), entry
);
100 return (0); /* one pane */
101 if (TAILQ_NEXT(wp
, entry
) != NULL
)
102 return (0); /* more than two panes */
103 if (direction
== 0 && wp
->xoff
== 0)
105 if (direction
== 1 && wp
->yoff
== 0)
110 /* Check if cell is on the border of a pane. */
111 static enum screen_redraw_border_type
112 screen_redraw_pane_border(struct screen_redraw_ctx
*ctx
, struct window_pane
*wp
,
115 struct options
*oo
= wp
->window
->options
;
117 u_int ex
= wp
->xoff
+ wp
->sx
, ey
= wp
->yoff
+ wp
->sy
;
118 int pane_status
= ctx
->pane_status
;
121 if (px
>= wp
->xoff
&& px
< ex
&& py
>= wp
->yoff
&& py
< ey
)
122 return (SCREEN_REDRAW_INSIDE
);
124 /* Get pane indicator. */
125 switch (options_get_number(oo
, "pane-border-indicators")) {
126 case PANE_BORDER_COLOUR
:
127 case PANE_BORDER_BOTH
:
132 /* Left/right borders. */
133 if (pane_status
== PANE_STATUS_OFF
) {
134 if (screen_redraw_two_panes(wp
->window
, 0) && split
) {
135 if (wp
->xoff
== 0 && px
== wp
->sx
&& py
<= wp
->sy
/ 2)
136 return (SCREEN_REDRAW_BORDER_RIGHT
);
138 px
== wp
->xoff
- 1 &&
140 return (SCREEN_REDRAW_BORDER_LEFT
);
142 if ((wp
->yoff
== 0 || py
>= wp
->yoff
- 1) && py
<= ey
) {
143 if (wp
->xoff
!= 0 && px
== wp
->xoff
- 1)
144 return (SCREEN_REDRAW_BORDER_LEFT
);
146 return (SCREEN_REDRAW_BORDER_RIGHT
);
150 if ((wp
->yoff
== 0 || py
>= wp
->yoff
- 1) && py
<= ey
) {
151 if (wp
->xoff
!= 0 && px
== wp
->xoff
- 1)
152 return (SCREEN_REDRAW_BORDER_LEFT
);
154 return (SCREEN_REDRAW_BORDER_RIGHT
);
158 /* Top/bottom borders. */
159 if (pane_status
== PANE_STATUS_OFF
) {
160 if (screen_redraw_two_panes(wp
->window
, 1) && split
) {
161 if (wp
->yoff
== 0 && py
== wp
->sy
&& px
<= wp
->sx
/ 2)
162 return (SCREEN_REDRAW_BORDER_BOTTOM
);
164 py
== wp
->yoff
- 1 &&
166 return (SCREEN_REDRAW_BORDER_TOP
);
168 if ((wp
->xoff
== 0 || px
>= wp
->xoff
- 1) && px
<= ex
) {
169 if (wp
->yoff
!= 0 && py
== wp
->yoff
- 1)
170 return (SCREEN_REDRAW_BORDER_TOP
);
172 return (SCREEN_REDRAW_BORDER_BOTTOM
);
175 } else if (pane_status
== PANE_STATUS_TOP
) {
176 if ((wp
->xoff
== 0 || px
>= wp
->xoff
- 1) && px
<= ex
) {
177 if (wp
->yoff
!= 0 && py
== wp
->yoff
- 1)
178 return (SCREEN_REDRAW_BORDER_TOP
);
181 if ((wp
->xoff
== 0 || px
>= wp
->xoff
- 1) && px
<= ex
) {
183 return (SCREEN_REDRAW_BORDER_BOTTOM
);
188 return (SCREEN_REDRAW_OUTSIDE
);
191 /* Check if a cell is on a border. */
193 screen_redraw_cell_border(struct screen_redraw_ctx
*ctx
, u_int px
, u_int py
)
195 struct client
*c
= ctx
->c
;
196 struct window
*w
= c
->session
->curw
->window
;
197 struct window_pane
*wp
;
200 if (ctx
->pane_status
== PANE_STATUS_BOTTOM
)
203 /* Outside the window? */
204 if (px
> w
->sx
|| py
> sy
)
207 /* On the window border? */
208 if (px
== w
->sx
|| py
== sy
)
211 /* Check all the panes. */
212 TAILQ_FOREACH(wp
, &w
->panes
, entry
) {
213 if (!window_pane_visible(wp
))
215 switch (screen_redraw_pane_border(ctx
, wp
, px
, py
)) {
216 case SCREEN_REDRAW_INSIDE
:
218 case SCREEN_REDRAW_OUTSIDE
:
228 /* Work out type of border cell from surrounding cells. */
230 screen_redraw_type_of_cell(struct screen_redraw_ctx
*ctx
, u_int px
, u_int py
)
232 struct client
*c
= ctx
->c
;
233 int pane_status
= ctx
->pane_status
;
234 struct window
*w
= c
->session
->curw
->window
;
235 u_int sx
= w
->sx
, sy
= w
->sy
;
238 if (pane_status
== PANE_STATUS_BOTTOM
)
241 /* Is this outside the window? */
242 if (px
> sx
|| py
> sy
)
243 return (CELL_OUTSIDE
);
246 * Construct a bitmask of whether the cells to the left (bit 4), right,
247 * top, and bottom (bit 1) of this cell are borders.
249 if (px
== 0 || screen_redraw_cell_border(ctx
, px
- 1, py
))
251 if (px
<= sx
&& screen_redraw_cell_border(ctx
, px
+ 1, py
))
253 if (pane_status
== PANE_STATUS_TOP
) {
255 screen_redraw_cell_border(ctx
, px
, py
- 1))
257 if (screen_redraw_cell_border(ctx
, px
, py
+ 1))
259 } else if (pane_status
== PANE_STATUS_BOTTOM
) {
261 screen_redraw_cell_border(ctx
, px
, py
- 1))
264 screen_redraw_cell_border(ctx
, px
, py
+ 1))
268 screen_redraw_cell_border(ctx
, px
, py
- 1))
270 if (screen_redraw_cell_border(ctx
, px
, py
+ 1))
275 * Figure out what kind of border this cell is. Only one bit set
276 * doesn't make sense (can't have a border cell with no others
280 case 15: /* 1111, left right top bottom */
282 case 14: /* 1110, left right top */
283 return (CELL_BOTTOMJOIN
);
284 case 13: /* 1101, left right bottom */
285 return (CELL_TOPJOIN
);
286 case 12: /* 1100, left right */
287 return (CELL_LEFTRIGHT
);
288 case 11: /* 1011, left top bottom */
289 return (CELL_RIGHTJOIN
);
290 case 10: /* 1010, left top */
291 return (CELL_BOTTOMRIGHT
);
292 case 9: /* 1001, left bottom */
293 return (CELL_TOPRIGHT
);
294 case 7: /* 0111, right top bottom */
295 return (CELL_LEFTJOIN
);
296 case 6: /* 0110, right top */
297 return (CELL_BOTTOMLEFT
);
298 case 5: /* 0101, right bottom */
299 return (CELL_TOPLEFT
);
300 case 3: /* 0011, top bottom */
301 return (CELL_TOPBOTTOM
);
303 return (CELL_OUTSIDE
);
306 /* Check if cell inside a pane. */
308 screen_redraw_check_cell(struct screen_redraw_ctx
*ctx
, u_int px
, u_int py
,
309 struct window_pane
**wpp
)
311 struct client
*c
= ctx
->c
;
312 struct window
*w
= c
->session
->curw
->window
;
313 struct window_pane
*wp
, *active
;
314 int pane_status
= ctx
->pane_status
;
315 u_int sx
= w
->sx
, sy
= w
->sy
;
321 if (px
> sx
|| py
> sy
)
322 return (CELL_OUTSIDE
);
323 if (px
== sx
|| py
== sy
) /* window border */
324 return (screen_redraw_type_of_cell(ctx
, px
, py
));
326 if (pane_status
!= PANE_STATUS_OFF
) {
327 active
= wp
= server_client_get_pane(c
);
329 if (!window_pane_visible(wp
))
332 if (pane_status
== PANE_STATUS_TOP
)
335 line
= wp
->yoff
+ sy
;
336 right
= wp
->xoff
+ 2 + wp
->status_size
- 1;
338 if (py
== line
&& px
>= wp
->xoff
+ 2 && px
<= right
)
339 return (CELL_INSIDE
);
342 wp
= TAILQ_NEXT(wp
, entry
);
344 wp
= TAILQ_FIRST(&w
->panes
);
345 } while (wp
!= active
);
348 active
= wp
= server_client_get_pane(c
);
350 if (!window_pane_visible(wp
))
355 * If definitely inside, return. If not on border, skip.
356 * Otherwise work out the cell.
358 border
= screen_redraw_pane_border(ctx
, wp
, px
, py
);
359 if (border
== SCREEN_REDRAW_INSIDE
)
360 return (CELL_INSIDE
);
361 if (border
== SCREEN_REDRAW_OUTSIDE
)
363 return (screen_redraw_type_of_cell(ctx
, px
, py
));
366 wp
= TAILQ_NEXT(wp
, entry
);
368 wp
= TAILQ_FIRST(&w
->panes
);
369 } while (wp
!= active
);
371 return (CELL_OUTSIDE
);
374 /* Check if the border of a particular pane. */
376 screen_redraw_check_is(struct screen_redraw_ctx
*ctx
, u_int px
, u_int py
,
377 struct window_pane
*wp
)
379 enum screen_redraw_border_type border
;
381 border
= screen_redraw_pane_border(ctx
, wp
, px
, py
);
382 if (border
!= SCREEN_REDRAW_INSIDE
&& border
!= SCREEN_REDRAW_OUTSIDE
)
387 /* Update pane status. */
389 screen_redraw_make_pane_status(struct client
*c
, struct window_pane
*wp
,
390 struct screen_redraw_ctx
*rctx
, enum pane_lines pane_lines
)
392 struct window
*w
= wp
->window
;
395 struct format_tree
*ft
;
397 int pane_status
= rctx
->pane_status
;
398 u_int width
, i
, cell_type
, px
, py
;
399 struct screen_write_ctx ctx
;
402 ft
= format_create(c
, NULL
, FORMAT_PANE
|wp
->id
, FORMAT_STATUS
);
403 format_defaults(ft
, c
, c
->session
, c
->session
->curw
, wp
);
405 if (wp
== server_client_get_pane(c
))
406 style_apply(&gc
, w
->options
, "pane-active-border-style", ft
);
408 style_apply(&gc
, w
->options
, "pane-border-style", ft
);
409 fmt
= options_get_string(wp
->options
, "pane-border-format");
411 expanded
= format_expand_time(ft
, fmt
);
413 wp
->status_size
= width
= 0;
415 wp
->status_size
= width
= wp
->sx
- 4;
417 memcpy(&old
, &wp
->status_screen
, sizeof old
);
418 screen_init(&wp
->status_screen
, width
, 1, 0);
419 wp
->status_screen
.mode
= 0;
421 screen_write_start(&ctx
, &wp
->status_screen
);
423 for (i
= 0; i
< width
; i
++) {
424 px
= wp
->xoff
+ 2 + i
;
425 if (pane_status
== PANE_STATUS_TOP
)
428 py
= wp
->yoff
+ wp
->sy
;
429 cell_type
= screen_redraw_type_of_cell(rctx
, px
, py
);
430 screen_redraw_border_set(w
, wp
, pane_lines
, cell_type
, &gc
);
431 screen_write_cell(&ctx
, &gc
);
433 gc
.attr
&= ~GRID_ATTR_CHARSET
;
435 screen_write_cursormove(&ctx
, 0, 0, 0);
436 format_draw(&ctx
, &gc
, width
, expanded
, NULL
, 0);
437 screen_write_stop(&ctx
);
442 if (grid_compare(wp
->status_screen
.grid
, old
.grid
) == 0) {
450 /* Draw pane status. */
452 screen_redraw_draw_pane_status(struct screen_redraw_ctx
*ctx
)
454 struct client
*c
= ctx
->c
;
455 struct window
*w
= c
->session
->curw
->window
;
456 struct tty
*tty
= &c
->tty
;
457 struct window_pane
*wp
;
459 u_int i
, x
, width
, xoff
, yoff
, size
;
461 log_debug("%s: %s @%u", __func__
, c
->name
, w
->id
);
463 TAILQ_FOREACH(wp
, &w
->panes
, entry
) {
464 if (!window_pane_visible(wp
))
466 s
= &wp
->status_screen
;
468 size
= wp
->status_size
;
469 if (ctx
->pane_status
== PANE_STATUS_TOP
)
472 yoff
= wp
->yoff
+ wp
->sy
;
475 if (xoff
+ size
<= ctx
->ox
||
476 xoff
>= ctx
->ox
+ ctx
->sx
||
478 yoff
>= ctx
->oy
+ ctx
->sy
)
481 if (xoff
>= ctx
->ox
&& xoff
+ size
<= ctx
->ox
+ ctx
->sx
) {
486 } else if (xoff
< ctx
->ox
&& xoff
+ size
> ctx
->ox
+ ctx
->sx
) {
487 /* Both left and right not visible. */
491 } else if (xoff
< ctx
->ox
) {
492 /* Left not visible. */
497 /* Right not visible. */
504 yoff
+= ctx
->statuslines
;
505 tty_draw_line(tty
, s
, i
, 0, width
, x
, yoff
- ctx
->oy
,
506 &grid_default_cell
, NULL
);
508 tty_cursor(tty
, 0, 0);
511 /* Update status line and change flags if unchanged. */
513 screen_redraw_update(struct client
*c
, uint64_t flags
)
515 struct window
*w
= c
->session
->curw
->window
;
516 struct window_pane
*wp
;
517 struct options
*wo
= w
->options
;
519 enum pane_lines lines
;
520 struct screen_redraw_ctx ctx
;
522 if (c
->message_string
!= NULL
)
523 redraw
= status_message_redraw(c
);
524 else if (c
->prompt_string
!= NULL
)
525 redraw
= status_prompt_redraw(c
);
527 redraw
= status_redraw(c
);
528 if (!redraw
&& (~flags
& CLIENT_REDRAWSTATUSALWAYS
))
529 flags
&= ~CLIENT_REDRAWSTATUS
;
531 if (c
->overlay_draw
!= NULL
)
532 flags
|= CLIENT_REDRAWOVERLAY
;
534 if (options_get_number(wo
, "pane-border-status") != PANE_STATUS_OFF
) {
535 screen_redraw_set_context(c
, &ctx
);
536 lines
= options_get_number(wo
, "pane-border-lines");
538 TAILQ_FOREACH(wp
, &w
->panes
, entry
) {
539 if (screen_redraw_make_pane_status(c
, wp
, &ctx
, lines
))
543 flags
|= CLIENT_REDRAWBORDERS
;
548 /* Set up redraw context. */
550 screen_redraw_set_context(struct client
*c
, struct screen_redraw_ctx
*ctx
)
552 struct session
*s
= c
->session
;
553 struct options
*oo
= s
->options
;
554 struct window
*w
= s
->curw
->window
;
555 struct options
*wo
= w
->options
;
558 memset(ctx
, 0, sizeof *ctx
);
561 lines
= status_line_size(c
);
562 if (c
->message_string
!= NULL
|| c
->prompt_string
!= NULL
)
563 lines
= (lines
== 0) ? 1 : lines
;
564 if (lines
!= 0 && options_get_number(oo
, "status-position") == 0)
566 ctx
->statuslines
= lines
;
568 ctx
->pane_status
= options_get_number(wo
, "pane-border-status");
569 ctx
->pane_lines
= options_get_number(wo
, "pane-border-lines");
571 tty_window_offset(&c
->tty
, &ctx
->ox
, &ctx
->oy
, &ctx
->sx
, &ctx
->sy
);
573 log_debug("%s: %s @%u ox=%u oy=%u sx=%u sy=%u %u/%d", __func__
, c
->name
,
574 w
->id
, ctx
->ox
, ctx
->oy
, ctx
->sx
, ctx
->sy
, ctx
->statuslines
,
578 /* Redraw entire screen. */
580 screen_redraw_screen(struct client
*c
)
582 struct screen_redraw_ctx ctx
;
585 if (c
->flags
& CLIENT_SUSPENDED
)
588 flags
= screen_redraw_update(c
, c
->flags
);
589 if ((flags
& CLIENT_ALLREDRAWFLAGS
) == 0)
592 screen_redraw_set_context(c
, &ctx
);
593 tty_sync_start(&c
->tty
);
594 tty_update_mode(&c
->tty
, c
->tty
.mode
, NULL
);
596 if (flags
& (CLIENT_REDRAWWINDOW
|CLIENT_REDRAWBORDERS
)) {
597 log_debug("%s: redrawing borders", c
->name
);
598 screen_redraw_draw_borders(&ctx
);
599 if (ctx
.pane_status
!= PANE_STATUS_OFF
)
600 screen_redraw_draw_pane_status(&ctx
);
602 if (flags
& CLIENT_REDRAWWINDOW
) {
603 log_debug("%s: redrawing panes", c
->name
);
604 screen_redraw_draw_panes(&ctx
);
606 if (ctx
.statuslines
!= 0 &&
607 (flags
& (CLIENT_REDRAWSTATUS
|CLIENT_REDRAWSTATUSALWAYS
))) {
608 log_debug("%s: redrawing status", c
->name
);
609 screen_redraw_draw_status(&ctx
);
611 if (c
->overlay_draw
!= NULL
&& (flags
& CLIENT_REDRAWOVERLAY
)) {
612 log_debug("%s: redrawing overlay", c
->name
);
613 c
->overlay_draw(c
, c
->overlay_data
, &ctx
);
619 /* Redraw a single pane. */
621 screen_redraw_pane(struct client
*c
, struct window_pane
*wp
)
623 struct screen_redraw_ctx ctx
;
625 if (!window_pane_visible(wp
))
628 screen_redraw_set_context(c
, &ctx
);
629 tty_sync_start(&c
->tty
);
630 tty_update_mode(&c
->tty
, c
->tty
.mode
, NULL
);
632 screen_redraw_draw_pane(&ctx
, wp
);
637 /* Get border cell style. */
638 static const struct grid_cell
*
639 screen_redraw_draw_borders_style(struct screen_redraw_ctx
*ctx
, u_int x
,
640 u_int y
, struct window_pane
*wp
)
642 struct client
*c
= ctx
->c
;
643 struct session
*s
= c
->session
;
644 struct window
*w
= s
->curw
->window
;
645 struct window_pane
*active
= server_client_get_pane(c
);
646 struct options
*oo
= w
->options
;
647 struct format_tree
*ft
;
649 if (wp
->border_gc_set
)
650 return (&wp
->border_gc
);
651 wp
->border_gc_set
= 1;
653 ft
= format_create_defaults(NULL
, c
, s
, s
->curw
, wp
);
654 if (screen_redraw_check_is(ctx
, x
, y
, active
))
655 style_apply(&wp
->border_gc
, oo
, "pane-active-border-style", ft
);
657 style_apply(&wp
->border_gc
, oo
, "pane-border-style", ft
);
660 return (&wp
->border_gc
);
663 /* Draw a border cell. */
665 screen_redraw_draw_borders_cell(struct screen_redraw_ctx
*ctx
, u_int i
, u_int j
)
667 struct client
*c
= ctx
->c
;
668 struct session
*s
= c
->session
;
669 struct window
*w
= s
->curw
->window
;
670 struct options
*oo
= w
->options
;
671 struct tty
*tty
= &c
->tty
;
672 struct format_tree
*ft
;
673 struct window_pane
*wp
, *active
= server_client_get_pane(c
);
675 const struct grid_cell
*tmp
;
676 struct overlay_ranges r
;
677 u_int cell_type
, x
= ctx
->ox
+ i
, y
= ctx
->oy
+ j
;
678 int arrows
= 0, border
;
681 if (c
->overlay_check
!= NULL
) {
682 c
->overlay_check(c
, c
->overlay_data
, x
, y
, 1, &r
);
683 if (r
.nx
[0] + r
.nx
[1] == 0)
687 cell_type
= screen_redraw_check_cell(ctx
, x
, y
, &wp
);
688 if (cell_type
== CELL_INSIDE
)
692 if (!ctx
->no_pane_gc_set
) {
693 ft
= format_create_defaults(NULL
, c
, s
, s
->curw
, NULL
);
694 memcpy(&ctx
->no_pane_gc
, &grid_default_cell
, sizeof gc
);
695 style_add(&ctx
->no_pane_gc
, oo
, "pane-border-style",
698 ctx
->no_pane_gc_set
= 1;
700 memcpy(&gc
, &ctx
->no_pane_gc
, sizeof gc
);
702 tmp
= screen_redraw_draw_borders_style(ctx
, x
, y
, wp
);
705 memcpy(&gc
, tmp
, sizeof gc
);
707 if (server_is_marked(s
, s
->curw
, marked_pane
.wp
) &&
708 screen_redraw_check_is(ctx
, x
, y
, marked_pane
.wp
))
709 gc
.attr
^= GRID_ATTR_REVERSE
;
711 screen_redraw_border_set(w
, wp
, ctx
->pane_lines
, cell_type
, &gc
);
713 if (cell_type
== CELL_TOPBOTTOM
&&
714 (c
->flags
& CLIENT_UTF8
) &&
715 tty_term_has(tty
->term
, TTYC_BIDI
))
721 tty_cursor(tty
, i
, ctx
->statuslines
+ j
);
723 tty_cursor(tty
, i
, j
);
725 tty_puts(tty
, END_ISOLATE
);
727 switch (options_get_number(oo
, "pane-border-indicators")) {
728 case PANE_BORDER_ARROWS
:
729 case PANE_BORDER_BOTH
:
734 if (wp
!= NULL
&& arrows
) {
735 border
= screen_redraw_pane_border(ctx
, active
, x
, y
);
736 if (((i
== wp
->xoff
+ 1 &&
737 (cell_type
== CELL_LEFTRIGHT
||
738 (cell_type
== CELL_TOPJOIN
&&
739 border
== SCREEN_REDRAW_BORDER_BOTTOM
) ||
740 (cell_type
== CELL_BOTTOMJOIN
&&
741 border
== SCREEN_REDRAW_BORDER_TOP
))) ||
742 (j
== wp
->yoff
+ 1 &&
743 (cell_type
== CELL_TOPBOTTOM
||
744 (cell_type
== CELL_LEFTJOIN
&&
745 border
== SCREEN_REDRAW_BORDER_RIGHT
) ||
746 (cell_type
== CELL_RIGHTJOIN
&&
747 border
== SCREEN_REDRAW_BORDER_LEFT
)))) &&
748 screen_redraw_check_is(ctx
, x
, y
, active
)) {
749 gc
.attr
|= GRID_ATTR_CHARSET
;
750 utf8_set(&gc
.data
, BORDER_MARKERS
[border
]);
754 tty_cell(tty
, &gc
, &grid_default_cell
, NULL
, NULL
);
756 tty_puts(tty
, START_ISOLATE
);
759 /* Draw the borders. */
761 screen_redraw_draw_borders(struct screen_redraw_ctx
*ctx
)
763 struct client
*c
= ctx
->c
;
764 struct session
*s
= c
->session
;
765 struct window
*w
= s
->curw
->window
;
766 struct window_pane
*wp
;
769 log_debug("%s: %s @%u", __func__
, c
->name
, w
->id
);
771 TAILQ_FOREACH(wp
, &w
->panes
, entry
)
772 wp
->border_gc_set
= 0;
774 for (j
= 0; j
< c
->tty
.sy
- ctx
->statuslines
; j
++) {
775 for (i
= 0; i
< c
->tty
.sx
; i
++)
776 screen_redraw_draw_borders_cell(ctx
, i
, j
);
780 /* Draw the panes. */
782 screen_redraw_draw_panes(struct screen_redraw_ctx
*ctx
)
784 struct client
*c
= ctx
->c
;
785 struct window
*w
= c
->session
->curw
->window
;
786 struct window_pane
*wp
;
788 log_debug("%s: %s @%u", __func__
, c
->name
, w
->id
);
790 TAILQ_FOREACH(wp
, &w
->panes
, entry
) {
791 if (window_pane_visible(wp
))
792 screen_redraw_draw_pane(ctx
, wp
);
796 /* Draw the status line. */
798 screen_redraw_draw_status(struct screen_redraw_ctx
*ctx
)
800 struct client
*c
= ctx
->c
;
801 struct window
*w
= c
->session
->curw
->window
;
802 struct tty
*tty
= &c
->tty
;
803 struct screen
*s
= c
->status
.active
;
806 log_debug("%s: %s @%u", __func__
, c
->name
, w
->id
);
811 y
= c
->tty
.sy
- ctx
->statuslines
;
812 for (i
= 0; i
< ctx
->statuslines
; i
++) {
813 tty_draw_line(tty
, s
, 0, i
, UINT_MAX
, 0, y
+ i
,
814 &grid_default_cell
, NULL
);
820 screen_redraw_draw_pane(struct screen_redraw_ctx
*ctx
, struct window_pane
*wp
)
822 struct client
*c
= ctx
->c
;
823 struct window
*w
= c
->session
->curw
->window
;
824 struct tty
*tty
= &c
->tty
;
825 struct screen
*s
= wp
->screen
;
826 struct colour_palette
*palette
= &wp
->palette
;
827 struct grid_cell defaults
;
828 u_int i
, j
, top
, x
, y
, width
;
830 log_debug("%s: %s @%u %%%u", __func__
, c
->name
, w
->id
, wp
->id
);
832 if (wp
->xoff
+ wp
->sx
<= ctx
->ox
|| wp
->xoff
>= ctx
->ox
+ ctx
->sx
)
835 top
= ctx
->statuslines
;
838 for (j
= 0; j
< wp
->sy
; j
++) {
839 if (wp
->yoff
+ j
< ctx
->oy
|| wp
->yoff
+ j
>= ctx
->oy
+ ctx
->sy
)
841 y
= top
+ wp
->yoff
+ j
- ctx
->oy
;
843 if (wp
->xoff
>= ctx
->ox
&&
844 wp
->xoff
+ wp
->sx
<= ctx
->ox
+ ctx
->sx
) {
847 x
= wp
->xoff
- ctx
->ox
;
849 } else if (wp
->xoff
< ctx
->ox
&&
850 wp
->xoff
+ wp
->sx
> ctx
->ox
+ ctx
->sx
) {
851 /* Both left and right not visible. */
855 } else if (wp
->xoff
< ctx
->ox
) {
856 /* Left not visible. */
857 i
= ctx
->ox
- wp
->xoff
;
861 /* Right not visible. */
863 x
= wp
->xoff
- ctx
->ox
;
866 log_debug("%s: %s %%%u line %u,%u at %u,%u, width %u",
867 __func__
, c
->name
, wp
->id
, i
, j
, x
, y
, width
);
869 tty_default_colours(&defaults
, wp
);
870 tty_draw_line(tty
, s
, i
, j
, width
, x
, y
, &defaults
, palette
);
874 tty_draw_images(c
, wp
, s
);