diff --git a/format.c b/format.c index cb9e34061..2e4b4057d 100644 --- a/format.c +++ b/format.c @@ -1,4 +1,4 @@ -/* $OpenBSD: format.c,v 1.425 2026/10/05 10:59:37 nicm Exp $ */ +/* $OpenBSD: format.c,v 1.427 2026/10/12 12:22:42 nicm Exp $ */ /* * Copyright (c) 2011 Nicholas Marriott @@ -3070,9 +3070,9 @@ format_cb_version(__unused struct format_tree *ft) return (xstrdup(getversion())); } -/* Callback for sixel_support. */ +/* Callback for image_support. */ static void * -format_cb_sixel_support(__unused struct format_tree *ft) +format_cb_image_support(__unused struct format_tree *ft) { #ifdef ENABLE_IMAGES return (xstrdup("1")); @@ -3753,6 +3753,9 @@ static const struct format_table_entry format_table[] = { { "host_short", FORMAT_TABLE_STRING, format_cb_host_short }, + { "image_support", FORMAT_TABLE_STRING, + format_cb_image_support + }, { "insert_flag", FORMAT_TABLE_STRING, format_cb_insert_flag }, @@ -4090,7 +4093,7 @@ static const struct format_table_entry format_table[] = { format_cb_session_windows }, { "sixel_support", FORMAT_TABLE_STRING, - format_cb_sixel_support + format_cb_image_support }, { "socket_path", FORMAT_TABLE_STRING, format_cb_socket_path @@ -5803,6 +5806,17 @@ format_loop_clients(struct format_expand_state *es, const char *fmt) return (value); } +/* Truncate a value to a long long, failing if it is NaN or out of range. */ +static int +format_truncate_integer(double *v) +{ + /* (double)LLONG_MAX is 2^63, which does not fit; -2^63 does. */ + if (isnan(*v) || *v >= (double)LLONG_MAX || *v < (double)LLONG_MIN) + return (-1); + *v = (long long)*v; + return (0); +} + static char * format_replace_expression(struct format_modifier *mexp, struct format_expand_state *es, const char *copy) @@ -5888,9 +5902,11 @@ format_replace_expression(struct format_modifier *mexp, goto fail; } - if (!use_fp) { - mleft = (long long)mleft; - mright = (long long)mright; + if (!use_fp && + (format_truncate_integer(&mleft) != 0 || + format_truncate_integer(&mright) != 0)) { + format_log(es, "expression side is out of range"); + goto fail; } format_log(es, "expression left side is: %.*f", prec, mleft); format_log(es, "expression right side is: %.*f", prec, mright); @@ -5930,10 +5946,11 @@ format_replace_expression(struct format_modifier *mexp, result = (mleft <= mright); break; } - if (use_fp) - xasprintf(&value, "%.*f", prec, result); - else - xasprintf(&value, "%.*f", prec, (double)(long long)result); + if (!use_fp && format_truncate_integer(&result) != 0) { + format_log(es, "expression result is out of range"); + goto fail; + } + xasprintf(&value, "%.*f", prec, result); format_log(es, "expression result is %s", value); free(right); diff --git a/menu.c b/menu.c index cb087296e..b7917fa72 100644 --- a/menu.c +++ b/menu.c @@ -1,4 +1,4 @@ -/* $OpenBSD: menu.c,v 1.71 2026/09/21 12:14:32 nicm Exp $ */ +/* $OpenBSD: menu.c,v 1.72 2026/10/12 10:46:12 nicm Exp $ */ /* * Copyright (c) 2019 Nicholas Marriott @@ -194,10 +194,19 @@ static void menu_reapply_styles(struct menu_data *md) { struct options *o = md->w->options; + struct session *s = NULL; + struct winlink *wl = NULL; + struct window_pane *wp = NULL; struct format_tree *ft; struct style sytmp; - ft = format_create_defaults(NULL, NULL, md->fs.s, md->fs.wl, md->fs.wp); + /* The pane (or session) the menu was opened for may be gone. */ + if (cmd_find_valid_state(&md->fs)) { + s = md->fs.s; + wl = md->fs.wl; + wp = md->fs.wp; + } + ft = format_create_defaults(NULL, NULL, s, wl, wp); /* Reapply menu style from options. */ memcpy(&md->style_gc, &grid_default_cell, sizeof md->style_gc); diff --git a/resize.c b/resize.c index 67562522d..108f7c318 100644 --- a/resize.c +++ b/resize.c @@ -1,4 +1,4 @@ -/* $OpenBSD: resize.c,v 1.59 2026/08/20 09:19:24 nicm Exp $ */ +/* $OpenBSD: resize.c,v 1.60 2026/10/12 13:08:19 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -152,7 +152,13 @@ clients_calculate_size(int type, int current, struct client *c, *sx = UINT_MAX; *sy = UINT_MAX; } - *xpixel = *ypixel = 0; + if (w != NULL && type == WINDOW_SIZE_MANUAL) { + *xpixel = w->xpixel; + *ypixel = w->ypixel; + } else { + *xpixel = 0; + *ypixel = 0; + } /* * For latest, count the number of clients with this window. We only @@ -380,16 +386,30 @@ recalculate_size(struct window *w, int now) /* Look for a suitable client and get the new size. */ changed = clients_calculate_size(type, current, NULL, NULL, w, recalculate_size_skip_client, &sx, &sy, &xpixel, &ypixel); + if (xpixel == 0) + xpixel = DEFAULT_XPIXEL; + if (ypixel == 0) + ypixel = DEFAULT_YPIXEL; /* * Make sure the size has actually changed. If the window has already * got a resize scheduled, then use the new size; otherwise the old. */ if (w->flags & WINDOW_RESIZE) { - if (!now && changed && w->new_sx == sx && w->new_sy == sy) + if (!now && + changed && + w->new_sx == sx && + w->new_sy == sy && + w->new_xpixel == xpixel && + w->new_ypixel == ypixel) changed = 0; } else { - if (!now && changed && w->sx == sx && w->sy == sy) + if (!now && + changed && + w->sx == sx && + w->sy == sy && + w->xpixel == xpixel && + w->ypixel == ypixel) changed = 0; } diff --git a/screen.c b/screen.c index 7120e1058..2a088edff 100644 --- a/screen.c +++ b/screen.c @@ -1,4 +1,4 @@ -/* $OpenBSD: screen.c,v 1.107 2026/07/26 09:20:54 nicm Exp $ */ +/* $OpenBSD: screen.c,v 1.108 2026/10/12 10:50:06 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -759,6 +759,10 @@ screen_alternate_off(struct screen *s, struct grid_cell *gc, int cursor) return 0; } + /* Clamp cursor to the current screen size. */ + if (s->cy > screen_size_y(s) - 1) + s->cy = screen_size_y(s) - 1; + /* Restore the saved grid. */ grid_duplicate_lines(s->grid, screen_hsize(s), s->saved_grid, 0, s->saved_grid->sy); diff --git a/server-client.c b/server-client.c index 46e4af0d1..6f824662d 100644 --- a/server-client.c +++ b/server-client.c @@ -1,4 +1,4 @@ -/* $OpenBSD: server-client.c,v 1.519 2026/10/09 10:16:02 nicm Exp $ */ +/* $OpenBSD: server-client.c,v 1.520 2026/10/12 10:48:05 nicm Exp $ */ /* * Copyright (c) 2009 Nicholas Marriott @@ -2599,7 +2599,7 @@ server_client_dispatch(struct imsg *imsg, void *arg) if (datalen != 0) goto bad; - if (c->flags & CLIENT_CONTROL) + if ((c->flags & CLIENT_CONTROL) || (~c->tty.flags & TTY_OPENED)) break; server_client_update_latest(c); old_sx = c->tty.sx; diff --git a/tmux.1 b/tmux.1 index 04279348e..0c48486a8 100644 --- a/tmux.1 +++ b/tmux.1 @@ -1,4 +1,4 @@ -.\" $OpenBSD: tmux.1,v 1.1182 2026/10/09 13:12:14 nicm Exp $ +.\" $OpenBSD: tmux.1,v 1.1184 2026/10/12 12:35:03 nicm Exp $ .\" .\" Copyright (c) 2007 Nicholas Marriott .\" @@ -14,7 +14,7 @@ .\" IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING .\" OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. .\" -.Dd $Mdocdate: October 9 2026 $ +.Dd $Mdocdate: October 12 2026 $ .Dt TMUX 1 .Os .Sh NAME @@ -5200,6 +5200,8 @@ Ignore function keys from and use the .Nm internal set only. +.It kittygraphics +Supports the Kitty graphics protocol with Unicode placeholders. .It margins Supports DECSLRM margins. .It mouse @@ -7469,6 +7471,7 @@ The following variables are available, where appropriate: .It Li "hook_window_name" Ta "" Ta "Name of window where hook was run, if any" .It Li "host" Ta "#H" Ta "Hostname of local host" .It Li "host_short" Ta "#h" Ta "Hostname of local host (no domain name)" +.It Li "image_support" Ta "" Ta "1 if server has support for images" .It Li "insert_flag" Ta "" Ta "Pane insert flag" .It Li "key_string" Ta "" Ta "String representation of the key binding" .It Li "key_repeat" Ta "" Ta "1 if key binding is repeatable" @@ -7623,7 +7626,6 @@ The following variables are available, where appropriate: .It Li "session_stack" Ta "" Ta "Window indexes in most recent order" .It Li "session_windows" Ta "" Ta "Number of windows in session" .It Li "socket_path" Ta "" Ta "Server socket path" -.It Li "sixel_support" Ta "" Ta "1 if server has support for SIXEL" .It Li "start_time" Ta "" Ta "Server start time" .It Li "synchronized_output_flag" Ta "" Ta "1 if pane has synchronized output enabled" .It Li "uid" Ta "" Ta "Server UID" diff --git a/tmux.h b/tmux.h index e7aa55eef..1fe443561 100644 --- a/tmux.h +++ b/tmux.h @@ -1,4 +1,4 @@ -/* $OpenBSD: tmux.h,v 1.1456 2026/10/12 10:39:05 nicm Exp $ */ +/* $OpenBSD: tmux.h,v 1.1457 2026/10/12 12:35:03 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -1765,6 +1765,7 @@ struct tty_term { #define TERM_SIXEL 0x40 #define TERM_INVALIDMS 0x80 #define TERM_NOREPLACE 0x100 +#define TERM_KITTYGRAPHICS 0x200 int flags; LIST_ENTRY(tty_term) entry; diff --git a/tty-features.c b/tty-features.c index 7d8568b57..1f4cd969a 100644 --- a/tty-features.c +++ b/tty-features.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tty-features.c,v 1.46 2026/09/24 08:16:13 nicm Exp $ */ +/* $OpenBSD: tty-features.c,v 1.48 2026/10/12 12:35:03 nicm Exp $ */ /* * Copyright (c) 2020 Nicholas Marriott @@ -369,6 +369,13 @@ static const struct tty_feature tty_feature_sixel = { TERM_SIXEL }; +/* Terminal supports Kitty graphics Unicode placeholders. */ +static const struct tty_feature tty_feature_kittygraphics = { + "kittygraphics", + NULL, + TERM_KITTYGRAPHICS +}; + /* Terminal supports the OSC 9;4 progress bar. */ static const char *const tty_feature_progressbar_capabilities[] = { "Spb=\\E]9;4;%p1%d;%p2%d\\E\\\\", @@ -399,6 +406,7 @@ static const struct tty_feature *const tty_features[] = { &tty_feature_extkeys, &tty_feature_focus, &tty_feature_ignorefkeys, + &tty_feature_kittygraphics, &tty_feature_margins, &tty_feature_mouse, &tty_feature_osc7, @@ -638,6 +646,7 @@ tty_default_features(struct client *c, const char *name, u_int version) "focus," "hyperlinks," "margins," + "sixel," "usstyle" }, { .name = "ghostty", @@ -652,7 +661,20 @@ tty_default_features(struct client *c, const char *name, u_int version) "osc7," "sync," "usstyle," - "progressbar" + "progressbar," + "kittygraphics" + }, + { .name = "kitty", + .features = TTY_FEATURES_BASE_MODERN_XTERM "," + "ccolour," + "cstyle," + "extkeys," + "focus," + "hyperlinks," + "osc7," + "sync," + "usstyle," + "kittygraphics" }, { .name = "Rio", .features = TTY_FEATURES_BASE_MODERN_XTERM "," diff --git a/tty-keys.c b/tty-keys.c index 96c73f1b6..b9ca2f019 100644 --- a/tty-keys.c +++ b/tty-keys.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tty-keys.c,v 1.216 2026/10/06 17:49:45 nicm Exp $ */ +/* $OpenBSD: tty-keys.c,v 1.217 2026/10/12 12:26:46 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -1675,6 +1675,8 @@ tty_keys_extended_device_attributes(struct tty *tty, const char *buf, tty_default_features(c, "mintty", 0); else if (strncmp(tmp, "foot(", 5) == 0) tty_default_features(c, "foot", 0); + else if (strncmp(tmp, "kitty(", 6) == 0) + tty_default_features(c, "kitty", 0); else if (strncmp(tmp, "WezTerm ", 7) == 0) tty_default_features(c, "WezTerm", 0); else if (strncmp(tmp, "ghostty ", 8) == 0) diff --git a/window-client.c b/window-client.c index 3c2f81097..05bb2f801 100644 --- a/window-client.c +++ b/window-client.c @@ -1,4 +1,4 @@ -/* $OpenBSD: window-client.c,v 1.49 2026/08/31 12:41:03 kirill Exp $ */ +/* $OpenBSD: window-client.c,v 1.50 2026/10/12 12:35:03 nicm Exp $ */ /* * Copyright (c) 2017 Nicholas Marriott @@ -89,19 +89,20 @@ static const char *window_client_info_lines[] = { " #[#{E:tree-mode-border-style},acs]x#[default] " WINDOW_CLIENT_FEATURE(hyperlinks) " " WINDOW_CLIENT_FEATURE(ignorefkeys) " " - WINDOW_CLIENT_FEATURE(margins) " " - WINDOW_CLIENT_FEATURE(mouse), + WINDOW_CLIENT_FEATURE(kittygraphics) " " + WINDOW_CLIENT_FEATURE(margins), " #[#{E:tree-mode-border-style},acs]x#[default] " + WINDOW_CLIENT_FEATURE(mouse) " " WINDOW_CLIENT_FEATURE(osc7) " " WINDOW_CLIENT_FEATURE(overline) " " - WINDOW_CLIENT_FEATURE(progressbar) " " - WINDOW_CLIENT_FEATURE(rectfill), + WINDOW_CLIENT_FEATURE(progressbar), " #[#{E:tree-mode-border-style},acs]x#[default] " + WINDOW_CLIENT_FEATURE(rectfill) " " WINDOW_CLIENT_FEATURE(sixel) " " WINDOW_CLIENT_FEATURE(strikethrough) " " - WINDOW_CLIENT_FEATURE(sync) " " - WINDOW_CLIENT_FEATURE(title), + WINDOW_CLIENT_FEATURE(sync), " #[#{E:tree-mode-border-style},acs]x#[default] " + WINDOW_CLIENT_FEATURE(title) " " WINDOW_CLIENT_FEATURE(usstyle) " " WINDOW_CLIENT_FEATURE(utf8), "#[#{E:tree-mode-border-style},acs]qqqqqqqqqqqqqqn#{R:q,#{window_width}}#[default]",