mirror of
https://github.com/tmux/tmux.git
synced 2026-06-22 10:06:59 +00:00
Draw pane borders.
This commit is contained in:
@@ -209,6 +209,7 @@ dist_tmux_SOURCES = \
|
|||||||
tty.c \
|
tty.c \
|
||||||
utf8-combined.c \
|
utf8-combined.c \
|
||||||
utf8.c \
|
utf8.c \
|
||||||
|
window-border.c \
|
||||||
window-buffer.c \
|
window-buffer.c \
|
||||||
window-client.c \
|
window-client.c \
|
||||||
window-clock.c \
|
window-clock.c \
|
||||||
|
|||||||
272
screen-redraw.c
272
screen-redraw.c
@@ -53,6 +53,10 @@ enum redraw_span_type {
|
|||||||
#define REDRAW_DRAW_SCROLLBAR 0x8
|
#define REDRAW_DRAW_SCROLLBAR 0x8
|
||||||
#define REDRAW_DRAW_ALL 0xff
|
#define REDRAW_DRAW_ALL 0xff
|
||||||
|
|
||||||
|
/* UTF-8 isolate characters. */
|
||||||
|
#define REDRAW_START_ISOLATE "\342\201\246"
|
||||||
|
#define REDRAW_END_ISOLATE "\342\201\251"
|
||||||
|
|
||||||
/* Data for a span. */
|
/* Data for a span. */
|
||||||
struct redraw_span_data {
|
struct redraw_span_data {
|
||||||
enum redraw_span_type type;
|
enum redraw_span_type type;
|
||||||
@@ -99,6 +103,7 @@ struct redraw_span_data {
|
|||||||
/* The pane and the offset into the status line. */
|
/* The pane and the offset into the status line. */
|
||||||
struct window_pane *wp;
|
struct window_pane *wp;
|
||||||
u_int offset;
|
u_int offset;
|
||||||
|
int cell_type;
|
||||||
} st;
|
} st;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
@@ -143,6 +148,8 @@ struct redraw_scene {
|
|||||||
u_int oy;
|
u_int oy;
|
||||||
|
|
||||||
struct redraw_line *lines;
|
struct redraw_line *lines;
|
||||||
|
int default_gc_set;
|
||||||
|
struct grid_cell default_gc;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Cell for building the scene. */
|
/* Cell for building the scene. */
|
||||||
@@ -445,8 +452,8 @@ screen_redraw_mark_border_status(struct redraw_build_ctx *bctx,
|
|||||||
struct window_pane *wp, int left, int right, int top, int bottom)
|
struct window_pane *wp, int left, int right, int top, int bottom)
|
||||||
{
|
{
|
||||||
struct redraw_build_cell *bc;
|
struct redraw_build_cell *bc;
|
||||||
u_int x, y, offset = 0;
|
u_int x, y, off = 0;
|
||||||
int pane_status, wy, sx, ex, wx;
|
int pane_status, wy, sx, ex, wx, cell_type;
|
||||||
|
|
||||||
pane_status = window_pane_get_pane_status(wp);
|
pane_status = window_pane_get_pane_status(wp);
|
||||||
if (pane_status == PANE_STATUS_OFF)
|
if (pane_status == PANE_STATUS_OFF)
|
||||||
@@ -466,15 +473,18 @@ screen_redraw_mark_border_status(struct redraw_build_ctx *bctx,
|
|||||||
if (sx > ex)
|
if (sx > ex)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
for (wx = sx; wx <= ex; wx++, offset++) {
|
for (wx = sx; wx <= ex; wx++, off++) {
|
||||||
if (!screen_redraw_window_scene(bctx, wx, wy, &x, &y))
|
if (!screen_redraw_window_scene(bctx, wx, wy, &x, &y))
|
||||||
continue;
|
continue;
|
||||||
bc = screen_redraw_cell(bctx, x, y);
|
bc = screen_redraw_cell(bctx, x, y);
|
||||||
if (bc->data.type != REDRAW_SPAN_BORDER)
|
if (bc->data.type != REDRAW_SPAN_BORDER)
|
||||||
continue;
|
continue;
|
||||||
|
cell_type = bc->data.b.cell_type;
|
||||||
|
|
||||||
bc->data.type = REDRAW_SPAN_STATUS;
|
bc->data.type = REDRAW_SPAN_STATUS;
|
||||||
bc->data.st.wp = wp;
|
bc->data.st.wp = wp;
|
||||||
bc->data.st.offset = offset;
|
bc->data.st.offset = off;
|
||||||
|
bc->data.st.cell_type = cell_type;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -709,7 +719,8 @@ screen_redraw_data_cmp(struct redraw_build_cell *a, struct redraw_build_cell *b)
|
|||||||
return (1);
|
return (1);
|
||||||
case REDRAW_SPAN_STATUS:
|
case REDRAW_SPAN_STATUS:
|
||||||
if (ad->st.wp != bd->st.wp ||
|
if (ad->st.wp != bd->st.wp ||
|
||||||
ad->st.offset + 1 != bd->st.offset)
|
ad->st.offset + 1 != bd->st.offset ||
|
||||||
|
ad->st.cell_type != bd->st.cell_type)
|
||||||
return (0);
|
return (0);
|
||||||
return (1);
|
return (1);
|
||||||
case REDRAW_SPAN_SCROLLBAR:
|
case REDRAW_SPAN_SCROLLBAR:
|
||||||
@@ -875,34 +886,167 @@ screen_redraw_draw_pane_span(struct redraw_scene *scene,
|
|||||||
|
|
||||||
px = span->data.p.px + (x - span->x);
|
px = span->data.p.px + (x - span->x);
|
||||||
py = span->data.p.py;
|
py = span->data.p.py;
|
||||||
|
|
||||||
tty_draw_line(tty, s, px, py, n, x, y, &style_ctx);
|
tty_draw_line(tty, s, px, py, n, x, y, &style_ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Get style for cells without a pane. */
|
||||||
|
static void
|
||||||
|
screen_redraw_draw_get_default_style(struct redraw_scene *scene,
|
||||||
|
struct grid_cell *gc)
|
||||||
|
{
|
||||||
|
struct client *c = scene->c;
|
||||||
|
struct session *s = c->session;
|
||||||
|
struct format_tree *ft;
|
||||||
|
struct grid_cell *dgc = &scene->default_gc;
|
||||||
|
|
||||||
|
if (!scene->default_gc_set) {
|
||||||
|
ft = format_create_defaults(NULL, c, s, s->curw, NULL);
|
||||||
|
memcpy(dgc, &grid_default_cell, sizeof *dgc);
|
||||||
|
style_add(dgc, scene->w->options, "pane-border-style", ft);
|
||||||
|
format_free(ft);
|
||||||
|
scene->default_gc_set = 1;
|
||||||
|
}
|
||||||
|
memcpy(gc, dgc, sizeof *gc);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Find pane to use for this span. */
|
||||||
|
static struct window_pane *
|
||||||
|
screen_redraw_draw_get_style_pane(struct redraw_scene *scene,
|
||||||
|
struct redraw_span *span)
|
||||||
|
{
|
||||||
|
struct window_pane *active = server_client_get_pane(scene->c);
|
||||||
|
|
||||||
|
if (span->data.type != REDRAW_SPAN_BORDER)
|
||||||
|
return (NULL);
|
||||||
|
|
||||||
|
if (span->data.b.style_wp != NULL)
|
||||||
|
return (span->data.b.style_wp);
|
||||||
|
if (active != NULL && screen_redraw_span_has_pane(span, active))
|
||||||
|
return (active);
|
||||||
|
|
||||||
|
if (span->data.b.top_wp != NULL)
|
||||||
|
return (span->data.b.top_wp);
|
||||||
|
if (span->data.b.bottom_wp != NULL)
|
||||||
|
return (span->data.b.bottom_wp);
|
||||||
|
if (span->data.b.left_wp != NULL)
|
||||||
|
return (span->data.b.left_wp);
|
||||||
|
if (span->data.b.right_wp != NULL)
|
||||||
|
return (span->data.b.right_wp);
|
||||||
|
return (NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Should this span use the active style? */
|
||||||
|
static int
|
||||||
|
screen_redraw_draw_border_active(struct redraw_scene *scene,
|
||||||
|
struct redraw_span *span)
|
||||||
|
{
|
||||||
|
struct window_pane *active = server_client_get_pane(scene->c);
|
||||||
|
|
||||||
|
if (span->data.type != REDRAW_SPAN_BORDER || active == NULL)
|
||||||
|
return (0);
|
||||||
|
if (span->data.b.style_wp != NULL)
|
||||||
|
return (span->data.b.style_wp == active);
|
||||||
|
return (screen_redraw_span_has_pane(span, active));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Draw arrow indicator if this border span is an arrow cell. */
|
||||||
|
static void
|
||||||
|
screen_redraw_draw_border_arrow(struct redraw_scene *scene,
|
||||||
|
struct redraw_span *span, struct grid_cell *gc)
|
||||||
|
{
|
||||||
|
struct window_pane *active = server_client_get_pane(scene->c);
|
||||||
|
char ch;
|
||||||
|
|
||||||
|
if (span->data.type != REDRAW_SPAN_BORDER || active == NULL)
|
||||||
|
return;
|
||||||
|
if (~span->data.b.flags & REDRAW_BORDER_IS_ARROW)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (span->data.b.left_wp == active)
|
||||||
|
ch = ',';
|
||||||
|
else if (span->data.b.right_wp == active)
|
||||||
|
ch = '+';
|
||||||
|
else if (span->data.b.top_wp == active)
|
||||||
|
ch = '-';
|
||||||
|
else if (span->data.b.bottom_wp == active)
|
||||||
|
ch = '.';
|
||||||
|
else
|
||||||
|
return;
|
||||||
|
|
||||||
|
utf8_set(&gc->data, ch);
|
||||||
|
gc->attr |= GRID_ATTR_CHARSET;
|
||||||
|
}
|
||||||
|
|
||||||
/* Draw a border span. */
|
/* Draw a border span. */
|
||||||
static void
|
static void
|
||||||
screen_redraw_draw_border_span(struct redraw_scene *scene,
|
screen_redraw_draw_border_span(struct redraw_scene *scene,
|
||||||
struct redraw_span *span, u_int x, u_int y, u_int n)
|
struct redraw_span *span, u_int x, u_int y, u_int n)
|
||||||
{
|
{
|
||||||
struct client *c = scene->c;
|
struct client *c = scene->c;
|
||||||
|
struct session *s = c->session;
|
||||||
struct tty *tty = &c->tty;
|
struct tty *tty = &c->tty;
|
||||||
|
struct window *w = scene->w;
|
||||||
|
struct options *oo = w->options;
|
||||||
|
struct window_pane *wp = NULL, *marked = marked_pane.wp;
|
||||||
|
struct grid_cell gc;
|
||||||
|
enum pane_lines pane_lines;
|
||||||
|
u_int i, cell_type;
|
||||||
|
int isolates = 0, active;
|
||||||
|
|
||||||
|
if (span->data.type != REDRAW_SPAN_BORDER)
|
||||||
|
cell_type = CELL_OUTSIDE;
|
||||||
|
else {
|
||||||
|
wp = screen_redraw_draw_get_style_pane(scene, span);
|
||||||
|
cell_type = span->data.b.cell_type;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (wp == NULL) {
|
||||||
|
pane_lines = options_get_number(oo, "pane-border-lines");
|
||||||
|
window_get_border_cell(w, NULL, pane_lines, cell_type, &gc);
|
||||||
|
screen_redraw_draw_get_default_style(scene, &gc);
|
||||||
|
} else {
|
||||||
|
active = screen_redraw_draw_border_active(scene, span);
|
||||||
|
window_pane_get_border_style(wp, c, active, &gc);
|
||||||
|
window_pane_get_border_cell(wp, cell_type, &gc);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (span->data.type == REDRAW_SPAN_BORDER &&
|
||||||
|
server_is_marked(s, s->curw, marked) &&
|
||||||
|
screen_redraw_span_has_pane(span, marked))
|
||||||
|
gc.attr ^= GRID_ATTR_REVERSE;
|
||||||
|
screen_redraw_draw_border_arrow(scene, span, &gc);
|
||||||
|
|
||||||
|
if (cell_type == CELL_TOPBOTTOM &&
|
||||||
|
(c->flags & CLIENT_UTF8) &&
|
||||||
|
tty_term_has(tty->term, TTYC_BIDI))
|
||||||
|
isolates = 1;
|
||||||
|
|
||||||
tty_cursor(tty, x, y);
|
tty_cursor(tty, x, y);
|
||||||
for (x = 0; x < n; x++)
|
if (isolates)
|
||||||
tty_putc(tty, '-');
|
tty_puts(tty, REDRAW_END_ISOLATE);
|
||||||
|
for (i = 0; i < n; i++)
|
||||||
|
tty_cell(tty, &gc, NULL);
|
||||||
|
if (isolates)
|
||||||
|
tty_puts(tty, REDRAW_START_ISOLATE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Draw a status span. */
|
/* Draw a pane status span. */
|
||||||
static void
|
static void
|
||||||
screen_redraw_draw_status_span(struct redraw_scene *scene,
|
screen_redraw_draw_status_span(struct redraw_scene *scene,
|
||||||
struct redraw_span *span, u_int x, u_int y, u_int n)
|
struct redraw_span *span, u_int x, u_int y, u_int n)
|
||||||
{
|
{
|
||||||
struct client *c = scene->c;
|
struct client *c = scene->c;
|
||||||
struct tty *tty = &c->tty;
|
struct tty *tty = &c->tty;
|
||||||
|
struct window_pane *wp = span->data.st.wp;
|
||||||
|
struct screen *s = &wp->status_screen;
|
||||||
|
u_int px, sx = screen_size_x(s);
|
||||||
|
|
||||||
tty_cursor(tty, x, y);
|
px = span->data.st.offset + (x - span->x);
|
||||||
for (x = 0; x < n; x++)
|
if (px < sx) {
|
||||||
tty_putc(tty, 's');
|
if (n > sx - px)
|
||||||
|
n = sx - px;
|
||||||
|
tty_draw_line(tty, s, px, 0, n, x, y, NULL);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Draw a scrollbar span. */
|
/* Draw a scrollbar span. */
|
||||||
@@ -1056,7 +1200,6 @@ screen_redraw_draw_pane_lines(struct redraw_scene *scene, u_int status_lines,
|
|||||||
TAILQ_FOREACH(span, spans, entry) {
|
TAILQ_FOREACH(span, spans, entry) {
|
||||||
if (span->data.sb.wp != wp)
|
if (span->data.sb.wp != wp)
|
||||||
continue;
|
continue;
|
||||||
cy = status_lines + y;
|
|
||||||
screen_redraw_draw_span(scene, span, cy);
|
screen_redraw_draw_span(scene, span, cy);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1106,6 +1249,53 @@ screen_redraw_draw_lines(struct redraw_scene *scene, u_int status_lines,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Get line for pane status line. */
|
||||||
|
static int
|
||||||
|
screen_redraw_pane_status_line(struct redraw_scene *scene,
|
||||||
|
struct window_pane *wp, u_int *line)
|
||||||
|
{
|
||||||
|
int pane_status, wy;
|
||||||
|
|
||||||
|
pane_status = window_pane_get_pane_status(wp);
|
||||||
|
if (pane_status == PANE_STATUS_OFF)
|
||||||
|
return (0);
|
||||||
|
|
||||||
|
if (pane_status == PANE_STATUS_TOP)
|
||||||
|
wy = (int)wp->yoff - 1;
|
||||||
|
else
|
||||||
|
wy = (int)wp->yoff + wp->sy;
|
||||||
|
if (wy < 0 || wy < (int)scene->oy)
|
||||||
|
return (0);
|
||||||
|
if ((u_int)wy >= scene->oy + scene->sy)
|
||||||
|
return (0);
|
||||||
|
*line = wy - scene->oy;
|
||||||
|
return (1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get available width for pane status line. */
|
||||||
|
static u_int
|
||||||
|
screen_redraw_pane_status_width(struct redraw_scene *scene,
|
||||||
|
struct window_pane *wp, struct redraw_span **first)
|
||||||
|
{
|
||||||
|
struct redraw_span *span;
|
||||||
|
u_int y, width = 0, end;
|
||||||
|
|
||||||
|
if (!screen_redraw_pane_status_line(scene, wp, &y))
|
||||||
|
return (0);
|
||||||
|
|
||||||
|
*first = NULL;
|
||||||
|
TAILQ_FOREACH(span, &scene->lines[y].spans[REDRAW_SPAN_STATUS], entry) {
|
||||||
|
if (span->data.st.wp == wp) {
|
||||||
|
if (*first == NULL)
|
||||||
|
*first = span;
|
||||||
|
end = span->data.st.offset + span->width;
|
||||||
|
if (end > width)
|
||||||
|
width = end;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return (width);
|
||||||
|
}
|
||||||
|
|
||||||
/* Draw scene to client. */
|
/* Draw scene to client. */
|
||||||
static void
|
static void
|
||||||
screen_redraw_draw(struct client *c, struct window_pane *wp, int flags)
|
screen_redraw_draw(struct client *c, struct window_pane *wp, int flags)
|
||||||
@@ -1114,6 +1304,9 @@ screen_redraw_draw(struct client *c, struct window_pane *wp, int flags)
|
|||||||
struct tty *tty = &c->tty;
|
struct tty *tty = &c->tty;
|
||||||
struct redraw_scene *scene;
|
struct redraw_scene *scene;
|
||||||
u_int status_lines = 0;
|
u_int status_lines = 0;
|
||||||
|
struct window_pane *loop;
|
||||||
|
u_int width;
|
||||||
|
struct redraw_span *first;
|
||||||
|
|
||||||
if (c->flags & CLIENT_SUSPENDED)
|
if (c->flags & CLIENT_SUSPENDED)
|
||||||
return;
|
return;
|
||||||
@@ -1122,9 +1315,26 @@ screen_redraw_draw(struct client *c, struct window_pane *wp, int flags)
|
|||||||
if (scene == NULL)
|
if (scene == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (flags == REDRAW_DRAW_ALL || (flags & REDRAW_DRAW_STATUS)) {
|
||||||
|
TAILQ_FOREACH(loop, &scene->w->panes, entry) {
|
||||||
|
width = screen_redraw_pane_status_width(scene, loop,
|
||||||
|
&first);
|
||||||
|
if (width != 0)
|
||||||
|
window_make_pane_status(loop, c, width, first);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (options_get_number(s->options, "status-position") == 0)
|
if (options_get_number(s->options, "status-position") == 0)
|
||||||
status_lines = status_line_size(c);
|
status_lines = status_line_size(c);
|
||||||
|
|
||||||
|
if (flags == REDRAW_DRAW_ALL || (flags & REDRAW_DRAW_BORDER)) {
|
||||||
|
scene->default_gc_set = 0;
|
||||||
|
TAILQ_FOREACH(loop, &scene->w->panes, entry) {
|
||||||
|
loop->border_gc_set = 0;
|
||||||
|
loop->active_border_gc_set = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
tty_sync_start(tty);
|
tty_sync_start(tty);
|
||||||
tty_update_mode(tty, 0, NULL);
|
tty_update_mode(tty, 0, NULL);
|
||||||
|
|
||||||
@@ -1139,6 +1349,27 @@ screen_redraw_draw(struct client *c, struct window_pane *wp, int flags)
|
|||||||
screen_redraw_free_scene(scene); //XXX
|
screen_redraw_free_scene(scene); //XXX
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Get cell type for offset from span. */
|
||||||
|
int
|
||||||
|
screen_redraw_get_span_cell_type(struct redraw_span *span, u_int x)
|
||||||
|
{
|
||||||
|
u_int start, end;
|
||||||
|
|
||||||
|
for (; span != NULL; span = TAILQ_NEXT(span, entry)) {
|
||||||
|
if (span->data.type != REDRAW_SPAN_STATUS)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
start = span->data.st.offset;
|
||||||
|
end = start + span->width;
|
||||||
|
if (x >= start && x < end)
|
||||||
|
return (span->data.st.cell_type);
|
||||||
|
|
||||||
|
if (start > x)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return (CELL_LEFTRIGHT);
|
||||||
|
}
|
||||||
|
|
||||||
/* Draw screen. */
|
/* Draw screen. */
|
||||||
void
|
void
|
||||||
screen_redraw_screen(struct client *c)
|
screen_redraw_screen(struct client *c)
|
||||||
@@ -1152,10 +1383,21 @@ screen_redraw_screen(struct client *c)
|
|||||||
flags |= (REDRAW_DRAW_BORDER|REDRAW_DRAW_STATUS);
|
flags |= (REDRAW_DRAW_BORDER|REDRAW_DRAW_STATUS);
|
||||||
if (c->flags & CLIENT_REDRAWSTATUS)
|
if (c->flags & CLIENT_REDRAWSTATUS)
|
||||||
flags |= REDRAW_DRAW_STATUS;
|
flags |= REDRAW_DRAW_STATUS;
|
||||||
|
if (flags != 0)
|
||||||
screen_redraw_draw(c, NULL, flags);
|
screen_redraw_draw(c, NULL, flags);
|
||||||
}
|
}
|
||||||
//XXX client status line
|
|
||||||
//XXX overlays
|
#if 0 //XXX
|
||||||
|
if (ctx.statuslines != 0 &&
|
||||||
|
(flags & (CLIENT_REDRAWSTATUS|CLIENT_REDRAWSTATUSALWAYS))) {
|
||||||
|
log_debug("%s: redrawing status", c->name);
|
||||||
|
screen_redraw_draw_status(&ctx);
|
||||||
|
}
|
||||||
|
if (c->overlay_draw != NULL && (flags & CLIENT_REDRAWOVERLAY)) {
|
||||||
|
log_debug("%s: redrawing overlay", c->name);
|
||||||
|
c->overlay_draw(c, c->overlay_data, &ctx);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Draw a single pane. */
|
/* Draw a single pane. */
|
||||||
|
|||||||
16
tmux.h
16
tmux.h
@@ -63,6 +63,7 @@ struct mouse_event;
|
|||||||
struct options;
|
struct options;
|
||||||
struct options_array_item;
|
struct options_array_item;
|
||||||
struct options_entry;
|
struct options_entry;
|
||||||
|
struct redraw_span;
|
||||||
struct screen_write_citem;
|
struct screen_write_citem;
|
||||||
struct screen_write_cline;
|
struct screen_write_cline;
|
||||||
struct screen_write_ctx;
|
struct screen_write_ctx;
|
||||||
@@ -1124,9 +1125,6 @@ struct screen_redraw_ctx {
|
|||||||
int pane_scrollbars;
|
int pane_scrollbars;
|
||||||
int pane_scrollbars_pos;
|
int pane_scrollbars_pos;
|
||||||
|
|
||||||
struct grid_cell no_pane_gc;
|
|
||||||
int no_pane_gc_set;
|
|
||||||
|
|
||||||
u_int sx;
|
u_int sx;
|
||||||
u_int sy;
|
u_int sy;
|
||||||
int ox;
|
int ox;
|
||||||
@@ -1336,7 +1334,6 @@ struct window_pane {
|
|||||||
struct screen base;
|
struct screen base;
|
||||||
|
|
||||||
struct screen status_screen;
|
struct screen status_screen;
|
||||||
size_t status_size;
|
|
||||||
|
|
||||||
TAILQ_HEAD(, window_mode_entry) modes;
|
TAILQ_HEAD(, window_mode_entry) modes;
|
||||||
|
|
||||||
@@ -3389,6 +3386,7 @@ void screen_write_alternateoff(struct screen_write_ctx *,
|
|||||||
void screen_redraw_screen(struct client *);
|
void screen_redraw_screen(struct client *);
|
||||||
void screen_redraw_pane(struct client *, struct window_pane *);
|
void screen_redraw_pane(struct client *, struct window_pane *);
|
||||||
void screen_redraw_pane_scrollbar(struct client *, struct window_pane *);
|
void screen_redraw_pane_scrollbar(struct client *, struct window_pane *);
|
||||||
|
int screen_redraw_get_span_cell_type(struct redraw_span *, u_int);
|
||||||
|
|
||||||
/* screen.c */
|
/* screen.c */
|
||||||
void screen_init(struct screen *, u_int, u_int, u_int);
|
void screen_init(struct screen *, u_int, u_int, u_int);
|
||||||
@@ -3536,6 +3534,16 @@ struct style_range *window_pane_status_get_range(struct window_pane *, u_int,
|
|||||||
u_int);
|
u_int);
|
||||||
int window_pane_is_floating(struct window_pane *);
|
int window_pane_is_floating(struct window_pane *);
|
||||||
|
|
||||||
|
/* window-border.c */
|
||||||
|
void window_get_border_cell(struct window *, struct window_pane *,
|
||||||
|
enum pane_lines, int, struct grid_cell *);
|
||||||
|
void window_pane_get_border_cell(struct window_pane *, int,
|
||||||
|
struct grid_cell *);
|
||||||
|
void window_pane_get_border_style(struct window_pane *,
|
||||||
|
struct client *, int, struct grid_cell *);
|
||||||
|
void window_make_pane_status(struct window_pane *, struct client *,
|
||||||
|
u_int, struct redraw_span *);
|
||||||
|
|
||||||
/* window-visible.c */
|
/* window-visible.c */
|
||||||
int window_position_is_visible(struct visible_ranges *, u_int);
|
int window_position_is_visible(struct visible_ranges *, u_int);
|
||||||
struct visible_ranges *window_visible_ranges(struct window_pane *, int, int,
|
struct visible_ranges *window_visible_ranges(struct window_pane *, int, int,
|
||||||
|
|||||||
163
window-border.c
Normal file
163
window-border.c
Normal file
@@ -0,0 +1,163 @@
|
|||||||
|
/* $OpenBSD$ */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2026 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
|
||||||
|
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
#include "tmux.h"
|
||||||
|
|
||||||
|
/* Get border cell. */
|
||||||
|
void
|
||||||
|
window_get_border_cell(struct window *w, struct window_pane *wp,
|
||||||
|
enum pane_lines pane_lines, int cell_type, struct grid_cell *gc)
|
||||||
|
{
|
||||||
|
u_int idx;
|
||||||
|
|
||||||
|
if (cell_type == CELL_OUTSIDE && w->fill_character != NULL) {
|
||||||
|
utf8_copy(&gc->data, &w->fill_character[0]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (pane_lines) {
|
||||||
|
case PANE_LINES_NUMBER:
|
||||||
|
if (cell_type == CELL_OUTSIDE) {
|
||||||
|
gc->attr |= GRID_ATTR_CHARSET;
|
||||||
|
utf8_set(&gc->data, CELL_BORDERS[CELL_OUTSIDE]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
gc->attr &= ~GRID_ATTR_CHARSET;
|
||||||
|
if (wp != NULL && window_pane_index(wp, &idx) == 0)
|
||||||
|
utf8_set(&gc->data, '0' + (idx % 10));
|
||||||
|
else
|
||||||
|
utf8_set(&gc->data, '*');
|
||||||
|
break;
|
||||||
|
case PANE_LINES_DOUBLE:
|
||||||
|
gc->attr &= ~GRID_ATTR_CHARSET;
|
||||||
|
utf8_copy(&gc->data, tty_acs_double_borders(cell_type));
|
||||||
|
break;
|
||||||
|
case PANE_LINES_HEAVY:
|
||||||
|
gc->attr &= ~GRID_ATTR_CHARSET;
|
||||||
|
utf8_copy(&gc->data, tty_acs_heavy_borders(cell_type));
|
||||||
|
break;
|
||||||
|
case PANE_LINES_SIMPLE:
|
||||||
|
gc->attr &= ~GRID_ATTR_CHARSET;
|
||||||
|
utf8_set(&gc->data, SIMPLE_BORDERS[cell_type]);
|
||||||
|
break;
|
||||||
|
case PANE_LINES_NONE:
|
||||||
|
case PANE_LINES_SPACES:
|
||||||
|
gc->attr &= ~GRID_ATTR_CHARSET;
|
||||||
|
utf8_set(&gc->data, ' ');
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
gc->attr |= GRID_ATTR_CHARSET;
|
||||||
|
utf8_set(&gc->data, CELL_BORDERS[cell_type]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get pane border cell. */
|
||||||
|
void
|
||||||
|
window_pane_get_border_cell(struct window_pane *wp, int cell_type,
|
||||||
|
struct grid_cell *gc)
|
||||||
|
{
|
||||||
|
enum pane_lines pane_lines = window_pane_get_pane_lines(wp);
|
||||||
|
|
||||||
|
window_get_border_cell(wp->window, wp, pane_lines, cell_type, gc);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get pane border style. */
|
||||||
|
void
|
||||||
|
window_pane_get_border_style(struct window_pane *wp, struct client *c,
|
||||||
|
int active, struct grid_cell *gc)
|
||||||
|
{
|
||||||
|
struct session *s = c->session;
|
||||||
|
struct format_tree *ft;
|
||||||
|
const char *option;
|
||||||
|
struct grid_cell *saved;
|
||||||
|
int *flag;
|
||||||
|
|
||||||
|
if (active) {
|
||||||
|
flag = &wp->active_border_gc_set;
|
||||||
|
saved = &wp->active_border_gc;
|
||||||
|
option = "pane-active-border-style";
|
||||||
|
} else {
|
||||||
|
flag = &wp->border_gc_set;
|
||||||
|
saved = &wp->border_gc;
|
||||||
|
option = "pane-border-style";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!*flag) {
|
||||||
|
ft = format_create_defaults(NULL, c, s, s->curw, wp);
|
||||||
|
style_apply(saved, wp->options, option, ft);
|
||||||
|
format_free(ft);
|
||||||
|
*flag = 1;
|
||||||
|
}
|
||||||
|
memcpy(gc, saved, sizeof *gc);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Build pane status line. */
|
||||||
|
void
|
||||||
|
window_make_pane_status(struct window_pane *wp, struct client *c, u_int width,
|
||||||
|
struct redraw_span *span)
|
||||||
|
{
|
||||||
|
struct grid_cell gc;
|
||||||
|
const char *fmt, *border_option;
|
||||||
|
struct format_tree *ft;
|
||||||
|
struct style_line_entry *sle = &wp->border_status_line;
|
||||||
|
struct screen_write_ctx ctx;
|
||||||
|
char *expanded;
|
||||||
|
u_int i;
|
||||||
|
int pane_status, cell_type;
|
||||||
|
|
||||||
|
pane_status = window_pane_get_pane_status(wp);
|
||||||
|
if (pane_status == PANE_STATUS_OFF || width == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
ft = format_create(c, NULL, FORMAT_PANE|wp->id, FORMAT_STATUS);
|
||||||
|
format_defaults(ft, c, c->session, c->session->curw, wp);
|
||||||
|
|
||||||
|
if (wp == server_client_get_pane(c))
|
||||||
|
border_option = "pane-active-border-style";
|
||||||
|
else
|
||||||
|
border_option = "pane-border-style";
|
||||||
|
style_apply(&gc, wp->options, border_option, ft);
|
||||||
|
|
||||||
|
fmt = options_get_string(wp->options, "pane-border-format");
|
||||||
|
expanded = format_expand_time(ft, fmt);
|
||||||
|
|
||||||
|
screen_init(&wp->status_screen, width, 1, 0);
|
||||||
|
wp->status_screen.mode = 0;
|
||||||
|
|
||||||
|
screen_write_start(&ctx, &wp->status_screen);
|
||||||
|
|
||||||
|
for (i = 0; i < width; i++) {
|
||||||
|
cell_type = screen_redraw_get_span_cell_type(span, i);
|
||||||
|
window_pane_get_border_cell(wp, cell_type, &gc);
|
||||||
|
screen_write_cell(&ctx, &gc);
|
||||||
|
}
|
||||||
|
gc.attr &= ~GRID_ATTR_CHARSET;
|
||||||
|
|
||||||
|
screen_write_cursormove(&ctx, 0, 0, 0);
|
||||||
|
style_ranges_free(&sle->ranges);
|
||||||
|
format_draw(&ctx, &gc, width, expanded, &sle->ranges, 0);
|
||||||
|
|
||||||
|
screen_write_stop(&ctx);
|
||||||
|
format_free(ft);
|
||||||
|
|
||||||
|
free(sle->expanded);
|
||||||
|
sle->expanded = expanded;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user