mirror of
https://github.com/tmux/tmux.git
synced 2026-10-16 16:44:30 +00:00
Add a vertical (side) status line, GitHub issue 5468 from John DeWyze.
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: cmd-display-menu.c,v 1.57 2026/10/15 22:16:32 nicm Exp $ */
|
/* $OpenBSD: cmd-display-menu.c,v 1.58 2026/10/16 07:59:06 nicm Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2019 Nicholas Marriott <nicholas.marriott@gmail.com>
|
* Copyright (c) 2019 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||||
@@ -104,7 +104,15 @@ cmd_display_menu_set_mouse_pos(struct client *tc, struct mouse_event *m,
|
|||||||
return;
|
return;
|
||||||
tty_window_offset(&tc->tty, &ox, &oy, &sx, &sy);
|
tty_window_offset(&tc->tty, &ox, &oy, &sx, &sy);
|
||||||
|
|
||||||
*mouse_x = m->x + ox;
|
if (m->sideat == 0) {
|
||||||
|
if (m->x >= m->sidewidth)
|
||||||
|
*mouse_x = m->x - m->sidewidth + ox;
|
||||||
|
else
|
||||||
|
*mouse_x = ox;
|
||||||
|
} else if (m->sideat > 0 && m->x >= (u_int)m->sideat)
|
||||||
|
*mouse_x = ox + sx - 1;
|
||||||
|
else
|
||||||
|
*mouse_x = m->x + ox;
|
||||||
if (m->statusat == 0) {
|
if (m->statusat == 0) {
|
||||||
if (m->y >= m->statuslines)
|
if (m->y >= m->statuslines)
|
||||||
*mouse_y = m->y - m->statuslines + oy;
|
*mouse_y = m->y - m->statuslines + oy;
|
||||||
@@ -118,40 +126,24 @@ cmd_display_menu_set_mouse_pos(struct client *tc, struct mouse_event *m,
|
|||||||
format_add(ft, "popup_mouse_y", "%ld", *mouse_y);
|
format_add(ft, "popup_mouse_y", "%ld", *mouse_y);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static void
|
||||||
cmd_display_menu_get_menu_pos(struct client *tc, struct cmdq_item *item,
|
cmd_display_menu_set_status_pos(struct client *tc, struct cmdq_item *item,
|
||||||
struct args *args, u_int *px, u_int *py, u_int w, u_int h)
|
struct format_tree *ft, u_int w, u_int h)
|
||||||
{
|
{
|
||||||
struct cmd_find_state *target = cmdq_get_target(item);
|
struct mouse_event *m = &cmdq_get_event(item)->m;
|
||||||
struct key_event *event = cmdq_get_event(item);
|
struct winlink *wl = cmdq_get_target(item)->wl;
|
||||||
struct session *s = tc->session;
|
struct window *window = wl->window;
|
||||||
struct winlink *wl = target->wl;
|
struct style_ranges *ranges;
|
||||||
struct window *window = target->w;
|
struct style_range *sr = NULL, *clicked;
|
||||||
struct window_pane *wp = target->wp;
|
u_int line, lines, ox, oy, sx, sy, x, y, sidey;
|
||||||
struct style_ranges *ranges = NULL;
|
int position, side;
|
||||||
struct style_range *sr = NULL;
|
|
||||||
const char *xp, *yp;
|
|
||||||
char *p;
|
|
||||||
u_int line, ox, oy, sx, sy, lines, position;
|
|
||||||
long n, max_x, max_y, mouse_x = 0, mouse_y = 0;
|
|
||||||
struct format_tree *ft;
|
|
||||||
|
|
||||||
if (event->m.valid)
|
|
||||||
window = tc->session->curw->window;
|
|
||||||
max_x = window->sx > w ? window->sx - w : 0;
|
|
||||||
max_y = window->sy > h ? window->sy - h : 0;
|
|
||||||
|
|
||||||
tty_window_offset(&tc->tty, &ox, &oy, &sx, &sy);
|
tty_window_offset(&tc->tty, &ox, &oy, &sx, &sy);
|
||||||
|
if (m->valid)
|
||||||
ft = format_create_from_target(item);
|
window = tc->session->curw->window;
|
||||||
cmd_display_menu_set_mouse_pos(tc, &event->m, ft, &mouse_x, &mouse_y);
|
|
||||||
|
|
||||||
format_add(ft, "popup_last_x", "%u", window->menu_last_px);
|
|
||||||
format_add(ft, "popup_last_y", "%u", window->menu_last_py + h);
|
|
||||||
|
|
||||||
lines = status_line_size(tc);
|
lines = status_line_size(tc);
|
||||||
position = options_get_number(s->options, "status-position");
|
position = status_at_line(tc);
|
||||||
if (status_at_line(tc) != -1 && lines != 0) {
|
if (position != -1 && lines != 0) {
|
||||||
for (line = 0; line < lines; line++) {
|
for (line = 0; line < lines; line++) {
|
||||||
ranges = &tc->status.entries[line].ranges;
|
ranges = &tc->status.entries[line].ranges;
|
||||||
TAILQ_FOREACH(sr, ranges, entry) {
|
TAILQ_FOREACH(sr, ranges, entry) {
|
||||||
@@ -163,23 +155,75 @@ cmd_display_menu_get_menu_pos(struct client *tc, struct cmdq_item *item,
|
|||||||
if (sr != NULL)
|
if (sr != NULL)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
if (position == 0)
|
||||||
|
y = h;
|
||||||
|
else
|
||||||
|
y = window->sy;
|
||||||
if (sr != NULL) {
|
if (sr != NULL) {
|
||||||
format_add(ft, "popup_window_status_line_x", "%u",
|
format_add(ft, "popup_window_status_line_x", "%u",
|
||||||
sr->start + ox);
|
sr->start + ox);
|
||||||
if (position == 0) {
|
format_add(ft, "popup_window_status_line_y", "%u", y);
|
||||||
format_add(ft, "popup_window_status_line_y",
|
|
||||||
"%u", h);
|
|
||||||
} else {
|
|
||||||
format_add(ft, "popup_window_status_line_y",
|
|
||||||
"%u", window->sy);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (position == 0)
|
format_add(ft, "popup_status_line_y", "%u", y);
|
||||||
format_add(ft, "popup_status_line_y", "%u", h);
|
|
||||||
else
|
|
||||||
format_add(ft, "popup_status_line_y", "%u", window->sy);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
side = status_side_at_column(tc);
|
||||||
|
if (side == -1)
|
||||||
|
return;
|
||||||
|
sidey = (position == 0 ? lines : 0);
|
||||||
|
if (m->valid && m->x >= (u_int)side &&
|
||||||
|
m->x < side + status_side_size(tc) &&
|
||||||
|
m->y >= sidey && m->y - sidey < status_side_rows(tc)) {
|
||||||
|
y = m->y - sidey;
|
||||||
|
clicked = status_side_get_range(tc, m->x - side, y);
|
||||||
|
if (clicked == NULL || clicked->type != STYLE_RANGE_WINDOW ||
|
||||||
|
clicked->argument != (u_int)wl->idx)
|
||||||
|
return;
|
||||||
|
sr = clicked;
|
||||||
|
} else {
|
||||||
|
if (sr != NULL)
|
||||||
|
return;
|
||||||
|
ranges = &tc->side_status.ranges;
|
||||||
|
TAILQ_FOREACH(sr, ranges, entry) {
|
||||||
|
if (sr->type == STYLE_RANGE_WINDOW &&
|
||||||
|
sr->argument == (u_int)wl->idx)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (sr == NULL)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
x = ox;
|
||||||
|
if (side != 0 && sx > w)
|
||||||
|
x += sx - w;
|
||||||
|
format_add(ft, "popup_window_status_line_x", "%u", x);
|
||||||
|
format_add(ft, "popup_window_status_line_y", "%u", oy + sr->y + h);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
cmd_display_menu_get_menu_pos(struct client *tc, struct cmdq_item *item,
|
||||||
|
struct args *args, u_int *px, u_int *py, u_int w, u_int h)
|
||||||
|
{
|
||||||
|
struct cmd_find_state *target = cmdq_get_target(item);
|
||||||
|
struct key_event *event = cmdq_get_event(item);
|
||||||
|
struct window *window = target->w;
|
||||||
|
struct window_pane *wp = target->wp;
|
||||||
|
const char *xp, *yp;
|
||||||
|
char *p;
|
||||||
|
long n, max_x, max_y, mouse_x = 0, mouse_y = 0;
|
||||||
|
struct format_tree *ft;
|
||||||
|
|
||||||
|
if (event->m.valid)
|
||||||
|
window = tc->session->curw->window;
|
||||||
|
max_x = window->sx > w ? window->sx - w : 0;
|
||||||
|
max_y = window->sy > h ? window->sy - h : 0;
|
||||||
|
|
||||||
|
ft = format_create_from_target(item);
|
||||||
|
cmd_display_menu_set_mouse_pos(tc, &event->m, ft, &mouse_x, &mouse_y);
|
||||||
|
format_add(ft, "popup_last_x", "%u", window->menu_last_px);
|
||||||
|
format_add(ft, "popup_last_y", "%u", window->menu_last_py + h);
|
||||||
|
|
||||||
|
cmd_display_menu_set_status_pos(tc, item, ft, w, h);
|
||||||
|
|
||||||
format_add(ft, "popup_width", "%u", w);
|
format_add(ft, "popup_width", "%u", w);
|
||||||
format_add(ft, "popup_height", "%u", h);
|
format_add(ft, "popup_height", "%u", h);
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: cmd-join-pane.c,v 1.78 2026/10/09 13:12:14 nicm Exp $ */
|
/* $OpenBSD: cmd-join-pane.c,v 1.79 2026/10/16 07:59:06 nicm Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2011 George Nachman <tmux@georgester.com>
|
* Copyright (c) 2011 George Nachman <tmux@georgester.com>
|
||||||
@@ -325,11 +325,19 @@ cmd_join_pane_mouse_move(struct client *c, struct mouse_event *m)
|
|||||||
y -= m->statuslines;
|
y -= m->statuslines;
|
||||||
else if (m->statusat > 0 && y >= m->statusat)
|
else if (m->statusat > 0 && y >= m->statusat)
|
||||||
y = m->statusat - 1;
|
y = m->statusat - 1;
|
||||||
|
if (m->sideat == 0 && x >= (int)m->sidewidth)
|
||||||
|
x -= m->sidewidth;
|
||||||
|
else if (m->sideat > 0 && x >= m->sideat)
|
||||||
|
x = m->sideat - 1;
|
||||||
ly = m->ly + m->oy; lx = m->lx + m->ox;
|
ly = m->ly + m->oy; lx = m->lx + m->ox;
|
||||||
if (m->statusat == 0 && ly >= (int)m->statuslines)
|
if (m->statusat == 0 && ly >= (int)m->statuslines)
|
||||||
ly -= m->statuslines;
|
ly -= m->statuslines;
|
||||||
else if (m->statusat > 0 && ly >= m->statusat)
|
else if (m->statusat > 0 && ly >= m->statusat)
|
||||||
ly = m->statusat - 1;
|
ly = m->statusat - 1;
|
||||||
|
if (m->sideat == 0 && lx >= (int)m->sidewidth)
|
||||||
|
lx -= m->sidewidth;
|
||||||
|
else if (m->sideat > 0 && lx >= m->sideat)
|
||||||
|
lx = m->sideat - 1;
|
||||||
|
|
||||||
if (x != lx || y != ly) {
|
if (x != lx || y != ly) {
|
||||||
oxoff = wp->xoff;
|
oxoff = wp->xoff;
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: cmd-resize-pane.c,v 1.71 2026/10/09 13:12:14 nicm Exp $ */
|
/* $OpenBSD: cmd-resize-pane.c,v 1.72 2026/10/16 07:59:06 nicm Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2009 Nicholas Marriott <nicholas.marriott@gmail.com>
|
* Copyright (c) 2009 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||||
@@ -267,11 +267,19 @@ cmd_resize_pane_mouse_resize_move_floating(struct client *c,
|
|||||||
y -= m->statuslines;
|
y -= m->statuslines;
|
||||||
else if (m->statusat > 0 && y >= m->statusat)
|
else if (m->statusat > 0 && y >= m->statusat)
|
||||||
y = m->statusat - 1;
|
y = m->statusat - 1;
|
||||||
|
if (m->sideat == 0 && x >= (int)m->sidewidth)
|
||||||
|
x -= m->sidewidth;
|
||||||
|
else if (m->sideat > 0 && x >= m->sideat)
|
||||||
|
x = m->sideat - 1;
|
||||||
ly = m->ly + m->oy; lx = m->lx + m->ox;
|
ly = m->ly + m->oy; lx = m->lx + m->ox;
|
||||||
if (m->statusat == 0 && ly >= (int)m->statuslines)
|
if (m->statusat == 0 && ly >= (int)m->statuslines)
|
||||||
ly -= m->statuslines;
|
ly -= m->statuslines;
|
||||||
else if (m->statusat > 0 && ly >= m->statusat)
|
else if (m->statusat > 0 && ly >= m->statusat)
|
||||||
ly = m->statusat - 1;
|
ly = m->statusat - 1;
|
||||||
|
if (m->sideat == 0 && lx >= (int)m->sidewidth)
|
||||||
|
lx -= m->sidewidth;
|
||||||
|
else if (m->sideat > 0 && lx >= m->sideat)
|
||||||
|
lx = m->sideat - 1;
|
||||||
|
|
||||||
if ((lx == left || lx == left + 1) && ly == wp->yoff - 1) {
|
if ((lx == left || lx == left + 1) && ly == wp->yoff - 1) {
|
||||||
/* Top left corner. */
|
/* Top left corner. */
|
||||||
@@ -381,11 +389,19 @@ cmd_resize_pane_mouse_resize_tiled(struct client *c, struct mouse_event *m)
|
|||||||
y -= m->statuslines;
|
y -= m->statuslines;
|
||||||
else if (m->statusat > 0 && y >= (u_int)m->statusat)
|
else if (m->statusat > 0 && y >= (u_int)m->statusat)
|
||||||
y = m->statusat - 1;
|
y = m->statusat - 1;
|
||||||
|
if (m->sideat == 0 && x >= m->sidewidth)
|
||||||
|
x -= m->sidewidth;
|
||||||
|
else if (m->sideat > 0 && x >= (u_int)m->sideat)
|
||||||
|
x = m->sideat - 1;
|
||||||
ly = m->ly + m->oy; lx = m->lx + m->ox;
|
ly = m->ly + m->oy; lx = m->lx + m->ox;
|
||||||
if (m->statusat == 0 && ly >= m->statuslines)
|
if (m->statusat == 0 && ly >= m->statuslines)
|
||||||
ly -= m->statuslines;
|
ly -= m->statuslines;
|
||||||
else if (m->statusat > 0 && ly >= (u_int)m->statusat)
|
else if (m->statusat > 0 && ly >= (u_int)m->statusat)
|
||||||
ly = m->statusat - 1;
|
ly = m->statusat - 1;
|
||||||
|
if (m->sideat == 0 && lx >= m->sidewidth)
|
||||||
|
lx -= m->sidewidth;
|
||||||
|
else if (m->sideat > 0 && lx >= (u_int)m->sideat)
|
||||||
|
lx = m->sideat - 1;
|
||||||
|
|
||||||
for (i = 0; i < nitems(cells); i++) {
|
for (i = 0; i < nitems(cells); i++) {
|
||||||
lc = layout_search_by_border(w->layout_root, lx + offsets[i][0],
|
lc = layout_search_by_border(w->layout_root, lx + offsets[i][0],
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: cmd-split-window.c,v 1.154 2026/10/15 15:42:35 nicm Exp $ */
|
/* $OpenBSD: cmd-split-window.c,v 1.155 2026/10/16 07:59:06 nicm Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2009 Nicholas Marriott <nicholas.marriott@gmail.com>
|
* Copyright (c) 2009 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||||
@@ -377,6 +377,10 @@ cmd_split_window_mouse_resize(struct client *c, struct mouse_event *m)
|
|||||||
y -= m->statuslines;
|
y -= m->statuslines;
|
||||||
else if (m->statusat > 0 && y >= m->statusat)
|
else if (m->statusat > 0 && y >= m->statusat)
|
||||||
y = m->statusat - 1;
|
y = m->statusat - 1;
|
||||||
|
if (m->sideat == 0 && x >= (int)m->sidewidth)
|
||||||
|
x -= m->sidewidth;
|
||||||
|
else if (m->sideat > 0 && x >= m->sideat)
|
||||||
|
x = m->sideat - 1;
|
||||||
|
|
||||||
lines = window_pane_get_pane_lines(wp);
|
lines = window_pane_get_pane_lines(wp);
|
||||||
border = (lines != PANE_LINES_NONE);
|
border = (lines != PANE_LINES_NONE);
|
||||||
|
|||||||
4
cmd.c
4
cmd.c
@@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: cmd.c,v 1.189 2026/07/17 08:29:34 nicm Exp $ */
|
/* $OpenBSD: cmd.c,v 1.190 2026/10/16 07:59:06 nicm Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
|
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||||
@@ -778,6 +778,8 @@ cmd_mouse_at(struct window_pane *wp, struct mouse_event *m, u_int *xp,
|
|||||||
|
|
||||||
if (m->statusat == 0 && y >= m->statuslines)
|
if (m->statusat == 0 && y >= m->statuslines)
|
||||||
y -= m->statuslines;
|
y -= m->statuslines;
|
||||||
|
if (m->sideat == 0 && x >= m->sidewidth)
|
||||||
|
x -= m->sidewidth;
|
||||||
|
|
||||||
if ((int)x < wp->xoff || (int)x >= wp->xoff + (int)wp->sx)
|
if ((int)x < wp->xoff || (int)x >= wp->xoff + (int)wp->sx)
|
||||||
return (-1);
|
return (-1);
|
||||||
|
|||||||
457
format-draw.c
457
format-draw.c
@@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: format-draw.c,v 1.36 2026/10/15 22:34:26 nicm Exp $ */
|
/* $OpenBSD: format-draw.c,v 1.37 2026/10/16 07:59:06 nicm Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2019 Nicholas Marriott <nicholas.marriott@gmail.com>
|
* Copyright (c) 2019 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||||
@@ -39,6 +39,30 @@ struct format_range {
|
|||||||
};
|
};
|
||||||
TAILQ_HEAD(format_ranges, format_range);
|
TAILQ_HEAD(format_ranges, format_range);
|
||||||
|
|
||||||
|
/* The style at a point in a format. */
|
||||||
|
struct format_style {
|
||||||
|
struct style sy;
|
||||||
|
struct grid_cell cur_def;
|
||||||
|
struct grid_cell base_def;
|
||||||
|
int fill;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* A single line of a format. */
|
||||||
|
struct format_line {
|
||||||
|
char *chunk;
|
||||||
|
struct format_style fs; /* at the start of the line */
|
||||||
|
int in_list;
|
||||||
|
int has_focus;
|
||||||
|
int marker; /* 0 = none, 1 = up, 2 = down */
|
||||||
|
};
|
||||||
|
|
||||||
|
/* State when splitting a format into lines. */
|
||||||
|
struct format_lines {
|
||||||
|
struct format_line *lines;
|
||||||
|
u_int nlines;
|
||||||
|
struct format_line current;
|
||||||
|
};
|
||||||
|
|
||||||
/* Does this range match this style? */
|
/* Does this range match this style? */
|
||||||
static int
|
static int
|
||||||
format_is_type(struct format_range *fr, struct style *sy)
|
format_is_type(struct format_range *fr, struct style *sy)
|
||||||
@@ -704,11 +728,42 @@ format_draw_many(struct screen_write_ctx *ctx, struct style *sy, char ch,
|
|||||||
screen_write_cell(ctx, &sy->gc);
|
screen_write_cell(ctx, &sy->gc);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Draw a format to a screen. */
|
/* Set up the style at the start of a format. */
|
||||||
void
|
static void
|
||||||
format_draw(struct screen_write_ctx *octx, const struct grid_cell *base,
|
format_init_style(struct format_style *fs, const struct grid_cell *base)
|
||||||
|
{
|
||||||
|
memcpy(&fs->base_def, base, sizeof fs->base_def);
|
||||||
|
memcpy(&fs->cur_def, base, sizeof fs->cur_def);
|
||||||
|
style_set(&fs->sy, base);
|
||||||
|
fs->fill = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Update the defaults if a style pushed, popped or set them. The previous cell
|
||||||
|
* is the one in use before the style.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
format_update_defaults(struct style *sy, const struct grid_cell *previous,
|
||||||
|
struct grid_cell *cur_def, struct grid_cell *base_def)
|
||||||
|
{
|
||||||
|
if (sy->default_type == STYLE_DEFAULT_PUSH) {
|
||||||
|
memcpy(cur_def, previous, sizeof *cur_def);
|
||||||
|
sy->default_type = STYLE_DEFAULT_BASE;
|
||||||
|
} else if (sy->default_type == STYLE_DEFAULT_POP) {
|
||||||
|
memcpy(cur_def, base_def, sizeof *cur_def);
|
||||||
|
sy->default_type = STYLE_DEFAULT_BASE;
|
||||||
|
} else if (sy->default_type == STYLE_DEFAULT_SET) {
|
||||||
|
memcpy(base_def, previous, sizeof *base_def);
|
||||||
|
memcpy(cur_def, previous, sizeof *cur_def);
|
||||||
|
sy->default_type = STYLE_DEFAULT_BASE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Draw a format to a screen, starting with a style. */
|
||||||
|
static void
|
||||||
|
format_draw1(struct screen_write_ctx *octx, const struct format_style *fs,
|
||||||
u_int available, const char *expanded, struct style_ranges *srs,
|
u_int available, const char *expanded, struct style_ranges *srs,
|
||||||
int default_colours)
|
int flags)
|
||||||
{
|
{
|
||||||
enum { LEFT,
|
enum { LEFT,
|
||||||
CENTRE,
|
CENTRE,
|
||||||
@@ -738,9 +793,9 @@ format_draw(struct screen_write_ctx *octx, const struct grid_cell *base,
|
|||||||
RIGHT,
|
RIGHT,
|
||||||
ABSOLUTE_CENTRE };
|
ABSOLUTE_CENTRE };
|
||||||
int focus_start = -1, focus_end = -1;
|
int focus_start = -1, focus_end = -1;
|
||||||
int list_state = -1, fill = -1, even;
|
int list_state = -1, fill, even;
|
||||||
enum style_align list_align = STYLE_ALIGN_DEFAULT;
|
enum style_align list_align = STYLE_ALIGN_DEFAULT;
|
||||||
struct grid_cell gc, current_default, base_default;
|
struct grid_cell gc, cur_def, base_def;
|
||||||
struct style sy, saved_sy;
|
struct style sy, saved_sy;
|
||||||
struct utf8_data *ud = &sy.gc.data;
|
struct utf8_data *ud = &sy.gc.data;
|
||||||
const char *cp, *end, *link_uri;
|
const char *cp, *end, *link_uri;
|
||||||
@@ -750,10 +805,10 @@ format_draw(struct screen_write_ctx *octx, const struct grid_cell *base,
|
|||||||
struct format_ranges frs;
|
struct format_ranges frs;
|
||||||
struct style_range *sr;
|
struct style_range *sr;
|
||||||
|
|
||||||
memcpy(&base_default, base, sizeof base_default);
|
memcpy(&base_def, &fs->base_def, sizeof base_def);
|
||||||
memcpy(¤t_default, base, sizeof current_default);
|
memcpy(&cur_def, &fs->cur_def, sizeof cur_def);
|
||||||
base = &base_default;
|
memcpy(&sy, &fs->sy, sizeof sy);
|
||||||
style_set(&sy, ¤t_default);
|
fill = fs->fill;
|
||||||
TAILQ_INIT(&frs);
|
TAILQ_INIT(&frs);
|
||||||
log_debug("%s: %s", __func__, expanded);
|
log_debug("%s: %s", __func__, expanded);
|
||||||
|
|
||||||
@@ -765,13 +820,43 @@ format_draw(struct screen_write_ctx *octx, const struct grid_cell *base,
|
|||||||
for (i = 0; i < TOTAL; i++) {
|
for (i = 0; i < TOTAL; i++) {
|
||||||
screen_init(&s[i], size, 1, 0);
|
screen_init(&s[i], size, 1, 0);
|
||||||
screen_write_start(&ctx[i], &s[i]);
|
screen_write_start(&ctx[i], &s[i]);
|
||||||
screen_write_clearendofline(&ctx[i], current_default.bg);
|
screen_write_clearendofline(&ctx[i], cur_def.bg);
|
||||||
width[i] = 0;
|
width[i] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Walk the string and add to the corresponding screens,
|
* Treat the starting style like a parsed style: apply the flags and
|
||||||
* parsing styles as we go.
|
* begin with its alignment, hyperlink and range. It is only different
|
||||||
|
* from the base for a line during a multiline format, which is drawn
|
||||||
|
* without its list.
|
||||||
|
*/
|
||||||
|
if (flags & FORMAT_DRAW_DEFAULT_COLOURS) {
|
||||||
|
sy.gc.bg = base_def.bg;
|
||||||
|
sy.gc.fg = base_def.fg;
|
||||||
|
}
|
||||||
|
if (flags & FORMAT_DRAW_NO_LIST)
|
||||||
|
sy.list = STYLE_LIST_OFF;
|
||||||
|
current = last = map[sy.align];
|
||||||
|
link_uri = style_link(&sy);
|
||||||
|
if (link_uri != NULL && hl != NULL)
|
||||||
|
sy.gc.link = hyperlinks_put(hl, link_uri, link_uri);
|
||||||
|
else
|
||||||
|
sy.gc.link = 0;
|
||||||
|
if (srs != NULL && sy.range_type != STYLE_RANGE_NONE) {
|
||||||
|
fr = xcalloc(1, sizeof *fr);
|
||||||
|
fr->index = current;
|
||||||
|
|
||||||
|
fr->s = &s[current];
|
||||||
|
fr->start = s[current].cx;
|
||||||
|
|
||||||
|
fr->type = sy.range_type;
|
||||||
|
fr->argument = sy.range_argument;
|
||||||
|
strlcpy(fr->string, sy.range_string, sizeof fr->string);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Walk the string and add to the corresponding screens, parsing styles
|
||||||
|
* as we go.
|
||||||
*/
|
*/
|
||||||
cp = expanded;
|
cp = expanded;
|
||||||
while (*cp != '\0') {
|
while (*cp != '\0') {
|
||||||
@@ -844,7 +929,7 @@ format_draw(struct screen_write_ctx *octx, const struct grid_cell *base,
|
|||||||
}
|
}
|
||||||
tmp = xstrndup(cp + 2, end - (cp + 2));
|
tmp = xstrndup(cp + 2, end - (cp + 2));
|
||||||
style_copy(&saved_sy, &sy);
|
style_copy(&saved_sy, &sy);
|
||||||
if (style_parse(&sy, ¤t_default, tmp) != 0) {
|
if (style_parse(&sy, &cur_def, tmp) != 0) {
|
||||||
log_debug("%s: invalid style '%s'", __func__, tmp);
|
log_debug("%s: invalid style '%s'", __func__, tmp);
|
||||||
free(tmp);
|
free(tmp);
|
||||||
cp = end + 1;
|
cp = end + 1;
|
||||||
@@ -853,10 +938,12 @@ format_draw(struct screen_write_ctx *octx, const struct grid_cell *base,
|
|||||||
log_debug("%s: style '%s' -> '%s'", __func__, tmp,
|
log_debug("%s: style '%s' -> '%s'", __func__, tmp,
|
||||||
style_tostring(&sy));
|
style_tostring(&sy));
|
||||||
free(tmp);
|
free(tmp);
|
||||||
if (default_colours) {
|
if (flags & FORMAT_DRAW_DEFAULT_COLOURS) {
|
||||||
sy.gc.bg = base->bg;
|
sy.gc.bg = base_def.bg;
|
||||||
sy.gc.fg = base->fg;
|
sy.gc.fg = base_def.fg;
|
||||||
}
|
}
|
||||||
|
if (flags & FORMAT_DRAW_NO_LIST)
|
||||||
|
sy.list = STYLE_LIST_OFF;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Resolve any hyperlink and store it in the cell. The URI
|
* Resolve any hyperlink and store it in the cell. The URI
|
||||||
@@ -874,20 +961,7 @@ format_draw(struct screen_write_ctx *octx, const struct grid_cell *base,
|
|||||||
fill = sy.fill;
|
fill = sy.fill;
|
||||||
|
|
||||||
/* If this style pushed or popped the default, update it. */
|
/* If this style pushed or popped the default, update it. */
|
||||||
if (sy.default_type == STYLE_DEFAULT_PUSH) {
|
format_update_defaults(&sy, &saved_sy.gc, &cur_def, &base_def);
|
||||||
memcpy(¤t_default, &saved_sy.gc,
|
|
||||||
sizeof current_default);
|
|
||||||
sy.default_type = STYLE_DEFAULT_BASE;
|
|
||||||
} else if (sy.default_type == STYLE_DEFAULT_POP) {
|
|
||||||
memcpy(¤t_default, base, sizeof current_default);
|
|
||||||
sy.default_type = STYLE_DEFAULT_BASE;
|
|
||||||
} else if (sy.default_type == STYLE_DEFAULT_SET) {
|
|
||||||
memcpy(&base_default, &saved_sy.gc,
|
|
||||||
sizeof base_default);
|
|
||||||
memcpy(¤t_default, &saved_sy.gc,
|
|
||||||
sizeof current_default);
|
|
||||||
sy.default_type = STYLE_DEFAULT_BASE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check the list state. */
|
/* Check the list state. */
|
||||||
switch (sy.list) {
|
switch (sy.list) {
|
||||||
@@ -1122,6 +1196,321 @@ out:
|
|||||||
screen_write_cursormove(octx, ocx, ocy, 0);
|
screen_write_cursormove(octx, ocx, ocy, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Draw a format to a screen. */
|
||||||
|
void
|
||||||
|
format_draw(struct screen_write_ctx *octx, const struct grid_cell *base,
|
||||||
|
u_int available, const char *expanded, struct style_ranges *srs,
|
||||||
|
int flags)
|
||||||
|
{
|
||||||
|
struct format_style fs;
|
||||||
|
|
||||||
|
format_init_style(&fs, base);
|
||||||
|
format_draw1(octx, &fs, available, expanded, srs, flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Add a line between start and end to the line array. */
|
||||||
|
static void
|
||||||
|
format_draw_lines_add(struct format_lines *fls, const char *start,
|
||||||
|
const char *end, const char *suffix)
|
||||||
|
{
|
||||||
|
struct format_line *fl;
|
||||||
|
|
||||||
|
fls->lines = xreallocarray(fls->lines, fls->nlines + 1,
|
||||||
|
sizeof *fls->lines);
|
||||||
|
fl = &fls->lines[fls->nlines++];
|
||||||
|
memcpy(fl, &fls->current, sizeof *fl);
|
||||||
|
xasprintf(&fl->chunk, "%.*s%s", (int)(end - start), start, suffix);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* End the current line and carry the current style state over to the start of
|
||||||
|
* the next line. A marker is a single line so marker state does not carry.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
format_draw_lines_break(struct format_lines *fls, struct format_style *fs,
|
||||||
|
enum style_list nomarker, const char *start, const char *end)
|
||||||
|
{
|
||||||
|
/* Close any open range at the break; the carried style reopens it. */
|
||||||
|
if (fs->sy.range_type != STYLE_RANGE_NONE)
|
||||||
|
format_draw_lines_add(fls, start, end, "#[norange]");
|
||||||
|
else
|
||||||
|
format_draw_lines_add(fls, start, end, "");
|
||||||
|
|
||||||
|
if (fs->sy.list == STYLE_LIST_LEFT_MARKER ||
|
||||||
|
fs->sy.list == STYLE_LIST_RIGHT_MARKER)
|
||||||
|
fs->sy.list = nomarker;
|
||||||
|
|
||||||
|
/* The next line starts with the style at the break. */
|
||||||
|
memset(&fls->current, 0, sizeof fls->current);
|
||||||
|
memcpy(&fls->current.fs, fs, sizeof fls->current.fs);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* A line is classified by the list state its text was drawn under. */
|
||||||
|
static void
|
||||||
|
format_draw_lines_text(struct format_lines *fls, const struct style *sy)
|
||||||
|
{
|
||||||
|
struct format_line *fl = &fls->current;
|
||||||
|
|
||||||
|
switch (sy->list) {
|
||||||
|
case STYLE_LIST_ON:
|
||||||
|
fl->in_list = 1;
|
||||||
|
break;
|
||||||
|
case STYLE_LIST_FOCUS:
|
||||||
|
fl->in_list = 1;
|
||||||
|
fl->has_focus = 1;
|
||||||
|
break;
|
||||||
|
case STYLE_LIST_LEFT_MARKER:
|
||||||
|
if (fl->marker == 0)
|
||||||
|
fl->marker = 1;
|
||||||
|
break;
|
||||||
|
case STYLE_LIST_RIGHT_MARKER:
|
||||||
|
if (fl->marker == 0)
|
||||||
|
fl->marker = 2;
|
||||||
|
break;
|
||||||
|
case STYLE_LIST_OFF:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Split an expanded format into lines at nl styles and literal newlines,
|
||||||
|
* walking the string and parsing styles the same way as format_draw.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
format_draw_lines_split(struct format_lines *fls, const char *expanded,
|
||||||
|
const struct grid_cell *base)
|
||||||
|
{
|
||||||
|
struct format_style fs;
|
||||||
|
struct style saved_sy;
|
||||||
|
enum style_list nomarker = STYLE_LIST_OFF;
|
||||||
|
const char *cp, *start, *end;
|
||||||
|
char *tmp;
|
||||||
|
u_int n;
|
||||||
|
|
||||||
|
format_init_style(&fs, base);
|
||||||
|
memcpy(&fls->current.fs, &fs, sizeof fls->current.fs);
|
||||||
|
|
||||||
|
cp = start = expanded;
|
||||||
|
while (*cp != '\0') {
|
||||||
|
/* Handle sequences of # in the same way as format_draw. */
|
||||||
|
if (cp[0] == '#' && cp[1] != '[' && cp[1] != '\0') {
|
||||||
|
format_draw_lines_text(fls, &fs.sy);
|
||||||
|
for (n = 1; cp[n] == '#'; n++)
|
||||||
|
/* nothing */;
|
||||||
|
if (cp[n] != '[') {
|
||||||
|
cp += n;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if ((n % 2) == 0)
|
||||||
|
cp += (n + 1);
|
||||||
|
else
|
||||||
|
cp += (n - 1);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Is this not a style? */
|
||||||
|
if (cp[0] != '#' || cp[1] != '[' || fs.sy.ignore) {
|
||||||
|
if (*cp == '\n') {
|
||||||
|
format_draw_lines_break(fls, &fs, nomarker,
|
||||||
|
start, cp);
|
||||||
|
cp++;
|
||||||
|
start = cp;
|
||||||
|
} else {
|
||||||
|
format_draw_lines_text(fls, &fs.sy);
|
||||||
|
cp++;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* This is a style. Work out where the end is and parse it. */
|
||||||
|
end = format_skip(cp + 2, "]");
|
||||||
|
if (end == NULL)
|
||||||
|
break;
|
||||||
|
tmp = xstrndup(cp + 2, end - (cp + 2));
|
||||||
|
style_copy(&saved_sy, &fs.sy);
|
||||||
|
if (style_parse(&fs.sy, &fs.cur_def, tmp) != 0) {
|
||||||
|
free(tmp);
|
||||||
|
cp = end + 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
free(tmp);
|
||||||
|
|
||||||
|
/* If this style has a fill colour, store it for later. */
|
||||||
|
if (fs.sy.fill != 8)
|
||||||
|
fs.fill = fs.sy.fill;
|
||||||
|
|
||||||
|
/* If this style pushed or popped the default, update it. */
|
||||||
|
format_update_defaults(&fs.sy, &saved_sy.gc, &fs.cur_def,
|
||||||
|
&fs.base_def);
|
||||||
|
|
||||||
|
/* Track the last list state that was not a marker. */
|
||||||
|
if (fs.sy.list != STYLE_LIST_LEFT_MARKER &&
|
||||||
|
fs.sy.list != STYLE_LIST_RIGHT_MARKER)
|
||||||
|
nomarker = fs.sy.list;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* End the line after the style if it has a line break, so the
|
||||||
|
* rest of the style (such as norange) applies to the line.
|
||||||
|
*/
|
||||||
|
if (fs.sy.nl) {
|
||||||
|
fs.sy.nl = 0;
|
||||||
|
format_draw_lines_break(fls, &fs, nomarker, start,
|
||||||
|
end + 1);
|
||||||
|
cp = end + 1;
|
||||||
|
start = cp;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
cp = end + 1;
|
||||||
|
}
|
||||||
|
if (cp != start || fls->nlines == 0)
|
||||||
|
format_draw_lines_add(fls, start, cp, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Draw one line and give any ranges it produces the line's y position. */
|
||||||
|
static void
|
||||||
|
format_draw_line(struct screen_write_ctx *octx,
|
||||||
|
const struct format_line *fl, u_int ox, u_int width, u_int py,
|
||||||
|
struct style_ranges *srs, int flags)
|
||||||
|
{
|
||||||
|
struct style_ranges line_srs;
|
||||||
|
struct style_range *sr, *sr1;
|
||||||
|
|
||||||
|
/* The list styles have already been used to choose the lines. */
|
||||||
|
flags |= FORMAT_DRAW_NO_LIST;
|
||||||
|
|
||||||
|
screen_write_cursormove(octx, ox, py, 0);
|
||||||
|
if (srs == NULL) {
|
||||||
|
format_draw1(octx, &fl->fs, width, fl->chunk, NULL, flags);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
style_ranges_init(&line_srs);
|
||||||
|
format_draw1(octx, &fl->fs, width, fl->chunk, &line_srs, flags);
|
||||||
|
TAILQ_FOREACH_SAFE(sr, &line_srs, entry, sr1) {
|
||||||
|
TAILQ_REMOVE(&line_srs, sr, entry);
|
||||||
|
sr->y = py;
|
||||||
|
TAILQ_INSERT_TAIL(srs, sr, entry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Draw a format across multiple lines. */
|
||||||
|
u_int
|
||||||
|
format_draw_lines(struct screen_write_ctx *octx, const struct grid_cell *base,
|
||||||
|
u_int ox, u_int width, u_int height, const char *expanded,
|
||||||
|
struct style_ranges *srs, int flags)
|
||||||
|
{
|
||||||
|
struct format_lines fls;
|
||||||
|
struct format_line *fl;
|
||||||
|
u_int *top, *list, *bottom;
|
||||||
|
u_int n_top = 0, n_list = 0, n_bottom = 0;
|
||||||
|
u_int vis_top, vis_list, vis_bottom, lstart, f;
|
||||||
|
u_int i, y, ocy = octx->s->cy;
|
||||||
|
int first_list = -1, last_list = -1;
|
||||||
|
int up = -1, down = -1;
|
||||||
|
|
||||||
|
if (height == 0)
|
||||||
|
return (0);
|
||||||
|
|
||||||
|
memset(&fls, 0, sizeof fls);
|
||||||
|
format_draw_lines_split(&fls, expanded, base);
|
||||||
|
|
||||||
|
/* Find the list section and the marker lines. */
|
||||||
|
for (i = 0; i < fls.nlines; i++) {
|
||||||
|
if (fls.lines[i].marker == 1) {
|
||||||
|
if (up == -1)
|
||||||
|
up = i;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (fls.lines[i].marker == 2) {
|
||||||
|
if (down == -1)
|
||||||
|
down = i;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (fls.lines[i].in_list) {
|
||||||
|
if (first_list == -1)
|
||||||
|
first_list = i;
|
||||||
|
last_list = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Partition the lines into above, inside and below the list. */
|
||||||
|
top = xreallocarray(NULL, fls.nlines, sizeof *top);
|
||||||
|
list = xreallocarray(NULL, fls.nlines, sizeof *list);
|
||||||
|
bottom = xreallocarray(NULL, fls.nlines, sizeof *bottom);
|
||||||
|
for (i = 0; i < fls.nlines; i++) {
|
||||||
|
if (fls.lines[i].marker != 0)
|
||||||
|
continue;
|
||||||
|
if (first_list == -1 || (int)i < first_list)
|
||||||
|
top[n_top++] = i;
|
||||||
|
else if ((int)i <= last_list)
|
||||||
|
list[n_list++] = i;
|
||||||
|
else
|
||||||
|
bottom[n_bottom++] = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Trim the list first, then the bottom, then the top. */
|
||||||
|
vis_top = n_top;
|
||||||
|
vis_list = n_list;
|
||||||
|
vis_bottom = n_bottom;
|
||||||
|
while (vis_top + vis_list + vis_bottom > height) {
|
||||||
|
if (vis_list > 0)
|
||||||
|
vis_list--;
|
||||||
|
else if (vis_bottom > 0)
|
||||||
|
vis_bottom--;
|
||||||
|
else
|
||||||
|
vis_top--;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Scroll the list to keep the focus line visible. */
|
||||||
|
f = 0;
|
||||||
|
for (i = 0; i < n_list; i++) {
|
||||||
|
if (fls.lines[list[i]].has_focus) {
|
||||||
|
f = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (vis_list == 0 || f < vis_list / 2)
|
||||||
|
lstart = 0;
|
||||||
|
else
|
||||||
|
lstart = f - vis_list / 2;
|
||||||
|
if (lstart + vis_list > n_list)
|
||||||
|
lstart = n_list - vis_list;
|
||||||
|
|
||||||
|
/* Draw the lines. */
|
||||||
|
y = 0;
|
||||||
|
for (i = 0; i < vis_top; i++) {
|
||||||
|
fl = &fls.lines[top[i]];
|
||||||
|
format_draw_line(octx, fl, ox, width, ocy + y, srs, flags);
|
||||||
|
y++;
|
||||||
|
}
|
||||||
|
/* Markers replace the first and last list lines but never the focus. */
|
||||||
|
for (i = 0; i < vis_list; i++) {
|
||||||
|
fl = &fls.lines[list[lstart + i]];
|
||||||
|
if (lstart + i != f) {
|
||||||
|
if (i == 0 && lstart > 0 && up != -1)
|
||||||
|
fl = &fls.lines[up];
|
||||||
|
else if (i == vis_list - 1 &&
|
||||||
|
lstart + vis_list < n_list && down != -1)
|
||||||
|
fl = &fls.lines[down];
|
||||||
|
}
|
||||||
|
format_draw_line(octx, fl, ox, width, ocy + y, srs, flags);
|
||||||
|
y++;
|
||||||
|
}
|
||||||
|
for (i = 0; i < vis_bottom; i++) {
|
||||||
|
fl = &fls.lines[bottom[i]];
|
||||||
|
format_draw_line(octx, fl, ox, width, ocy + y, srs, flags);
|
||||||
|
y++;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < fls.nlines; i++)
|
||||||
|
free(fls.lines[i].chunk);
|
||||||
|
free(fls.lines);
|
||||||
|
free(top);
|
||||||
|
free(list);
|
||||||
|
free(bottom);
|
||||||
|
return (y);
|
||||||
|
}
|
||||||
|
|
||||||
/* Get width, taking #[] into account. */
|
/* Get width, taking #[] into account. */
|
||||||
u_int
|
u_int
|
||||||
format_width(const char *expanded)
|
format_width(const char *expanded)
|
||||||
@@ -1158,8 +1547,8 @@ format_width(const char *expanded)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Trim on the left, taking #[] into account. Note, we copy the whole set of
|
* Trim on the left, taking #[] into account. Copies the whole set of unescaped
|
||||||
* unescaped #s, but only add their escaped size to width. This is because the
|
* #s, but only adds their escaped size to width. This is because the
|
||||||
* format_draw function will actually do the escaping.
|
* format_draw function will actually do the escaping.
|
||||||
*/
|
*/
|
||||||
char *
|
char *
|
||||||
|
|||||||
109
format.c
109
format.c
@@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: format.c,v 1.429 2026/10/15 07:25:07 nicm Exp $ */
|
/* $OpenBSD: format.c,v 1.430 2026/10/16 07:59:06 nicm Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2011 Nicholas Marriott <nicholas.marriott@gmail.com>
|
* Copyright (c) 2011 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||||
@@ -1366,27 +1366,44 @@ format_cb_mouse_line(struct format_tree *ft)
|
|||||||
return (format_grid_line(gd, gd->hsize + y));
|
return (format_grid_line(gd, gd->hsize + y));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Get mouse status position: 0 horizontal, 1 side, -1 unavailable. */
|
||||||
|
static int
|
||||||
|
format_mouse_status_at(struct format_tree *ft, u_int *x, u_int *y)
|
||||||
|
{
|
||||||
|
struct mouse_event *m = &ft->m;
|
||||||
|
|
||||||
|
if (!m->valid)
|
||||||
|
return (-1);
|
||||||
|
if (ft->c == NULL || (~ft->c->tty.flags & TTY_STARTED))
|
||||||
|
return (-1);
|
||||||
|
|
||||||
|
*x = m->x;
|
||||||
|
*y = m->y;
|
||||||
|
if (m->statusat == 0 && m->y < m->statuslines)
|
||||||
|
return (0);
|
||||||
|
if (m->statusat > 0 && m->y >= (u_int)m->statusat) {
|
||||||
|
*y -= m->statusat;
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
if (m->sideat == -1 ||
|
||||||
|
m->x < (u_int)m->sideat ||
|
||||||
|
m->x >= m->sideat + m->sidewidth)
|
||||||
|
return (-1);
|
||||||
|
*x -= m->sideat;
|
||||||
|
if (m->statusat == 0)
|
||||||
|
*y -= m->statuslines;
|
||||||
|
return (1);
|
||||||
|
}
|
||||||
|
|
||||||
/* Callback for mouse_status_line. */
|
/* Callback for mouse_status_line. */
|
||||||
static void *
|
static void *
|
||||||
format_cb_mouse_status_line(struct format_tree *ft)
|
format_cb_mouse_status_line(struct format_tree *ft)
|
||||||
{
|
{
|
||||||
char *value;
|
u_int x, y;
|
||||||
u_int y;
|
|
||||||
|
|
||||||
if (!ft->m.valid)
|
if (format_mouse_status_at(ft, &x, &y) == -1)
|
||||||
return (NULL);
|
return (NULL);
|
||||||
if (ft->c == NULL || (~ft->c->tty.flags & TTY_STARTED))
|
return (format_printf("%u", y));
|
||||||
return (NULL);
|
|
||||||
|
|
||||||
if (ft->m.statusat == 0 && ft->m.y < ft->m.statuslines) {
|
|
||||||
y = ft->m.y;
|
|
||||||
} else if (ft->m.statusat > 0 && ft->m.y >= (u_int)ft->m.statusat) {
|
|
||||||
y = ft->m.y - ft->m.statusat;
|
|
||||||
} else
|
|
||||||
return (NULL);
|
|
||||||
xasprintf(&value, "%u", y);
|
|
||||||
return (value);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Callback for mouse_status_range. */
|
/* Callback for mouse_status_range. */
|
||||||
@@ -1395,22 +1412,16 @@ format_cb_mouse_status_range(struct format_tree *ft)
|
|||||||
{
|
{
|
||||||
struct style_range *sr;
|
struct style_range *sr;
|
||||||
u_int x, y;
|
u_int x, y;
|
||||||
|
int side;
|
||||||
|
|
||||||
if (!ft->m.valid)
|
side = format_mouse_status_at(ft, &x, &y);
|
||||||
return (NULL);
|
if (side == -1)
|
||||||
if (ft->c == NULL || (~ft->c->tty.flags & TTY_STARTED))
|
|
||||||
return (NULL);
|
return (NULL);
|
||||||
|
if (side)
|
||||||
|
sr = status_side_get_range(ft->c, x, y);
|
||||||
|
else
|
||||||
|
sr = status_get_range(ft->c, x, y);
|
||||||
|
|
||||||
if (ft->m.statusat == 0 && ft->m.y < ft->m.statuslines) {
|
|
||||||
x = ft->m.x;
|
|
||||||
y = ft->m.y;
|
|
||||||
} else if (ft->m.statusat > 0 && ft->m.y >= (u_int)ft->m.statusat) {
|
|
||||||
x = ft->m.x;
|
|
||||||
y = ft->m.y - ft->m.statusat;
|
|
||||||
} else
|
|
||||||
return (NULL);
|
|
||||||
|
|
||||||
sr = status_get_range(ft->c, x, y);
|
|
||||||
if (sr == NULL)
|
if (sr == NULL)
|
||||||
return (NULL);
|
return (NULL);
|
||||||
switch (sr->type) {
|
switch (sr->type) {
|
||||||
@@ -2064,6 +2075,24 @@ format_cb_mouse_utf8_flag(struct format_tree *ft)
|
|||||||
return (NULL);
|
return (NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Callback for mouse_absolute_x. */
|
||||||
|
static void *
|
||||||
|
format_cb_mouse_absolute_x(struct format_tree *ft)
|
||||||
|
{
|
||||||
|
if (!ft->m.valid)
|
||||||
|
return (NULL);
|
||||||
|
return (format_printf("%u", ft->m.x));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Callback for mouse_absolute_y. */
|
||||||
|
static void *
|
||||||
|
format_cb_mouse_absolute_y(struct format_tree *ft)
|
||||||
|
{
|
||||||
|
if (!ft->m.valid)
|
||||||
|
return (NULL);
|
||||||
|
return (format_printf("%u", ft->m.y));
|
||||||
|
}
|
||||||
|
|
||||||
/* Callback for mouse_x. */
|
/* Callback for mouse_x. */
|
||||||
static void *
|
static void *
|
||||||
format_cb_mouse_x(struct format_tree *ft)
|
format_cb_mouse_x(struct format_tree *ft)
|
||||||
@@ -2073,15 +2102,11 @@ format_cb_mouse_x(struct format_tree *ft)
|
|||||||
|
|
||||||
if (!ft->m.valid)
|
if (!ft->m.valid)
|
||||||
return (NULL);
|
return (NULL);
|
||||||
|
if (format_mouse_status_at(ft, &x, &y) != -1)
|
||||||
|
return (format_printf("%u", x));
|
||||||
wp = cmd_mouse_pane(&ft->m, NULL, NULL);
|
wp = cmd_mouse_pane(&ft->m, NULL, NULL);
|
||||||
if (wp != NULL && cmd_mouse_at(wp, &ft->m, &x, &y, 0) == 0)
|
if (wp != NULL && cmd_mouse_at(wp, &ft->m, &x, &y, 0) == 0)
|
||||||
return (format_printf("%u", x));
|
return (format_printf("%u", x));
|
||||||
if (ft->c != NULL && (ft->c->tty.flags & TTY_STARTED)) {
|
|
||||||
if (ft->m.statusat == 0 && ft->m.y < ft->m.statuslines)
|
|
||||||
return (format_printf("%u", ft->m.x));
|
|
||||||
if (ft->m.statusat > 0 && ft->m.y >= (u_int)ft->m.statusat)
|
|
||||||
return (format_printf("%u", ft->m.x));
|
|
||||||
}
|
|
||||||
return (NULL);
|
return (NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2094,15 +2119,11 @@ format_cb_mouse_y(struct format_tree *ft)
|
|||||||
|
|
||||||
if (!ft->m.valid)
|
if (!ft->m.valid)
|
||||||
return (NULL);
|
return (NULL);
|
||||||
|
if (format_mouse_status_at(ft, &x, &y) != -1)
|
||||||
|
return (format_printf("%u", y));
|
||||||
wp = cmd_mouse_pane(&ft->m, NULL, NULL);
|
wp = cmd_mouse_pane(&ft->m, NULL, NULL);
|
||||||
if (wp != NULL && cmd_mouse_at(wp, &ft->m, &x, &y, 0) == 0)
|
if (wp != NULL && cmd_mouse_at(wp, &ft->m, &x, &y, 0) == 0)
|
||||||
return (format_printf("%u", y));
|
return (format_printf("%u", y));
|
||||||
if (ft->c != NULL && (ft->c->tty.flags & TTY_STARTED)) {
|
|
||||||
if (ft->m.statusat == 0 && ft->m.y < ft->m.statuslines)
|
|
||||||
return (format_printf("%u", ft->m.y));
|
|
||||||
if (ft->m.statusat > 0 && ft->m.y >= (u_int)ft->m.statusat)
|
|
||||||
return (format_printf("%u", ft->m.y - ft->m.statusat));
|
|
||||||
}
|
|
||||||
return (NULL);
|
return (NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3761,6 +3782,12 @@ static const struct format_table_entry format_table[] = {
|
|||||||
{ "last_window_index", FORMAT_TABLE_STRING,
|
{ "last_window_index", FORMAT_TABLE_STRING,
|
||||||
format_cb_last_window_index
|
format_cb_last_window_index
|
||||||
},
|
},
|
||||||
|
{ "mouse_absolute_x", FORMAT_TABLE_STRING,
|
||||||
|
format_cb_mouse_absolute_x
|
||||||
|
},
|
||||||
|
{ "mouse_absolute_y", FORMAT_TABLE_STRING,
|
||||||
|
format_cb_mouse_absolute_y
|
||||||
|
},
|
||||||
{ "mouse_all_flag", FORMAT_TABLE_STRING,
|
{ "mouse_all_flag", FORMAT_TABLE_STRING,
|
||||||
format_cb_mouse_all_flag
|
format_cb_mouse_all_flag
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: key-bindings.c,v 1.194 2026/10/08 07:50:05 nicm Exp $ */
|
/* $OpenBSD: key-bindings.c,v 1.195 2026/10/16 07:59:06 nicm Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
|
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||||
@@ -534,6 +534,10 @@ key_bindings_init(void)
|
|||||||
"bind -n MouseDown1Status { switch-client -t= }",
|
"bind -n MouseDown1Status { switch-client -t= }",
|
||||||
"bind -n C-MouseDown1Status { swap-window -t@ }",
|
"bind -n C-MouseDown1Status { swap-window -t@ }",
|
||||||
|
|
||||||
|
/* Mouse button 1 drag on side status border. */
|
||||||
|
"bind -n MouseDrag1StatusBorder { if -F '#{e|>=:#{client_width},3}' { run -C \"set -t '#{session_id}' side-status-width #{?#{==:#{side-status},left},#{e|+:#{?#{e|<:#{mouse_absolute_x},1},1,#{?#{e|>:#{mouse_absolute_x},#{e|-:#{client_width},2}},#{e|-:#{client_width},2},#{mouse_absolute_x}}},1},#{e|-:#{client_width},#{?#{e|<:#{mouse_absolute_x},1},1,#{?#{e|>:#{mouse_absolute_x},#{e|-:#{client_width},2}},#{e|-:#{client_width},2},#{mouse_absolute_x}}}}}\" } }",
|
||||||
|
"bind -n DoubleClick1StatusBorder { set -u side-status-width }",
|
||||||
|
|
||||||
/* Mouse button 1 down on default pane-border-format */
|
/* Mouse button 1 down on default pane-border-format */
|
||||||
"bind -n MouseDown1Control9 { display-menu -t= -xM -yM -O -T 'Kill pane #{pane_index}?' 'Yes' 'y' { kill-pane -t= } 'No' 'n' {}}",
|
"bind -n MouseDown1Control9 { display-menu -t= -xM -yM -O -T 'Kill pane #{pane_index}?' 'Yes' 'y' { kill-pane -t= } 'No' 'n' {}}",
|
||||||
"bind -n MouseDown1Control8 { resize-pane -Z }",
|
"bind -n MouseDown1Control8 { resize-pane -Z }",
|
||||||
|
|||||||
11
mode-tree.c
11
mode-tree.c
@@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: mode-tree.c,v 1.104 2026/10/12 18:23:25 nicm Exp $ */
|
/* $OpenBSD: mode-tree.c,v 1.105 2026/10/16 07:59:06 nicm Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2017 Nicholas Marriott <nicholas.marriott@gmail.com>
|
* Copyright (c) 2017 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||||
@@ -957,16 +957,19 @@ mode_tree_draw(struct mode_tree_data *mtd)
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
screen_write_clearendofline(&ctx, gc.bg);
|
screen_write_clearendofline(&ctx, gc.bg);
|
||||||
format_draw(&ctx, &gc, prefix_width, prefix, NULL, 1);
|
format_draw(&ctx, &gc, prefix_width, prefix, NULL,
|
||||||
|
FORMAT_DRAW_DEFAULT_COLOURS);
|
||||||
if (left != 0) {
|
if (left != 0) {
|
||||||
screen_write_cursormove(&ctx, prefix_width,
|
screen_write_cursormove(&ctx, prefix_width,
|
||||||
i - mtd->offset, 0);
|
i - mtd->offset, 0);
|
||||||
format_draw(&ctx, &gc, left, text, NULL, 1);
|
format_draw(&ctx, &gc, left, text, NULL,
|
||||||
|
FORMAT_DRAW_DEFAULT_COLOURS);
|
||||||
if (mti->text != NULL && width < w) {
|
if (mti->text != NULL && width < w) {
|
||||||
screen_write_cursormove(&ctx, width,
|
screen_write_cursormove(&ctx, width,
|
||||||
i - mtd->offset, 0);
|
i - mtd->offset, 0);
|
||||||
format_draw(&ctx, &gc, w - width,
|
format_draw(&ctx, &gc, w - width,
|
||||||
mti->text, NULL, 1);
|
mti->text, NULL,
|
||||||
|
FORMAT_DRAW_DEFAULT_COLOURS);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: options-table.c,v 1.253 2026/10/15 13:08:43 nicm Exp $ */
|
/* $OpenBSD: options-table.c,v 1.254 2026/10/16 07:59:06 nicm Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2011 Nicholas Marriott <nicholas.marriott@gmail.com>
|
* Copyright (c) 2011 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||||
@@ -54,6 +54,9 @@ static const char *options_table_status_justify_list[] = {
|
|||||||
static const char *options_table_status_position_list[] = {
|
static const char *options_table_status_position_list[] = {
|
||||||
"top", "bottom", NULL
|
"top", "bottom", NULL
|
||||||
};
|
};
|
||||||
|
static const char *options_table_side_status_list[] = {
|
||||||
|
"off", "left", "right", NULL
|
||||||
|
};
|
||||||
static const char *options_table_bell_action_list[] = {
|
static const char *options_table_bell_action_list[] = {
|
||||||
"none", "any", "current", "other", NULL
|
"none", "any", "current", "other", NULL
|
||||||
};
|
};
|
||||||
@@ -244,6 +247,50 @@ static const char *options_table_status_format_default[] = {
|
|||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* Side status line format. */
|
||||||
|
#define OPTIONS_TABLE_SIDE_STATUS_WINDOW \
|
||||||
|
"#[range=window|#{window_index} #{E:window-status-style}]" \
|
||||||
|
"#I:#W#{?window_flags,#{window_flags}, }" \
|
||||||
|
"#[norange default]#[nl]"
|
||||||
|
#define OPTIONS_TABLE_SIDE_STATUS_CURRENT \
|
||||||
|
"#[range=window|#{window_index} list=focus " \
|
||||||
|
"#{?#{!=:#{E:window-status-current-style},default}," \
|
||||||
|
"#{E:window-status-current-style}," \
|
||||||
|
"#{E:window-status-style}" \
|
||||||
|
"}" \
|
||||||
|
"]" \
|
||||||
|
"#I:#W#{?window_flags,#{window_flags}, }" \
|
||||||
|
"#[norange list=on default]#[nl]"
|
||||||
|
#define OPTIONS_TABLE_SIDE_STATUS_BRANCH \
|
||||||
|
"#[acs fg=themelightgrey]#{?window_end_flag,mq,tq}+" \
|
||||||
|
"#[noacs default] "
|
||||||
|
#define OPTIONS_TABLE_SIDE_STATUS_FORMAT1 \
|
||||||
|
"#[list=on]" \
|
||||||
|
"#[list=left-marker]#[acs]-#[noacs]#[nl]" \
|
||||||
|
"#[list=right-marker]#[acs].#[noacs]#[nl]" \
|
||||||
|
"#{?#{e|>:#{server_sessions},1}," \
|
||||||
|
"#{S:" \
|
||||||
|
"#[range=session|#{session_id}]" \
|
||||||
|
"#{session_name}" \
|
||||||
|
"#[norange]#[nl]" \
|
||||||
|
"#{?#{==:#{session_name},#{client_session}}," \
|
||||||
|
"#{W:" \
|
||||||
|
OPTIONS_TABLE_SIDE_STATUS_BRANCH \
|
||||||
|
OPTIONS_TABLE_SIDE_STATUS_WINDOW \
|
||||||
|
"," \
|
||||||
|
OPTIONS_TABLE_SIDE_STATUS_BRANCH \
|
||||||
|
OPTIONS_TABLE_SIDE_STATUS_CURRENT \
|
||||||
|
"}" \
|
||||||
|
",}" \
|
||||||
|
"}" \
|
||||||
|
"," \
|
||||||
|
"#{W:" \
|
||||||
|
OPTIONS_TABLE_SIDE_STATUS_WINDOW \
|
||||||
|
"," \
|
||||||
|
OPTIONS_TABLE_SIDE_STATUS_CURRENT \
|
||||||
|
"}" \
|
||||||
|
"}"
|
||||||
|
|
||||||
/* Helpers for hook options. */
|
/* Helpers for hook options. */
|
||||||
#define OPTIONS_TABLE_HOOK(hook_name, default_value, hook_text) \
|
#define OPTIONS_TABLE_HOOK(hook_name, default_value, hook_text) \
|
||||||
{ .name = hook_name, \
|
{ .name = hook_name, \
|
||||||
@@ -998,6 +1045,40 @@ const struct options_table_entry options_table[] = {
|
|||||||
.text = "Format of the terminal title to set."
|
.text = "Format of the terminal title to set."
|
||||||
},
|
},
|
||||||
|
|
||||||
|
{ .name = "side-status",
|
||||||
|
.type = OPTIONS_TABLE_CHOICE,
|
||||||
|
.scope = OPTIONS_TABLE_SESSION,
|
||||||
|
.choices = options_table_side_status_list,
|
||||||
|
.default_num = 0,
|
||||||
|
.text = "Whether to draw a vertical status line at the left or "
|
||||||
|
"right of the terminal."
|
||||||
|
},
|
||||||
|
|
||||||
|
{ .name = "side-status-format",
|
||||||
|
.type = OPTIONS_TABLE_STRING,
|
||||||
|
.scope = OPTIONS_TABLE_SESSION,
|
||||||
|
.default_str = OPTIONS_TABLE_SIDE_STATUS_FORMAT1,
|
||||||
|
.text = "Format for the side status line."
|
||||||
|
},
|
||||||
|
|
||||||
|
{ .name = "side-status-style",
|
||||||
|
.type = OPTIONS_TABLE_STRING,
|
||||||
|
.scope = OPTIONS_TABLE_SESSION,
|
||||||
|
.default_str = "fg=themegreen",
|
||||||
|
.flags = OPTIONS_TABLE_IS_STYLE,
|
||||||
|
.separator = ",",
|
||||||
|
.text = "Style of the side status line."
|
||||||
|
},
|
||||||
|
|
||||||
|
{ .name = "side-status-width",
|
||||||
|
.type = OPTIONS_TABLE_NUMBER,
|
||||||
|
.scope = OPTIONS_TABLE_SESSION,
|
||||||
|
.minimum = 1,
|
||||||
|
.maximum = SHRT_MAX,
|
||||||
|
.default_num = 14,
|
||||||
|
.text = "Width of the side status line."
|
||||||
|
},
|
||||||
|
|
||||||
{ .name = "silence-action",
|
{ .name = "silence-action",
|
||||||
.type = OPTIONS_TABLE_CHOICE,
|
.type = OPTIONS_TABLE_CHOICE,
|
||||||
.scope = OPTIONS_TABLE_SESSION,
|
.scope = OPTIONS_TABLE_SESSION,
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: options.c,v 1.92 2026/07/27 19:15:58 nicm Exp $ */
|
/* $OpenBSD: options.c,v 1.93 2026/10/16 07:59:06 nicm Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2008 Nicholas Marriott <nicholas.marriott@gmail.com>
|
* Copyright (c) 2008 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||||
@@ -1407,10 +1407,13 @@ options_push_changes(const char *name)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (strcmp(name, "status") == 0 ||
|
if (strcmp(name, "status") == 0 ||
|
||||||
strcmp(name, "status-interval") == 0)
|
strcmp(name, "status-interval") == 0 ||
|
||||||
|
strcmp(name, "side-status") == 0)
|
||||||
status_timer_start_all();
|
status_timer_start_all();
|
||||||
if (strcmp(name, "status") == 0 ||
|
if (strcmp(name, "status") == 0 ||
|
||||||
strcmp(name, "status-position") == 0 ||
|
strcmp(name, "status-position") == 0 ||
|
||||||
|
strcmp(name, "side-status") == 0 ||
|
||||||
|
strcmp(name, "side-status-width") == 0 ||
|
||||||
strcmp(name, "pane-border-indicators") == 0 ||
|
strcmp(name, "pane-border-indicators") == 0 ||
|
||||||
strcmp(name, "pane-border-lines") == 0 ||
|
strcmp(name, "pane-border-lines") == 0 ||
|
||||||
strcmp(name, "pane-border-status") == 0 ||
|
strcmp(name, "pane-border-status") == 0 ||
|
||||||
|
|||||||
10
resize.c
10
resize.c
@@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: resize.c,v 1.61 2026/10/15 22:28:41 nicm Exp $ */
|
/* $OpenBSD: resize.c,v 1.62 2026/10/16 07:59:06 nicm Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
|
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||||
@@ -196,7 +196,7 @@ clients_calculate_size(int type, int current, struct client *c,
|
|||||||
if (w == NULL ||
|
if (w == NULL ||
|
||||||
!control_get_window_size(loop, w->id, &cx, &cy) ||
|
!control_get_window_size(loop, w->id, &cx, &cy) ||
|
||||||
cx == 0 || cy == 0) {
|
cx == 0 || cy == 0) {
|
||||||
cx = loop->tty.sx;
|
cx = loop->tty.sx - status_side_size(loop);
|
||||||
cy = loop->tty.sy - status_line_size(loop);
|
cy = loop->tty.sy - status_line_size(loop);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -301,7 +301,7 @@ default_window_size(struct client *c, struct session *s, struct window *w,
|
|||||||
* client and no window, use the default size as for manual type.
|
* client and no window, use the default size as for manual type.
|
||||||
*/
|
*/
|
||||||
if (type == WINDOW_SIZE_LATEST && c != NULL && !ignore_client_size(c)) {
|
if (type == WINDOW_SIZE_LATEST && c != NULL && !ignore_client_size(c)) {
|
||||||
*sx = c->tty.sx;
|
*sx = c->tty.sx - status_side_size(c);
|
||||||
*sy = c->tty.sy - status_line_size(c);
|
*sy = c->tty.sy - status_line_size(c);
|
||||||
*xpixel = c->tty.xpixel;
|
*xpixel = c->tty.xpixel;
|
||||||
*ypixel = c->tty.ypixel;
|
*ypixel = c->tty.ypixel;
|
||||||
@@ -478,6 +478,10 @@ recalculate_sizes_now(int now)
|
|||||||
c->flags |= CLIENT_STATUSOFF;
|
c->flags |= CLIENT_STATUSOFF;
|
||||||
else
|
else
|
||||||
c->flags &= ~CLIENT_STATUSOFF;
|
c->flags &= ~CLIENT_STATUSOFF;
|
||||||
|
if (s->sidestatusat != -1 && c->tty.sx <= s->sidestatuswidth)
|
||||||
|
c->flags |= CLIENT_SIDESTATUSOFF;
|
||||||
|
else
|
||||||
|
c->flags &= ~CLIENT_SIDESTATUSOFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Walk each window and adjust the size. */
|
/* Walk each window and adjust the size. */
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: screen-redraw.c,v 1.168 2026/10/14 13:03:47 nicm Exp $ */
|
/* $OpenBSD: screen-redraw.c,v 1.169 2026/10/16 07:59:06 nicm Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2026 Nicholas Marriott <nicholas.marriott@gmail.com>
|
* Copyright (c) 2026 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||||
@@ -100,6 +100,7 @@ enum redraw_phase {
|
|||||||
#define REDRAW_PANE_SCROLLBAR 0x20
|
#define REDRAW_PANE_SCROLLBAR 0x20
|
||||||
#define REDRAW_STATUS 0x40
|
#define REDRAW_STATUS 0x40
|
||||||
#define REDRAW_MENU 0x80
|
#define REDRAW_MENU 0x80
|
||||||
|
#define REDRAW_SIDE_STATUS 0x100
|
||||||
|
|
||||||
/* Draw everything. */
|
/* Draw everything. */
|
||||||
#define REDRAW_ALL 0x7fffffff
|
#define REDRAW_ALL 0x7fffffff
|
||||||
@@ -267,6 +268,7 @@ struct redraw_draw_ctx {
|
|||||||
struct window_pane *marked;
|
struct window_pane *marked;
|
||||||
|
|
||||||
u_int status_lines;
|
u_int status_lines;
|
||||||
|
u_int side_left;
|
||||||
enum pane_lines pane_lines;
|
enum pane_lines pane_lines;
|
||||||
struct grid_cell default_gc;
|
struct grid_cell default_gc;
|
||||||
|
|
||||||
@@ -311,7 +313,7 @@ redraw_get_window_offset(struct client *c, u_int *ox, u_int *oy, u_int *sx,
|
|||||||
|
|
||||||
tty_window_offset(&c->tty, ox, oy, sx, sy);
|
tty_window_offset(&c->tty, ox, oy, sx, sy);
|
||||||
|
|
||||||
tty_sx = c->tty.sx;
|
tty_sx = c->tty.sx - status_side_size(c);
|
||||||
tty_sy = c->tty.sy - status_line_size(c);
|
tty_sy = c->tty.sy - status_line_size(c);
|
||||||
if (*sx < tty_sx)
|
if (*sx < tty_sx)
|
||||||
*sx = tty_sx;
|
*sx = tty_sx;
|
||||||
@@ -804,23 +806,24 @@ redraw_mark_pane_borders(struct redraw_build_ctx *bctx, struct window_pane *wp,
|
|||||||
static void
|
static void
|
||||||
redraw_mark_pane(struct redraw_build_ctx *bctx, struct window_pane *wp)
|
redraw_mark_pane(struct redraw_build_ctx *bctx, struct window_pane *wp)
|
||||||
{
|
{
|
||||||
int sb_w = 0, sb_left = 0, overlay = 0;
|
struct style *sb_style = &wp->scrollbar_style;
|
||||||
|
int sb_w = 0, sb_left = 0, overlay = 0;
|
||||||
|
|
||||||
if (!window_pane_is_visible(wp))
|
if (!window_pane_is_visible(wp))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (window_pane_scrollbar_visible(wp)) {
|
if (window_pane_scrollbar_visible(wp)) {
|
||||||
overlay = window_pane_scrollbar_overlay(wp);
|
overlay = window_pane_scrollbar_overlay(wp);
|
||||||
if (overlay) {
|
if (!overlay)
|
||||||
sb_w = wp->scrollbar_style.width +
|
sb_w = sb_style->width + sb_style->pad;
|
||||||
wp->scrollbar_style.pad;
|
else {
|
||||||
|
sb_w = sb_style->width + sb_style->pad;
|
||||||
if (sb_w > (int)wp->sx) {
|
if (sb_w > (int)wp->sx) {
|
||||||
sb_w = wp->scrollbar_style.width;
|
sb_w = sb_style->width;
|
||||||
if (sb_w > (int)wp->sx)
|
if (sb_w > (int)wp->sx)
|
||||||
sb_w = wp->sx;
|
sb_w = wp->sx;
|
||||||
}
|
}
|
||||||
} else
|
}
|
||||||
sb_w = wp->scrollbar_style.width + wp->scrollbar_style.pad;
|
|
||||||
}
|
}
|
||||||
if (sb_w != 0 && bctx->w->sb_pos == PANE_SCROLLBARS_LEFT)
|
if (sb_w != 0 && bctx->w->sb_pos == PANE_SCROLLBARS_LEFT)
|
||||||
sb_left = 1;
|
sb_left = 1;
|
||||||
@@ -1301,7 +1304,7 @@ redraw_draw_pane_span(struct redraw_draw_ctx *dctx,
|
|||||||
style_ctx.palette = &wp->palette;
|
style_ctx.palette = &wp->palette;
|
||||||
style_ctx.hyperlinks = s->hyperlinks;
|
style_ctx.hyperlinks = s->hyperlinks;
|
||||||
|
|
||||||
px = span->data.p.px + (x - span->x);
|
px = span->data.p.px + (x - dctx->side_left - 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);
|
||||||
}
|
}
|
||||||
@@ -1455,7 +1458,7 @@ redraw_draw_status_span(struct redraw_draw_ctx *dctx,
|
|||||||
struct screen *s = &wp->status_screen;
|
struct screen *s = &wp->status_screen;
|
||||||
u_int px, sx = screen_size_x(s);
|
u_int px, sx = screen_size_x(s);
|
||||||
|
|
||||||
px = span->data.st.offset + (x - span->x);
|
px = span->data.st.offset + (x - dctx->side_left - span->x);
|
||||||
if (px < sx) {
|
if (px < sx) {
|
||||||
if (n > sx - px)
|
if (n > sx - px)
|
||||||
n = sx - px;
|
n = sx - px;
|
||||||
@@ -1517,7 +1520,7 @@ redraw_draw_scrollbar_span(struct redraw_draw_ctx *dctx,
|
|||||||
|
|
||||||
sb_w = sb_style->width;
|
sb_w = sb_style->width;
|
||||||
sb_pad = sb_style->pad;
|
sb_pad = sb_style->pad;
|
||||||
off = x - span->x;
|
off = x - dctx->side_left - span->x;
|
||||||
|
|
||||||
tty_cursor(tty, x, y);
|
tty_cursor(tty, x, y);
|
||||||
for (i = 0; i < n; i++) {
|
for (i = 0; i < n; i++) {
|
||||||
@@ -1551,7 +1554,7 @@ redraw_draw_menu_span(struct redraw_draw_ctx *dctx,
|
|||||||
struct screen *s = menu_screen(span->data.m.md);
|
struct screen *s = menu_screen(span->data.m.md);
|
||||||
u_int px;
|
u_int px;
|
||||||
|
|
||||||
px = span->data.m.px + (x - span->x);
|
px = span->data.m.px + (x - dctx->side_left - span->x);
|
||||||
tty_draw_line(tty, s, px, span->data.m.py, n, x, y, NULL);
|
tty_draw_line(tty, s, px, span->data.m.py, n, x, y, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1562,6 +1565,7 @@ redraw_draw_span(struct redraw_draw_ctx *dctx, struct redraw_span *span,
|
|||||||
{
|
{
|
||||||
struct redraw_span_data *data = &span->data;
|
struct redraw_span_data *data = &span->data;
|
||||||
enum redraw_span_type type = data->type;
|
enum redraw_span_type type = data->type;
|
||||||
|
u_int x = dctx->side_left + span->x;
|
||||||
u_int width = span->width;
|
u_int width = span->width;
|
||||||
|
|
||||||
if (type == REDRAW_SPAN_STATUS && ~data->st.wp->flags & PANE_NEWSTATUS)
|
if (type == REDRAW_SPAN_STATUS && ~data->st.wp->flags & PANE_NEWSTATUS)
|
||||||
@@ -1572,21 +1576,21 @@ redraw_draw_span(struct redraw_draw_ctx *dctx, struct redraw_span *span,
|
|||||||
switch (span->data.type) {
|
switch (span->data.type) {
|
||||||
case REDRAW_SPAN_PANE:
|
case REDRAW_SPAN_PANE:
|
||||||
if (phase == REDRAW_TEXT)
|
if (phase == REDRAW_TEXT)
|
||||||
redraw_draw_pane_span(dctx, span, span->x, y, width);
|
redraw_draw_pane_span(dctx, span, x, y, width);
|
||||||
break;
|
break;
|
||||||
case REDRAW_SPAN_BORDER:
|
case REDRAW_SPAN_BORDER:
|
||||||
case REDRAW_SPAN_EMPTY:
|
case REDRAW_SPAN_EMPTY:
|
||||||
case REDRAW_SPAN_OUTSIDE:
|
case REDRAW_SPAN_OUTSIDE:
|
||||||
redraw_draw_border_span(dctx, span, span->x, y, width);
|
redraw_draw_border_span(dctx, span, x, y, width);
|
||||||
break;
|
break;
|
||||||
case REDRAW_SPAN_STATUS:
|
case REDRAW_SPAN_STATUS:
|
||||||
redraw_draw_status_span(dctx, span, span->x, y, width);
|
redraw_draw_status_span(dctx, span, x, y, width);
|
||||||
break;
|
break;
|
||||||
case REDRAW_SPAN_SCROLLBAR:
|
case REDRAW_SPAN_SCROLLBAR:
|
||||||
redraw_draw_scrollbar_span(dctx, span, span->x, y, width);
|
redraw_draw_scrollbar_span(dctx, span, x, y, width);
|
||||||
break;
|
break;
|
||||||
case REDRAW_SPAN_MENU:
|
case REDRAW_SPAN_MENU:
|
||||||
redraw_draw_menu_span(dctx, span, span->x, y, width);
|
redraw_draw_menu_span(dctx, span, x, y, width);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1794,6 +1798,9 @@ redraw_set_draw_context(struct redraw_draw_ctx *dctx,
|
|||||||
dctx->flags |= REDRAW_STATUS_TOP;
|
dctx->flags |= REDRAW_STATUS_TOP;
|
||||||
dctx->status_lines = lines;
|
dctx->status_lines = lines;
|
||||||
|
|
||||||
|
if (status_side_at_column(c) == 0)
|
||||||
|
dctx->side_left = status_side_size(c);
|
||||||
|
|
||||||
if ((c->flags & CLIENT_UTF8) && tty_term_has(tty->term, TTYC_BIDI))
|
if ((c->flags & CLIENT_UTF8) && tty_term_has(tty->term, TTYC_BIDI))
|
||||||
dctx->flags |= REDRAW_ISOLATES;
|
dctx->flags |= REDRAW_ISOLATES;
|
||||||
}
|
}
|
||||||
@@ -1827,6 +1834,7 @@ redraw_draw_pane_prompt(struct redraw_draw_ctx *dctx, struct window_pane *wp)
|
|||||||
int ox = scene->ox, oy = scene->oy;
|
int ox = scene->ox, oy = scene->oy;
|
||||||
int sx = scene->sx, sy = scene->sy;
|
int sx = scene->sx, sy = scene->sy;
|
||||||
int line, cy, px, offset, width, wy;
|
int line, cy, px, offset, width, wy;
|
||||||
|
u_int side_left = dctx->side_left;
|
||||||
|
|
||||||
if (wp->prompt == NULL || wp->sx == 0 || wp->sy == 0)
|
if (wp->prompt == NULL || wp->sx == 0 || wp->sy == 0)
|
||||||
return;
|
return;
|
||||||
@@ -1857,7 +1865,7 @@ redraw_draw_pane_prompt(struct redraw_draw_ctx *dctx, struct window_pane *wp)
|
|||||||
width = sx - px;
|
width = sx - px;
|
||||||
|
|
||||||
redraw_make_pane_prompt(wp, &screen);
|
redraw_make_pane_prompt(wp, &screen);
|
||||||
tty_draw_line(tty, &screen, offset, 0, width, px, cy, NULL);
|
tty_draw_line(tty, &screen, offset, 0, width, side_left + px, cy, NULL);
|
||||||
screen_free(&screen);
|
screen_free(&screen);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1872,7 +1880,8 @@ redraw_draw(struct client *c, struct window_pane *wp, int flags)
|
|||||||
struct screen *sl;
|
struct screen *sl;
|
||||||
struct redraw_scene *scene;
|
struct redraw_scene *scene;
|
||||||
struct window_pane *loop;
|
struct window_pane *loop;
|
||||||
u_int width, i, y, lines;
|
u_int width, i, y, lines, side_width;
|
||||||
|
int side_x;
|
||||||
struct redraw_span *first;
|
struct redraw_span *first;
|
||||||
int redraw;
|
int redraw;
|
||||||
|
|
||||||
@@ -1895,6 +1904,16 @@ redraw_draw(struct client *c, struct window_pane *wp, int flags)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (flags & REDRAW_SIDE_STATUS) {
|
||||||
|
if (!status_side_redraw(c) &&
|
||||||
|
(~c->flags & CLIENT_REDRAWSTATUSALWAYS) &&
|
||||||
|
!REDRAW_IS_ALL(flags)) {
|
||||||
|
flags &= ~REDRAW_SIDE_STATUS;
|
||||||
|
if (flags == 0)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (log_get_level() != 0) {
|
if (log_get_level() != 0) {
|
||||||
log_debug("%s: starting @%u redraw (%s)", c->name, w->id,
|
log_debug("%s: starting @%u redraw (%s)", c->name, w->id,
|
||||||
redraw_flags_to_string(flags));
|
redraw_flags_to_string(flags));
|
||||||
@@ -1974,6 +1993,21 @@ redraw_draw(struct client *c, struct window_pane *wp, int flags)
|
|||||||
if (w->menu != NULL && (flags & REDRAW_MENU))
|
if (w->menu != NULL && (flags & REDRAW_MENU))
|
||||||
redraw_draw_menu_lines(&dctx);
|
redraw_draw_menu_lines(&dctx);
|
||||||
|
|
||||||
|
if (flags & REDRAW_SIDE_STATUS) {
|
||||||
|
side_width = status_side_size(c);
|
||||||
|
side_x = status_side_at_column(c);
|
||||||
|
if (side_width != 0 && side_x != -1) {
|
||||||
|
if (dctx.flags & REDRAW_STATUS_TOP)
|
||||||
|
y = dctx.status_lines;
|
||||||
|
else
|
||||||
|
y = 0;
|
||||||
|
for (i = 0; i < status_side_rows(c); i++) {
|
||||||
|
tty_draw_line(tty, &c->side_status.screen, 0, i,
|
||||||
|
side_width, side_x, y + i, NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (flags & REDRAW_STATUS) {
|
if (flags & REDRAW_STATUS) {
|
||||||
lines = dctx.status_lines;
|
lines = dctx.status_lines;
|
||||||
if (c->message_string != NULL || c->prompt != NULL)
|
if (c->message_string != NULL || c->prompt != NULL)
|
||||||
@@ -2039,7 +2073,8 @@ redraw_screen(struct client *c)
|
|||||||
if (c->flags & CLIENT_REDRAWBORDERS)
|
if (c->flags & CLIENT_REDRAWBORDERS)
|
||||||
flags |= (REDRAW_PANE_BORDER|REDRAW_PANE_STATUS);
|
flags |= (REDRAW_PANE_BORDER|REDRAW_PANE_STATUS);
|
||||||
if (c->flags & (CLIENT_REDRAWSTATUS|CLIENT_REDRAWSTATUSALWAYS))
|
if (c->flags & (CLIENT_REDRAWSTATUS|CLIENT_REDRAWSTATUSALWAYS))
|
||||||
flags |= (REDRAW_STATUS|REDRAW_PANE_STATUS);
|
flags |= (REDRAW_STATUS|REDRAW_PANE_STATUS|
|
||||||
|
REDRAW_SIDE_STATUS);
|
||||||
if (c->flags & CLIENT_REDRAWMENU)
|
if (c->flags & CLIENT_REDRAWMENU)
|
||||||
flags |= REDRAW_MENU;
|
flags |= REDRAW_MENU;
|
||||||
if (c->session->curw->window->menu != NULL)
|
if (c->session->curw->window->menu != NULL)
|
||||||
@@ -2093,6 +2128,7 @@ redraw_damage_draw_pane_prompt(struct redraw_draw_ctx *dctx,
|
|||||||
struct tty *tty = &scene->c->tty;
|
struct tty *tty = &scene->c->tty;
|
||||||
struct screen screen;
|
struct screen screen;
|
||||||
u_int px = span->data.p.px, width, prompt_y;
|
u_int px = span->data.p.px, width, prompt_y;
|
||||||
|
u_int x = dctx->side_left + span->x;
|
||||||
|
|
||||||
if (wp->prompt == NULL || wp->sx == 0 || wp->sy == 0)
|
if (wp->prompt == NULL || wp->sx == 0 || wp->sy == 0)
|
||||||
return;
|
return;
|
||||||
@@ -2107,7 +2143,7 @@ redraw_damage_draw_pane_prompt(struct redraw_draw_ctx *dctx,
|
|||||||
width = span->width;
|
width = span->width;
|
||||||
if (width > screen_size_x(&screen) - px)
|
if (width > screen_size_x(&screen) - px)
|
||||||
width = screen_size_x(&screen) - px;
|
width = screen_size_x(&screen) - px;
|
||||||
tty_draw_line(tty, &screen, px, 0, width, span->x, y, NULL);
|
tty_draw_line(tty, &screen, px, 0, width, x, y, NULL);
|
||||||
}
|
}
|
||||||
screen_free(&screen);
|
screen_free(&screen);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: screen-write.c,v 1.301 2026/10/14 13:36:37 nicm Exp $ */
|
/* $OpenBSD: screen-write.c,v 1.302 2026/10/16 07:59:06 nicm Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
|
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||||
@@ -185,6 +185,8 @@ screen_write_set_client_cb(struct tty_ctx *ttyctx, struct client *c)
|
|||||||
|
|
||||||
if (status_at_line(c) == 0)
|
if (status_at_line(c) == 0)
|
||||||
ttyctx->yoff += status_line_size(c);
|
ttyctx->yoff += status_line_size(c);
|
||||||
|
if (status_side_at_column(c) == 0)
|
||||||
|
ttyctx->xoff += status_side_size(c);
|
||||||
|
|
||||||
return (1);
|
return (1);
|
||||||
}
|
}
|
||||||
|
|||||||
224
server-client.c
224
server-client.c
@@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: server-client.c,v 1.522 2026/10/15 08:21:11 nicm Exp $ */
|
/* $OpenBSD: server-client.c,v 1.523 2026/10/16 07:59:06 nicm Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2009 Nicholas Marriott <nicholas.marriott@gmail.com>
|
* Copyright (c) 2009 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||||
@@ -192,6 +192,7 @@ server_client_create(int fd)
|
|||||||
c->theme = THEME_UNKNOWN;
|
c->theme = THEME_UNKNOWN;
|
||||||
|
|
||||||
status_init(c);
|
status_init(c);
|
||||||
|
status_side_init(c);
|
||||||
c->flags |= CLIENT_FOCUSED;
|
c->flags |= CLIENT_FOCUSED;
|
||||||
|
|
||||||
c->keytable = key_bindings_get_table("root", 1);
|
c->keytable = key_bindings_get_table("root", 1);
|
||||||
@@ -419,6 +420,7 @@ server_client_lost(struct client *c)
|
|||||||
tty_term_free_list(c->term_caps, c->term_ncaps);
|
tty_term_free_list(c->term_caps, c->term_ncaps);
|
||||||
|
|
||||||
status_free(c);
|
status_free(c);
|
||||||
|
status_side_free(c);
|
||||||
input_cancel_requests(c);
|
input_cancel_requests(c);
|
||||||
|
|
||||||
free(c->title);
|
free(c->title);
|
||||||
@@ -748,15 +750,123 @@ server_client_check_mouse_in_pane(struct window_pane *wp, int px, int py,
|
|||||||
return (KEYC_MOUSE_LOCATION_NOWHERE);
|
return (KEYC_MOUSE_LOCATION_NOWHERE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Check for mouse events on the status lines. */
|
||||||
|
static int
|
||||||
|
server_client_check_mouse_status(struct client *c, struct mouse_event *m,
|
||||||
|
enum key_code_type type, u_int x, u_int y,
|
||||||
|
enum key_code_mouse_location *loc)
|
||||||
|
{
|
||||||
|
struct winlink *fwl;
|
||||||
|
struct window_pane *fwp;
|
||||||
|
struct session *s = c->session, *fs;
|
||||||
|
struct style_range *sr;
|
||||||
|
u_int n, sidey, separator;
|
||||||
|
|
||||||
|
*loc = KEYC_MOUSE_LOCATION_NOWHERE;
|
||||||
|
|
||||||
|
m->statusat = status_at_line(c);
|
||||||
|
m->statuslines = status_line_size(c);
|
||||||
|
m->sideat = status_side_at_column(c);
|
||||||
|
m->sidewidth = status_side_size(c);
|
||||||
|
if (c->tty.mouse_drag_flag != 0 &&
|
||||||
|
c->tty.mouse_drag_location == KEYC_MOUSE_LOCATION_STATUS_BORDER) {
|
||||||
|
*loc = KEYC_MOUSE_LOCATION_STATUS_BORDER;
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m->statusat != -1 &&
|
||||||
|
y >= (u_int)m->statusat &&
|
||||||
|
y < m->statusat + m->statuslines) {
|
||||||
|
sr = status_get_range(c, x, y - m->statusat);
|
||||||
|
} else {
|
||||||
|
if (m->sideat == -1 ||
|
||||||
|
x < (u_int)m->sideat ||
|
||||||
|
x >= m->sideat + m->sidewidth)
|
||||||
|
return (0);
|
||||||
|
if (m->statusat == 0)
|
||||||
|
sidey = m->statuslines;
|
||||||
|
else
|
||||||
|
sidey = 0;
|
||||||
|
if (y < sidey || y - sidey >= status_side_rows(c))
|
||||||
|
return (0);
|
||||||
|
separator = m->sideat;
|
||||||
|
if (separator == 0)
|
||||||
|
separator = m->sidewidth - 1;
|
||||||
|
if (m->sidewidth > 1 && x == separator) {
|
||||||
|
*loc = KEYC_MOUSE_LOCATION_STATUS_BORDER;
|
||||||
|
if (type == KEYC_TYPE_MOUSEDRAG &&
|
||||||
|
c->tty.mouse_drag_flag == 0)
|
||||||
|
c->tty.mouse_drag_status = 1;
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
sr = status_side_get_range(c, x - m->sideat, y - sidey);
|
||||||
|
}
|
||||||
|
if (type == KEYC_TYPE_MOUSEDRAG && c->tty.mouse_drag_flag == 0)
|
||||||
|
c->tty.mouse_drag_status = 1;
|
||||||
|
if (sr == NULL) {
|
||||||
|
*loc = KEYC_MOUSE_LOCATION_STATUS_DEFAULT;
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (sr->type) {
|
||||||
|
case STYLE_RANGE_NONE:
|
||||||
|
return (-1);
|
||||||
|
case STYLE_RANGE_LEFT:
|
||||||
|
log_debug("mouse range: left");
|
||||||
|
*loc = KEYC_MOUSE_LOCATION_STATUS_LEFT;
|
||||||
|
break;
|
||||||
|
case STYLE_RANGE_RIGHT:
|
||||||
|
log_debug("mouse range: right");
|
||||||
|
*loc = KEYC_MOUSE_LOCATION_STATUS_RIGHT;
|
||||||
|
break;
|
||||||
|
case STYLE_RANGE_PANE:
|
||||||
|
fwp = window_pane_find_by_id(sr->argument);
|
||||||
|
if (fwp == NULL)
|
||||||
|
return (-1);
|
||||||
|
m->wp = sr->argument;
|
||||||
|
|
||||||
|
log_debug("mouse range: pane %%%u", m->wp);
|
||||||
|
*loc = KEYC_MOUSE_LOCATION_STATUS;
|
||||||
|
break;
|
||||||
|
case STYLE_RANGE_WINDOW:
|
||||||
|
fwl = winlink_find_by_index(&s->windows, sr->argument);
|
||||||
|
if (fwl == NULL)
|
||||||
|
return (-1);
|
||||||
|
m->w = fwl->window->id;
|
||||||
|
|
||||||
|
log_debug("mouse range: window @%u", m->w);
|
||||||
|
*loc = KEYC_MOUSE_LOCATION_STATUS;
|
||||||
|
break;
|
||||||
|
case STYLE_RANGE_SESSION:
|
||||||
|
fs = session_find_by_id(sr->argument);
|
||||||
|
if (fs == NULL)
|
||||||
|
return (-1);
|
||||||
|
m->s = sr->argument;
|
||||||
|
|
||||||
|
log_debug("mouse range: session $%u", m->s);
|
||||||
|
*loc = KEYC_MOUSE_LOCATION_STATUS;
|
||||||
|
break;
|
||||||
|
case STYLE_RANGE_USER:
|
||||||
|
log_debug("mouse range: user");
|
||||||
|
*loc = KEYC_MOUSE_LOCATION_STATUS;
|
||||||
|
break;
|
||||||
|
case STYLE_RANGE_CONTROL:
|
||||||
|
n = sr->argument; /* parsing keeps this < 10 */
|
||||||
|
log_debug("mouse range: control %u", n);
|
||||||
|
*loc = KEYC_MOUSE_LOCATION_CONTROL0 + n;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
/* Check for mouse keys. */
|
/* Check for mouse keys. */
|
||||||
static key_code
|
static key_code
|
||||||
server_client_check_mouse(struct client *c, struct key_event *event)
|
server_client_check_mouse(struct client *c, struct key_event *event)
|
||||||
{
|
{
|
||||||
struct mouse_event *m = &event->m;
|
struct mouse_event *m = &event->m;
|
||||||
struct session *s = c->session, *fs;
|
struct session *s = c->session;
|
||||||
struct window *w = s->curw->window;
|
struct window *w = s->curw->window;
|
||||||
struct winlink *fwl;
|
struct window_pane *wp, *lwp = NULL;
|
||||||
struct window_pane *wp, *fwp, *lwp = NULL;
|
|
||||||
u_int x, y, sx, sy, px, py, n, sl_mpos = 0;
|
u_int x, y, sx, sy, px, py, n, sl_mpos = 0;
|
||||||
u_int b, bn;
|
u_int b, bn;
|
||||||
int ignore = 0;
|
int ignore = 0;
|
||||||
@@ -858,69 +968,8 @@ have_event:
|
|||||||
m->wp = -1;
|
m->wp = -1;
|
||||||
m->ignore = ignore;
|
m->ignore = ignore;
|
||||||
|
|
||||||
/* Is this on the status line? */
|
if (server_client_check_mouse_status(c, m, type, x, y, &loc) != 0)
|
||||||
m->statusat = status_at_line(c);
|
return (KEYC_UNKNOWN);
|
||||||
m->statuslines = status_line_size(c);
|
|
||||||
if (m->statusat != -1 &&
|
|
||||||
y >= (u_int)m->statusat &&
|
|
||||||
y < m->statusat + m->statuslines) {
|
|
||||||
if (type == KEYC_TYPE_MOUSEDRAG && c->tty.mouse_drag_flag == 0)
|
|
||||||
c->tty.mouse_drag_status = 1;
|
|
||||||
sr = status_get_range(c, x, y - m->statusat);
|
|
||||||
if (sr == NULL) {
|
|
||||||
loc = KEYC_MOUSE_LOCATION_STATUS_DEFAULT;
|
|
||||||
} else {
|
|
||||||
switch (sr->type) {
|
|
||||||
case STYLE_RANGE_NONE:
|
|
||||||
return (KEYC_UNKNOWN);
|
|
||||||
case STYLE_RANGE_LEFT:
|
|
||||||
log_debug("mouse range: left");
|
|
||||||
loc = KEYC_MOUSE_LOCATION_STATUS_LEFT;
|
|
||||||
break;
|
|
||||||
case STYLE_RANGE_RIGHT:
|
|
||||||
log_debug("mouse range: right");
|
|
||||||
loc = KEYC_MOUSE_LOCATION_STATUS_RIGHT;
|
|
||||||
break;
|
|
||||||
case STYLE_RANGE_PANE:
|
|
||||||
fwp = window_pane_find_by_id(sr->argument);
|
|
||||||
if (fwp == NULL)
|
|
||||||
return (KEYC_UNKNOWN);
|
|
||||||
m->wp = sr->argument;
|
|
||||||
|
|
||||||
log_debug("mouse range: pane %%%u", m->wp);
|
|
||||||
loc = KEYC_MOUSE_LOCATION_STATUS;
|
|
||||||
break;
|
|
||||||
case STYLE_RANGE_WINDOW:
|
|
||||||
fwl = winlink_find_by_index(&s->windows,
|
|
||||||
sr->argument);
|
|
||||||
if (fwl == NULL)
|
|
||||||
return (KEYC_UNKNOWN);
|
|
||||||
m->w = fwl->window->id;
|
|
||||||
|
|
||||||
log_debug("mouse range: window @%u", m->w);
|
|
||||||
loc = KEYC_MOUSE_LOCATION_STATUS;
|
|
||||||
break;
|
|
||||||
case STYLE_RANGE_SESSION:
|
|
||||||
fs = session_find_by_id(sr->argument);
|
|
||||||
if (fs == NULL)
|
|
||||||
return (KEYC_UNKNOWN);
|
|
||||||
m->s = sr->argument;
|
|
||||||
|
|
||||||
log_debug("mouse range: session $%u", m->s);
|
|
||||||
loc = KEYC_MOUSE_LOCATION_STATUS;
|
|
||||||
break;
|
|
||||||
case STYLE_RANGE_USER:
|
|
||||||
log_debug("mouse range: user");
|
|
||||||
loc = KEYC_MOUSE_LOCATION_STATUS;
|
|
||||||
break;
|
|
||||||
case STYLE_RANGE_CONTROL:
|
|
||||||
n = sr->argument; /* parsing keeps this < 10 */
|
|
||||||
log_debug("mouse range: control %u", n);
|
|
||||||
loc = KEYC_MOUSE_LOCATION_CONTROL0 + n;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Not on status line. Adjust position and check for border, pane, or
|
* Not on status line. Adjust position and check for border, pane, or
|
||||||
@@ -933,7 +982,12 @@ have_event:
|
|||||||
m->w = lwp->window->id;
|
m->w = lwp->window->id;
|
||||||
}
|
}
|
||||||
} else if (loc == KEYC_MOUSE_LOCATION_NOWHERE) {
|
} else if (loc == KEYC_MOUSE_LOCATION_NOWHERE) {
|
||||||
px = x;
|
if (m->sideat == 0 && x >= m->sidewidth)
|
||||||
|
px = x - m->sidewidth;
|
||||||
|
else if (m->sideat > 0 && x >= (u_int)m->sideat)
|
||||||
|
px = m->sideat - 1;
|
||||||
|
else
|
||||||
|
px = x;
|
||||||
if (m->statusat == 0 && y >= m->statuslines)
|
if (m->statusat == 0 && y >= m->statuslines)
|
||||||
py = y - m->statuslines;
|
py = y - m->statuslines;
|
||||||
else if (m->statusat > 0 && y >= (u_int)m->statusat)
|
else if (m->statusat > 0 && y >= (u_int)m->statusat)
|
||||||
@@ -1097,6 +1151,7 @@ have_event:
|
|||||||
* where the user grabbed.
|
* where the user grabbed.
|
||||||
*/
|
*/
|
||||||
if (c->tty.mouse_drag_flag == 0) {
|
if (c->tty.mouse_drag_flag == 0) {
|
||||||
|
c->tty.mouse_drag_location = loc;
|
||||||
if (c->tty.mouse_drag_status) {
|
if (c->tty.mouse_drag_status) {
|
||||||
c->tty.mouse_drag_x = x;
|
c->tty.mouse_drag_x = x;
|
||||||
c->tty.mouse_drag_y = y;
|
c->tty.mouse_drag_y = y;
|
||||||
@@ -1627,18 +1682,29 @@ server_client_handle_menu_key(struct client *c, struct key_event *event)
|
|||||||
m = &new_event.m;
|
m = &new_event.m;
|
||||||
m->statusat = status_at_line(c);
|
m->statusat = status_at_line(c);
|
||||||
m->statuslines = status_line_size(c);
|
m->statuslines = status_line_size(c);
|
||||||
|
m->sideat = status_side_at_column(c);
|
||||||
|
m->sidewidth = status_side_size(c);
|
||||||
|
|
||||||
tty_window_offset(&c->tty, &ox, &oy, &sx, &sy);
|
tty_window_offset(&c->tty, &ox, &oy, &sx, &sy);
|
||||||
m->x += ox;
|
if (m->sideat == 0 && m->x < m->sidewidth)
|
||||||
if (m->statusat == 0) {
|
m->x = m->y = UINT_MAX;
|
||||||
if (m->y < m->statuslines)
|
else if (m->sideat > 0 && m->x >= (u_int)m->sideat)
|
||||||
|
m->x = m->y = UINT_MAX;
|
||||||
|
else {
|
||||||
|
if (m->sideat == 0)
|
||||||
|
m->x -= m->sidewidth;
|
||||||
|
m->x += ox;
|
||||||
|
if (m->statusat == 0) {
|
||||||
|
if (m->y < m->statuslines)
|
||||||
|
m->x = m->y = UINT_MAX;
|
||||||
|
else
|
||||||
|
m->y = m->y - m->statuslines + oy;
|
||||||
|
} else if (m->statusat > 0 &&
|
||||||
|
m->y >= (u_int)m->statusat)
|
||||||
m->x = m->y = UINT_MAX;
|
m->x = m->y = UINT_MAX;
|
||||||
else
|
else
|
||||||
m->y = m->y - m->statuslines + oy;
|
m->y += oy;
|
||||||
} else if (m->statusat > 0 && m->y >= (u_int)m->statusat)
|
}
|
||||||
m->x = m->y = UINT_MAX;
|
|
||||||
else
|
|
||||||
m->y += oy;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (menu_key(c, w->menu, &new_event) == 1)
|
if (menu_key(c, w->menu, &new_event) == 1)
|
||||||
@@ -2042,6 +2108,8 @@ server_client_prompt_cursor(struct client *c, struct window_pane *wp, int *mode,
|
|||||||
if (window_position_is_visible(r, *cx)) {
|
if (window_position_is_visible(r, *cx)) {
|
||||||
if (status_at_line(c) == 0)
|
if (status_at_line(c) == 0)
|
||||||
*cy += status_line_size(c);
|
*cy += status_line_size(c);
|
||||||
|
if (status_side_at_column(c) == 0)
|
||||||
|
*cx += status_side_size(c);
|
||||||
*mode |= MODE_CURSOR;
|
*mode |= MODE_CURSOR;
|
||||||
}
|
}
|
||||||
return (1);
|
return (1);
|
||||||
@@ -2110,6 +2178,8 @@ server_client_reset_state(struct client *c)
|
|||||||
cy -= oy;
|
cy -= oy;
|
||||||
if (status_at_line(c) == 0)
|
if (status_at_line(c) == 0)
|
||||||
cy += status_line_size(c);
|
cy += status_line_size(c);
|
||||||
|
if (status_side_at_column(c) == 0)
|
||||||
|
cx += status_side_size(c);
|
||||||
}
|
}
|
||||||
prompt = 1;
|
prompt = 1;
|
||||||
} else {
|
} else {
|
||||||
@@ -2149,6 +2219,8 @@ server_client_reset_state(struct client *c)
|
|||||||
|
|
||||||
if (status_at_line(c) == 0)
|
if (status_at_line(c) == 0)
|
||||||
cy += status_line_size(c);
|
cy += status_line_size(c);
|
||||||
|
if (status_side_at_column(c) == 0)
|
||||||
|
cx += status_side_size(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!cursor)
|
if (!cursor)
|
||||||
|
|||||||
211
status.c
211
status.c
@@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: status.c,v 1.274 2026/09/21 10:22:31 nicm Exp $ */
|
/* $OpenBSD: status.c,v 1.275 2026/10/16 07:59:06 nicm Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
|
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||||
@@ -68,7 +68,9 @@ status_timer_start(struct client *c)
|
|||||||
else
|
else
|
||||||
evtimer_set(&c->status.timer, status_timer_callback, c);
|
evtimer_set(&c->status.timer, status_timer_callback, c);
|
||||||
|
|
||||||
if (s != NULL && options_get_number(s->options, "status"))
|
if (s != NULL &&
|
||||||
|
(options_get_number(s->options, "status") ||
|
||||||
|
options_get_number(s->options, "side-status")))
|
||||||
status_timer_callback(-1, 0, c);
|
status_timer_callback(-1, 0, c);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -86,13 +88,28 @@ status_timer_start_all(void)
|
|||||||
void
|
void
|
||||||
status_update_cache(struct session *s)
|
status_update_cache(struct session *s)
|
||||||
{
|
{
|
||||||
s->statuslines = options_get_number(s->options, "status");
|
struct options *oo = s->options;
|
||||||
|
|
||||||
|
s->statuslines = options_get_number(oo, "status");
|
||||||
if (s->statuslines == 0)
|
if (s->statuslines == 0)
|
||||||
s->statusat = -1;
|
s->statusat = -1;
|
||||||
else if (options_get_number(s->options, "status-position") == 0)
|
else if (options_get_number(oo, "status-position") == 0)
|
||||||
s->statusat = 0;
|
s->statusat = 0;
|
||||||
else
|
else
|
||||||
s->statusat = 1;
|
s->statusat = 1;
|
||||||
|
|
||||||
|
switch (options_get_number(oo, "side-status")) {
|
||||||
|
case 1:
|
||||||
|
s->sidestatusat = 0;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
s->sidestatusat = 1;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
s->sidestatusat = -1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
s->sidestatuswidth = options_get_number(oo, "side-status-width");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get screen line of status line. -1 means off. */
|
/* Get screen line of status line. -1 means off. */
|
||||||
@@ -121,6 +138,44 @@ status_line_size(struct client *c)
|
|||||||
return (s->statuslines);
|
return (s->statuslines);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Get width of side status line for client's session. 0 means off. */
|
||||||
|
u_int
|
||||||
|
status_side_size(struct client *c)
|
||||||
|
{
|
||||||
|
struct session *s = c->session;
|
||||||
|
|
||||||
|
if (c->flags & (CLIENT_SIDESTATUSOFF|CLIENT_CONTROL))
|
||||||
|
return (0);
|
||||||
|
if (s == NULL || s->sidestatusat == -1)
|
||||||
|
return (0);
|
||||||
|
return (s->sidestatuswidth);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get starting column of side status line. -1 means off. */
|
||||||
|
int
|
||||||
|
status_side_at_column(struct client *c)
|
||||||
|
{
|
||||||
|
struct session *s = c->session;
|
||||||
|
u_int width = status_side_size(c);
|
||||||
|
|
||||||
|
if (width == 0)
|
||||||
|
return (-1);
|
||||||
|
if (s->sidestatusat == 0)
|
||||||
|
return (0);
|
||||||
|
return (c->tty.sx - width);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get number of rows of side status line for client. */
|
||||||
|
u_int
|
||||||
|
status_side_rows(struct client *c)
|
||||||
|
{
|
||||||
|
u_int lines = status_line_size(c);
|
||||||
|
|
||||||
|
if (status_side_size(c) == 0 || c->tty.sy <= lines)
|
||||||
|
return (0);
|
||||||
|
return (c->tty.sy - lines);
|
||||||
|
}
|
||||||
|
|
||||||
/* Get the prompt line number for client's session. 1 means at the bottom. */
|
/* Get the prompt line number for client's session. 1 means at the bottom. */
|
||||||
u_int
|
u_int
|
||||||
status_prompt_line_at(struct client *c)
|
status_prompt_line_at(struct client *c)
|
||||||
@@ -313,6 +368,154 @@ status_redraw(struct client *c)
|
|||||||
return (force || changed);
|
return (force || changed);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Prepare side status line. */
|
||||||
|
void
|
||||||
|
status_side_init(struct client *c)
|
||||||
|
{
|
||||||
|
struct side_status_line *ss = &c->side_status;
|
||||||
|
|
||||||
|
screen_init(&ss->screen, 1, 1, 0);
|
||||||
|
ss->linex = -1;
|
||||||
|
style_ranges_init(&ss->ranges);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Free side status line. */
|
||||||
|
void
|
||||||
|
status_side_free(struct client *c)
|
||||||
|
{
|
||||||
|
struct side_status_line *ss = &c->side_status;
|
||||||
|
|
||||||
|
style_ranges_free(&ss->ranges);
|
||||||
|
free(ss->expanded);
|
||||||
|
screen_free(&ss->screen);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Get the column of the ACS line separating the side status line from the
|
||||||
|
* window area, or -1 if there is none. The line takes the edge column
|
||||||
|
* nearest the window area out of the side status width.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
status_side_line_at(struct client *c)
|
||||||
|
{
|
||||||
|
struct session *s = c->session;
|
||||||
|
u_int width = status_side_size(c);
|
||||||
|
|
||||||
|
if (width < 2)
|
||||||
|
return (-1);
|
||||||
|
if (s->sidestatusat == 0)
|
||||||
|
return (width - 1);
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get side status range for position. */
|
||||||
|
struct style_range *
|
||||||
|
status_side_get_range(struct client *c, u_int x, u_int y)
|
||||||
|
{
|
||||||
|
struct side_status_line *ss = &c->side_status;
|
||||||
|
|
||||||
|
/* On a right side status line, content starts after the line. */
|
||||||
|
if (status_side_line_at(c) == 0) {
|
||||||
|
if (x == 0)
|
||||||
|
return (NULL);
|
||||||
|
x--;
|
||||||
|
}
|
||||||
|
return (style_ranges_get_range_at(&ss->ranges, x, y));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Draw side status line for client. Returns 1 if changed. */
|
||||||
|
int
|
||||||
|
status_side_redraw(struct client *c)
|
||||||
|
{
|
||||||
|
struct side_status_line *ss = &c->side_status;
|
||||||
|
struct session *s = c->session;
|
||||||
|
struct screen_write_ctx ctx;
|
||||||
|
struct grid_cell gc, lgc;
|
||||||
|
struct format_tree *ft;
|
||||||
|
char *expanded;
|
||||||
|
u_int width, rows, n;
|
||||||
|
int flags, force = 0, linex;
|
||||||
|
|
||||||
|
log_debug("%s enter", __func__);
|
||||||
|
|
||||||
|
/* No side status line? */
|
||||||
|
width = status_side_size(c);
|
||||||
|
rows = status_side_rows(c);
|
||||||
|
if (width == 0 || rows == 0)
|
||||||
|
return (0);
|
||||||
|
|
||||||
|
/* Create format tree. */
|
||||||
|
flags = FORMAT_STATUS;
|
||||||
|
if (c->flags & CLIENT_STATUSFORCE)
|
||||||
|
flags |= FORMAT_FORCE;
|
||||||
|
ft = format_create(c, NULL, FORMAT_NONE, flags);
|
||||||
|
format_defaults(ft, c, NULL, NULL, NULL);
|
||||||
|
|
||||||
|
/* Set up default colour. */
|
||||||
|
style_apply(&gc, s->options, "side-status-style", ft);
|
||||||
|
if (!grid_cells_equal(&gc, &ss->style)) {
|
||||||
|
force = 1;
|
||||||
|
memcpy(&ss->style, &gc, sizeof ss->style);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Resize the target screen. */
|
||||||
|
if (screen_size_x(&ss->screen) != width ||
|
||||||
|
screen_size_y(&ss->screen) != rows) {
|
||||||
|
screen_resize(&ss->screen, width, rows, 0);
|
||||||
|
force = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The line moves if the side status line changes side. */
|
||||||
|
linex = status_side_line_at(c);
|
||||||
|
if (linex != ss->linex) {
|
||||||
|
force = 1;
|
||||||
|
ss->linex = linex;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Expand the format. */
|
||||||
|
expanded = format_expand_time(ft,
|
||||||
|
options_get_string(s->options, "side-status-format"));
|
||||||
|
format_free(ft);
|
||||||
|
|
||||||
|
/* Skip the redraw if nothing has changed. */
|
||||||
|
if (!force &&
|
||||||
|
ss->expanded != NULL &&
|
||||||
|
strcmp(expanded, ss->expanded) == 0) {
|
||||||
|
free(expanded);
|
||||||
|
log_debug("%s exit: unchanged", __func__);
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Draw the rows over a blank background. */
|
||||||
|
screen_write_start(&ctx, &ss->screen);
|
||||||
|
screen_write_cursormove(&ctx, 0, 0, 0);
|
||||||
|
for (n = 0; n < width * rows; n++)
|
||||||
|
screen_write_putc(&ctx, &gc, ' ');
|
||||||
|
style_ranges_free(&ss->ranges);
|
||||||
|
|
||||||
|
/* Draw the line on the edge next to the window area. */
|
||||||
|
if (linex != -1) {
|
||||||
|
memcpy(&lgc, &gc, sizeof lgc);
|
||||||
|
lgc.attr |= GRID_ATTR_CHARSET;
|
||||||
|
for (n = 0; n < rows; n++) {
|
||||||
|
screen_write_cursormove(&ctx, linex, n, 0);
|
||||||
|
screen_write_putc(&ctx, &lgc, 'x');
|
||||||
|
}
|
||||||
|
width--;
|
||||||
|
}
|
||||||
|
|
||||||
|
screen_write_cursormove(&ctx, 0, 0, 0);
|
||||||
|
format_draw_lines(&ctx, &gc, linex == 0 ? 1 : 0, width, rows, expanded,
|
||||||
|
&ss->ranges, 0);
|
||||||
|
screen_write_stop(&ctx);
|
||||||
|
|
||||||
|
free(ss->expanded);
|
||||||
|
ss->expanded = expanded;
|
||||||
|
|
||||||
|
log_debug("%s exit: changed", __func__);
|
||||||
|
return (1);
|
||||||
|
}
|
||||||
|
|
||||||
/* Escape # characters in a string so format_draw treats them as literal. */
|
/* Escape # characters in a string so format_draw treats them as literal. */
|
||||||
static char *
|
static char *
|
||||||
status_message_escape(const char *s)
|
status_message_escape(const char *s)
|
||||||
|
|||||||
25
style.c
25
style.c
@@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: style.c,v 1.47 2026/06/29 17:08:52 nicm Exp $ */
|
/* $OpenBSD: style.c,v 1.48 2026/10/16 07:59:06 nicm Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
|
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||||
@@ -41,10 +41,10 @@ static struct style style_default = {
|
|||||||
STYLE_RANGE_NONE, 0, "",
|
STYLE_RANGE_NONE, 0, "",
|
||||||
|
|
||||||
STYLE_WIDTH_DEFAULT, 0, STYLE_PAD_DEFAULT,
|
STYLE_WIDTH_DEFAULT, 0, STYLE_PAD_DEFAULT,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
|
||||||
STYLE_DEFAULT_BASE,
|
STYLE_DEFAULT_BASE
|
||||||
|
|
||||||
0
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -110,6 +110,8 @@ style_parse(struct style *sy, const struct grid_cell *base, const char *in)
|
|||||||
sy->default_type = STYLE_DEFAULT_POP;
|
sy->default_type = STYLE_DEFAULT_POP;
|
||||||
else if (strcasecmp(tmp, "set-default") == 0)
|
else if (strcasecmp(tmp, "set-default") == 0)
|
||||||
sy->default_type = STYLE_DEFAULT_SET;
|
sy->default_type = STYLE_DEFAULT_SET;
|
||||||
|
else if (strcasecmp(tmp, "nl") == 0)
|
||||||
|
sy->nl = 1;
|
||||||
else if (strcasecmp(tmp, "nolist") == 0)
|
else if (strcasecmp(tmp, "nolist") == 0)
|
||||||
sy->list = STYLE_LIST_OFF;
|
sy->list = STYLE_LIST_OFF;
|
||||||
else if (strncasecmp(tmp, "list=", 5) == 0) {
|
else if (strncasecmp(tmp, "list=", 5) == 0) {
|
||||||
@@ -577,3 +579,18 @@ style_ranges_get_range(struct style_ranges *srs, u_int x)
|
|||||||
}
|
}
|
||||||
return (NULL);
|
return (NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Get range for position and row from style ranges. */
|
||||||
|
struct style_range *
|
||||||
|
style_ranges_get_range_at(struct style_ranges *srs, u_int x, u_int y)
|
||||||
|
{
|
||||||
|
struct style_range *sr;
|
||||||
|
|
||||||
|
if (srs == NULL)
|
||||||
|
return (NULL);
|
||||||
|
TAILQ_FOREACH(sr, srs, entry) {
|
||||||
|
if (x >= sr->start && x < sr->end && y == sr->y)
|
||||||
|
return (sr);
|
||||||
|
}
|
||||||
|
return (NULL);
|
||||||
|
}
|
||||||
|
|||||||
43
tmux.1
43
tmux.1
@@ -1,4 +1,4 @@
|
|||||||
.\" $OpenBSD: tmux.1,v 1.1187 2026/10/15 08:07:17 nicm Exp $
|
.\" $OpenBSD: tmux.1,v 1.1188 2026/10/16 07:59:06 nicm Exp $
|
||||||
.\"
|
.\"
|
||||||
.\" Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
|
.\" Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||||
.\"
|
.\"
|
||||||
@@ -14,7 +14,7 @@
|
|||||||
.\" IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
|
.\" IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
|
||||||
.\" OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
.\" OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
.\"
|
.\"
|
||||||
.Dd $Mdocdate: October 15 2026 $
|
.Dd $Mdocdate: October 16 2026 $
|
||||||
.Dt TMUX 1
|
.Dt TMUX 1
|
||||||
.Os
|
.Os
|
||||||
.Sh NAME
|
.Sh NAME
|
||||||
@@ -5638,6 +5638,41 @@ is on.
|
|||||||
Formats are expanded, see the
|
Formats are expanded, see the
|
||||||
.Sx FORMATS
|
.Sx FORMATS
|
||||||
section.
|
section.
|
||||||
|
.It Xo Ic side\-status
|
||||||
|
.Op Cm off | left | right
|
||||||
|
.Xc
|
||||||
|
Show a vertical status line at the left or right of the terminal.
|
||||||
|
The side status line uses the
|
||||||
|
.Ic side\-status\-style
|
||||||
|
colours, draws a vertical line on the edge next to the window area and is
|
||||||
|
updated every
|
||||||
|
.Ic status\-interval
|
||||||
|
seconds like the status line.
|
||||||
|
.It Ic side\-status\-format Ar format
|
||||||
|
Specify the format used for the side status line.
|
||||||
|
The format may produce multiple rows using the
|
||||||
|
.Ic nl
|
||||||
|
style or a newline character.
|
||||||
|
.Pp
|
||||||
|
Rows drawn with
|
||||||
|
.Ic list=on
|
||||||
|
are trimmed to the available height and scrolled to keep the row drawn with
|
||||||
|
.Ic list=focus
|
||||||
|
visible; rows drawn with
|
||||||
|
.Ic list=left\-marker
|
||||||
|
and
|
||||||
|
.Ic list=right\-marker
|
||||||
|
replace the first and last visible list row when rows are hidden above or
|
||||||
|
below.
|
||||||
|
.It Ic side\-status\-style Ar style
|
||||||
|
Set the style of the side status line.
|
||||||
|
For how to specify
|
||||||
|
.Ar style ,
|
||||||
|
see the
|
||||||
|
.Sx STYLES
|
||||||
|
section.
|
||||||
|
.It Ic side\-status\-width Ar width
|
||||||
|
Set the width of the side status line.
|
||||||
.It Xo Ic silence\-action
|
.It Xo Ic silence\-action
|
||||||
.Op Cm any | none | current | other
|
.Op Cm any | none | current | other
|
||||||
.Xc
|
.Xc
|
||||||
@@ -7498,6 +7533,8 @@ The following variables are available, where appropriate:
|
|||||||
.It Li "line" Ta "" Ta "Line number in the list"
|
.It Li "line" Ta "" Ta "Line number in the list"
|
||||||
.It Li "loop_index" Ta "" Ta "Index of item in the W:, P:, S:, or L: loop"
|
.It Li "loop_index" Ta "" Ta "Index of item in the W:, P:, S:, or L: loop"
|
||||||
.It Li "loop_last_flag" Ta "" Ta "1 if last window, pane, session, client in the W:, P:, S:, or L: loop"
|
.It Li "loop_last_flag" Ta "" Ta "1 if last window, pane, session, client in the W:, P:, S:, or L: loop"
|
||||||
|
.It Li "mouse_absolute_x" Ta "" Ta "Mouse X position in terminal, if any"
|
||||||
|
.It Li "mouse_absolute_y" Ta "" Ta "Mouse Y position in terminal, if any"
|
||||||
.It Li "mouse_all_flag" Ta "" Ta "Pane mouse all flag"
|
.It Li "mouse_all_flag" Ta "" Ta "Pane mouse all flag"
|
||||||
.It Li "mouse_any_flag" Ta "" Ta "Pane mouse any flag"
|
.It Li "mouse_any_flag" Ta "" Ta "Pane mouse any flag"
|
||||||
.It Li "mouse_button_flag" Ta "" Ta "Pane mouse button flag"
|
.It Li "mouse_button_flag" Ta "" Ta "Pane mouse button flag"
|
||||||
@@ -7814,6 +7851,8 @@ and
|
|||||||
.Ic list=right\-marker
|
.Ic list=right\-marker
|
||||||
mark the text to be used to mark that text has been trimmed from the left or
|
mark the text to be used to mark that text has been trimmed from the left or
|
||||||
right of the list if there is not enough space.
|
right of the list if there is not enough space.
|
||||||
|
.It Ic nl
|
||||||
|
End the current row when drawn over multiple rows
|
||||||
.It Ic noattr
|
.It Ic noattr
|
||||||
Do not copy attributes from the default style.
|
Do not copy attributes from the default style.
|
||||||
.It Xo Ic push\-default ,
|
.It Xo Ic push\-default ,
|
||||||
|
|||||||
42
tmux.h
42
tmux.h
@@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: tmux.h,v 1.1464 2026/10/15 08:07:17 nicm Exp $ */
|
/* $OpenBSD: tmux.h,v 1.1465 2026/10/16 07:59:06 nicm Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
|
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||||
@@ -179,6 +179,7 @@ enum key_code_mouse_location {
|
|||||||
KEYC_MOUSE_LOCATION_STATUS_LEFT,
|
KEYC_MOUSE_LOCATION_STATUS_LEFT,
|
||||||
KEYC_MOUSE_LOCATION_STATUS_RIGHT,
|
KEYC_MOUSE_LOCATION_STATUS_RIGHT,
|
||||||
KEYC_MOUSE_LOCATION_STATUS_DEFAULT,
|
KEYC_MOUSE_LOCATION_STATUS_DEFAULT,
|
||||||
|
KEYC_MOUSE_LOCATION_STATUS_BORDER,
|
||||||
KEYC_MOUSE_LOCATION_BORDER,
|
KEYC_MOUSE_LOCATION_BORDER,
|
||||||
KEYC_MOUSE_LOCATION_SCROLLBAR_UP,
|
KEYC_MOUSE_LOCATION_SCROLLBAR_UP,
|
||||||
KEYC_MOUSE_LOCATION_SCROLLBAR_SLIDER,
|
KEYC_MOUSE_LOCATION_SCROLLBAR_SLIDER,
|
||||||
@@ -236,6 +237,7 @@ enum key_code_mouse_location {
|
|||||||
KEYC_MOUSE_KEY(KEYC_ ## t, KEYC_TYPE_ ## t, STATUS_LEFT), \
|
KEYC_MOUSE_KEY(KEYC_ ## t, KEYC_TYPE_ ## t, STATUS_LEFT), \
|
||||||
KEYC_MOUSE_KEY(KEYC_ ## t, KEYC_TYPE_ ## t, STATUS_RIGHT), \
|
KEYC_MOUSE_KEY(KEYC_ ## t, KEYC_TYPE_ ## t, STATUS_RIGHT), \
|
||||||
KEYC_MOUSE_KEY(KEYC_ ## t, KEYC_TYPE_ ## t, STATUS_DEFAULT), \
|
KEYC_MOUSE_KEY(KEYC_ ## t, KEYC_TYPE_ ## t, STATUS_DEFAULT), \
|
||||||
|
KEYC_MOUSE_KEY(KEYC_ ## t, KEYC_TYPE_ ## t, STATUS_BORDER), \
|
||||||
KEYC_MOUSE_KEY(KEYC_ ## t, KEYC_TYPE_ ## t, BORDER), \
|
KEYC_MOUSE_KEY(KEYC_ ## t, KEYC_TYPE_ ## t, BORDER), \
|
||||||
KEYC_MOUSE_KEY(KEYC_ ## t, KEYC_TYPE_ ## t, SCROLLBAR_UP), \
|
KEYC_MOUSE_KEY(KEYC_ ## t, KEYC_TYPE_ ## t, SCROLLBAR_UP), \
|
||||||
KEYC_MOUSE_KEY(KEYC_ ## t, KEYC_TYPE_ ## t, SCROLLBAR_SLIDER), \
|
KEYC_MOUSE_KEY(KEYC_ ## t, KEYC_TYPE_ ## t, SCROLLBAR_SLIDER), \
|
||||||
@@ -272,6 +274,7 @@ enum key_code_mouse_location {
|
|||||||
{ #s "StatusLeft", KEYC_ ## name ## _STATUS_LEFT }, \
|
{ #s "StatusLeft", KEYC_ ## name ## _STATUS_LEFT }, \
|
||||||
{ #s "StatusRight", KEYC_ ## name ## _STATUS_RIGHT }, \
|
{ #s "StatusRight", KEYC_ ## name ## _STATUS_RIGHT }, \
|
||||||
{ #s "StatusDefault", KEYC_ ## name ## _STATUS_DEFAULT }, \
|
{ #s "StatusDefault", KEYC_ ## name ## _STATUS_DEFAULT }, \
|
||||||
|
{ #s "StatusBorder", KEYC_ ## name ## _STATUS_BORDER }, \
|
||||||
{ #s "ScrollbarUp", KEYC_ ## name ## _SCROLLBAR_UP }, \
|
{ #s "ScrollbarUp", KEYC_ ## name ## _SCROLLBAR_UP }, \
|
||||||
{ #s "ScrollbarSlider", KEYC_ ## name ## _SCROLLBAR_SLIDER }, \
|
{ #s "ScrollbarSlider", KEYC_ ## name ## _SCROLLBAR_SLIDER }, \
|
||||||
{ #s "ScrollbarDown", KEYC_ ## name ## _SCROLLBAR_DOWN }, \
|
{ #s "ScrollbarDown", KEYC_ ## name ## _SCROLLBAR_DOWN }, \
|
||||||
@@ -983,6 +986,7 @@ struct style_range {
|
|||||||
|
|
||||||
u_int start;
|
u_int start;
|
||||||
u_int end; /* not included */
|
u_int end; /* not included */
|
||||||
|
u_int y; /* row for multi-row areas */
|
||||||
|
|
||||||
TAILQ_ENTRY(style_range) entry;
|
TAILQ_ENTRY(style_range) entry;
|
||||||
};
|
};
|
||||||
@@ -1023,10 +1027,10 @@ struct style {
|
|||||||
int width;
|
int width;
|
||||||
int width_percentage;
|
int width_percentage;
|
||||||
int pad;
|
int pad;
|
||||||
|
int nl;
|
||||||
|
u_int link;
|
||||||
|
|
||||||
enum style_default_type default_type;
|
enum style_default_type default_type;
|
||||||
|
|
||||||
u_int link;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Cursor style. */
|
/* Cursor style. */
|
||||||
@@ -1626,6 +1630,8 @@ struct session {
|
|||||||
|
|
||||||
int statusat;
|
int statusat;
|
||||||
u_int statuslines;
|
u_int statuslines;
|
||||||
|
int sidestatusat; /* -1 off, 0 left, 1 right */
|
||||||
|
u_int sidestatuswidth;
|
||||||
|
|
||||||
struct options *options;
|
struct options *options;
|
||||||
|
|
||||||
@@ -1685,6 +1691,8 @@ struct mouse_event {
|
|||||||
|
|
||||||
int statusat;
|
int statusat;
|
||||||
u_int statuslines;
|
u_int statuslines;
|
||||||
|
int sideat;
|
||||||
|
u_int sidewidth;
|
||||||
|
|
||||||
u_int x;
|
u_int x;
|
||||||
u_int y;
|
u_int y;
|
||||||
@@ -1825,6 +1833,7 @@ struct tty {
|
|||||||
u_int mouse_last_b;
|
u_int mouse_last_b;
|
||||||
int mouse_drag_flag;
|
int mouse_drag_flag;
|
||||||
int mouse_drag_status;
|
int mouse_drag_status;
|
||||||
|
enum key_code_mouse_location mouse_drag_location;
|
||||||
u_int mouse_drag_x;
|
u_int mouse_drag_x;
|
||||||
u_int mouse_drag_y;
|
u_int mouse_drag_y;
|
||||||
int mouse_scrolling_flag;
|
int mouse_scrolling_flag;
|
||||||
@@ -2074,9 +2083,18 @@ struct status_line {
|
|||||||
int references;
|
int references;
|
||||||
|
|
||||||
u_int prompt_cx;
|
u_int prompt_cx;
|
||||||
|
struct grid_cell style;
|
||||||
|
struct style_line_entry entries[STATUS_LINES_LIMIT];
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Side status line. */
|
||||||
|
struct side_status_line {
|
||||||
|
struct screen screen;
|
||||||
|
|
||||||
struct grid_cell style;
|
struct grid_cell style;
|
||||||
struct style_line_entry entries[STATUS_LINES_LIMIT];
|
char *expanded;
|
||||||
|
int linex;
|
||||||
|
struct style_ranges ranges;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* File in client. */
|
/* File in client. */
|
||||||
@@ -2245,6 +2263,7 @@ struct client {
|
|||||||
struct mouse_event click_event;
|
struct mouse_event click_event;
|
||||||
|
|
||||||
struct status_line status;
|
struct status_line status;
|
||||||
|
struct side_status_line side_status;
|
||||||
struct event cycle_timer;
|
struct event cycle_timer;
|
||||||
enum client_theme theme;
|
enum client_theme theme;
|
||||||
|
|
||||||
@@ -2291,6 +2310,7 @@ struct client {
|
|||||||
#define CLIENT_WRITE_ACK 0x4000000000ULL
|
#define CLIENT_WRITE_ACK 0x4000000000ULL
|
||||||
#define CLIENT_NO_DETACH_ON_DESTROY 0x8000000000ULL
|
#define CLIENT_NO_DETACH_ON_DESTROY 0x8000000000ULL
|
||||||
#define CLIENT_CONTROL_DISCARD 0x10000000000ULL
|
#define CLIENT_CONTROL_DISCARD 0x10000000000ULL
|
||||||
|
#define CLIENT_SIDESTATUSOFF 0x20000000000ULL
|
||||||
#define CLIENT_ALLREDRAWFLAGS \
|
#define CLIENT_ALLREDRAWFLAGS \
|
||||||
(CLIENT_REDRAWWINDOW| \
|
(CLIENT_REDRAWWINDOW| \
|
||||||
CLIENT_REDRAWSTATUS| \
|
CLIENT_REDRAWSTATUS| \
|
||||||
@@ -2759,8 +2779,13 @@ void events_fire_pane(const char *, struct window_pane *);
|
|||||||
void events_fire_winlink(const char *, struct winlink *);
|
void events_fire_winlink(const char *, struct winlink *);
|
||||||
|
|
||||||
/* format-draw.c */
|
/* format-draw.c */
|
||||||
|
#define FORMAT_DRAW_DEFAULT_COLOURS 0x1
|
||||||
|
#define FORMAT_DRAW_NO_LIST 0x2
|
||||||
void format_draw(struct screen_write_ctx *, const struct grid_cell *,
|
void format_draw(struct screen_write_ctx *, const struct grid_cell *,
|
||||||
u_int, const char *, struct style_ranges *, int);
|
u_int, const char *, struct style_ranges *, int);
|
||||||
|
u_int format_draw_lines(struct screen_write_ctx *,
|
||||||
|
const struct grid_cell *, u_int, u_int, u_int, const char *,
|
||||||
|
struct style_ranges *, int);
|
||||||
u_int format_width(const char *);
|
u_int format_width(const char *);
|
||||||
char *format_trim_left(const char *, u_int);
|
char *format_trim_left(const char *, u_int);
|
||||||
char *format_trim_right(const char *, u_int);
|
char *format_trim_right(const char *, u_int);
|
||||||
@@ -3347,6 +3372,13 @@ void status_update_cache(struct session *);
|
|||||||
u_int status_prompt_line_at(struct client *);
|
u_int status_prompt_line_at(struct client *);
|
||||||
int status_at_line(struct client *);
|
int status_at_line(struct client *);
|
||||||
u_int status_line_size(struct client *);
|
u_int status_line_size(struct client *);
|
||||||
|
u_int status_side_size(struct client *);
|
||||||
|
int status_side_at_column(struct client *);
|
||||||
|
u_int status_side_rows(struct client *);
|
||||||
|
void status_side_init(struct client *);
|
||||||
|
void status_side_free(struct client *);
|
||||||
|
int status_side_redraw(struct client *);
|
||||||
|
struct style_range *status_side_get_range(struct client *, u_int, u_int);
|
||||||
struct style_range *status_get_range(struct client *, u_int, u_int);
|
struct style_range *status_get_range(struct client *, u_int, u_int);
|
||||||
void status_init(struct client *);
|
void status_init(struct client *);
|
||||||
void status_free(struct client *);
|
void status_free(struct client *);
|
||||||
@@ -4182,6 +4214,8 @@ void style_set_scrollbar_style_from_option(struct style *,
|
|||||||
void style_ranges_init(struct style_ranges *);
|
void style_ranges_init(struct style_ranges *);
|
||||||
void style_ranges_free(struct style_ranges *);
|
void style_ranges_free(struct style_ranges *);
|
||||||
struct style_range *style_ranges_get_range(struct style_ranges *, u_int);
|
struct style_range *style_ranges_get_range(struct style_ranges *, u_int);
|
||||||
|
struct style_range *style_ranges_get_range_at(struct style_ranges *, u_int,
|
||||||
|
u_int);
|
||||||
|
|
||||||
/* spawn.c */
|
/* spawn.c */
|
||||||
struct winlink *spawn_window(struct spawn_context *, char **);
|
struct winlink *spawn_window(struct spawn_context *, char **);
|
||||||
|
|||||||
42
tty.c
42
tty.c
@@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: tty.c,v 1.490 2026/10/15 22:29:15 nicm Exp $ */
|
/* $OpenBSD: tty.c,v 1.491 2026/10/16 07:59:06 nicm Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
|
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||||
@@ -954,7 +954,11 @@ tty_window_bigger(struct tty *tty)
|
|||||||
struct client *c = tty->client;
|
struct client *c = tty->client;
|
||||||
struct window *w = c->session->curw->window;
|
struct window *w = c->session->curw->window;
|
||||||
|
|
||||||
return (tty->sx < w->sx || tty->sy - status_line_size(c) < w->sy);
|
if (tty->sx - status_side_size(c) < w->sx)
|
||||||
|
return (1);
|
||||||
|
if (tty->sy - status_line_size(c) < w->sy)
|
||||||
|
return (1);
|
||||||
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* What offset should this window be drawn at? */
|
/* What offset should this window be drawn at? */
|
||||||
@@ -976,11 +980,12 @@ tty_window_offset1(struct tty *tty, u_int *ox, u_int *oy, u_int *sx, u_int *sy)
|
|||||||
struct client *c = tty->client;
|
struct client *c = tty->client;
|
||||||
struct window *w = c->session->curw->window;
|
struct window *w = c->session->curw->window;
|
||||||
struct window_pane *wp = w->active;
|
struct window_pane *wp = w->active;
|
||||||
u_int cx, cy, lines;
|
u_int cx, cy, lines, side;
|
||||||
|
|
||||||
lines = status_line_size(c);
|
lines = status_line_size(c);
|
||||||
|
side = status_side_size(c);
|
||||||
|
|
||||||
if (tty->sx >= w->sx && tty->sy - lines >= w->sy) {
|
if (tty->sx - side >= w->sx && tty->sy - lines >= w->sy) {
|
||||||
*ox = 0;
|
*ox = 0;
|
||||||
*oy = 0;
|
*oy = 0;
|
||||||
*sx = w->sx;
|
*sx = w->sx;
|
||||||
@@ -990,7 +995,7 @@ tty_window_offset1(struct tty *tty, u_int *ox, u_int *oy, u_int *sx, u_int *sy)
|
|||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
*sx = tty->sx;
|
*sx = tty->sx - side;
|
||||||
*sy = tty->sy - lines;
|
*sy = tty->sy - lines;
|
||||||
|
|
||||||
if (c->pan_window == w) {
|
if (c->pan_window == w) {
|
||||||
@@ -1173,18 +1178,18 @@ tty_clamp_line(struct tty *tty, const struct tty_ctx *ctx, u_int px, u_int py,
|
|||||||
} else if (xoff < (int)ctx->wox && xoff + nx > ctx->wox + ctx->wsx) {
|
} else if (xoff < (int)ctx->wox && xoff + nx > ctx->wox + ctx->wsx) {
|
||||||
/* Both left and right not visible. */
|
/* Both left and right not visible. */
|
||||||
*i = ctx->wox - xoff;
|
*i = ctx->wox - xoff;
|
||||||
*x = 0;
|
*x = ctx->xoff - ctx->rxoff;
|
||||||
*rx = ctx->wsx;
|
*rx = ctx->wsx;
|
||||||
} else if (xoff < (int)ctx->wox) {
|
} else if (xoff < (int)ctx->wox) {
|
||||||
/* Left not visible. */
|
/* Left not visible. */
|
||||||
*i = ctx->wox - (ctx->xoff + px);
|
*i = ctx->wox - xoff;
|
||||||
*x = 0;
|
*x = ctx->xoff - ctx->rxoff;
|
||||||
*rx = nx - *i;
|
*rx = nx - *i;
|
||||||
} else {
|
} else {
|
||||||
/* Right not visible. */
|
/* Right not visible. */
|
||||||
*i = 0;
|
*i = 0;
|
||||||
*x = (ctx->xoff + px) - ctx->wox;
|
*x = (ctx->xoff + px) - ctx->wox;
|
||||||
*rx = ctx->wsx - *x;
|
*rx = ctx->wox + ctx->wsx - xoff;
|
||||||
}
|
}
|
||||||
if (*rx > nx)
|
if (*rx > nx)
|
||||||
fatalx("%s: x too big, %u > %u", __func__, *rx, nx);
|
fatalx("%s: x too big, %u > %u", __func__, *rx, nx);
|
||||||
@@ -1267,18 +1272,18 @@ tty_clamp_area(struct tty *tty, const struct tty_ctx *ctx, u_int px, u_int py,
|
|||||||
} else if (xoff < ctx->wox && xoff + nx > ctx->wox + ctx->wsx) {
|
} else if (xoff < ctx->wox && xoff + nx > ctx->wox + ctx->wsx) {
|
||||||
/* Both left and right not visible. */
|
/* Both left and right not visible. */
|
||||||
*i = ctx->wox - xoff;
|
*i = ctx->wox - xoff;
|
||||||
*x = 0;
|
*x = ctx->xoff - ctx->rxoff;
|
||||||
*rx = ctx->wsx;
|
*rx = ctx->wsx;
|
||||||
} else if (xoff < ctx->wox) {
|
} else if (xoff < ctx->wox) {
|
||||||
/* Left not visible. */
|
/* Left not visible. */
|
||||||
*i = ctx->wox - (ctx->xoff + px);
|
*i = ctx->wox - xoff;
|
||||||
*x = 0;
|
*x = ctx->xoff - ctx->rxoff;
|
||||||
*rx = nx - *i;
|
*rx = nx - *i;
|
||||||
} else {
|
} else {
|
||||||
/* Right not visible. */
|
/* Right not visible. */
|
||||||
*i = 0;
|
*i = 0;
|
||||||
*x = (ctx->xoff + px) - ctx->wox;
|
*x = (ctx->xoff + px) - ctx->wox;
|
||||||
*rx = ctx->wsx - *x;
|
*rx = ctx->wox + ctx->wsx - xoff;
|
||||||
}
|
}
|
||||||
if (*rx > nx)
|
if (*rx > nx)
|
||||||
fatalx("%s: x too big, %u > %u", __func__, *rx, nx);
|
fatalx("%s: x too big, %u > %u", __func__, *rx, nx);
|
||||||
@@ -1919,8 +1924,8 @@ tty_cmd_cells(struct tty *tty, const struct tty_ctx *ctx)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
if ((ctx->flags & TTY_CTX_WINDOW_BIGGER) &&
|
if ((ctx->flags & TTY_CTX_WINDOW_BIGGER) &&
|
||||||
(ctx->xoff + ctx->ocx < ctx->wox ||
|
(ctx->rxoff + ctx->ocx < ctx->wox ||
|
||||||
ctx->xoff + ctx->ocx + n > ctx->wox + ctx->wsx)) {
|
ctx->rxoff + ctx->ocx + n > ctx->wox + ctx->wsx)) {
|
||||||
if ((~ctx->flags & TTY_CTX_WRAPPED) ||
|
if ((~ctx->flags & TTY_CTX_WRAPPED) ||
|
||||||
!tty_full_width(tty, ctx) ||
|
!tty_full_width(tty, ctx) ||
|
||||||
(tty->term->flags & TERM_NOAM) ||
|
(tty->term->flags & TERM_NOAM) ||
|
||||||
@@ -2112,10 +2117,11 @@ tty_margin_off(struct tty *tty)
|
|||||||
static void
|
static void
|
||||||
tty_margin_pane(struct tty *tty, const struct tty_ctx *ctx)
|
tty_margin_pane(struct tty *tty, const struct tty_ctx *ctx)
|
||||||
{
|
{
|
||||||
|
u_int xoff = ctx->xoff - ctx->rxoff;
|
||||||
int l, r;
|
int l, r;
|
||||||
|
|
||||||
l = ctx->xoff - ctx->wox;
|
l = ctx->rxoff - ctx->wox;
|
||||||
r = ctx->xoff + ctx->sx - 1 - ctx->wox;
|
r = ctx->rxoff + ctx->sx - 1 - ctx->wox;
|
||||||
|
|
||||||
if (l < 0)
|
if (l < 0)
|
||||||
l = 0;
|
l = 0;
|
||||||
@@ -2126,7 +2132,7 @@ tty_margin_pane(struct tty *tty, const struct tty_ctx *ctx)
|
|||||||
if (r > (int)ctx->wsx)
|
if (r > (int)ctx->wsx)
|
||||||
r = ctx->wsx;
|
r = ctx->wsx;
|
||||||
|
|
||||||
tty_margin(tty, l, r);
|
tty_margin(tty, xoff + l, xoff + r);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set margin at absolute position. */
|
/* Set margin at absolute position. */
|
||||||
|
|||||||
Reference in New Issue
Block a user