Merge changes from master.

This commit is contained in:
Michael Grant
2025-12-08 14:30:57 +00:00
29 changed files with 536 additions and 176 deletions

239
CHANGES
View File

@@ -1,3 +1,242 @@
CHANGES FROM 3.6 TO 3.6a
* Fix a buffer overread and an infinite loop in format processing (reported by
Giorgi Kobakhia, issue 4735).
* Allow drag in alternate screen again (issue 4743 reported by Brad King).
* Fix y offset of mouse if status at top (issue 4738 from Michael Grant).
* Add a missing skin tone (from Jake Stewart, issue 4736).
* Allow characters to be combined in either order (issue 4726, reported by Jake
Stewart).
* Fix horizontal mouse resizing when pane status lines are on (from Michael
Grant, issue 4720).
* Fix noattr so it does not delete attributes set in the style itself (issue
4713).
* Newer libevents do not allow event_del on a zero'd event (issue 4706).
* Place cursor on correct line if message-line is not 0 (issue 4707).
* Fix compile error on FreeBSD (from Yasuhiro Kimura, issue 4701).
CHANGES FROM 3.5a TO 3.6
* Add seconds options for clock mode (issue 4697).
* Add a resize callback for menus so that they are correctly moved on resize
(issue 4696).
* Make -v to source-file pass through to subsequent source-file commands (issue
4216).
* If display-popup is used inside a popup, modify that popup (issue 4678).
* Add selection-mode command to expilcitly set the selection mode in copy mode
(issue 3842).
* Save and restore images in alternate screen (issue 3732).
* Ignore Hangul filler character (issue 3998).
* Improve handling of regional indicators and emoji modifiers (issue 3998).
* Preserve marked pane with swap-window and move-window (issue 3443).
* Set and check COLORTERM as a hint for RGB colour.
* If tmux receives a palette request (OSC 4) in a pane and the palette entry
has not been set, send a request to the most recently used client and
forward any response instead (based on change from Tim Culverhouse, issue
4665).
* Add -l flag to command-prompt to disable splitting into multiple prompts
(issue 4483).
* Don't enter copy mode on mouse wheel in alternate screen (issue 3705).
* Add commands to centre the cursor in copy mode (issue 4662).
* Support case insensitive search in modes in the same way as copy mode
(like emacs, so all-lowercase means case insensitive) (issue 4396).
* Fix the logic of the no-detached case for the detach-on-destroy option (from
Martin Louazel, issue 4649).
* Add buffer_full format variable (from Mohammad AlSaleh, issue 4630).
* Introduce a new window option, tiled-layout-max-columns, which configures the
maximum number of columns in the tiled layout.
* Add support for DECRQSS SP q (report cursor style), DECRQM ?12 (report cursor
blink state) and DECRQM ?2004, ?1004, ?1006 (report mouse state) ( rom
Andrea Alberti, issue 4618).
* Fix missing argument from OSC 4 reply (issue 4596).
* Add -k flag to display-popup which allows any key to dismiss the popup once
the command has exited (from Meriel Luna Mittelbach, issue 4612).
* Add nicer default second and third status lines (from Michael Grant, issue
4490).
* Add a pane-border-lines "spaces" value to use spaces for pane borders (issue
4587).
* Replace invalid UTF-8 characters with the placeholder instead of ignoring
them (issue 4514).
* Fix incorrect handling of Korean Hangul Jamo characters (from Roy Jung, issue
4546).
* Allow uppercase letters in gray/grey color names (from Pavel Roskin, issue
4560).
* Add sorting to W, P, L loop operators (from Michael Grant, issue 4516).
* Detect support for OSC 52 using the device attributes report (from James
Holderness, issue 4539).
* Add noattr for styles and use in mode-style to allow whether attributes are
ignored or used to be configured (issue 4498).
* Add a set-default style attribute which replaces the current default colours
and attributes completely.
* Add -E to run-shell to forward stderr as well as stdout (issue 4246).
* Add an option variation-selector-always-wide to instruct tmux not to
always interpret VS16 as a wide character and assume the terminal does
likewise.
* Switch to getopt_long from OpenSSH (from Koichi Murase, issue 4492).
* Add more features for boolean expressions in formats: 1) extend && and || to
support arbitrarily many arguments and 2) add ! and !! for not and not-not
(from David Mandelberg).
* Do not mistake other DCS sequences for SIXEL sequences (from James
Holderness, issue 4488).
* Improve #? conditional expression in formats: add support for else if and
default empty string if no else value (from David Mandelberg, issue 4451).
* Add default-client-command to set the command used if tmux is run without a
command; the default stays new-session (from David Mandelberg, issue
4422).
* Add S-Up and S-Down to move windows in tree mode (from David Mandelberg,
issue 4415).
* Add mode 2031 support to automatically report dark or light theme. tmux will
guess the theme from the background colour on terminals which do not
themselves support the escape sequence (from Jonathan Slenders, issue 4353).
* Add -M flag to capture-pane to use the copy mode screen (issue 4358).
* Align index numbers in trees (from David Mandelberg, issue 4360).
* Add display-message -C flag to update pane while message is displayed (from
Vitaly Ostrosablin, issue 4363).
* Make list-commands command show only one command if an argument is given
(from Ilya Grigoriev, issue 4352).
* Count line numbers correctly inside strings in configuration files (reported
by Pedro Navarro, issue 4325).
* Map bright black (colour 8) to white (7) if the background is black on
terminals with only eight colours so the text is not invisible (from Dmytro
Bagrii, issue 4322).
* New codepoint-widths option allowing users to override the width of
individual Unicode codepoints.
* Add a nesting limit to source-file (from Fadi Afani, issue 4223).
* Add copy-mode-position-style and copy-mode-selection-style options for copy
mode.
* Add no-detach-on-destroy client option (issue 4242).
* Add input-buffer-size option (from Ken Lau).
* Add support for a scrollbar at the side of each pane. New options
pane-scrollbars turn them on or off, pane-scrollbars-position sets the
position (left or right), and pane-scrollbars-style to set the colours (from
Michael Grant, issue 4221).
* Allow control characters to be entered at the command prompt by prefixing
with C-v (from Alexander Arch, issue 4206).
* Do not attempt to search for zero length strings (from Alexander Arch, issue
4209).
* Preserve tabs for copying and capture-pane (from Alexander Arch, issue
4201).
* Increase the maximum for repeat-time.
* Adjust how Ctrl and Meta keys are sent to use standard representation if
available in mode 1 (from Stanislav Kljuhhin, issue 4188).
* Allow attributes in menu style (from Japin Li, issue 4194).
* Add a sixel_support format variable which is 1 if SIXEL is supported, always
0 on OpenBSD (requested by Misaki Masa, issue 4177).
* Add prompt-cursor-colour and prompt-cursor-style to set the style of the
cursor in the command prompt and remove the emulated cursor (from Alexander
Arch, issue 4170).
* Add initial-repeat-time option to allow the first repeat time to be increased
and later reduced (from David le Blanc, issue 4164).
* Send focus events to pane when entering or leaving popup (issue 3991).
* Add copy-mode-position-format to configure the position indicator.
* Add -y flag to disable confirmation prompts in modes (issue 4152).
* Add -C and -P flags to the copy commands in copy mode: -C prevents the
commands from sending the text to the clipboard and -P prevents them from
adding the text as a paste buffer (issue 4153).
* Preserve transparency and raster attribute dimensions when sending a SIXEL
image, and avoid collapsing empty lines (issue 4149).
* Bypass permission check for Cygwin (based on a change by Yuya Adachi via
Rafael Kitover, issue 4148).
* Add MSYSTEM to default update-environment (for Cgywin).
* Set client stdout file descriptor also for Cgywin (from Michael Wild via Rafael
Kitover, issue 4148).
* Use global cursor style and colour options for modes instead of default
(issue 4117).
* Fix pasting so it does not interpret keys but instead copies the input
without interpretation (reported by Mark Kelly).
* Try to query window pixel size from the outside terminal if the values
returned by TIOCGWINSZ are zero (Dmitry Galchinsky, issue 4099).
CHANGES FROM 3.5 TO 3.5a
* Do not translate BSpace as Unicode with extended keys.
* Fix so that keys with Shift are represented correctly with extended keys.
* Revert to using /bin/sh for #() and run-shell and if-shell; the change to use
default-shell only applies now to popups.
* Fix grey colour without a number suffix in styles.
CHANGES FROM 3.4 TO 3.5
* Revamp extended keys support to more closely match xterm and support mode 2

