mirror of
https://github.com/tmux/tmux.git
synced 2026-10-12 05:34:24 +00:00
Merge remote-tracking branch 'refs/remotes/tmux-openbsd/master'
* refs/remotes/tmux-openbsd/master: Include menus when working out what parts of a pane are visible to avoid overwriting them, GitHub issue 5593. Modify display-message -c target-client to use the data relative to target-client, GitHub issue 5613 from Michael Grant. Quote session_alert in status-format[2], GitHub issue 5671. Only skip collecting text except for right margin when autowrap is off, from Jang-Ho Hwang. Change to the new working directory even if getcwd fails, GitHub issue 5658.
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: cmd-display-message.c,v 1.66 2026/09/08 08:33:10 nicm Exp $ */
|
/* $OpenBSD: cmd-display-message.c,v 1.67 2026/10/02 15:13:07 nicm Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2009 Tiago Cunha <me@tiagocunha.org>
|
* Copyright (c) 2009 Tiago Cunha <me@tiagocunha.org>
|
||||||
@@ -114,12 +114,10 @@ cmd_display_message_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
template = DISPLAY_MESSAGE_TEMPLATE;
|
template = DISPLAY_MESSAGE_TEMPLATE;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* -c is intended to be the client where the message should be
|
* -c is also used for the client formats. If it was not given, tc is
|
||||||
* displayed if -p is not given. But it makes sense to use it for the
|
* only the current client, so use it only if it matches the session.
|
||||||
* formats too, assuming it matches the session. If it doesn't, use the
|
|
||||||
* best client for the session.
|
|
||||||
*/
|
*/
|
||||||
if (tc != NULL && tc->session == s)
|
if (tc != NULL && (args_has(args, 'c') || tc->session == s))
|
||||||
c = tc;
|
c = tc;
|
||||||
else if (s != NULL)
|
else if (s != NULL)
|
||||||
c = cmd_find_best_client(s);
|
c = cmd_find_best_client(s);
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: options-table.c,v 1.247 2026/09/21 10:22:31 nicm Exp $ */
|
/* $OpenBSD: options-table.c,v 1.248 2026/10/02 15:04:27 nicm Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2011 Nicholas Marriott <nicholas.marriott@gmail.com>
|
* Copyright (c) 2011 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||||
@@ -217,7 +217,7 @@ static const char *options_table_copy_mode_line_numbers_list[] = {
|
|||||||
"#{E:session-status-style}" \
|
"#{E:session-status-style}" \
|
||||||
"]" \
|
"]" \
|
||||||
"#[push-default]" \
|
"#[push-default]" \
|
||||||
"#S#{session_alert}" \
|
"#S#{q/h:session_alert}" \
|
||||||
"#[pop-default]" \
|
"#[pop-default]" \
|
||||||
"#[norange list=on default] " \
|
"#[norange list=on default] " \
|
||||||
"," \
|
"," \
|
||||||
@@ -228,7 +228,7 @@ static const char *options_table_copy_mode_line_numbers_list[] = {
|
|||||||
"}" \
|
"}" \
|
||||||
"]" \
|
"]" \
|
||||||
"#[push-default]" \
|
"#[push-default]" \
|
||||||
"#S*#{session_alert}" \
|
"#S*#{q/h:session_alert}" \
|
||||||
"#[pop-default]" \
|
"#[pop-default]" \
|
||||||
"#[norange list=on default] " \
|
"#[norange list=on default] " \
|
||||||
"}"
|
"}"
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: screen-write.c,v 1.296 2026/10/02 12:53:26 nicm Exp $ */
|
/* $OpenBSD: screen-write.c,v 1.298 2026/10/02 15:20:41 nicm Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
|
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||||
@@ -189,11 +189,12 @@ screen_write_set_client_cb(struct tty_ctx *ttyctx, struct client *c)
|
|||||||
return (1);
|
return (1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return 1 if there is a floating window pane overlapping this pane. */
|
/* Return 1 if a menu or floating pane overlaps this pane. */
|
||||||
static int
|
static int
|
||||||
screen_write_pane_is_obscured(struct screen_write_ctx *ctx)
|
screen_write_pane_is_obscured(struct screen_write_ctx *ctx)
|
||||||
{
|
{
|
||||||
struct window_pane *wp = ctx->wp;
|
struct window_pane *wp = ctx->wp;
|
||||||
|
struct menu_data *md;
|
||||||
|
|
||||||
if (ctx->wp == NULL)
|
if (ctx->wp == NULL)
|
||||||
return (0);
|
return (0);
|
||||||
@@ -204,6 +205,16 @@ screen_write_pane_is_obscured(struct screen_write_ctx *ctx)
|
|||||||
}
|
}
|
||||||
ctx->flags |= SCREEN_WRITE_CHECKED_IF_OBSCURED;
|
ctx->flags |= SCREEN_WRITE_CHECKED_IF_OBSCURED;
|
||||||
|
|
||||||
|
md = wp->window->menu;
|
||||||
|
if (md != NULL &&
|
||||||
|
(int)menu_x(md) < wp->xoff + (int)wp->sx &&
|
||||||
|
(int)(menu_x(md) + menu_width(md)) > wp->xoff &&
|
||||||
|
(int)menu_y(md) < wp->yoff + (int)wp->sy &&
|
||||||
|
(int)(menu_y(md) + menu_height(md)) > wp->yoff) {
|
||||||
|
ctx->flags |= SCREEN_WRITE_OBSCURED;
|
||||||
|
return (1);
|
||||||
|
}
|
||||||
|
|
||||||
if (ctx->wp->xoff < 0 ||
|
if (ctx->wp->xoff < 0 ||
|
||||||
ctx->wp->yoff < 0 ||
|
ctx->wp->yoff < 0 ||
|
||||||
ctx->wp->xoff + ctx->wp->sx > ctx->wp->window->sx ||
|
ctx->wp->xoff + ctx->wp->sx > ctx->wp->window->sx ||
|
||||||
@@ -2522,13 +2533,18 @@ screen_write_collect_flush_line(struct screen_write_ctx *ctx, u_int y)
|
|||||||
ttyctx.n = w_length;
|
ttyctx.n = w_length;
|
||||||
tty_write(tty_cmd_clearcharacter, &ttyctx);
|
tty_write(tty_cmd_clearcharacter, &ttyctx);
|
||||||
} else {
|
} else {
|
||||||
screen_write_initctx(ctx, &ttyctx, 0, 0);
|
screen_write_initctx(ctx, &ttyctx, 0, 1);
|
||||||
ttyctx.cell = &ci->gc;
|
if (ttyctx.flags & TTY_CTX_PANE_OBSCURED) {
|
||||||
if (ci->wrapped)
|
ttyctx.n = w_length;
|
||||||
ttyctx.flags |= TTY_CTX_WRAPPED;
|
tty_write(tty_cmd_redrawline, &ttyctx);
|
||||||
ttyctx.data.data = cl->data + w_start;
|
} else {
|
||||||
ttyctx.data.size = w_length;
|
ttyctx.cell = &ci->gc;
|
||||||
tty_write(tty_cmd_cells, &ttyctx);
|
if (ci->wrapped)
|
||||||
|
ttyctx.flags |= TTY_CTX_WRAPPED;
|
||||||
|
ttyctx.data.data = cl->data + w_start;
|
||||||
|
ttyctx.data.size = w_length;
|
||||||
|
tty_write(tty_cmd_cells, &ttyctx);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
items++;
|
items++;
|
||||||
written = 1;
|
written = 1;
|
||||||
@@ -2756,6 +2772,10 @@ screen_write_collect_add(struct screen_write_ctx *ctx,
|
|||||||
* Don't need to check that the attributes and whatnot are still the
|
* Don't need to check that the attributes and whatnot are still the
|
||||||
* same - input_parse will end the collection when anything that isn't
|
* same - input_parse will end the collection when anything that isn't
|
||||||
* a plain character is encountered.
|
* a plain character is encountered.
|
||||||
|
*
|
||||||
|
* Without wrapping, collect up to but not including the last column.
|
||||||
|
* Leave that cell to screen_write_cell so repeated writes overwrite it
|
||||||
|
* and the cursor remains at the right edge.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
collect = 1;
|
collect = 1;
|
||||||
@@ -2765,7 +2785,8 @@ screen_write_collect_add(struct screen_write_ctx *ctx,
|
|||||||
collect = 0;
|
collect = 0;
|
||||||
else if (gc->attr & GRID_ATTR_CHARSET)
|
else if (gc->attr & GRID_ATTR_CHARSET)
|
||||||
collect = 0;
|
collect = 0;
|
||||||
else if (~s->mode & MODE_WRAP)
|
else if ((~s->mode & MODE_WRAP) &&
|
||||||
|
s->cx + ctx->item->used >= sx - 1)
|
||||||
collect = 0;
|
collect = 0;
|
||||||
else if (s->mode & MODE_INSERT)
|
else if (s->mode & MODE_INSERT)
|
||||||
collect = 0;
|
collect = 0;
|
||||||
@@ -2931,6 +2952,11 @@ screen_write_cell(struct screen_write_ctx *ctx, const struct grid_cell *gc)
|
|||||||
/* Create space for character in insert mode. */
|
/* Create space for character in insert mode. */
|
||||||
if (s->mode & MODE_INSERT) {
|
if (s->mode & MODE_INSERT) {
|
||||||
screen_write_collect_flush(ctx, 0, __func__);
|
screen_write_collect_flush(ctx, 0, __func__);
|
||||||
|
if (wp != NULL && screen_write_pane_is_obscured(ctx)) {
|
||||||
|
if (screen_write_should_draw_line(ctx, s->cy))
|
||||||
|
screen_write_redraw_line(ctx, &ttyctx, s->cy);
|
||||||
|
return;
|
||||||
|
}
|
||||||
ttyctx.n = width;
|
ttyctx.n = width;
|
||||||
if (screen_write_should_draw_line(ctx, s->cy))
|
if (screen_write_should_draw_line(ctx, s->cy))
|
||||||
tty_write(tty_cmd_insertcharacter, &ttyctx);
|
tty_write(tty_cmd_insertcharacter, &ttyctx);
|
||||||
|
|||||||
18
spawn.c
18
spawn.c
@@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: spawn.c,v 1.53 2026/09/21 12:43:36 nicm Exp $ */
|
/* $OpenBSD: spawn.c,v 1.54 2026/10/02 13:20:42 nicm Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2019 Nicholas Marriott <nicholas.marriott@gmail.com>
|
* Copyright (c) 2019 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||||
@@ -465,14 +465,14 @@ spawn_pane(struct spawn_context *sc, char **cause)
|
|||||||
new_wp->flags &= ~PANE_EMPTY;
|
new_wp->flags &= ~PANE_EMPTY;
|
||||||
|
|
||||||
/* Store current working directory and change to new one. */
|
/* Store current working directory and change to new one. */
|
||||||
if (getcwd(path, sizeof path) != NULL) {
|
if (getcwd(path, sizeof path) == NULL)
|
||||||
if (chdir(new_wp->cwd) == 0)
|
strlcpy(path, "/", sizeof path);
|
||||||
actual_cwd = new_wp->cwd;
|
if (chdir(new_wp->cwd) == 0)
|
||||||
else if (home != NULL && chdir(home) == 0)
|
actual_cwd = new_wp->cwd;
|
||||||
actual_cwd = home;
|
else if (home != NULL && chdir(home) == 0)
|
||||||
else if (chdir("/") == 0)
|
actual_cwd = home;
|
||||||
actual_cwd = "/";
|
else if (chdir("/") == 0)
|
||||||
}
|
actual_cwd = "/";
|
||||||
|
|
||||||
/* Fork the new process. */
|
/* Fork the new process. */
|
||||||
new_wp->pid = fdforkpty(ptm_fd, &new_wp->fd, new_wp->tty, NULL, &ws);
|
new_wp->pid = fdforkpty(ptm_fd, &new_wp->fd, new_wp->tty, NULL, &ws);
|
||||||
|
|||||||
163
window-visible.c
163
window-visible.c
@@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: window-visible.c,v 1.5 2026/07/19 17:25:38 nicm Exp $ */
|
/* $OpenBSD: window-visible.c,v 1.6 2026/10/02 15:20:41 nicm Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
|
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||||
@@ -25,7 +25,7 @@
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Check if a single character is within a visible range (not obscured by a
|
* Check if a single character is within a visible range (not obscured by a
|
||||||
* floating pane).
|
* menu or floating pane).
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
window_position_is_visible(struct visible_ranges *r, u_int px)
|
window_position_is_visible(struct visible_ranges *r, u_int px)
|
||||||
@@ -43,9 +43,45 @@ window_position_is_visible(struct visible_ranges *r, u_int px)
|
|||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Remove width cells starting at px from the visible ranges. */
|
||||||
|
static void
|
||||||
|
window_visible_ranges_remove(struct visible_ranges *r, int px, u_int width)
|
||||||
|
{
|
||||||
|
struct visible_range *ri;
|
||||||
|
u_int i;
|
||||||
|
int start, end, right = px + width;
|
||||||
|
|
||||||
|
if (width == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (i = 0; i < r->used; i++) {
|
||||||
|
ri = &r->ranges[i];
|
||||||
|
start = ri->px;
|
||||||
|
end = start + ri->nx;
|
||||||
|
if (ri->nx == 0 || right <= start || px >= end)
|
||||||
|
continue;
|
||||||
|
if (px <= start) {
|
||||||
|
/* Remove the left part or the whole range. */
|
||||||
|
ri->px = right < end ? right : end;
|
||||||
|
ri->nx = end - ri->px;
|
||||||
|
} else {
|
||||||
|
/* Keep the left part, and split off any right part. */
|
||||||
|
ri->nx = px - start;
|
||||||
|
if (right < end) {
|
||||||
|
server_client_ensure_ranges(r, r->used + 1);
|
||||||
|
memmove(&r->ranges[i + 2], &r->ranges[i + 1],
|
||||||
|
(r->used - i - 1) * sizeof *r->ranges);
|
||||||
|
r->ranges[i + 1].px = right;
|
||||||
|
r->ranges[i + 1].nx = end - right;
|
||||||
|
r->used++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Construct ranges array for the line at starting at px,py of width cells of
|
* Construct ranges array for the line at starting at px,py of width cells of
|
||||||
* base_wp that are unobsructed. All ranges are in window coordinates.
|
* base_wp that are unobstructed. All ranges are in window coordinates.
|
||||||
*/
|
*/
|
||||||
struct visible_ranges *
|
struct visible_ranges *
|
||||||
window_visible_ranges(struct window_pane *base_wp, int px, int py, u_int width,
|
window_visible_ranges(struct window_pane *base_wp, int px, int py, u_int width,
|
||||||
@@ -53,11 +89,10 @@ window_visible_ranges(struct window_pane *base_wp, int px, int py, u_int width,
|
|||||||
{
|
{
|
||||||
struct window_pane *wp;
|
struct window_pane *wp;
|
||||||
struct window *w;
|
struct window *w;
|
||||||
struct visible_range *ri;
|
struct menu_data *md;
|
||||||
static struct visible_ranges sr = { NULL, 0, 0 };
|
static struct visible_ranges sr = { NULL, 0, 0 };
|
||||||
int found_self, sb_w, sb_pos;
|
int found_self, sb_w, sb_pos;
|
||||||
int lb, rb, tb, bb, sx, ex, no_border;
|
int lb, rb, tb, bb, no_border;
|
||||||
u_int i, s;
|
|
||||||
|
|
||||||
if (py < 0 || width == 0)
|
if (py < 0 || width == 0)
|
||||||
goto empty;
|
goto empty;
|
||||||
@@ -95,6 +130,13 @@ window_visible_ranges(struct window_pane *base_wp, int px, int py, u_int width,
|
|||||||
r->used = 1;
|
r->used = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* The menu is above every pane in the window. */
|
||||||
|
md = w->menu;
|
||||||
|
if (md != NULL &&
|
||||||
|
(u_int)py >= menu_y(md) &&
|
||||||
|
(u_int)py - menu_y(md) < menu_height(md)) {
|
||||||
|
window_visible_ranges_remove(r, menu_x(md), menu_width(md));
|
||||||
|
}
|
||||||
|
|
||||||
found_self = 0;
|
found_self = 0;
|
||||||
TAILQ_FOREACH_REVERSE(wp, &w->z_index, window_panes_zindex, zentry) {
|
TAILQ_FOREACH_REVERSE(wp, &w->z_index, window_panes_zindex, zentry) {
|
||||||
@@ -129,89 +171,36 @@ window_visible_ranges(struct window_pane *base_wp, int px, int py, u_int width,
|
|||||||
else
|
else
|
||||||
sb_w = sb_pos = 0;
|
sb_w = sb_pos = 0;
|
||||||
|
|
||||||
for (i = 0; i < r->used; i++) {
|
if (no_border) {
|
||||||
ri = &r->ranges[i];
|
lb = wp->xoff;
|
||||||
if (ri->nx == 0)
|
rb = wp->xoff + (int)wp->sx - 1;
|
||||||
continue;
|
} else if (sb_pos == PANE_SCROLLBARS_LEFT) {
|
||||||
if (no_border) {
|
if (wp->xoff > sb_w)
|
||||||
lb = wp->xoff;
|
lb = wp->xoff - 1 - sb_w;
|
||||||
rb = wp->xoff + (int)wp->sx - 1;
|
else
|
||||||
} else if (sb_pos == PANE_SCROLLBARS_LEFT) {
|
lb = 0;
|
||||||
if (wp->xoff > sb_w)
|
} else { /* PANE_SCROLLBARS_RIGHT or none. */
|
||||||
lb = wp->xoff - 1 - sb_w;
|
if (wp->xoff > 0)
|
||||||
else
|
lb = wp->xoff - 1;
|
||||||
lb = 0;
|
else
|
||||||
} else { /* PANE_SCROLLBARS_RIGHT or none. */
|
|
||||||
if (wp->xoff > 0)
|
|
||||||
lb = wp->xoff - 1;
|
|
||||||
else
|
|
||||||
lb = 0;
|
|
||||||
}
|
|
||||||
if (!no_border) {
|
|
||||||
if (sb_pos == PANE_SCROLLBARS_LEFT)
|
|
||||||
rb = wp->xoff + (int)wp->sx;
|
|
||||||
else /* PANE_SCROLLBARS_RIGHT or none. */
|
|
||||||
rb = wp->xoff + (int)wp->sx + sb_w;
|
|
||||||
}
|
|
||||||
if (lb < 0)
|
|
||||||
lb = 0;
|
lb = 0;
|
||||||
if (rb < 0)
|
|
||||||
continue;
|
|
||||||
if (no_border && rb >= (int)w->sx)
|
|
||||||
rb = w->sx - 1;
|
|
||||||
else if (!no_border && rb > (int)w->sx)
|
|
||||||
rb = w->sx - 1;
|
|
||||||
if (lb > rb)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
sx = ri->px;
|
|
||||||
ex = sx + ri->nx - 1;
|
|
||||||
if (lb > sx && lb <= ex && rb > ex) {
|
|
||||||
/*
|
|
||||||
* If the left edge of floating pane falls
|
|
||||||
* inside this range and right edge covers up
|
|
||||||
* to right of range, then shrink left edge of
|
|
||||||
* range.
|
|
||||||
*/
|
|
||||||
ri->nx = lb - sx;
|
|
||||||
} else if (rb >= sx && rb <= ex && lb <= sx) {
|
|
||||||
/*
|
|
||||||
* Else if the right edge of floating pane falls
|
|
||||||
* inside of this range and left edge covers
|
|
||||||
* the left of range, then move px forward to
|
|
||||||
* right edge of pane.
|
|
||||||
*/
|
|
||||||
ri->nx = ex - rb;
|
|
||||||
ri->px = rb + 1;
|
|
||||||
} else if (lb > sx && rb <= ex) {
|
|
||||||
/*
|
|
||||||
* Else if pane fully inside range then split
|
|
||||||
* into 2 ranges.
|
|
||||||
*/
|
|
||||||
server_client_ensure_ranges(r, r->used + 1);
|
|
||||||
for (s = r->used; s > i; s--) {
|
|
||||||
memcpy(&r->ranges[s], &r->ranges[s - 1],
|
|
||||||
sizeof *r->ranges);
|
|
||||||
}
|
|
||||||
ri = &r->ranges[i];
|
|
||||||
r->ranges[i + 1].px = rb + 1;
|
|
||||||
r->ranges[i + 1].nx = ex - rb;
|
|
||||||
/* ri->px was copied, unchanged. */
|
|
||||||
ri->nx = lb - sx;
|
|
||||||
r->used++;
|
|
||||||
} else if (lb <= sx && rb > ex) {
|
|
||||||
/*
|
|
||||||
* If floating pane completely covers this range
|
|
||||||
* then delete it (make it 0 length).
|
|
||||||
*/
|
|
||||||
ri->nx = 0;
|
|
||||||
} else {
|
|
||||||
/*
|
|
||||||
* The range is already obscured, do
|
|
||||||
* nothing.
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
if (!no_border) {
|
||||||
|
if (sb_pos == PANE_SCROLLBARS_LEFT)
|
||||||
|
rb = wp->xoff + (int)wp->sx;
|
||||||
|
else /* PANE_SCROLLBARS_RIGHT or none. */
|
||||||
|
rb = wp->xoff + (int)wp->sx + sb_w;
|
||||||
|
}
|
||||||
|
if (lb < 0)
|
||||||
|
lb = 0;
|
||||||
|
if (rb < 0)
|
||||||
|
continue;
|
||||||
|
if (no_border && rb >= (int)w->sx)
|
||||||
|
rb = w->sx - 1;
|
||||||
|
else if (!no_border && rb > (int)w->sx)
|
||||||
|
rb = w->sx - 1;
|
||||||
|
if (lb <= rb)
|
||||||
|
window_visible_ranges_remove(r, lb, rb - lb + 1);
|
||||||
}
|
}
|
||||||
return (r);
|
return (r);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user