mirror of
https://github.com/tmux/tmux.git
synced 2026-10-13 14:24:28 +00:00
Merge branch 'master' into 4902-image-support
# Conflicts: # Makefile.am # configure.ac # format.c # image-sixel.c # regress/tty-keys-replies.sh # resize.c # screen-redraw.c # screen-write.c # screen.c # tmux.1 # tmux.h # tty-features.c # tty.c
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: cmd-new-session.c,v 1.153 2026/10/09 13:12:14 nicm Exp $ */
|
/* $OpenBSD: cmd-new-session.c,v 1.154 2026/10/12 07:52:05 nicm Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
|
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||||
@@ -82,7 +82,8 @@ cmd_new_session_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
char *cause, *cwd = NULL, *cp, *ename;
|
char *cause, *cwd = NULL, *cp, *ename;
|
||||||
char *wname = NULL, *sname = NULL, *prefix = NULL;
|
char *wname = NULL, *sname = NULL, *prefix = NULL;
|
||||||
int detached, already_attached, is_control = 0;
|
int detached, already_attached, is_control = 0;
|
||||||
u_int sx, sy, dsx, dsy, count = args_count(args);
|
u_int sx, sy, dsx, dsy, idx;
|
||||||
|
u_int count = args_count(args);
|
||||||
struct spawn_context sc = { 0 };
|
struct spawn_context sc = { 0 };
|
||||||
enum cmd_retval retval;
|
enum cmd_retval retval;
|
||||||
struct cmd_find_state fs;
|
struct cmd_find_state fs;
|
||||||
@@ -316,12 +317,17 @@ cmd_new_session_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
* so add it to the group and synchronize.
|
* so add it to the group and synchronize.
|
||||||
*/
|
*/
|
||||||
if (group != NULL) {
|
if (group != NULL) {
|
||||||
if (sg == NULL) {
|
if (sg == NULL && groupwith == NULL)
|
||||||
if (groupwith != NULL) {
|
sg = session_group_new(group);
|
||||||
sg = session_group_new(groupwith->name);
|
else if (sg == NULL) {
|
||||||
session_group_add(sg, groupwith);
|
cp = xstrdup(groupwith->name);
|
||||||
} else
|
for (idx = 1; session_group_find(cp) != NULL; idx++) {
|
||||||
sg = session_group_new(group);
|
free(cp);
|
||||||
|
xasprintf(&cp, "%s-%u", groupwith->name, idx);
|
||||||
|
}
|
||||||
|
sg = session_group_new(cp);
|
||||||
|
free(cp);
|
||||||
|
session_group_add(sg, groupwith);
|
||||||
}
|
}
|
||||||
session_group_add(sg, s);
|
session_group_add(sg, s);
|
||||||
session_group_synchronize_to(s);
|
session_group_synchronize_to(s);
|
||||||
|
|||||||
15
configure.ac
15
configure.ac
@@ -544,18 +544,17 @@ fi
|
|||||||
# Enable image support.
|
# Enable image support.
|
||||||
AC_ARG_ENABLE(
|
AC_ARG_ENABLE(
|
||||||
images,
|
images,
|
||||||
AS_HELP_STRING(--enable-images, enable Kitty/SIXEL/ASCII images)
|
AS_HELP_STRING(--enable-images, enable image support)
|
||||||
)
|
)
|
||||||
|
|
||||||
# Keep the old option as an alias for one compatibility cycle.
|
|
||||||
AC_ARG_ENABLE(
|
AC_ARG_ENABLE(
|
||||||
sixel,
|
sixel,
|
||||||
AS_HELP_STRING(--enable-sixel, deprecated alias for --enable-images)
|
AS_HELP_STRING(--enable-sixel, alias for --enable-images),
|
||||||
|
[
|
||||||
|
if test "x$enable_images" = x; then
|
||||||
|
enable_images=$enable_sixel
|
||||||
|
fi
|
||||||
|
]
|
||||||
)
|
)
|
||||||
if test "x$enable_sixel" = xyes; then
|
|
||||||
AC_MSG_WARN([--enable-sixel is deprecated, use --enable-images instead to enable.])
|
|
||||||
enable_images=yes
|
|
||||||
fi
|
|
||||||
if test "x$enable_images" = xyes; then
|
if test "x$enable_images" = xyes; then
|
||||||
PKG_CHECK_MODULES(
|
PKG_CHECK_MODULES(
|
||||||
IMAGE,
|
IMAGE,
|
||||||
|
|||||||
37
format.c
37
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 <nicholas.marriott@gmail.com>
|
* Copyright (c) 2011 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||||
@@ -3074,14 +3074,11 @@ format_cb_version(__unused struct format_tree *ft)
|
|||||||
static void *
|
static void *
|
||||||
format_cb_image_support(__unused struct format_tree *ft)
|
format_cb_image_support(__unused struct format_tree *ft)
|
||||||
{
|
{
|
||||||
char *value;
|
|
||||||
|
|
||||||
#ifdef ENABLE_IMAGES
|
#ifdef ENABLE_IMAGES
|
||||||
value = xstrdup("1");
|
return (xstrdup("1"));
|
||||||
#else
|
#else
|
||||||
value = xstrdup("0");
|
return (xstrdup("0"));
|
||||||
#endif
|
#endif
|
||||||
return (value);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Callback for active_window_index. */
|
/* Callback for active_window_index. */
|
||||||
@@ -5809,6 +5806,17 @@ format_loop_clients(struct format_expand_state *es, const char *fmt)
|
|||||||
return (value);
|
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 *
|
static char *
|
||||||
format_replace_expression(struct format_modifier *mexp,
|
format_replace_expression(struct format_modifier *mexp,
|
||||||
struct format_expand_state *es, const char *copy)
|
struct format_expand_state *es, const char *copy)
|
||||||
@@ -5894,9 +5902,11 @@ format_replace_expression(struct format_modifier *mexp,
|
|||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!use_fp) {
|
if (!use_fp &&
|
||||||
mleft = (long long)mleft;
|
(format_truncate_integer(&mleft) != 0 ||
|
||||||
mright = (long long)mright;
|
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 left side is: %.*f", prec, mleft);
|
||||||
format_log(es, "expression right side is: %.*f", prec, mright);
|
format_log(es, "expression right side is: %.*f", prec, mright);
|
||||||
@@ -5936,10 +5946,11 @@ format_replace_expression(struct format_modifier *mexp,
|
|||||||
result = (mleft <= mright);
|
result = (mleft <= mright);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (use_fp)
|
if (!use_fp && format_truncate_integer(&result) != 0) {
|
||||||
xasprintf(&value, "%.*f", prec, result);
|
format_log(es, "expression result is out of range");
|
||||||
else
|
goto fail;
|
||||||
xasprintf(&value, "%.*f", prec, (double)(long long)result);
|
}
|
||||||
|
xasprintf(&value, "%.*f", prec, result);
|
||||||
format_log(es, "expression result is %s", value);
|
format_log(es, "expression result is %s", value);
|
||||||
|
|
||||||
free(right);
|
free(right);
|
||||||
|
|||||||
9
grid.c
9
grid.c
@@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: grid.c,v 1.159 2026/10/08 07:50:05 nicm Exp $ */
|
/* $OpenBSD: grid.c,v 1.160 2026/10/12 08:08:37 nicm Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2008 Nicholas Marriott <nicholas.marriott@gmail.com>
|
* Copyright (c) 2008 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||||
@@ -45,7 +45,7 @@ const struct grid_cell grid_default_cell = {
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Padding grid cell data. Padding cells are the only zero width cell that
|
* Padding grid cell data. Padding cells are the only zero width cell that
|
||||||
* appears in the grid - because of this, they are always extended cells.
|
* appears in the grid.
|
||||||
*/
|
*/
|
||||||
static const struct grid_cell grid_padding_cell = {
|
static const struct grid_cell grid_padding_cell = {
|
||||||
{ { '!' }, 0, 0, 0 }, 0, GRID_FLAG_PADDING, 8, 8, 8, 0
|
{ { '!' }, 0, 0, 0 }, 0, GRID_FLAG_PADDING, 8, 8, 8, 0
|
||||||
@@ -651,7 +651,10 @@ grid_get_cell1(struct grid_line *gl, u_int px, struct grid_cell *gc)
|
|||||||
if (gce->flags & GRID_FLAG_BG256)
|
if (gce->flags & GRID_FLAG_BG256)
|
||||||
gc->bg |= COLOUR_FLAG_256;
|
gc->bg |= COLOUR_FLAG_256;
|
||||||
gc->us = 8;
|
gc->us = 8;
|
||||||
utf8_set(&gc->data, gce->data.data);
|
if (gc->flags & GRID_FLAG_PADDING)
|
||||||
|
memcpy(&gc->data, &grid_padding_cell.data, sizeof gc->data);
|
||||||
|
else
|
||||||
|
utf8_set(&gc->data, gce->data.data);
|
||||||
gc->link = 0;
|
gc->link = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -19,6 +19,7 @@
|
|||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@@ -236,19 +237,21 @@ sixel_parse_write(struct sixel_image *si, u_int ch)
|
|||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Parse a number, clamping values too large for u_int so limit checks fail. */
|
static int
|
||||||
static u_int
|
sixel_parse_number(const char *cp, char **endptr, u_int *value)
|
||||||
sixel_parse_number(const char *cp, char **endptr)
|
|
||||||
{
|
{
|
||||||
unsigned long value;
|
unsigned long long number;
|
||||||
|
|
||||||
value = strtoul(cp, endptr, 10);
|
if (*cp < '0' || *cp > '9')
|
||||||
if (value > UINT_MAX)
|
return (1);
|
||||||
return (UINT_MAX);
|
errno = 0;
|
||||||
return (value);
|
number = strtoull(cp, endptr, 10);
|
||||||
|
if (errno == ERANGE || number > UINT_MAX)
|
||||||
|
return (1);
|
||||||
|
*value = number;
|
||||||
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Parse a SIXEL raster attribute sequence. */
|
|
||||||
static const char *
|
static const char *
|
||||||
sixel_parse_attributes(struct sixel_image *si, const char *cp, const char *end)
|
sixel_parse_attributes(struct sixel_image *si, const char *cp, const char *end)
|
||||||
{
|
{
|
||||||
@@ -274,7 +277,10 @@ sixel_parse_attributes(struct sixel_image *si, const char *cp, const char *end)
|
|||||||
return (NULL);
|
return (NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
x = sixel_parse_number(endptr + 1, &endptr);
|
if (sixel_parse_number(endptr + 1, &endptr, &x) != 0) {
|
||||||
|
log_debug("%s: invalid number", __func__);
|
||||||
|
return (NULL);
|
||||||
|
}
|
||||||
if (endptr == last || *endptr != ';') {
|
if (endptr == last || *endptr != ';') {
|
||||||
log_debug("%s: missing ;", __func__);
|
log_debug("%s: missing ;", __func__);
|
||||||
return (NULL);
|
return (NULL);
|
||||||
@@ -283,7 +289,10 @@ sixel_parse_attributes(struct sixel_image *si, const char *cp, const char *end)
|
|||||||
log_debug("%s: image is too wide", __func__);
|
log_debug("%s: image is too wide", __func__);
|
||||||
return (NULL);
|
return (NULL);
|
||||||
}
|
}
|
||||||
y = sixel_parse_number(endptr + 1, &endptr);
|
if (sixel_parse_number(endptr + 1, &endptr, &y) != 0) {
|
||||||
|
log_debug("%s: invalid number", __func__);
|
||||||
|
return (NULL);
|
||||||
|
}
|
||||||
if (endptr != last) {
|
if (endptr != last) {
|
||||||
log_debug("%s: extra ;", __func__);
|
log_debug("%s: extra ;", __func__);
|
||||||
return (NULL);
|
return (NULL);
|
||||||
@@ -319,7 +328,10 @@ sixel_parse_colour(struct sixel_image *si, const char *cp, const char *end)
|
|||||||
last++;
|
last++;
|
||||||
}
|
}
|
||||||
|
|
||||||
c = sixel_parse_number(cp, &endptr);
|
if (sixel_parse_number(cp, &endptr, &c) != 0) {
|
||||||
|
log_debug("%s: invalid number", __func__);
|
||||||
|
return (NULL);
|
||||||
|
}
|
||||||
if (c > SIXEL_COLOUR_REGISTERS) {
|
if (c > SIXEL_COLOUR_REGISTERS) {
|
||||||
log_debug("%s: too many colours", __func__);
|
log_debug("%s: too many colours", __func__);
|
||||||
return (NULL);
|
return (NULL);
|
||||||
@@ -330,22 +342,34 @@ sixel_parse_colour(struct sixel_image *si, const char *cp, const char *end)
|
|||||||
if (endptr == last || *endptr != ';')
|
if (endptr == last || *endptr != ';')
|
||||||
return (last);
|
return (last);
|
||||||
|
|
||||||
type = sixel_parse_number(endptr + 1, &endptr);
|
if (sixel_parse_number(endptr + 1, &endptr, &type) != 0) {
|
||||||
|
log_debug("%s: invalid number", __func__);
|
||||||
|
return (NULL);
|
||||||
|
}
|
||||||
if (endptr == last || *endptr != ';') {
|
if (endptr == last || *endptr != ';') {
|
||||||
log_debug("%s: missing ;", __func__);
|
log_debug("%s: missing ;", __func__);
|
||||||
return (NULL);
|
return (NULL);
|
||||||
}
|
}
|
||||||
c1 = sixel_parse_number(endptr + 1, &endptr);
|
if (sixel_parse_number(endptr + 1, &endptr, &c1) != 0) {
|
||||||
|
log_debug("%s: invalid number", __func__);
|
||||||
|
return (NULL);
|
||||||
|
}
|
||||||
if (endptr == last || *endptr != ';') {
|
if (endptr == last || *endptr != ';') {
|
||||||
log_debug("%s: missing ;", __func__);
|
log_debug("%s: missing ;", __func__);
|
||||||
return (NULL);
|
return (NULL);
|
||||||
}
|
}
|
||||||
c2 = sixel_parse_number(endptr + 1, &endptr);
|
if (sixel_parse_number(endptr + 1, &endptr, &c2) != 0) {
|
||||||
|
log_debug("%s: invalid number", __func__);
|
||||||
|
return (NULL);
|
||||||
|
}
|
||||||
if (endptr == last || *endptr != ';') {
|
if (endptr == last || *endptr != ';') {
|
||||||
log_debug("%s: missing ;", __func__);
|
log_debug("%s: missing ;", __func__);
|
||||||
return (NULL);
|
return (NULL);
|
||||||
}
|
}
|
||||||
c3 = sixel_parse_number(endptr + 1, &endptr);
|
if (sixel_parse_number(endptr + 1, &endptr, &c3) != 0) {
|
||||||
|
log_debug("%s: invalid number", __func__);
|
||||||
|
return (NULL);
|
||||||
|
}
|
||||||
if (endptr != last) {
|
if (endptr != last) {
|
||||||
log_debug("%s: missing ;", __func__);
|
log_debug("%s: missing ;", __func__);
|
||||||
return (NULL);
|
return (NULL);
|
||||||
|
|||||||
2
image.c
2
image.c
@@ -138,7 +138,7 @@ static const struct image_backend image_backend_sixel = {
|
|||||||
static const struct image_backend *
|
static const struct image_backend *
|
||||||
image_tty_find_backend(struct tty *tty)
|
image_tty_find_backend(struct tty *tty)
|
||||||
{
|
{
|
||||||
if (tty->term != NULL && tty->term->flags & TERM_KITTY)
|
if (tty->term != NULL && tty->term->flags & TERM_KITTYGRAPHICS)
|
||||||
return (&image_backend_kitty);
|
return (&image_backend_kitty);
|
||||||
if (tty->term != NULL && tty->term->flags & TERM_SIXEL &&
|
if (tty->term != NULL && tty->term->flags & TERM_SIXEL &&
|
||||||
tty->xpixel != 0 && tty->ypixel != 0) {
|
tty->xpixel != 0 && tty->ypixel != 0) {
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: input-keys.c,v 1.114 2026/06/15 21:47:01 nicm Exp $ */
|
/* $OpenBSD: input-keys.c,v 1.115 2026/10/12 09:37:07 nicm Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
|
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||||
@@ -620,7 +620,7 @@ input_key(struct screen *s, struct bufferevent *bev, key_code key)
|
|||||||
key = '\011' | (key & ~KEYC_MASK_KEY) | KEYC_SHIFT;
|
key = '\011' | (key & ~KEYC_MASK_KEY) | KEYC_SHIFT;
|
||||||
} else {
|
} else {
|
||||||
/* Otherwise clear modifiers. */
|
/* Otherwise clear modifiers. */
|
||||||
key &= ~KEYC_MASK_MODIFIERS;
|
key &= ~(KEYC_MASK_MODIFIERS|KEYC_IMPLIED_META);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
13
menu.c
13
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 <nicholas.marriott@gmail.com>
|
* Copyright (c) 2019 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||||
@@ -194,10 +194,19 @@ static void
|
|||||||
menu_reapply_styles(struct menu_data *md)
|
menu_reapply_styles(struct menu_data *md)
|
||||||
{
|
{
|
||||||
struct options *o = md->w->options;
|
struct options *o = md->w->options;
|
||||||
|
struct session *s = NULL;
|
||||||
|
struct winlink *wl = NULL;
|
||||||
|
struct window_pane *wp = NULL;
|
||||||
struct format_tree *ft;
|
struct format_tree *ft;
|
||||||
struct style sytmp;
|
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. */
|
/* Reapply menu style from options. */
|
||||||
memcpy(&md->style_gc, &grid_default_cell, sizeof md->style_gc);
|
memcpy(&md->style_gc, &grid_default_cell, sizeof md->style_gc);
|
||||||
|
|||||||
@@ -557,7 +557,6 @@ const struct options_table_entry options_table[] = {
|
|||||||
.scope = OPTIONS_TABLE_SERVER,
|
.scope = OPTIONS_TABLE_SERVER,
|
||||||
.flags = OPTIONS_TABLE_IS_ARRAY,
|
.flags = OPTIONS_TABLE_IS_ARRAY,
|
||||||
.default_str = "xterm*:clipboard:ccolour:cstyle:focus:title,"
|
.default_str = "xterm*:clipboard:ccolour:cstyle:focus:title,"
|
||||||
"xterm-kitty*:kitty,"
|
|
||||||
"screen*:title,"
|
"screen*:title,"
|
||||||
"rxvt*:ignorefkeys",
|
"rxvt*:ignorefkeys",
|
||||||
.separator = ",",
|
.separator = ",",
|
||||||
|
|||||||
87
regress/alt-screen-saved-cursor.sh
Normal file
87
regress/alt-screen-saved-cursor.sh
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
# 1049h saves the cursor when it enters the alternate screen, and neither 47l
|
||||||
|
# nor 1049l clears it. If the screen was resized after it was saved, 1049l can
|
||||||
|
# restore a row below the saved grid it reflows.
|
||||||
|
|
||||||
|
PATH=/bin:/usr/bin
|
||||||
|
TERM=screen
|
||||||
|
|
||||||
|
[ -z "$TEST_TMUX" ] && TEST_TMUX=$(readlink -f ../tmux)
|
||||||
|
TMUX="$TEST_TMUX -Ltest$$ -f/dev/null"
|
||||||
|
DIR=$(mktemp -d)
|
||||||
|
trap '$TMUX kill-server 2>/dev/null; rm -rf $DIR' 0 1 15
|
||||||
|
|
||||||
|
exit_status=0
|
||||||
|
|
||||||
|
# Wait until the pane's program has set its path (OSC 7) to $1.
|
||||||
|
wait_path() {
|
||||||
|
_i=0
|
||||||
|
while [ "$($TMUX display -p '#{pane_path}' 2>/dev/null)" != "$1" ]; do
|
||||||
|
if ! $TMUX has 2>/dev/null; then
|
||||||
|
echo "FAIL: $2: the server died"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
_i=$((_i + 1))
|
||||||
|
if [ $_i -ge 400 ]; then
|
||||||
|
echo "FAIL: $2: timed out waiting for $1"
|
||||||
|
exit_status=1
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
sleep 0.05
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
# Respawn the pane, $2 by $3, running $1. Where the program waits for a file
|
||||||
|
# in $DIR, the test resizes the window and then creates it.
|
||||||
|
run() {
|
||||||
|
rm -f $DIR/go*
|
||||||
|
$TMUX resize-window -x $2 -y $3 || exit 1
|
||||||
|
$TMUX respawn-pane -k "$1; exec sleep 1000" || exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
check() {
|
||||||
|
if [ "$2" != "$3" ]; then
|
||||||
|
echo "FAIL: $1: '$2', not '$3'"
|
||||||
|
exit_status=1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
$TMUX new -d -x 10 -y 5 'sleep 1000' || exit 1
|
||||||
|
$TMUX set -g window-size manual || exit 1
|
||||||
|
|
||||||
|
# Outside the alternate screen (47l): the cursor after a full line goes to
|
||||||
|
# the last column, as with no 47l. Unchanged.
|
||||||
|
run "printf 'abcdefghij\\033[?1049h\\033[?47l\\033[?1049lX\\033]7;done\\007'" 10 5
|
||||||
|
if wait_path done "1049l outside the alternate screen"; then
|
||||||
|
check "1049l outside the alternate screen" \
|
||||||
|
"$($TMUX capture-pane -p | head -1)" abcdefghiX
|
||||||
|
fi
|
||||||
|
|
||||||
|
# A full line, 1049h, a wider screen, 1049l: the cursor is after the line's
|
||||||
|
# last character and X follows it. Unchanged.
|
||||||
|
run "printf 'abcdefghij\\033[?1049h\\033]7;in\\007'; while [ ! -e $DIR/go ]; do sleep 0.05; done; printf '\\033[?1049lX\\033]7;done\\007'" 10 5
|
||||||
|
if wait_path in "full line, then wider"; then
|
||||||
|
$TMUX resize-window -x 20 || exit 1
|
||||||
|
touch $DIR/go
|
||||||
|
wait_path done "full line, then wider" &&
|
||||||
|
check "full line, then wider" \
|
||||||
|
"$($TMUX capture-pane -p | head -1)" abcdefghijX
|
||||||
|
fi
|
||||||
|
|
||||||
|
# cy 8 saved 10 high; 47l, 20x4, 47h, 40x4, 1049l. The cursor goes to the
|
||||||
|
# last row of the saved grid, which is 4 high.
|
||||||
|
run "printf '\\033[9;1Hrow\\033[?1049h\\033[?47l\\033]7;one\\007'; while [ ! -e $DIR/go1 ]; do sleep 0.05; done; printf '\\033[?47h\\033]7;two\\007'; while [ ! -e $DIR/go2 ]; do sleep 0.05; done; printf '\\033[?1049lX\\033]7;done\\007'" 40 10
|
||||||
|
if wait_path one "saved taller"; then
|
||||||
|
$TMUX resize-window -x 20 -y 4 || exit 1
|
||||||
|
touch $DIR/go1
|
||||||
|
if wait_path two "saved taller"; then
|
||||||
|
$TMUX resize-window -x 40 -y 4 || exit 1
|
||||||
|
touch $DIR/go2
|
||||||
|
wait_path done "saved taller" &&
|
||||||
|
check "saved taller" \
|
||||||
|
"$($TMUX capture-pane -p | grep row)" rowX
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
exit $exit_status
|
||||||
72
regress/client-exit-resize.sh
Executable file
72
regress/client-exit-resize.sh
Executable file
@@ -0,0 +1,72 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
# A client that has sent MSG_EXITING can still send MSG_RESIZE. The server
|
||||||
|
# must not use the tty it closed for MSG_EXITING. Here the client is stopped
|
||||||
|
# and sent SIGTERM and then SIGWINCH for a size with no pixel size, so the
|
||||||
|
# server would ask the terminal for one.
|
||||||
|
|
||||||
|
PATH=/bin:/usr/bin:/usr/local/bin
|
||||||
|
TERM=screen
|
||||||
|
|
||||||
|
[ -z "$TEST_TMUX" ] && TEST_TMUX=$(readlink -f ../tmux)
|
||||||
|
TMUX="$TEST_TMUX -Ltest$$ -f/dev/null"
|
||||||
|
trap '$TMUX kill-server 2>/dev/null' 0 1 15
|
||||||
|
|
||||||
|
$TMUX new -d 'sleep 1000' || exit 1
|
||||||
|
$TMUX set-hook -g client-resized 'set -g @resized 1' || exit 1
|
||||||
|
python3 - $TMUX <<'EOF2' || exit 1
|
||||||
|
import fcntl, os, pty, signal, struct, subprocess, sys, termios, time
|
||||||
|
|
||||||
|
tmux = sys.argv[1:]
|
||||||
|
|
||||||
|
def size(fd, rows, cols, xpixel, ypixel):
|
||||||
|
fcntl.ioctl(fd, termios.TIOCSWINSZ,
|
||||||
|
struct.pack("HHHH", rows, cols, cols * xpixel, rows * ypixel))
|
||||||
|
|
||||||
|
master, slave = pty.openpty()
|
||||||
|
size(slave, 20, 60, 8, 16)
|
||||||
|
client = os.fork()
|
||||||
|
if client == 0:
|
||||||
|
os.setsid()
|
||||||
|
fcntl.ioctl(slave, termios.TIOCSCTTY, 0)
|
||||||
|
for fd in (0, 1, 2):
|
||||||
|
os.dup2(slave, fd)
|
||||||
|
os.environ["TERM"] = "xterm"
|
||||||
|
os.execvp(tmux[0], tmux + ["attach"])
|
||||||
|
os.set_blocking(master, False)
|
||||||
|
|
||||||
|
# Wait until the server has handled the resize the client sends when it
|
||||||
|
# attaches.
|
||||||
|
for i in range(200):
|
||||||
|
try:
|
||||||
|
os.read(master, 65536)
|
||||||
|
except OSError:
|
||||||
|
pass
|
||||||
|
out = subprocess.run(tmux + ["show", "-gv", "@resized"],
|
||||||
|
stdout=subprocess.PIPE, stderr=subprocess.DEVNULL).stdout
|
||||||
|
if out.strip() == b"1":
|
||||||
|
break
|
||||||
|
time.sleep(0.05)
|
||||||
|
else:
|
||||||
|
print("the client did not attach")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
# SIGTERM is sent before SIGWINCH, so the client handles it first whether
|
||||||
|
# it handles pending signals in signal number order or in the order sent.
|
||||||
|
os.kill(client, signal.SIGSTOP)
|
||||||
|
os.waitpid(client, os.WUNTRACED)
|
||||||
|
os.kill(client, signal.SIGTERM)
|
||||||
|
size(master, 23, 61, 0, 0)
|
||||||
|
os.kill(client, signal.SIGWINCH)
|
||||||
|
os.kill(client, signal.SIGCONT)
|
||||||
|
for i in range(200):
|
||||||
|
if os.waitpid(client, os.WNOHANG)[0] != 0:
|
||||||
|
break
|
||||||
|
time.sleep(0.05)
|
||||||
|
else:
|
||||||
|
print("the client did not exit")
|
||||||
|
sys.exit(1)
|
||||||
|
EOF2
|
||||||
|
sleep 1
|
||||||
|
$TMUX has || { echo "the server died"; exit 1; }
|
||||||
|
exit 0
|
||||||
@@ -226,10 +226,24 @@ test_format "#{e|/|f|2:10,3}" "3.33"
|
|||||||
# Default number of decimal places for float is two.
|
# Default number of decimal places for float is two.
|
||||||
test_format "#{e|*|f:2.5,2}" "5.00"
|
test_format "#{e|*|f:2.5,2}" "5.00"
|
||||||
|
|
||||||
# Division by zero must not crash the server (result is unspecified).
|
# An integer expression with a side or result that is NaN or out of the range
|
||||||
$TMUX display-message -p "#{e|/|:5,0}" >/dev/null 2>&1
|
# of a long long expands to empty: division or modulus by zero, nan or inf, or
|
||||||
$TMUX display-message -p "#{e|/|f:5,0}" >/dev/null 2>&1
|
# 1e30. LLONG_MAX written out is 2^63 as a double, which is out of range; the
|
||||||
assert_alive "division by zero"
|
# largest double below 2^63 and -2^63 still convert. Comparisons are integer
|
||||||
|
# expressions too. Floating point gives inf.
|
||||||
|
test_format "#{e|/|:5,0}" ""
|
||||||
|
test_format "#{e|m|:0,0}" ""
|
||||||
|
test_format "#{e|m|:7,0}" ""
|
||||||
|
test_format "#{e|+|:nan,0}" ""
|
||||||
|
test_format "#{e|+|:-inf,1}" ""
|
||||||
|
test_format "#{e|-|:1e30,1e30}" ""
|
||||||
|
test_format "#{e|*|:1e30,1}" ""
|
||||||
|
test_format "#{e|+|:9223372036854775807,0}" ""
|
||||||
|
test_format "#{e|<|:nan,1}" ""
|
||||||
|
test_format "#{e|+|:9223372036854774784,0}" "9223372036854774784"
|
||||||
|
test_format "#{e|-|:-9223372036854775808,0}" "-9223372036854775808"
|
||||||
|
test_format "#{e|/|f:5,0}" "inf"
|
||||||
|
assert_alive "expressions with no integer value"
|
||||||
|
|
||||||
|
|
||||||
# --- ASCII and repeat ----------------------------------------------------
|
# --- ASCII and repeat ----------------------------------------------------
|
||||||
|
|||||||
@@ -79,6 +79,7 @@ history_limit
|
|||||||
history_size
|
history_size
|
||||||
host
|
host
|
||||||
host_short
|
host_short
|
||||||
|
image_support
|
||||||
insert_flag
|
insert_flag
|
||||||
keypad_cursor_flag
|
keypad_cursor_flag
|
||||||
keypad_flag
|
keypad_flag
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ $TMUX new-session -d -x 10 -y 4 "
|
|||||||
$TMUX set -g status off || exit 1
|
$TMUX set -g status off || exit 1
|
||||||
$TMUX set -g scroll-on-clear off || exit 1
|
$TMUX set -g scroll-on-clear off || exit 1
|
||||||
$TMUX set -as terminal-features ',*:sixel@' || exit 1
|
$TMUX set -as terminal-features ',*:sixel@' || exit 1
|
||||||
$TMUX set -as terminal-features ',*:kitty@' || exit 1
|
$TMUX set -as terminal-features ',*:kittygraphics@' || exit 1
|
||||||
$TMUX set -as terminal-features ',*:RGB' || exit 1
|
$TMUX set -as terminal-features ',*:RGB' || exit 1
|
||||||
$TMUX2 new-session -d -x 10 -y 4 "$TMUX attach-session" || exit 1
|
$TMUX2 new-session -d -x 10 -y 4 "$TMUX attach-session" || exit 1
|
||||||
$TMUX2 set -g status off || exit 1
|
$TMUX2 set -g status off || exit 1
|
||||||
|
|||||||
@@ -109,7 +109,7 @@ with tempfile.TemporaryDirectory(prefix='tmux-kitty-layers-') as tmp:
|
|||||||
if run(inner, 'display-message', '-p', '#{image_support}') == '0':
|
if run(inner, 'display-message', '-p', '#{image_support}') == '0':
|
||||||
raise SystemExit(0)
|
raise SystemExit(0)
|
||||||
run(inner, 'set', '-g', 'status', 'off')
|
run(inner, 'set', '-g', 'status', 'off')
|
||||||
run(inner, 'set', '-as', 'terminal-features', ',*:kitty')
|
run(inner, 'set', '-as', 'terminal-features', ',*:kittygraphics')
|
||||||
pane = run(outer, 'new-session', '-dP', '-F', '#{pane_id}',
|
pane = run(outer, 'new-session', '-dP', '-F', '#{pane_id}',
|
||||||
'-x', '40', '-y', '12', 'exec sh')
|
'-x', '40', '-y', '12', 'exec sh')
|
||||||
run(outer, 'set', '-g', 'status', 'off')
|
run(outer, 'set', '-g', 'status', 'off')
|
||||||
|
|||||||
@@ -112,7 +112,7 @@ with tempfile.TemporaryDirectory(prefix='tmux-kitty-protocol-') as tmp:
|
|||||||
raise SystemExit(0)
|
raise SystemExit(0)
|
||||||
run('set', '-g', 'status', 'off')
|
run('set', '-g', 'status', 'off')
|
||||||
run('set', '-as', 'terminal-features', ',*:sixel@')
|
run('set', '-as', 'terminal-features', ',*:sixel@')
|
||||||
run('set', '-as', 'terminal-features', ',*:kitty@')
|
run('set', '-as', 'terminal-features', ',*:kittygraphics@')
|
||||||
run('set', '-as', 'terminal-features', ',*:RGB')
|
run('set', '-as', 'terminal-features', ',*:RGB')
|
||||||
subprocess.run(outer + ['new-session', '-d', '-x', '40', '-y', '12'], check=True)
|
subprocess.run(outer + ['new-session', '-d', '-x', '40', '-y', '12'], check=True)
|
||||||
subprocess.run(outer + ['set', '-g', 'status', 'off'], check=True)
|
subprocess.run(outer + ['set', '-g', 'status', 'off'], check=True)
|
||||||
|
|||||||
@@ -55,12 +55,12 @@ $TMUX new-session -d -s inner -x 40 -y 20 "printf '$HEADER'; exec sh" ||
|
|||||||
sleep 0.3
|
sleep 0.3
|
||||||
|
|
||||||
[ "$($TMUX display-message -p '#{image_support}')" = 0 ] && exit 0
|
[ "$($TMUX display-message -p '#{image_support}')" = 0 ] && exit 0
|
||||||
$TMUX set -as terminal-features ',*:kitty' || exit 1
|
$TMUX set -as terminal-features ',*:kittygraphics' || exit 1
|
||||||
|
|
||||||
$TMUX2 new-session -d -x 40 -y 20 || exit 1
|
$TMUX2 new-session -d -x 40 -y 20 || exit 1
|
||||||
OUTER=$($TMUX2 list-panes -F '#{pane_id}' | head -1)
|
OUTER=$($TMUX2 list-panes -F '#{pane_id}' | head -1)
|
||||||
[ -n "$OUTER" ] || fail "No outer pane."
|
[ -n "$OUTER" ] || fail "No outer pane."
|
||||||
$TMUX2 set -as terminal-features ',*:kitty@' || fail "disable outer kitty failed"
|
$TMUX2 set -as terminal-features ',*:kittygraphics@' || fail "disable outer kitty failed"
|
||||||
$TMUX2 pipe-pane -t "$OUTER" -O "cat >$TMP" || fail "pipe-pane failed"
|
$TMUX2 pipe-pane -t "$OUTER" -O "cat >$TMP" || fail "pipe-pane failed"
|
||||||
$TMUX2 send-keys -t "$OUTER" -l "$TMUX attach -t inner" || fail "send attach failed"
|
$TMUX2 send-keys -t "$OUTER" -l "$TMUX attach -t inner" || fail "send attach failed"
|
||||||
$TMUX2 send-keys -t "$OUTER" Enter || fail "send enter failed"
|
$TMUX2 send-keys -t "$OUTER" Enter || fail "send enter failed"
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ scroll_markers()
|
|||||||
$TMUX2 new-session -d -x 40 -y 20 || exit 1
|
$TMUX2 new-session -d -x 40 -y 20 || exit 1
|
||||||
OUTER=$($TMUX2 list-panes -F '#{pane_id}' | head -1)
|
OUTER=$($TMUX2 list-panes -F '#{pane_id}' | head -1)
|
||||||
[ -n "$OUTER" ] || fail "No outer pane."
|
[ -n "$OUTER" ] || fail "No outer pane."
|
||||||
$TMUX2 set -as terminal-features ',*:kitty@' ||
|
$TMUX2 set -as terminal-features ',*:kittygraphics@' ||
|
||||||
fail "disable outer kitty failed"
|
fail "disable outer kitty failed"
|
||||||
: >"$TMP"
|
: >"$TMP"
|
||||||
$TMUX2 pipe-pane -t "$OUTER" -O "cat >$TMP" || fail "pipe-pane failed"
|
$TMUX2 pipe-pane -t "$OUTER" -O "cat >$TMP" || fail "pipe-pane failed"
|
||||||
@@ -76,11 +76,11 @@ scroll_markers()
|
|||||||
N=$(grep -ac MARKER "$TMP")
|
N=$(grep -ac MARKER "$TMP")
|
||||||
}
|
}
|
||||||
|
|
||||||
scroll_markers ',*:kitty,*:imagescroll'
|
scroll_markers ',*:kittygraphics,*:imagescroll'
|
||||||
[ "$N" -eq 0 ] ||
|
[ "$N" -eq 0 ] ||
|
||||||
fail "existing text was redrawn ($N lines) scrolling with imagescroll"
|
fail "existing text was redrawn ($N lines) scrolling with imagescroll"
|
||||||
|
|
||||||
scroll_markers ',*:kitty'
|
scroll_markers ',*:kittygraphics'
|
||||||
[ "$N" -gt 0 ] ||
|
[ "$N" -gt 0 ] ||
|
||||||
fail "text was not redrawn scrolling without imagescroll"
|
fail "text was not redrawn scrolling without imagescroll"
|
||||||
|
|
||||||
|
|||||||
88
regress/input-combine-width.sh
Normal file
88
regress/input-combine-width.sh
Normal file
@@ -0,0 +1,88 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
. ./input-common.inc
|
||||||
|
|
||||||
|
# Exercise expansion by VS16, a skin tone modifier and a regional indicator.
|
||||||
|
for kind in variation modifier flag; do
|
||||||
|
case "$kind" in
|
||||||
|
variation)
|
||||||
|
combine_seq='\342\234\224\357\270\217'
|
||||||
|
text='✔️'
|
||||||
|
;;
|
||||||
|
modifier)
|
||||||
|
combine_seq='\342\230\235\360\237\217\273'
|
||||||
|
text='☝🏻'
|
||||||
|
;;
|
||||||
|
flag)
|
||||||
|
combine_seq='\360\237\207\254\360\237\207\247'
|
||||||
|
text='🇬🇧'
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
start_pane "$kind-overwrite" 10 3 "A\347\225\214BC\r${combine_seq}X"
|
||||||
|
check_capture "$kind-overwrite" "${text}XBC"
|
||||||
|
check_cursor "$kind-overwrite" '3,0'
|
||||||
|
check_raw_matches "$kind-overwrite" \
|
||||||
|
"C 0,0 data=\(2,[0-9]+,$text\) flags=NONE\[0\]" \
|
||||||
|
'C 0,1 .*flags=PADDING\[[0-9a-f]+\]' \
|
||||||
|
'C 0,2 data=\(1,1,X\) flags=NONE\[0\]'
|
||||||
|
|
||||||
|
start_pane "$kind-edge" 5 3 "abcd${combine_seq}X"
|
||||||
|
check_capture "$kind-edge" "abcd
|
||||||
|
${text}X"
|
||||||
|
check_cursor "$kind-edge" '3,1'
|
||||||
|
check_raw_matches "$kind-edge" \
|
||||||
|
'L 0 \(0\) flags=.*WRAPPED' \
|
||||||
|
'C 0,4 data=\(1,1, \)' \
|
||||||
|
"C 1,0 data=\(2,[0-9]+,$text\) flags=NONE\[0\]" \
|
||||||
|
'C 1,1 .*flags=PADDING\[[0-9a-f]+\]' \
|
||||||
|
'C 1,2 data=\(1,1,X\) flags=NONE\[0\]'
|
||||||
|
|
||||||
|
start_pane "$kind-fit" 5 3 "abc${combine_seq}X"
|
||||||
|
check_capture "$kind-fit" "abc${text}
|
||||||
|
X"
|
||||||
|
check_cursor "$kind-fit" '1,1'
|
||||||
|
|
||||||
|
start_pane "$kind-scroll" 5 2 "11111\r\nabcd${combine_seq}X"
|
||||||
|
check_capture "$kind-scroll" "abcd
|
||||||
|
${text}X"
|
||||||
|
check_cursor "$kind-scroll" '3,1'
|
||||||
|
|
||||||
|
start_pane "$kind-region" 5 4 \
|
||||||
|
"top\033[2;1Hold\033[4;1Hend\033[2;3r\033[3;1Habcd${combine_seq}X"
|
||||||
|
check_capture "$kind-region" "top
|
||||||
|
abcd
|
||||||
|
${text}X
|
||||||
|
end"
|
||||||
|
check_cursor "$kind-region" '3,2'
|
||||||
|
|
||||||
|
start_pane "$kind-insert" 10 3 "ABCDE\r\033[4h${combine_seq}X"
|
||||||
|
check_capture "$kind-insert" "${text}XABCDE"
|
||||||
|
check_cursor "$kind-insert" '3,0'
|
||||||
|
|
||||||
|
start_pane "$kind-insert-edge" 5 3 \
|
||||||
|
"\033[2;1HABCDE\033[1;1Habcd\033[4h${combine_seq}X"
|
||||||
|
check_capture "$kind-insert-edge" "abcd
|
||||||
|
${text}XAB"
|
||||||
|
check_cursor "$kind-insert-edge" '3,1'
|
||||||
|
|
||||||
|
start_pane "$kind-nowrap" 5 3 "\033[?7labc${combine_seq}"
|
||||||
|
check_capture "$kind-nowrap" "abc${text}"
|
||||||
|
check_cursor "$kind-nowrap" '4,0'
|
||||||
|
check_raw_matches "$kind-nowrap" \
|
||||||
|
"C 0,3 data=\(2,[0-9]+,$text\) flags=NONE\[0\]" \
|
||||||
|
'C 0,4 .*flags=PADDING\[[0-9a-f]+\]'
|
||||||
|
done
|
||||||
|
|
||||||
|
# A two-column cluster cannot fit in a one-column pane. Keep its narrow base.
|
||||||
|
start_pane one-column 1 3 '\342\234\224\357\270\217'
|
||||||
|
check_capture one-column '✔'
|
||||||
|
check_cursor one-column '1,0'
|
||||||
|
check_raw_no_matches one-column 'data=\(2,'
|
||||||
|
|
||||||
|
# Without wrapping, even a wide cell filling the pane leaves the cursor inside.
|
||||||
|
start_pane two-columns-nowrap 2 3 '\033[?7l\342\234\224\357\270\217'
|
||||||
|
check_capture two-columns-nowrap '✔️'
|
||||||
|
check_cursor two-columns-nowrap '1,0'
|
||||||
|
|
||||||
|
exit $exit_status
|
||||||
@@ -40,7 +40,7 @@ start_pane tabs 12 3 'A\tB\033[2g\r\033[IC'
|
|||||||
check_raw_matches tabs \
|
check_raw_matches tabs \
|
||||||
'L 0 \(0\) flags=EXTENDED\[[0-9a-f]+\]' \
|
'L 0 \(0\) flags=EXTENDED\[[0-9a-f]+\]' \
|
||||||
'C 0,1 data=\(7,7, \) flags=TAB\[[0-9a-f]+\]' \
|
'C 0,1 data=\(7,7, \) flags=TAB\[[0-9a-f]+\]' \
|
||||||
'C 0,2 data=\(1,1,!\) flags=PADDING\[[0-9a-f]+\]' \
|
'C 0,2 data=\(0,0,\) flags=PADDING\[[0-9a-f]+\]' \
|
||||||
'C 0,8 data=\(1,1,B\) flags=NONE\[0\]' \
|
'C 0,8 data=\(1,1,B\) flags=NONE\[0\]' \
|
||||||
'C 0,0 data=\(1,1,C\) flags=NONE\[0\]'
|
'C 0,0 data=\(1,1,C\) flags=NONE\[0\]'
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ check_capture wide 'AあB'
|
|||||||
check_raw_matches wide \
|
check_raw_matches wide \
|
||||||
'L 0 \(0\) flags=EXTENDED\[[0-9a-f]+\]' \
|
'L 0 \(0\) flags=EXTENDED\[[0-9a-f]+\]' \
|
||||||
'C 0,1 data=\(2,3,あ\) flags=NONE\[0\] attr=NONE\[0\]' \
|
'C 0,1 data=\(2,3,あ\) flags=NONE\[0\] attr=NONE\[0\]' \
|
||||||
'C 0,2 data=\(1,1,!\) flags=PADDING\[[0-9a-f]+\] attr=NONE\[0\]' \
|
'C 0,2 data=\(0,0,\) flags=PADDING\[[0-9a-f]+\] attr=NONE\[0\]' \
|
||||||
'C 0,3 data=\(1,1,B\) flags=NONE\[0\]'
|
'C 0,3 data=\(1,1,B\) flags=NONE\[0\]'
|
||||||
|
|
||||||
start_pane combining 8 3 'e\314\201x'
|
start_pane combining 8 3 'e\314\201x'
|
||||||
@@ -20,21 +20,21 @@ start_pane emoji 10 3 '\360\237\230\200Z'
|
|||||||
check_raw_matches emoji \
|
check_raw_matches emoji \
|
||||||
'L 0 \(0\) flags=EXTENDED\[[0-9a-f]+\]' \
|
'L 0 \(0\) flags=EXTENDED\[[0-9a-f]+\]' \
|
||||||
'C 0,0 data=\(2,4,😀\) flags=NONE\[0\] attr=NONE\[0\]' \
|
'C 0,0 data=\(2,4,😀\) flags=NONE\[0\] attr=NONE\[0\]' \
|
||||||
'C 0,1 data=\(1,1,!\) flags=PADDING\[[0-9a-f]+\] attr=NONE\[0\]' \
|
'C 0,1 data=\(0,0,\) flags=PADDING\[[0-9a-f]+\] attr=NONE\[0\]' \
|
||||||
'C 0,2 data=\(1,1,Z\) flags=NONE\[0\]'
|
'C 0,2 data=\(1,1,Z\) flags=NONE\[0\]'
|
||||||
|
|
||||||
start_pane flag 10 3 '\360\237\207\254\360\237\207\247!'
|
start_pane flag 10 3 '\360\237\207\254\360\237\207\247!'
|
||||||
check_raw_matches flag \
|
check_raw_matches flag \
|
||||||
'L 0 \(0\) flags=EXTENDED\[[0-9a-f]+\]' \
|
'L 0 \(0\) flags=EXTENDED\[[0-9a-f]+\]' \
|
||||||
'C 0,0 data=\(2,8,🇬🇧\) flags=NONE\[0\] attr=NONE\[0\]' \
|
'C 0,0 data=\(2,8,🇬🇧\) flags=NONE\[0\] attr=NONE\[0\]' \
|
||||||
'C 0,1 data=\(1,1,!\) flags=PADDING\[[0-9a-f]+\] attr=NONE\[0\]' \
|
'C 0,1 data=\(0,0,\) flags=PADDING\[[0-9a-f]+\] attr=NONE\[0\]' \
|
||||||
'C 0,2 data=\(1,1,!\) flags=NONE\[0\]'
|
'C 0,2 data=\(1,1,!\) flags=NONE\[0\]'
|
||||||
|
|
||||||
start_pane variation 10 3 '*\357\270\217!'
|
start_pane variation 10 3 '*\357\270\217!'
|
||||||
check_raw_matches variation \
|
check_raw_matches variation \
|
||||||
'L 0 \(0\) flags=EXTENDED\[[0-9a-f]+\]' \
|
'L 0 \(0\) flags=EXTENDED\[[0-9a-f]+\]' \
|
||||||
'C 0,0 data=\(2,[0-9]+,.*\) flags=NONE\[0\] attr=NONE\[0\]' \
|
'C 0,0 data=\(2,[0-9]+,.*\) flags=NONE\[0\] attr=NONE\[0\]' \
|
||||||
'C 0,1 data=\(1,1,!\) flags=PADDING\[[0-9a-f]+\] attr=NONE\[0\]' \
|
'C 0,1 data=\(0,0,\) flags=PADDING\[[0-9a-f]+\] attr=NONE\[0\]' \
|
||||||
'C 0,2 data=\(1,1,!\) flags=NONE\[0\]'
|
'C 0,2 data=\(1,1,!\) flags=NONE\[0\]'
|
||||||
|
|
||||||
start_pane invalid 10 3 '\377A'
|
start_pane invalid 10 3 '\377A'
|
||||||
@@ -69,14 +69,14 @@ check_raw_matches overwrite-wide-pad \
|
|||||||
start_pane overwrite-wide-with-wide 10 3 'A\343\201\202B\r\033[1C\347\225\214'
|
start_pane overwrite-wide-with-wide 10 3 'A\343\201\202B\r\033[1C\347\225\214'
|
||||||
check_raw_matches overwrite-wide-with-wide \
|
check_raw_matches overwrite-wide-with-wide \
|
||||||
'C 0,1 data=\(2,3,界\) flags=NONE\[0\] attr=NONE\[0\]' \
|
'C 0,1 data=\(2,3,界\) flags=NONE\[0\] attr=NONE\[0\]' \
|
||||||
'C 0,2 data=\(1,1,!\) flags=PADDING\[[0-9a-f]+\] attr=NONE\[0\]' \
|
'C 0,2 data=\(0,0,\) flags=PADDING\[[0-9a-f]+\] attr=NONE\[0\]' \
|
||||||
'C 0,3 data=\(1,1,B\) flags=NONE\[0\]'
|
'C 0,3 data=\(1,1,B\) flags=NONE\[0\]'
|
||||||
|
|
||||||
start_pane wide-right-edge 4 3 'ABC\343\201\202Z'
|
start_pane wide-right-edge 4 3 'ABC\343\201\202Z'
|
||||||
check_raw_matches wide-right-edge \
|
check_raw_matches wide-right-edge \
|
||||||
'L 0 \(0\) flags=WRAPPED\[[0-9a-f]+\]' \
|
'L 0 \(0\) flags=WRAPPED\[[0-9a-f]+\]' \
|
||||||
'C 1,0 data=\(2,3,あ\) flags=NONE\[0\] attr=NONE\[0\]' \
|
'C 1,0 data=\(2,3,あ\) flags=NONE\[0\] attr=NONE\[0\]' \
|
||||||
'C 1,1 data=\(1,1,!\) flags=PADDING\[[0-9a-f]+\] attr=NONE\[0\]' \
|
'C 1,1 data=\(0,0,\) flags=PADDING\[[0-9a-f]+\] attr=NONE\[0\]' \
|
||||||
'C 1,2 data=\(1,1,Z\) flags=NONE\[0\]'
|
'C 1,2 data=\(1,1,Z\) flags=NONE\[0\]'
|
||||||
|
|
||||||
exit $exit_status
|
exit $exit_status
|
||||||
|
|||||||
60
regress/input-reflow-wide.sh
Normal file
60
regress/input-reflow-wide.sh
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
# Wide-character padding must not count towards the reflowed line width.
|
||||||
|
|
||||||
|
. ./input-common.inc
|
||||||
|
|
||||||
|
check_reflow()
|
||||||
|
{
|
||||||
|
# Resizing can move the first physical line into history.
|
||||||
|
$TMUX capture-pane -pN"$2" -t "$1:" -S - -E - |
|
||||||
|
normalize_capture >"$TMP"
|
||||||
|
printf '%s\n' "${3:-$text}" >"$EXP"
|
||||||
|
cmp "$TMP" "$EXP" || fail "$1 reflow (width $width, flags -pN$2)"
|
||||||
|
}
|
||||||
|
|
||||||
|
text='中文文档甲 中文文档乙 中文文档丙 中文文档丁 中文文档戊 中文文档己'
|
||||||
|
|
||||||
|
# Default and RGB backgrounds exercise compact and extended padding cells.
|
||||||
|
for padding in compact extended; do
|
||||||
|
style=''
|
||||||
|
if [ "$padding" = extended ]; then
|
||||||
|
style='\033[48;2;1;2;3m'
|
||||||
|
fi
|
||||||
|
width=96
|
||||||
|
start_pane_history "wide-$padding" 96 18 "${style}${text}\\n"
|
||||||
|
check_reflow "wide-$padding" ''
|
||||||
|
for width in 47 96 47 96; do
|
||||||
|
$TMUX resize-window -t "wide-$padding:" -x "$width" -y 18 ||
|
||||||
|
exit 1
|
||||||
|
check_reflow "wide-$padding" J
|
||||||
|
if [ "$width" = 96 ]; then
|
||||||
|
check_reflow "wide-$padding" ''
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
done
|
||||||
|
|
||||||
|
# Include both a split between wide characters and an odd-width boundary.
|
||||||
|
text='中文文档'
|
||||||
|
start_pane_history boundary 8 18 "${text}\\n"
|
||||||
|
for width in 4 8 3 8; do
|
||||||
|
$TMUX resize-window -t boundary: -x "$width" -y 18 || exit 1
|
||||||
|
check_reflow boundary J
|
||||||
|
case "$width" in
|
||||||
|
4)
|
||||||
|
check_reflow boundary '' '中文
|
||||||
|
文档'
|
||||||
|
;;
|
||||||
|
3)
|
||||||
|
check_reflow boundary '' '中
|
||||||
|
文
|
||||||
|
文
|
||||||
|
档'
|
||||||
|
;;
|
||||||
|
8)
|
||||||
|
check_reflow boundary ''
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
exit $exit_status
|
||||||
29
regress/menu-pane-killed.sh
Executable file
29
regress/menu-pane-killed.sh
Executable file
@@ -0,0 +1,29 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
# A menu opened for a pane is drawn again after the pane is killed. Drawing it
|
||||||
|
# must not use the pane. The terminal is a pane of a second server.
|
||||||
|
|
||||||
|
PATH=/bin:/usr/bin
|
||||||
|
TERM=screen
|
||||||
|
|
||||||
|
[ -z "$TEST_TMUX" ] && TEST_TMUX=$(readlink -f ../tmux)
|
||||||
|
TMUX="$TEST_TMUX -Ltest$$ -f/dev/null"
|
||||||
|
TMUX2="$TEST_TMUX -Ltest2$$ -f/dev/null"
|
||||||
|
trap '$TMUX kill-server 2>/dev/null; $TMUX2 kill-server 2>/dev/null' 0 1 15
|
||||||
|
|
||||||
|
$TMUX new -d 'sleep 1000' || exit 1
|
||||||
|
$TMUX2 new -d "unset TMUX; exec $TMUX attach" || exit 1
|
||||||
|
n=0
|
||||||
|
while [ -z "$($TMUX lsc 2>/dev/null)" ]; do
|
||||||
|
n=$((n + 1))
|
||||||
|
[ $n -gt 100 ] && exit 1
|
||||||
|
sleep 0.1
|
||||||
|
done
|
||||||
|
|
||||||
|
P=$($TMUX splitw -d -P -F '#{pane_id}' 'sleep 1000') || exit 1
|
||||||
|
$TMUX display-menu -c "$($TMUX lsc -F '#{client_name}')" -t $P one 1 '' ||
|
||||||
|
exit 1
|
||||||
|
$TMUX kill-pane -t $P
|
||||||
|
sleep 1
|
||||||
|
$TMUX has || { echo "the server died"; exit 1; }
|
||||||
|
exit 0
|
||||||
48
regress/ncv.sh
Normal file
48
regress/ncv.sh
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
# Check that attributes listed in ncv are not used with colours.
|
||||||
|
|
||||||
|
PATH=/bin:/usr/bin
|
||||||
|
TERM=screen
|
||||||
|
LC_ALL=C.UTF-8
|
||||||
|
export TERM LC_ALL
|
||||||
|
|
||||||
|
[ -z "$TEST_TMUX" ] && TEST_TMUX=$(readlink -f ../tmux)
|
||||||
|
TMUX="$TEST_TMUX -LtestA$$ -f/dev/null"
|
||||||
|
TMUX2="$TEST_TMUX -LtestB$$ -f/dev/null"
|
||||||
|
|
||||||
|
fail() {
|
||||||
|
echo "$*" >&2
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
$TMUX kill-server 2>/dev/null
|
||||||
|
$TMUX2 kill-server 2>/dev/null
|
||||||
|
|
||||||
|
TMP=$(mktemp)
|
||||||
|
trap "rm -f $TMP; $TMUX kill-server 2>/dev/null; $TMUX2 kill-server 2>/dev/null" 0 1 15
|
||||||
|
|
||||||
|
$TMUX2 new -d -x20 -y5 \
|
||||||
|
"printf '\033[2;4mPLAIN\033[0m'; exec sleep 100" || exit 1
|
||||||
|
$TMUX2 set -g status-left '' || exit 1
|
||||||
|
$TMUX2 set -g status-right '' || exit 1
|
||||||
|
$TMUX2 set -g status-format[0] \
|
||||||
|
'#[fg=black,bg=green,underscore,dim]MARK' || exit 1
|
||||||
|
$TMUX2 set -as terminal-overrides ',screen:ncv=18' || exit 1
|
||||||
|
|
||||||
|
$TMUX new -d -x20 -y5 || exit 1
|
||||||
|
$TMUX set -g status off || exit 1
|
||||||
|
$TMUX send -l "$TMUX2 attach" || exit 1
|
||||||
|
$TMUX send Enter || exit 1
|
||||||
|
sleep 1
|
||||||
|
|
||||||
|
$TMUX capturep -pe >$TMP || exit 1
|
||||||
|
ESC=$(printf '\033')
|
||||||
|
grep -q "${ESC}\\[30m${ESC}\\[42mMARK" $TMP ||
|
||||||
|
fail "coloured status text missing"
|
||||||
|
grep -q "${ESC}\\[2;4mPLAIN" $TMP ||
|
||||||
|
fail "attributes without colours were filtered"
|
||||||
|
tail -1 $TMP | grep -q "${ESC}\\[4m" && fail "underline not filtered"
|
||||||
|
tail -1 $TMP | grep -q "${ESC}\\[2m" && fail "dim not filtered"
|
||||||
|
|
||||||
|
exit 0
|
||||||
43
regress/session-group-name.sh
Normal file
43
regress/session-group-name.sh
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
# Reusing a session name must not reuse an unrelated session group.
|
||||||
|
|
||||||
|
PATH=/bin:/usr/bin
|
||||||
|
TERM=screen
|
||||||
|
|
||||||
|
[ -z "$TEST_TMUX" ] && TEST_TMUX=$(readlink -f ../tmux)
|
||||||
|
TMUX="$TEST_TMUX -LtestA$$ -f/dev/null"
|
||||||
|
trap '$TMUX kill-server 2>/dev/null' 0 1 15
|
||||||
|
|
||||||
|
$TMUX new -d -s a || exit 1
|
||||||
|
$TMUX new -d -t a -s b || exit 1
|
||||||
|
$TMUX kill-session -t a || exit 1
|
||||||
|
|
||||||
|
# Occupy the first suffix too, without creating a session of that name.
|
||||||
|
$TMUX new -d -t a-1 -s other || exit 1
|
||||||
|
$TMUX new -d -s a || exit 1
|
||||||
|
AW=$($TMUX display -p -t a: '#{window_id}')
|
||||||
|
BW=$($TMUX display -p -t b: '#{window_id}')
|
||||||
|
$TMUX new -d -t a -s c || exit 1
|
||||||
|
|
||||||
|
[ "$($TMUX display -p -t a: '#{session_group}')" = a-2 ] || exit 1
|
||||||
|
[ "$($TMUX display -p -t c: '#{session_group}')" = a-2 ] || exit 1
|
||||||
|
[ "$($TMUX display -p -t b: '#{session_group_list}')" = b ] || exit 1
|
||||||
|
[ "$($TMUX display -p -t a: '#{window_id}')" = "$AW" ] || exit 1
|
||||||
|
[ "$($TMUX display -p -t c: '#{window_id}')" = "$AW" ] || exit 1
|
||||||
|
[ "$AW" != "$BW" ] || exit 1
|
||||||
|
|
||||||
|
# Window changes propagate only within the new group.
|
||||||
|
$TMUX new-window -d -t a || exit 1
|
||||||
|
[ "$($TMUX display -p -t c: '#{session_windows}')" = 2 ] || exit 1
|
||||||
|
[ "$($TMUX display -p -t b: '#{session_windows}')" = 1 ] || exit 1
|
||||||
|
|
||||||
|
# An existing session still joins its group; a group-only target still works.
|
||||||
|
$TMUX new -d -t c -s d || exit 1
|
||||||
|
[ "$($TMUX display -p -t d: '#{session_group}')" = a-2 ] || exit 1
|
||||||
|
$TMUX new -d -t a-1 -s e || exit 1
|
||||||
|
[ "$($TMUX display -p -t e: '#{session_group}')" = a-1 ] || exit 1
|
||||||
|
[ "$($TMUX display -p -t e: '#{window_id}')" = \
|
||||||
|
"$($TMUX display -p -t other: '#{window_id}')" ] || exit 1
|
||||||
|
|
||||||
|
exit 0
|
||||||
101
regress/tty-keys-backtab.sh
Normal file
101
regress/tty-keys-backtab.sh
Normal file
@@ -0,0 +1,101 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
# Extended Shift+Tab must remain BackTab when the pane does not request
|
||||||
|
# modifyOtherKeys=2, including when the input carries implied Meta.
|
||||||
|
|
||||||
|
PATH=/bin:/usr/bin
|
||||||
|
TERM=screen
|
||||||
|
export PATH TERM
|
||||||
|
|
||||||
|
[ -z "$TEST_TMUX" ] && TEST_TMUX=$(readlink -f ../tmux)
|
||||||
|
INNER="$TEST_TMUX -LtestI$$ -f/dev/null"
|
||||||
|
OUTER="$TEST_TMUX -LtestO$$ -f/dev/null"
|
||||||
|
|
||||||
|
fail()
|
||||||
|
{
|
||||||
|
echo "$*" >&2
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
cleanup()
|
||||||
|
{
|
||||||
|
$OUTER kill-server 2>/dev/null
|
||||||
|
$INNER kill-server 2>/dev/null
|
||||||
|
}
|
||||||
|
trap cleanup 0
|
||||||
|
trap 'exit 1' 1 2 15
|
||||||
|
|
||||||
|
$INNER new-session -d -s inner -x80 -y24 \
|
||||||
|
'stty raw -echo; exec cat -tv' || exit 1
|
||||||
|
$INNER set-option -g status off || exit 1
|
||||||
|
$INNER set-option -g assume-paste-time 0 || exit 1
|
||||||
|
$INNER set-option -s extended-keys on || exit 1
|
||||||
|
$INNER set-option -s escape-time 1000 || exit 1
|
||||||
|
$INNER unbind-key -a -T root || exit 1
|
||||||
|
$OUTER new-session -d -s outer -x80 -y24 "$INNER attach -t inner" ||
|
||||||
|
exit 1
|
||||||
|
$OUTER set-option -g assume-paste-time 0 || exit 1
|
||||||
|
|
||||||
|
i=0
|
||||||
|
while [ -z "$($INNER list-clients -F '#{client_name}')" ]; do
|
||||||
|
[ "$i" -lt 100 ] || fail 'inner client did not attach'
|
||||||
|
sleep 0.05
|
||||||
|
i=$((i + 1))
|
||||||
|
done
|
||||||
|
|
||||||
|
expected_output=
|
||||||
|
|
||||||
|
assert_key()
|
||||||
|
{
|
||||||
|
name=$1
|
||||||
|
expected_output=$expected_output$2
|
||||||
|
bytes=$(printf '%s' "$3" | od -An -v -tx1)
|
||||||
|
$OUTER send-keys -H $bytes || exit 1
|
||||||
|
i=0
|
||||||
|
while [ "$i" -lt 100 ]; do
|
||||||
|
actual=$($INNER capture-pane -p | tr -d '\n')
|
||||||
|
[ "$actual" = "$expected_output" ] && return 0
|
||||||
|
sleep 0.05
|
||||||
|
i=$((i + 1))
|
||||||
|
done
|
||||||
|
fail "$name: got '$actual', expected '$expected_output'"
|
||||||
|
}
|
||||||
|
|
||||||
|
pane_state='#{pane_key_mode}:#{pane_current_command}'
|
||||||
|
for mode in 0 1 2; do
|
||||||
|
for format in xterm csi-u; do
|
||||||
|
$INNER new-window \
|
||||||
|
"printf '\033[>4;${mode}m'; stty raw -echo; exec cat -tv" ||
|
||||||
|
exit 1
|
||||||
|
key_mode="Ext $mode"
|
||||||
|
[ "$mode" -eq 0 ] && key_mode=VT10x
|
||||||
|
i=0
|
||||||
|
while [ "$($INNER display-message -p "$pane_state")" != \
|
||||||
|
"$key_mode:cat" ]; do
|
||||||
|
[ "$i" -lt 100 ] || fail "pane did not enter mode $mode"
|
||||||
|
sleep 0.05
|
||||||
|
i=$((i + 1))
|
||||||
|
done
|
||||||
|
$INNER set-option -s extended-keys-format "$format" || exit 1
|
||||||
|
expected_output=
|
||||||
|
# Every modifier combination containing Shift.
|
||||||
|
for modifier in 2 4 6 8; do
|
||||||
|
if [ "$mode" -eq 2 ]; then
|
||||||
|
if [ "$format" = xterm ]; then
|
||||||
|
expected="^[[27;${modifier};9~"
|
||||||
|
else
|
||||||
|
expected="^[[9;${modifier}u"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
expected='^[[Z'
|
||||||
|
fi
|
||||||
|
case_name="mode $mode, $format, modifier $modifier"
|
||||||
|
assert_key "$case_name, CSI u input" "$expected" \
|
||||||
|
"$(printf '\033[9;%su' "$modifier")"
|
||||||
|
assert_key "$case_name, xterm input" "$expected" \
|
||||||
|
"$(printf '\033[27;%s;9~' "$modifier")"
|
||||||
|
done
|
||||||
|
done
|
||||||
|
done
|
||||||
|
|
||||||
|
exit 0
|
||||||
@@ -43,8 +43,22 @@ def matches(name, value):
|
|||||||
return "ignorefkeys" in features
|
return "ignorefkeys" in features
|
||||||
if name == "XDA":
|
if name == "XDA":
|
||||||
return kind == "ReplyTest"
|
return kind == "ReplyTest"
|
||||||
if name == "XDA-kitty":
|
if name in ("XDA-kitty", "XDA-kitty-nosync"):
|
||||||
return kind == "kitty(0.43.0)" and "kitty" in features
|
required = {
|
||||||
|
"256", "RGB", "bpaste", "clipboard", "mouse",
|
||||||
|
"strikethrough", "title", "ccolour", "cstyle", "extkeys",
|
||||||
|
"focus", "hyperlinks", "osc7", "usstyle", "kittygraphics"}
|
||||||
|
if name == "XDA-kitty":
|
||||||
|
required.add("sync")
|
||||||
|
elif "sync" in features:
|
||||||
|
return False
|
||||||
|
return kind == "kitty(0.43.0)" and required <= features
|
||||||
|
if name == "XDA-ghostty":
|
||||||
|
return kind == "ghostty 1.2.0" and {
|
||||||
|
"kittygraphics", "margins", "sync", "usstyle", "progressbar"} <= features
|
||||||
|
if name == "XDA-WezTerm":
|
||||||
|
return kind == "WezTerm 20240203-110809-5046fc22" and {
|
||||||
|
"sixel", "margins", "usstyle"} <= features
|
||||||
if name == "sync":
|
if name == "sync":
|
||||||
return "sync" in features
|
return "sync" in features
|
||||||
if name == "characters":
|
if name == "characters":
|
||||||
@@ -57,6 +71,9 @@ reports = [
|
|||||||
("DA2", b"\033[>85;1;0c"),
|
("DA2", b"\033[>85;1;0c"),
|
||||||
("XDA", b"\033P>|ReplyTest\033\\"),
|
("XDA", b"\033P>|ReplyTest\033\\"),
|
||||||
("XDA-kitty", b"\033P>|kitty(0.43.0)\033\\"),
|
("XDA-kitty", b"\033P>|kitty(0.43.0)\033\\"),
|
||||||
|
("XDA-kitty-nosync", b"\033P>|kitty(0.43.0)\033\\"),
|
||||||
|
("XDA-ghostty", b"\033P>|ghostty 1.2.0\033\\"),
|
||||||
|
("XDA-WezTerm", b"\033P>|WezTerm 20240203-110809-5046fc22\033\\"),
|
||||||
("sync", b"\033[?2026;2$y"),
|
("sync", b"\033[?2026;2$y"),
|
||||||
("characters", b"\033[8;17;61t"),
|
("characters", b"\033[8;17;61t"),
|
||||||
("pixels", b"\033[4;480;800t"),
|
("pixels", b"\033[4;480;800t"),
|
||||||
@@ -83,6 +100,8 @@ for name, report in reports:
|
|||||||
else:
|
else:
|
||||||
run("set-option", "-s", "escape-time", "60000")
|
run("set-option", "-s", "escape-time", "60000")
|
||||||
run("set-option", "-g", "@seen", "")
|
run("set-option", "-g", "@seen", "")
|
||||||
|
if name == "XDA-kitty-nosync":
|
||||||
|
run("set-option", "-as", "terminal-features", ",*:sync@")
|
||||||
run("bind-key", "-n", "Escape", "set-option", "-gF",
|
run("bind-key", "-n", "Escape", "set-option", "-gF",
|
||||||
"@seen", "#{@seen}E")
|
"@seen", "#{@seen}E")
|
||||||
pid, fd = os.forkpty()
|
pid, fd = os.forkpty()
|
||||||
@@ -143,6 +162,12 @@ for name, report in reports:
|
|||||||
assert actual == baseline, (context, "unexpected effect", actual)
|
assert actual == baseline, (context, "unexpected effect", actual)
|
||||||
else:
|
else:
|
||||||
assert matches(name, actual), (context, "missing effect", actual)
|
assert matches(name, actual), (context, "missing effect", actual)
|
||||||
|
if name in ("XDA-kitty", "XDA-kitty-nosync", "XDA-ghostty"):
|
||||||
|
assert run("display-message", "-p", "#{I/f:kittygraphics}") == "1", (
|
||||||
|
context, "kittygraphics feature lookup failed")
|
||||||
|
if name == "XDA-kitty-nosync":
|
||||||
|
assert run("display-message", "-p", "#{I/f:sync}") == "0", (
|
||||||
|
context, "kitty enabled synchronized updates")
|
||||||
assert run("show-option", "-gv", "@seen") == (
|
assert run("show-option", "-gv", "@seen") == (
|
||||||
"E" if prefixed else ""), (context, "Escape count")
|
"E" if prefixed else ""), (context, "Escape count")
|
||||||
cases += 1
|
cases += 1
|
||||||
|
|||||||
30
resize.c
30
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 <nicholas.marriott@gmail.com>
|
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||||
@@ -159,8 +159,10 @@ clients_calculate_size(int type, int current, struct client *c,
|
|||||||
*/
|
*/
|
||||||
*xpixel = w->xpixel;
|
*xpixel = w->xpixel;
|
||||||
*ypixel = w->ypixel;
|
*ypixel = w->ypixel;
|
||||||
} else
|
} else {
|
||||||
*xpixel = *ypixel = 0;
|
*xpixel = 0;
|
||||||
|
*ypixel = 0;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* For latest, count the number of clients with this window. We only
|
* For latest, count the number of clients with this window. We only
|
||||||
@@ -388,21 +390,31 @@ recalculate_size(struct window *w, int now)
|
|||||||
/* Look for a suitable client and get the new size. */
|
/* Look for a suitable client and get the new size. */
|
||||||
changed = clients_calculate_size(type, current, NULL, NULL, w,
|
changed = clients_calculate_size(type, current, NULL, NULL, w,
|
||||||
recalculate_size_skip_client, &sx, &sy, &xpixel, &ypixel);
|
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
|
* Make sure the size has actually changed. If the window has already
|
||||||
* got a resize scheduled, then use the new size; otherwise the old.
|
* got a resize scheduled, then use the new size; otherwise the old.
|
||||||
*/
|
*/
|
||||||
if (w->flags & WINDOW_RESIZE) {
|
if (w->flags & WINDOW_RESIZE) {
|
||||||
if (!now && changed && w->new_sx == sx && w->new_sy == sy &&
|
if (!now &&
|
||||||
w->new_xpixel == xpixel && w->new_ypixel == ypixel) {
|
changed &&
|
||||||
|
w->new_sx == sx &&
|
||||||
|
w->new_sy == sy &&
|
||||||
|
w->new_xpixel == xpixel &&
|
||||||
|
w->new_ypixel == ypixel)
|
||||||
changed = 0;
|
changed = 0;
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
if (!now && changed && w->sx == sx && w->sy == sy &&
|
if (!now &&
|
||||||
w->xpixel == xpixel && w->ypixel == ypixel) {
|
changed &&
|
||||||
|
w->sx == sx &&
|
||||||
|
w->sy == sy &&
|
||||||
|
w->xpixel == xpixel &&
|
||||||
|
w->ypixel == ypixel)
|
||||||
changed = 0;
|
changed = 0;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
6
screen.c
6
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 <nicholas.marriott@gmail.com>
|
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||||
@@ -716,6 +716,10 @@ screen_alternate_off(struct screen *s, struct grid_cell *gc, int cursor)
|
|||||||
return 0;
|
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. */
|
/* Restore the saved grid. */
|
||||||
grid_duplicate_lines(s->grid, screen_hsize(s), s->saved_grid, 0,
|
grid_duplicate_lines(s->grid, screen_hsize(s), s->saved_grid, 0,
|
||||||
s->saved_grid->sy);
|
s->saved_grid->sy);
|
||||||
|
|||||||
@@ -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 <nicholas.marriott@gmail.com>
|
* Copyright (c) 2009 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||||
@@ -2599,7 +2599,7 @@ server_client_dispatch(struct imsg *imsg, void *arg)
|
|||||||
if (datalen != 0)
|
if (datalen != 0)
|
||||||
goto bad;
|
goto bad;
|
||||||
|
|
||||||
if (c->flags & CLIENT_CONTROL)
|
if ((c->flags & CLIENT_CONTROL) || (~c->tty.flags & TTY_OPENED))
|
||||||
break;
|
break;
|
||||||
server_client_update_latest(c);
|
server_client_update_latest(c);
|
||||||
old_sx = c->tty.sx;
|
old_sx = c->tty.sx;
|
||||||
|
|||||||
9
tmux.1
9
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 <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 9 2026 $
|
.Dd $Mdocdate: October 12 2026 $
|
||||||
.Dt TMUX 1
|
.Dt TMUX 1
|
||||||
.Os
|
.Os
|
||||||
.Sh NAME
|
.Sh NAME
|
||||||
@@ -5206,8 +5206,8 @@ Ignore function keys from
|
|||||||
and use the
|
and use the
|
||||||
.Nm
|
.Nm
|
||||||
internal set only.
|
internal set only.
|
||||||
.It kitty
|
.It kittygraphics
|
||||||
Supports the Kitty graphics protocol.
|
Supports the Kitty graphics protocol with Unicode placeholders.
|
||||||
.It margins
|
.It margins
|
||||||
Supports DECSLRM margins.
|
Supports DECSLRM margins.
|
||||||
.It mouse
|
.It mouse
|
||||||
@@ -7632,7 +7632,6 @@ The following variables are available, where appropriate:
|
|||||||
.It Li "session_stack" Ta "" Ta "Window indexes in most recent order"
|
.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 "session_windows" Ta "" Ta "Number of windows in session"
|
||||||
.It Li "socket_path" Ta "" Ta "Server socket path"
|
.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 "start_time" Ta "" Ta "Server start time"
|
||||||
.It Li "synchronized_output_flag" Ta "" Ta "1 if pane has synchronized output enabled"
|
.It Li "synchronized_output_flag" Ta "" Ta "1 if pane has synchronized output enabled"
|
||||||
.It Li "uid" Ta "" Ta "Server UID"
|
.It Li "uid" Ta "" Ta "Server UID"
|
||||||
|
|||||||
7
tmux.h
7
tmux.h
@@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: tmux.h,v 1.1455 2026/10/09 13:12:14 nicm Exp $ */
|
/* $OpenBSD: tmux.h,v 1.1457 2026/10/12 12:35:03 nicm Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
|
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||||
@@ -643,6 +643,7 @@ enum tty_code_code {
|
|||||||
TTYC_KUP6,
|
TTYC_KUP6,
|
||||||
TTYC_KUP7,
|
TTYC_KUP7,
|
||||||
TTYC_MS,
|
TTYC_MS,
|
||||||
|
TTYC_NCV,
|
||||||
TTYC_NOBR,
|
TTYC_NOBR,
|
||||||
TTYC_OL,
|
TTYC_OL,
|
||||||
TTYC_OP,
|
TTYC_OP,
|
||||||
@@ -1871,8 +1872,8 @@ struct tty_term {
|
|||||||
#define TERM_VT100LIKE 0x20
|
#define TERM_VT100LIKE 0x20
|
||||||
#define TERM_SIXEL 0x40
|
#define TERM_SIXEL 0x40
|
||||||
#define TERM_INVALIDMS 0x80
|
#define TERM_INVALIDMS 0x80
|
||||||
#define TERM_KITTY 0x100
|
#define TERM_NOREPLACE 0x100
|
||||||
#define TERM_NOREPLACE 0x200
|
#define TERM_KITTYGRAPHICS 0x200
|
||||||
#ifdef ENABLE_IMAGES
|
#ifdef ENABLE_IMAGES
|
||||||
#define TERM_IMAGE_QUADRANTS 0x400
|
#define TERM_IMAGE_QUADRANTS 0x400
|
||||||
#define TERM_IMAGE_SEXTANTS 0x800
|
#define TERM_IMAGE_SEXTANTS 0x800
|
||||||
|
|||||||
@@ -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 <nicholas.marriott@gmail.com>
|
* Copyright (c) 2020 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||||
@@ -236,11 +236,9 @@ static const struct tty_feature tty_feature_strikethrough = {
|
|||||||
0
|
0
|
||||||
};
|
};
|
||||||
|
|
||||||
#define TTY_FEATURE_SYNC "Sync=\\E[?2026%?%p1%{1}%-%tl%eh%;"
|
|
||||||
|
|
||||||
/* Terminal supports synchronized updates. */
|
/* Terminal supports synchronized updates. */
|
||||||
static const char *const tty_feature_sync_capabilities[] = {
|
static const char *const tty_feature_sync_capabilities[] = {
|
||||||
TTY_FEATURE_SYNC,
|
"Sync=\\E[?2026%?%p1%{1}%-%tl%eh%;",
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
static const struct tty_feature tty_feature_sync = {
|
static const struct tty_feature tty_feature_sync = {
|
||||||
@@ -371,16 +369,11 @@ static const struct tty_feature tty_feature_sixel = {
|
|||||||
TERM_SIXEL
|
TERM_SIXEL
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Terminal has Kitty graphics protocol Unicode placeholder capability. */
|
/* Terminal supports Kitty graphics Unicode placeholders. */
|
||||||
static const char *const tty_feature_kitty_capabilities[] = {
|
static const struct tty_feature tty_feature_kittygraphics = {
|
||||||
"Kty",
|
"kittygraphics",
|
||||||
TTY_FEATURE_SYNC,
|
NULL,
|
||||||
NULL
|
TERM_KITTYGRAPHICS
|
||||||
};
|
|
||||||
static const struct tty_feature tty_feature_kitty = {
|
|
||||||
"kitty",
|
|
||||||
tty_feature_kitty_capabilities,
|
|
||||||
TERM_KITTY
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef ENABLE_IMAGES
|
#ifdef ENABLE_IMAGES
|
||||||
@@ -439,7 +432,7 @@ static const struct tty_feature *const tty_features[] = {
|
|||||||
&tty_feature_extkeys,
|
&tty_feature_extkeys,
|
||||||
&tty_feature_focus,
|
&tty_feature_focus,
|
||||||
&tty_feature_ignorefkeys,
|
&tty_feature_ignorefkeys,
|
||||||
&tty_feature_kitty,
|
&tty_feature_kittygraphics,
|
||||||
#ifdef ENABLE_IMAGES
|
#ifdef ENABLE_IMAGES
|
||||||
&tty_feature_image_quadrants,
|
&tty_feature_image_quadrants,
|
||||||
&tty_feature_image_sextants,
|
&tty_feature_image_sextants,
|
||||||
@@ -702,7 +695,7 @@ tty_default_features(struct client *c, const char *name, u_int version)
|
|||||||
"sync,"
|
"sync,"
|
||||||
"usstyle,"
|
"usstyle,"
|
||||||
"progressbar,"
|
"progressbar,"
|
||||||
"kitty"
|
"kittygraphics"
|
||||||
},
|
},
|
||||||
{ .name = "kitty",
|
{ .name = "kitty",
|
||||||
.features = TTY_FEATURES_BASE_MODERN_XTERM ","
|
.features = TTY_FEATURES_BASE_MODERN_XTERM ","
|
||||||
@@ -715,7 +708,7 @@ tty_default_features(struct client *c, const char *name, u_int version)
|
|||||||
"osc7,"
|
"osc7,"
|
||||||
"sync,"
|
"sync,"
|
||||||
"usstyle,"
|
"usstyle,"
|
||||||
"kitty"
|
"kittygraphics"
|
||||||
},
|
},
|
||||||
{ .name = "Rio",
|
{ .name = "Rio",
|
||||||
.features = TTY_FEATURES_BASE_MODERN_XTERM ","
|
.features = TTY_FEATURES_BASE_MODERN_XTERM ","
|
||||||
|
|||||||
@@ -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 <nicholas.marriott@gmail.com>
|
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: tty-term.c,v 1.111 2026/09/22 14:10:26 nicm Exp $ */
|
/* $OpenBSD: tty-term.c,v 1.112 2026/10/12 10:39:05 nicm Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2008 Nicholas Marriott <nicholas.marriott@gmail.com>
|
* Copyright (c) 2008 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||||
@@ -254,6 +254,7 @@ static const struct tty_term_code_entry tty_term_codes[] = {
|
|||||||
[TTYC_KUP6] = { TTYCODE_STRING, "kUP6" },
|
[TTYC_KUP6] = { TTYCODE_STRING, "kUP6" },
|
||||||
[TTYC_KUP7] = { TTYCODE_STRING, "kUP7" },
|
[TTYC_KUP7] = { TTYCODE_STRING, "kUP7" },
|
||||||
[TTYC_MS] = { TTYCODE_STRING, "Ms" },
|
[TTYC_MS] = { TTYCODE_STRING, "Ms" },
|
||||||
|
[TTYC_NCV] = { TTYCODE_NUMBER, "ncv" },
|
||||||
[TTYC_NOBR] = { TTYCODE_STRING, "Nobr" },
|
[TTYC_NOBR] = { TTYCODE_STRING, "Nobr" },
|
||||||
[TTYC_OL] = { TTYCODE_STRING, "ol" },
|
[TTYC_OL] = { TTYCODE_STRING, "ol" },
|
||||||
[TTYC_OP] = { TTYCODE_STRING, "op" },
|
[TTYC_OP] = { TTYCODE_STRING, "op" },
|
||||||
|
|||||||
31
tty.c
31
tty.c
@@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: tty.c,v 1.485 2026/10/07 07:34:59 nicm Exp $ */
|
/* $OpenBSD: tty.c,v 1.486 2026/10/12 10:39:05 nicm Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
|
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||||
@@ -51,6 +51,7 @@ static void tty_check_bg(struct tty *, struct colour_palette *,
|
|||||||
struct grid_cell *);
|
struct grid_cell *);
|
||||||
static void tty_check_us(struct tty *, struct colour_palette *,
|
static void tty_check_us(struct tty *, struct colour_palette *,
|
||||||
struct grid_cell *);
|
struct grid_cell *);
|
||||||
|
static void tty_check_ncv(struct tty *, struct grid_cell *);
|
||||||
static int tty_map_theme_colour(struct tty *, int);
|
static int tty_map_theme_colour(struct tty *, int);
|
||||||
static void tty_colours_fg(struct tty *, const struct grid_cell *);
|
static void tty_colours_fg(struct tty *, const struct grid_cell *);
|
||||||
static void tty_colours_bg(struct tty *, const struct grid_cell *);
|
static void tty_colours_bg(struct tty *, const struct grid_cell *);
|
||||||
@@ -2425,6 +2426,33 @@ tty_dim_default_colour(struct tty *tty, int c, int foreground)
|
|||||||
return (c);
|
return (c);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
tty_check_ncv(struct tty *tty, struct grid_cell *gc)
|
||||||
|
{
|
||||||
|
int n;
|
||||||
|
|
||||||
|
if (COLOUR_DEFAULT(gc->fg) && COLOUR_DEFAULT(gc->bg))
|
||||||
|
return;
|
||||||
|
|
||||||
|
n = tty_term_number(tty->term, TTYC_NCV);
|
||||||
|
if (n & 2)
|
||||||
|
gc->attr &= ~GRID_ATTR_ALL_UNDERSCORE;
|
||||||
|
if (n & 4)
|
||||||
|
gc->attr &= ~GRID_ATTR_REVERSE;
|
||||||
|
if (n & 8)
|
||||||
|
gc->attr &= ~GRID_ATTR_BLINK;
|
||||||
|
if (n & 16)
|
||||||
|
gc->attr &= ~GRID_ATTR_DIM;
|
||||||
|
if (n & 32)
|
||||||
|
gc->attr &= ~GRID_ATTR_BRIGHT;
|
||||||
|
if (n & 64)
|
||||||
|
gc->attr &= ~GRID_ATTR_HIDDEN;
|
||||||
|
if (n & 256)
|
||||||
|
gc->attr &= ~GRID_ATTR_CHARSET;
|
||||||
|
if (n & 32768)
|
||||||
|
gc->attr &= ~GRID_ATTR_ITALICS;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
tty_attributes(struct tty *tty, const struct grid_cell *gc,
|
tty_attributes(struct tty *tty, const struct grid_cell *gc,
|
||||||
const struct tty_style_ctx *style_ctx)
|
const struct tty_style_ctx *style_ctx)
|
||||||
@@ -2495,6 +2523,7 @@ tty_attributes(struct tty *tty, const struct grid_cell *gc,
|
|||||||
tty_check_fg(tty, palette, &gc2);
|
tty_check_fg(tty, palette, &gc2);
|
||||||
tty_check_bg(tty, palette, &gc2);
|
tty_check_bg(tty, palette, &gc2);
|
||||||
tty_check_us(tty, palette, &gc2);
|
tty_check_us(tty, palette, &gc2);
|
||||||
|
tty_check_ncv(tty, &gc2);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If any bits are being cleared or the underline colour is now default,
|
* If any bits are being cleared or the underline colour is now default,
|
||||||
|
|||||||
@@ -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 <nicholas.marriott@gmail.com>
|
* Copyright (c) 2017 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||||
@@ -89,19 +89,20 @@ static const char *window_client_info_lines[] = {
|
|||||||
" #[#{E:tree-mode-border-style},acs]x#[default] "
|
" #[#{E:tree-mode-border-style},acs]x#[default] "
|
||||||
WINDOW_CLIENT_FEATURE(hyperlinks) " "
|
WINDOW_CLIENT_FEATURE(hyperlinks) " "
|
||||||
WINDOW_CLIENT_FEATURE(ignorefkeys) " "
|
WINDOW_CLIENT_FEATURE(ignorefkeys) " "
|
||||||
WINDOW_CLIENT_FEATURE(margins) " "
|
WINDOW_CLIENT_FEATURE(kittygraphics) " "
|
||||||
WINDOW_CLIENT_FEATURE(mouse),
|
WINDOW_CLIENT_FEATURE(margins),
|
||||||
" #[#{E:tree-mode-border-style},acs]x#[default] "
|
" #[#{E:tree-mode-border-style},acs]x#[default] "
|
||||||
|
WINDOW_CLIENT_FEATURE(mouse) " "
|
||||||
WINDOW_CLIENT_FEATURE(osc7) " "
|
WINDOW_CLIENT_FEATURE(osc7) " "
|
||||||
WINDOW_CLIENT_FEATURE(overline) " "
|
WINDOW_CLIENT_FEATURE(overline) " "
|
||||||
WINDOW_CLIENT_FEATURE(progressbar) " "
|
WINDOW_CLIENT_FEATURE(progressbar),
|
||||||
WINDOW_CLIENT_FEATURE(rectfill),
|
|
||||||
" #[#{E:tree-mode-border-style},acs]x#[default] "
|
" #[#{E:tree-mode-border-style},acs]x#[default] "
|
||||||
|
WINDOW_CLIENT_FEATURE(rectfill) " "
|
||||||
WINDOW_CLIENT_FEATURE(sixel) " "
|
WINDOW_CLIENT_FEATURE(sixel) " "
|
||||||
WINDOW_CLIENT_FEATURE(strikethrough) " "
|
WINDOW_CLIENT_FEATURE(strikethrough) " "
|
||||||
WINDOW_CLIENT_FEATURE(sync) " "
|
WINDOW_CLIENT_FEATURE(sync),
|
||||||
WINDOW_CLIENT_FEATURE(title),
|
|
||||||
" #[#{E:tree-mode-border-style},acs]x#[default] "
|
" #[#{E:tree-mode-border-style},acs]x#[default] "
|
||||||
|
WINDOW_CLIENT_FEATURE(title) " "
|
||||||
WINDOW_CLIENT_FEATURE(usstyle) " "
|
WINDOW_CLIENT_FEATURE(usstyle) " "
|
||||||
WINDOW_CLIENT_FEATURE(utf8),
|
WINDOW_CLIENT_FEATURE(utf8),
|
||||||
"#[#{E:tree-mode-border-style},acs]qqqqqqqqqqqqqqn#{R:q,#{window_width}}#[default]",
|
"#[#{E:tree-mode-border-style},acs]qqqqqqqqqqqqqqn#{R:q,#{window_width}}#[default]",
|
||||||
|
|||||||
Reference in New Issue
Block a user