View File

@@ -31,7 +31,7 @@ attributes_tostring(int attr)
if (attr == 0)
return ("none");
len = xsnprintf(buf, sizeof buf, "%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
len = xsnprintf(buf, sizeof buf, "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
(attr & GRID_ATTR_CHARSET) ? "acs," : "",
(attr & GRID_ATTR_BRIGHT) ? "bright," : "",
(attr & GRID_ATTR_DIM) ? "dim," : "",
@@ -45,7 +45,8 @@ attributes_tostring(int attr)
(attr & GRID_ATTR_UNDERSCORE_3) ? "curly-underscore," : "",
(attr & GRID_ATTR_UNDERSCORE_4) ? "dotted-underscore," : "",
(attr & GRID_ATTR_UNDERSCORE_5) ? "dashed-underscore," : "",
(attr & GRID_ATTR_OVERLINE) ? "overline," : "");
(attr & GRID_ATTR_OVERLINE) ? "overline," : "",
(attr & GRID_ATTR_NOATTR) ? "noattr," : "");
if (len > 0)
buf[len - 1] = '\0';

View File

@@ -34,7 +34,7 @@ const struct cmd_entry cmd_refresh_client_entry = {
.name = "refresh-client",
.alias = "refresh",
.args = { "A:B:cC:Df:r:F:l::LRSt:U", 0, 1, NULL },
.args = { "A:B:cC:Df:r:F:lLRSt:U", 0, 1, NULL },
.usage = "[-cDlLRSU] [-A pane:state] [-B name:what:format] "
"[-C XxY] [-f flags] [-r pane:report] " CMD_TARGET_CLIENT_USAGE
" [adjustment]",
@@ -163,37 +163,6 @@ out:
free(copy);
}
static enum cmd_retval
cmd_refresh_client_clipboard(struct cmd *self, struct cmdq_item *item)
{
struct args *args = cmd_get_args(self);
struct client *tc = cmdq_get_target_client(item);
const char *p;
u_int i;
struct cmd_find_state fs;
p = args_get(args, 'l');
if (p == NULL) {
if (tc->flags & CLIENT_CLIPBOARDBUFFER)
return (CMD_RETURN_NORMAL);
tc->flags |= CLIENT_CLIPBOARDBUFFER;
} else {
if (cmd_find_target(&fs, item, p, CMD_FIND_PANE, 0) != 0)
return (CMD_RETURN_ERROR);
for (i = 0; i < tc->clipboard_npanes; i++) {
if (tc->clipboard_panes[i] == fs.wp->id)
break;
}
if (i != tc->clipboard_npanes)
return (CMD_RETURN_NORMAL);
tc->clipboard_panes = xreallocarray(tc->clipboard_panes,
tc->clipboard_npanes + 1, sizeof *tc->clipboard_panes);
tc->clipboard_panes[tc->clipboard_npanes++] = fs.wp->id;
}
tty_clipboard_query(&tc->tty);
return (CMD_RETURN_NORMAL);
}
static void
cmd_refresh_report(struct tty *tty, const char *value)
{
@@ -284,8 +253,10 @@ cmd_refresh_client_exec(struct cmd *self, struct cmdq_item *item)
return (CMD_RETURN_NORMAL);
}
if (args_has(args, 'l'))
return (cmd_refresh_client_clipboard(self, item));
if (args_has(args, 'l')) {
tty_clipboard_query(&tc->tty);
return (CMD_RETURN_NORMAL);
}
if (args_has(args, 'F')) /* -F is an alias for -f */
server_client_set_flags(tc, args_get(args, 'F'));

View File

@@ -1082,22 +1082,22 @@ colour_palette_free(struct colour_palette *p)
/* Get a colour from a palette. */
int
colour_palette_get(struct colour_palette *p, int c)
colour_palette_get(struct colour_palette *p, int n)
{
if (p == NULL)
return (-1);
if (c >= 90 && c <= 97)
c = 8 + c - 90;
else if (c & COLOUR_FLAG_256)
c &= ~COLOUR_FLAG_256;
else if (c >= 8)
if (n >= 90 && n <= 97)
n = 8 + n - 90;
else if (n & COLOUR_FLAG_256)
n &= ~COLOUR_FLAG_256;
else if (n >= 8)
return (-1);
if (p->palette != NULL && p->palette[c] != -1)
return (p->palette[c]);
if (p->default_palette != NULL && p->default_palette[c] != -1)
return (p->default_palette[c]);
if (p->palette != NULL && p->palette[n] != -1)
return (p->palette[n]);
if (p->default_palette != NULL && p->default_palette[n] != -1)
return (p->default_palette[n]);
return (-1);
}
@@ -1107,15 +1107,14 @@ colour_palette_set(struct colour_palette *p, int n, int c)
{
u_int i;
if (p == NULL || n > 255)
if (p == NULL || n < 0 || n > 255)
return (0);
if (c == -1 && p->palette == NULL)
return (0);
if (c != -1 && p->palette == NULL) {
if (p->palette == NULL)
p->palette = xcalloc(256, sizeof *p->palette);
if (p->palette == NULL) {
p->palette = xcalloc(256, sizeof *p->palette);
for (i = 0; i < 256; i++)
p->palette[i] = -1;
}

View File

@@ -1,6 +1,6 @@
# configure.ac
AC_INIT([tmux], next-3.6)
AC_INIT([tmux], next-3.7)
AC_PREREQ([2.60])
AC_CONFIG_AUX_DIR(etc)

View File

@@ -263,11 +263,6 @@ environ_for_session(struct session *s, int no_TERM)
environ_set(env, "TERM_PROGRAM", 0, "%s", "tmux");
environ_set(env, "TERM_PROGRAM_VERSION", 0, "%s", getversion());
environ_set(env, "COLORTERM", 0, "truecolor");
} else {
environ_unset(env, "TERM");
environ_unset(env, "TERM_PROGRAM");
environ_unset(env, "TERM_PROGRAM_VERSION");
environ_unset(env, "COLORTERM");
}
#ifdef HAVE_SYSTEMD

View File

@@ -1104,8 +1104,6 @@ format_width(const char *expanded)
more = utf8_append(&ud, *cp);
if (more == UTF8_DONE)
width += ud.width;
else
cp -= ud.have;
} else if (*cp > 0x1f && *cp < 0x7f) {
width++;
cp++;

View File

@@ -5545,7 +5545,8 @@ format_expand1(struct format_expand_state *es, const char *fmt)
buf[off++] = *fmt++;
continue;
}
fmt++;
if (*fmt++ == '\0')
break;
ch = (u_char)*fmt++;
switch (ch) {

91
input.c
View File

@@ -3069,18 +3069,41 @@ input_osc_133(struct input_ctx *ictx, const char *p)
}
}
/* Handle OSC 52 reply. */
static void
input_osc_52_reply(struct input_ctx *ictx)
{
struct paste_buffer *pb;
int state;
const char *buf;
size_t len;
state = options_get_number(global_options, "get-clipboard");
if (state == 0)
return;
if (state == 1) {
if ((pb = paste_get_top(NULL)) == NULL)
return;
buf = paste_buffer_data(pb, &len);
if (ictx->input_end == INPUT_END_BEL)
input_reply_clipboard(ictx->event, buf, len, "\007");
else
input_reply_clipboard(ictx->event, buf, len, "\033\\");
return;
}
input_add_request(ictx, INPUT_REQUEST_CLIPBOARD, ictx->input_end);
}
/* Handle the OSC 52 sequence for setting the clipboard. */
static void
input_osc_52(struct input_ctx *ictx, const char *p)
{
struct window_pane *wp = ictx->wp;
size_t len;
char *end;
const char *buf = NULL;
size_t len = 0;
u_char *out;
int outlen, state;
struct screen_write_ctx ctx;
struct paste_buffer *pb;
const char* allow = "cpqs01234567";
char flags[sizeof "cpqs01234567"] = "";
u_int i, j = 0;
@@ -3105,12 +3128,7 @@ input_osc_52(struct input_ctx *ictx, const char *p)
log_debug("%s: %.*s %s", __func__, (int)(end - p - 1), p, flags);
if (strcmp(end, "?") == 0) {
if ((pb = paste_get_top(NULL)) != NULL)
buf = paste_buffer_data(pb, &len);
if (ictx->input_end == INPUT_END_BEL)
input_reply_clipboard(ictx->event, buf, len, "\007");
else
input_reply_clipboard(ictx->event, buf, len, "\033\\");
input_osc_52_reply(ictx);
return;
}
@@ -3169,6 +3187,7 @@ input_osc_104(struct input_ctx *ictx, const char *p)
free(copy);
}
/* Send a clipboard reply. */
void
input_reply_clipboard(struct bufferevent *bev, const char *buf, size_t len,
const char *end)
@@ -3305,6 +3324,9 @@ input_add_request(struct input_ctx *ictx, enum input_request_type type, int idx)
xsnprintf(s, sizeof s, "\033]4;%d;?\033\\", idx);
tty_puts(&c->tty, s);
break;
case INPUT_REQUEST_CLIPBOARD:
tty_putcode_ss(&c->tty, TTYC_MS, "", "?");
break;
case INPUT_REQUEST_QUEUE:
break;
}
@@ -3312,6 +3334,39 @@ input_add_request(struct input_ctx *ictx, enum input_request_type type, int idx)
return (0);
}
/* Handle a palette reply. */
static void
input_request_palette_reply(struct input_request *ir, void *data)
{
struct input_request_palette_data *pd = data;
input_osc_colour_reply(ir->ictx, 0, 4, pd->idx, pd->c, ir->end);
}
/* Handle a clipboard reply. */
static void
input_request_clipboard_reply(struct input_request *ir, void *data)
{
struct input_ctx *ictx = ir->ictx;
struct input_request_clipboard_data *cd = data;
int state;
char *copy;
state = options_get_number(global_options, "get-clipboard");
if (state == 0 || state == 1)
return;
if (state == 3) {
copy = xmalloc(cd->len);
memcpy(copy, cd->buf, cd->len);
paste_add(NULL, copy, cd->len);
}
if (ir->idx == INPUT_END_BEL)
input_reply_clipboard(ictx->event, cd->buf, cd->len, "\007");
else
input_reply_clipboard(ictx->event, cd->buf, cd->len, "\033\\");
}
/* Handle a reply to a request. */
void
input_request_reply(struct client *c, enum input_request_type type, void *data)
@@ -3321,11 +3376,18 @@ input_request_reply(struct client *c, enum input_request_type type, void *data)
int complete = 0;
TAILQ_FOREACH_SAFE(ir, &c->input_requests, centry, ir1) {
if (ir->type == type && pd->idx == ir->idx) {
if (ir->type != type) {
input_free_request(ir);
continue;
}
if (type == INPUT_REQUEST_PALETTE && pd->idx == ir->idx) {
found = ir;
break;
}
if (type == INPUT_REQUEST_CLIPBOARD) {
found = ir;
break;
}
input_free_request(ir);
}
if (found == NULL)
return;
@@ -3335,8 +3397,11 @@ input_request_reply(struct client *c, enum input_request_type type, void *data)
break;
if (ir->type == INPUT_REQUEST_QUEUE)
input_send_reply(ir->ictx, ir->data);
else if (ir == found && ir->type == INPUT_REQUEST_PALETTE) {
input_osc_colour_reply(ir->ictx, 0, 4, pd->idx, pd->c, ir->end);
else if (ir == found) {
if (ir->type == INPUT_REQUEST_PALETTE)
input_request_palette_reply(ir, data);
else if (ir->type == INPUT_REQUEST_CLIPBOARD)
input_request_clipboard_reply(ir, data);
complete = 1;
}
input_free_request(ir);

View File

@@ -442,7 +442,7 @@ key_bindings_init(void)
"bind -n MouseDown1Pane { select-pane -t=; send -M }",
/* Mouse button 1 drag on pane. */
"bind -n MouseDrag1Pane { if -F '#{||:#{alternate_on},#{pane_in_mode},#{mouse_any_flag}}' { send -M } { copy-mode -M } }",
"bind -n MouseDrag1Pane { if -F '#{||:#{pane_in_mode},#{mouse_any_flag}}' { send -M } { copy-mode -M } }",
/* Mouse wheel up on pane. */
"bind -n WheelUpPane { if -F '#{||:#{alternate_on},#{pane_in_mode},#{mouse_any_flag}}' { send -M } { copy-mode -e } }",

View File

@@ -1159,9 +1159,8 @@ int
layout_spread_cell(struct window *w, struct layout_cell *parent)
{
struct layout_cell *lc;
struct style *sb_style = &w->active->scrollbar_style;
u_int number, each, size, this, remainder;
int change, changed, status, scrollbars;
int change, changed, status;
number = 0;
TAILQ_FOREACH (lc, &parent->cells, entry)
@@ -1169,14 +1168,9 @@ layout_spread_cell(struct window *w, struct layout_cell *parent)
if (number <= 1)
return (0);
status = options_get_number(w->options, "pane-border-status");
scrollbars = options_get_number(w->options, "pane-scrollbars");
if (parent->type == LAYOUT_LEFTRIGHT) {
if (scrollbars)
size = parent->sx - sb_style->width + sb_style->pad;
else
size = parent->sx;
}
if (parent->type == LAYOUT_LEFTRIGHT)
size = parent->sx;
else if (parent->type == LAYOUT_TOPBOTTOM) {
if (layout_add_horizontal_border(w, parent, status))
size = parent->sy - 1;

34
menu.c
View File

@@ -438,6 +438,38 @@ chosen:
return (1);
}
static void
menu_resize_cb(struct client *c, void *data)
{
struct menu_data *md = data;
u_int nx, ny, w, h;
if (md == NULL)
return;
nx = md->px;
ny = md->py;
w = md->menu->width + 4;
h = md->menu->count + 2;
if (nx + w > c->tty.sx) {
if (c->tty.sx <= w)
nx = 0;
else
nx = c->tty.sx - w;
}
if (ny + h > c->tty.sy) {
if (c->tty.sy <= h)
ny = 0;
else
ny = c->tty.sy - h;
}
md->px = nx;
md->py = ny;
}
static void
menu_set_style(struct client *c, struct grid_cell *gc, const char *style,
const char *option)
@@ -551,6 +583,6 @@ menu_display(struct menu *menu, int flags, int starting_choice,
if (md == NULL)
return (-1);
server_client_set_overlay(c, 0, NULL, menu_mode_cb, menu_draw_cb,
menu_key_cb, menu_free_cb, NULL, md);
menu_key_cb, menu_free_cb, menu_resize_cb, md);
return (0);
}

View File

@@ -36,7 +36,7 @@ static const char *options_table_mode_keys_list[] = {
"emacs", "vi", NULL
};
static const char *options_table_clock_mode_style_list[] = {
"12", "24", NULL
"12", "24", "12-with-seconds", "24-with-seconds", NULL
};
static const char *options_table_status_list[] = {
"off", "on", "2", "3", "4", "5", NULL
@@ -84,6 +84,9 @@ static const char *options_table_popup_border_lines_list[] = {
static const char *options_table_set_clipboard_list[] = {
"off", "external", "on", NULL
};
static const char *options_table_get_clipboard_list[] = {
"off", "buffer", "request", "both", NULL
};
static const char *options_table_window_size_list[] = {
"largest", "smallest", "manual", "latest", NULL
};
@@ -405,6 +408,18 @@ const struct options_table_entry options_table[] = {
.text = "Whether to send focus events to applications."
},
{ .name = "get-clipboard",
.type = OPTIONS_TABLE_CHOICE,
.scope = OPTIONS_TABLE_SERVER,
.choices = options_table_get_clipboard_list,
.default_num = 1,
.text = "When an application requests the clipboard, whether to "
"ignore the request ('off'); respond with the newest buffer "
"('buffer'); request the clipboard from the most recently "
"used terminal ('request'); or to request the clipboard, "
"create a buffer, and send it to the application ('both')."
},
{ .name = "history-file",
.type = OPTIONS_TABLE_STRING,
.scope = OPTIONS_TABLE_SERVER,

View File

@@ -4,7 +4,7 @@
Λ̊1
🏻2
👍🏻3
👍🏻 👍🏻4
👍🏻 👍🏻4
🤷5
7
🤷8

View File

@@ -1313,8 +1313,10 @@ screen_redraw_draw_scrollbar(struct screen_redraw_ctx *ctx,
int yoff = wp->yoff;
struct visible_ranges *vr;
if (ctx->statustop)
if (ctx->statustop) {
sb_y += ctx->statuslines;
sy += ctx->statuslines;
}
/* Set up style for slider. */
gc = sb_style->gc;

View File

@@ -2206,6 +2206,8 @@ screen_write_combine(struct screen_write_ctx *ctx, const struct grid_cell *gc)
case HANGULJAMO_STATE_NOT_HANGULJAMO:
if (utf8_should_combine(&last.data, ud))
force_wide = 1;
else if (utf8_should_combine(ud, &last.data))
force_wide = 1;
else if (!utf8_has_zwj(&last.data))
return (0);
break;

View File

@@ -594,8 +594,12 @@ screen_select_cell(struct screen *s, struct grid_cell *dst,
if (COLOUR_DEFAULT(dst->bg))
dst->bg = src->bg;
utf8_copy(&dst->data, &src->data);
dst->attr = src->attr;
dst->flags = src->flags;
if (dst->attr & GRID_ATTR_NOATTR)
dst->attr |= (src->attr & GRID_ATTR_CHARSET);
else
dst->attr |= src->attr;
}
/* Reflow wrapped lines. */

View File

@@ -617,7 +617,8 @@ server_client_check_mouse_in_pane(struct window_pane *wp, u_int px, u_int py,
pane_status_line = -1; /* not used */
/* Check if point is within the pane or scrollbar. */
if (((pane_status != PANE_STATUS_OFF && py != pane_status_line) ||
if (((pane_status != PANE_STATUS_OFF &&
py != pane_status_line && py != wp->yoff + wp->sy) ||
(wp->yoff == 0 && py < wp->sy) ||
((int)py >= wp->yoff && py < wp->yoff + wp->sy)) &&
((sb_pos == PANE_SCROLLBARS_RIGHT &&
@@ -1307,7 +1308,11 @@ have_event:
if (c->tty.mouse_scrolling_flag == 0 &&
where == SCROLLBAR_SLIDER) {
c->tty.mouse_scrolling_flag = 1;
c->tty.mouse_slider_mpos = sl_mpos;
if (m->statusat == 0) {
c->tty.mouse_slider_mpos = sl_mpos +
m->statuslines;
} else
c->tty.mouse_slider_mpos = sl_mpos;
}
break;
case WHEEL:
@@ -2938,8 +2943,8 @@ server_client_reset_state(struct client *c)
struct window_pane *wp = server_client_get_pane(c), *loop;
struct screen *s = NULL;
struct options *oo = c->session->options;
int mode = 0, cursor, flags, n;
u_int cx = 0, cy = 0, ox, oy, sx, sy;
int mode = 0, cursor, flags;
u_int cx = 0, cy = 0, ox, oy, sx, sy, n;
if (c->flags & (CLIENT_CONTROL|CLIENT_SUSPENDED))
return;
@@ -2971,13 +2976,13 @@ server_client_reset_state(struct client *c)
if (c->prompt_string != NULL) {
n = options_get_number(oo, "status-position");
if (n == 0)
cy = 0;
cy = status_prompt_line_at(c);
else {
n = status_line_size(c);
if (n == 0)
cy = tty->sy - 1;
else
n = status_line_size(c) - status_prompt_line_at(c);
if (n <= tty->sy)
cy = tty->sy - n;
else
cy = tty->sy - 1;
}
cx = c->prompt_cursor;
} else if (c->overlay_draw == NULL) {

View File

@@ -20,6 +20,7 @@
#include <sys/wait.h>
#include <sys/uio.h>
#include <signal.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

View File

@@ -264,14 +264,19 @@ status_line_size(struct client *c)
}
/* Get the prompt line number for client's session. 1 means at the bottom. */
static u_int
u_int
status_prompt_line_at(struct client *c)
{
struct session *s = c->session;
u_int line, lines;
if (c->flags & (CLIENT_STATUSOFF|CLIENT_CONTROL))
return (1);
return (options_get_number(s->options, "message-line"));
lines = status_line_size(c);
if (lines == 0)
return (0);
line = options_get_number(s->options, "message-line");
if (line >= lines)
return (lines - 1);
return (line);
}
/* Get window at window list position. */

35
style.c
View File

@@ -218,20 +218,23 @@ style_parse(struct style *sy, const struct grid_cell *base, const char *in)
sy->gc.attr = 0;
else if (end > 2 && strncasecmp(tmp, "no", 2) == 0) {
if (strcmp(tmp + 2, "attr") == 0)
value = 0xffff & ~GRID_ATTR_CHARSET;
else if ((value = attributes_fromstring(tmp + 2)) == -1)
goto error;
sy->gc.attr &= ~value;
sy->gc.attr |= GRID_ATTR_NOATTR;
else {
value = attributes_fromstring(tmp + 2);
if (value == -1)
goto error;
sy->gc.attr &= ~value;
}
} else if (end > 6 && strncasecmp(tmp, "width=", 6) == 0) {
n = strtonum(tmp + 6, 0, UINT_MAX, &errstr);
if (errstr != NULL)
goto error;
sy->width = (int)n;
n = strtonum(tmp + 6, 0, UINT_MAX, &errstr);
if (errstr != NULL)
goto error;
sy->width = (int)n;
} else if (end > 4 && strncasecmp(tmp, "pad=", 4) == 0) {
n = strtonum(tmp + 4, 0, UINT_MAX, &errstr);
if (errstr != NULL)
goto error;
sy->pad = (int)n;
n = strtonum(tmp + 4, 0, UINT_MAX, &errstr);
if (errstr != NULL)
goto error;
sy->pad = (int)n;
} else {
if ((value = attributes_fromstring(tmp)) == -1)
goto error;
@@ -344,13 +347,13 @@ style_tostring(struct style *sy)
attributes_tostring(gc->attr));
comma = ",";
}
if (sy->width >= 0) {
xsnprintf(s + off, sizeof s - off, "%swidth=%u", comma,
if (sy->width >= 0) {
xsnprintf(s + off, sizeof s - off, "%swidth=%u", comma,
sy->width);
comma = ",";
}
if (sy->pad >= 0) {
xsnprintf(s + off, sizeof s - off, "%spad=%u", comma,
if (sy->pad >= 0) {
xsnprintf(s + off, sizeof s - off, "%spad=%u", comma,
sy->pad);
comma = ",";
}

39
tmux.1
View File

@@ -1363,12 +1363,11 @@ and sets an environment variable for the newly created session; it may be
specified multiple times.
.Tg refresh
.It Xo Ic refresh-client
.Op Fl cDLRSU
.Op Fl cDlLRSU
.Op Fl A Ar pane:state
.Op Fl B Ar name:what:format
.Op Fl C Ar size
.Op Fl f Ar flags
.Op Fl l Op Ar target-pane
.Op Fl r Ar pane:report
.Op Fl t Ar target-client
.Op Ar adjustment
@@ -1489,11 +1488,7 @@ a colon, then a report escape sequence.
.Fl l
requests the clipboard from the client using the
.Xr xterm 1
escape sequence.
If
.Ar target-pane
is given, the clipboard is sent (in encoded form), otherwise it is stored in a
new paste buffer.
escape sequence and stores it in a new paste buffer.
.Pp
.Fl L ,
.Fl R ,
@@ -4241,6 +4236,32 @@ passed through to applications running in
.Nm .
Attached clients should be detached and attached again after changing this
option.
.It Xo Ic get-clipboard
.Op Ic both | request | buffer | off
.Xc
Controls the behaviour when an application requests the clipboard from
.Nm .
.Pp
If
.Ic off ,
the request is ignored;
if
.Ic buffer ,
.Nm
responds with the newest paste buffer;
.Ic request
causes
.Nm
to request the clipboard from the most recently used client (if possible) and
send the reply (if any) back to the application;
.Ic buffer
is the same as
.Ic request
but also creates a paste buffer.
.Pp
See also the
.Ic set-clipboard
option.
.It Ic history-file Ar path
If not empty, a file to which
.Nm
@@ -4927,7 +4948,7 @@ option is enabled.
Set clock colour.
.Pp
.It Xo Ic clock-mode-style
.Op Ic 12 | 24
.Op Ic 12 | 24 | 12-with-seconds | 24-with-seconds
.Xc
Set clock hour format.
.Pp
@@ -6135,7 +6156,6 @@ The following variables are available, where appropriate:
.It Li "insert_flag" Ta "" Ta "Pane insert flag"
.It Li "keypad_cursor_flag" Ta "" Ta "Pane keypad cursor flag"
.It Li "keypad_flag" Ta "" Ta "Pane keypad flag"
.It Li "last_session_index" Ta "" Ta "Index of last session"
.It Li "last_window_index" Ta "" Ta "Index of last window in session"
.It Li "line" Ta "" Ta "Line number in the list"
.It Li "loop_last_flag" Ta "" Ta "1 if last window, pane, session, client in the W:, P:, S:, or L: loop"
@@ -6227,7 +6247,6 @@ The following variables are available, where appropriate:
.It Li "session_group_size" Ta "" Ta "Size of session group"
.It Li "session_grouped" Ta "" Ta "1 if session in a group"
.It Li "session_id" Ta "" Ta "Unique session ID"
.It Li "session_index" Ta "" Ta "Index of session"
.It Li "session_last_attached" Ta "" Ta "Time session last attached"
.It Li "session_many_attached" Ta "" Ta "1 if multiple clients attached"
.It Li "session_marked" Ta "" Ta "1 if this session contains the marked pane"

11
tmux.h
View File

@@ -727,6 +727,7 @@ struct colour_palette {
#define GRID_ATTR_UNDERSCORE_4 0x800
#define GRID_ATTR_UNDERSCORE_5 0x1000
#define GRID_ATTR_OVERLINE 0x2000
#define GRID_ATTR_NOATTR 0x4000
/* All underscore attributes. */
#define GRID_ATTR_ALL_UNDERSCORE \
@@ -1129,6 +1130,7 @@ struct window_mode_entry {
/* Type of request to client. */
enum input_request_type {
INPUT_REQUEST_PALETTE,
INPUT_REQUEST_CLIPBOARD,
INPUT_REQUEST_QUEUE
};
@@ -1138,6 +1140,12 @@ struct input_request_palette_data {
int c;
};
/* Clipboard request reply data. */
struct input_request_clipboard_data {
char *buf;
size_t len;
};
/* Request sent to client on behalf of pane. */
TAILQ_HEAD(input_requests, input_request);
@@ -2016,7 +2024,7 @@ struct client {
#define CLIENT_CONTROL_PAUSEAFTER 0x100000000ULL
#define CLIENT_CONTROL_WAITEXIT 0x200000000ULL
#define CLIENT_WINDOWSIZECHANGED 0x400000000ULL
#define CLIENT_CLIPBOARDBUFFER 0x800000000ULL
/* 0x800000000ULL unused */
#define CLIENT_BRACKETPASTING 0x1000000000ULL
#define CLIENT_ASSUMEPASTING 0x2000000000ULL
#define CLIENT_REDRAWSCROLLBARS 0x4000000000ULL
@@ -2959,6 +2967,7 @@ extern u_int status_prompt_hsize[];
void status_timer_start(struct client *);
void status_timer_start_all(void);
void status_update_cache(struct session *);
u_int status_prompt_line_at(struct client *);
int status_at_line(struct client *);
u_int status_line_size(struct client *);
struct style_range *status_get_range(struct client *, u_int, u_int);

View File

@@ -1301,12 +1301,11 @@ tty_keys_mouse(struct tty *tty, const char *buf, size_t len, size_t *size,
static int
tty_keys_clipboard(struct tty *tty, const char *buf, size_t len, size_t *size)
{
struct client *c = tty->client;
struct window_pane *wp;
size_t end, terminator = 0, needed;
char *copy, *out;
int outlen;
u_int i;
struct client *c = tty->client;
size_t end, terminator = 0, needed;
char *copy, *out;
int outlen;
struct input_request_clipboard_data cd;
*size = 0;
@@ -1364,12 +1363,6 @@ tty_keys_clipboard(struct tty *tty, const char *buf, size_t len, size_t *size)
buf++;
end--;
/* If we did not request this, ignore it. */
if (~tty->flags & TTY_OSC52QUERY)
return (0);
tty->flags &= ~TTY_OSC52QUERY;
evtimer_del(&tty->clipboard_timer);
/* It has to be a string so copy it. */
copy = xmalloc(end + 1);
memcpy(copy, buf, end);
@@ -1384,22 +1377,22 @@ tty_keys_clipboard(struct tty *tty, const char *buf, size_t len, size_t *size)
return (0);
}
free(copy);
/* Create a new paste buffer and forward to panes. */
log_debug("%s: %.*s", __func__, outlen, out);
if (c->flags & CLIENT_CLIPBOARDBUFFER) {
paste_add(NULL, out, outlen);
c->flags &= ~CLIENT_CLIPBOARDBUFFER;
}
for (i = 0; i < c->clipboard_npanes; i++) {
wp = window_pane_find_by_id(c->clipboard_panes[i]);
if (wp != NULL)
input_reply_clipboard(wp->event, out, outlen, "\033\\");
}
free(c->clipboard_panes);
c->clipboard_panes = NULL;
c->clipboard_npanes = 0;
/* Set reply if any. */
cd.buf = out;
cd.len = outlen;
input_request_reply(c, INPUT_REQUEST_CLIPBOARD, &cd);
/* Create a buffer if requested. */
if (tty->flags & TTY_OSC52QUERY) {
paste_add(NULL, out, outlen);
out = NULL;
evtimer_del(&tty->clipboard_timer);
tty->flags &= ~TTY_OSC52QUERY;
}
free(out);
return (0);
}

24
tty.c
View File

@@ -35,6 +35,8 @@
static int tty_log_fd = -1;
static void tty_start_timer_callback(int, short, void *);
static void tty_clipboard_query_callback(int, short, void *);
static void tty_set_italics(struct tty *);
static int tty_try_colour(struct tty *, int, const char *);
static void tty_force_cursor_colour(struct tty *, int);
@@ -296,6 +298,8 @@ tty_open(struct tty *tty, char **cause)
if (tty->out == NULL)
fatal("out of memory");
evtimer_set(&tty->clipboard_timer, tty_clipboard_query_callback, tty);
evtimer_set(&tty->start_timer, tty_start_timer_callback, tty);
evtimer_set(&tty->timer, tty_timer_callback, tty);
tty_start_tty(tty);
@@ -327,7 +331,6 @@ tty_start_start_timer(struct tty *tty)
log_debug("%s: start timer started", c->name);
evtimer_del(&tty->start_timer);
evtimer_set(&tty->start_timer, tty_start_timer_callback, tty);
evtimer_add(&tty->start_timer, &tv);
}
@@ -445,6 +448,7 @@ tty_stop_tty(struct tty *tty)
tty->flags &= ~TTY_STARTED;
evtimer_del(&tty->start_timer);
evtimer_del(&tty->clipboard_timer);
event_del(&tty->timer);
tty->flags &= ~TTY_BLOCK;
@@ -3296,12 +3300,6 @@ static void
tty_clipboard_query_callback(__unused int fd, __unused short events, void *data)
{
struct tty *tty = data;
struct client *c = tty->client;
c->flags &= ~CLIENT_CLIPBOARDBUFFER;
free(c->clipboard_panes);
c->clipboard_panes = NULL;
c->clipboard_npanes = 0;
tty->flags &= ~TTY_OSC52QUERY;
}
@@ -3311,11 +3309,9 @@ tty_clipboard_query(struct tty *tty)
{
struct timeval tv = { .tv_sec = TTY_QUERY_TIMEOUT };
if ((~tty->flags & TTY_STARTED) || (tty->flags & TTY_OSC52QUERY))
return;
tty_putcode_ss(tty, TTYC_MS, "", "?");
tty->flags |= TTY_OSC52QUERY;
evtimer_set(&tty->clipboard_timer, tty_clipboard_query_callback, tty);
evtimer_add(&tty->clipboard_timer, &tv);
if ((tty->flags & TTY_STARTED) && (~tty->flags & TTY_OSC52QUERY)) {
tty_putcode_ss(tty, TTYC_MS, "", "?");
tty->flags |= TTY_OSC52QUERY;
evtimer_add(&tty->clipboard_timer, &tv);
}
}

View File

@@ -122,6 +122,7 @@ utf8_should_combine(const struct utf8_data *with, const struct utf8_data *add)
case 0x1F47C:
case 0x1F481:
case 0x1F482:
case 0x1F483:
case 0x1F485:
case 0x1F486:
case 0x1F487:

View File

@@ -45,7 +45,7 @@ const struct window_mode window_clock_mode = {
};
struct window_clock_mode_data {
struct screen screen;
struct screen screen;
time_t tim;
struct event timer;
};
@@ -142,7 +142,7 @@ window_clock_timer_callback(__unused int fd, __unused short events, void *arg)
t = time(NULL);
gmtime_r(&t, &now);
gmtime_r(&data->tim, &then);
if (now.tm_min == then.tm_min)
if (now.tm_sec == then.tm_sec)
return;
data->tim = t;
@@ -207,11 +207,12 @@ window_clock_draw_screen(struct window_mode_entry *wme)
{
struct window_pane *wp = wme->wp;
struct window_clock_mode_data *data = wme->data;
struct screen_write_ctx ctx;
struct screen_write_ctx ctx;
int colour, style;
struct screen *s = &data->screen;
struct grid_cell gc;
char tim[64], *ptr;
const char *timeformat;
time_t t;
struct tm *tm;
u_int i, j, x, y, idx;
@@ -223,14 +224,23 @@ window_clock_draw_screen(struct window_mode_entry *wme)
t = time(NULL);
tm = localtime(&t);
if (style == 0) {
strftime(tim, sizeof tim, "%l:%M ", localtime(&t));
if (style == 0 || style == 2) {
if (style == 2)
timeformat = "%l:%M:%S ";
else
timeformat = "%l:%M ";
strftime(tim, sizeof tim, timeformat, localtime(&t));
if (tm->tm_hour >= 12)
strlcat(tim, "PM", sizeof tim);
else
strlcat(tim, "AM", sizeof tim);
} else
strftime(tim, sizeof tim, "%H:%M", tm);
} else {
if (style == 3)
timeformat = "%H:%M:%S";
else
timeformat = "%H:%M";
strftime(tim, sizeof tim, timeformat, tm);
}
screen_write_clearscreen(&ctx, 8);

View File

@@ -627,7 +627,7 @@ window_copy_scroll1(struct window_mode_entry *wme, struct window_pane *wp,
new_slider_y = sb_top - wp->yoff + (sb_height - slider_height);
} else {
/* Slider is somewhere in the middle. */
new_slider_y = my - wp->yoff - sl_mpos + 1;
new_slider_y = my - wp->yoff - sl_mpos;
}
if (TAILQ_FIRST(&wp->modes) == NULL ||

View File

@@ -1851,7 +1851,7 @@ window_pane_mode(struct window_pane *wp)
int
window_pane_show_scrollbar(struct window_pane *wp, int sb_option)
{
if (SCREEN_IS_ALTERNATE(wp->screen))
if (SCREEN_IS_ALTERNATE(&wp->base))
return (0);
if (sb_option == PANE_SCROLLBARS_ALWAYS ||
(sb_option == PANE_SCROLLBARS_MODAL &&