Compare commits

..

20 Commits
3.6 ... 3.6b

Author SHA1 Message Date
Nicholas Marriott
0623d1e968 Bump version. 2026-05-20 16:39:41 +01:00
Nicholas Marriott
c5fb5e8bb0 Update CHANGES. 2026-05-20 12:17:30 +01:00
Nicholas Marriott
b8434182c9 Track which list (images or saved_images) each image is on so they can be
removed from the correct list when the total image count is reached. Fixes
crash reported by xlabai at tencent dot com.
2026-05-20 12:15:34 +01:00
Nicholas Marriott
e1f942f26a Add a define for max images and bump to 20 for the moment. 2026-05-20 12:14:22 +01:00
Nicholas Marriott
cc117b5048 Update CHANGES. 2025-12-05 05:39:46 +00:00
nicm
faebe7a70a Do not read over buffer if format is a single #, and do not loop forever
if UTF-8 is unfinished in a format. Reported by Giorgi Kobakhia im
GitHub issue 4735.
2025-12-05 05:38:05 +00:00
nicm
01962e25dc Allow drag in alternate screen again, GitHub issue 4743 reported by Brad
King.
2025-12-05 05:37:57 +00:00
nicm
ff207eb583 Fix y offset of mouse if status at top. GitHub issue 4738 from Michael
Grant.
2025-12-05 05:37:48 +00:00
Nicholas Marriott
2fc123cf4a Update CHANGES. 2025-12-04 20:54:44 +00:00
nicm
3b57077d01 Add a missing skin tone, from Jake Stewart in GitHub issue 4736. 2025-12-04 20:53:01 +00:00
nicm
33c1ba1549 Allow characters to be combined in either order, reported by Jake
Stewart in GitHub issue 4726.
2025-12-04 20:52:55 +00:00
Nicholas Marriott
52917abe21 Update CHANGES. 2025-12-02 14:26:30 +00:00
nicm
a40f98df0a Change noattr to be an explicit attribute in the style so that it works
correctly and does not delete attributes set in the style itself, GitHub
issue 4713.
2025-12-02 14:25:05 +00:00
nicm
2c78a5aceb Add horizontal border case to server_client_check_mouse_in_pane to fix
mouse resizing. GitHub issue 4720 from Michael Grant, reported by
someone in GitHub issue 4715.
2025-12-02 14:24:57 +00:00
Nicholas Marriott
bfecbb0685 Fix combine-test.result, GitHub issue 4717. 2025-12-01 08:21:04 +00:00
Nicholas Marriott
640e1a7643 Update CHANGES. 2025-11-27 07:26:09 +00:00
nicm
2a0b078e15 Place cursor on correct line if message-line is not 0, reported by
Alexis Hildebrandt.
2025-11-27 07:24:50 +00:00
nicm
0af04295f3 Newer libevents do not allow event_del on a zero'd event. 2025-11-27 07:24:47 +00:00
Nicholas Marriott
ec4b5b52af Version and CHANGES. 2025-11-26 19:00:17 +00:00
Nicholas Marriott
6db6a30ab5 Need signal.h for utempter, from Yasuhiro Kimura. 2025-11-26 18:43:11 +00:00
19 changed files with 123 additions and 47 deletions

31
CHANGES
View File

@@ -1,3 +1,34 @@
CHANGES FROM 3.6a TO 3.6b
* Remove images from the correct list when they are removed while in the
alternate screen (reported by xlabai at tencent dot com).
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).

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

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

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) {

View File

@@ -25,6 +25,7 @@
static struct images all_images = TAILQ_HEAD_INITIALIZER(all_images);
static u_int all_images_count;
#define MAX_IMAGE_COUNT 20
static void
image_free(struct image *im)
@@ -34,7 +35,7 @@ image_free(struct image *im)
TAILQ_REMOVE(&all_images, im, all_entry);
all_images_count--;
TAILQ_REMOVE(&s->images, im, entry);
TAILQ_REMOVE(im->list, im, entry);
sixel_free(im->data);
free(im->fallback);
free(im);
@@ -108,10 +109,11 @@ image_store(struct screen *s, struct sixel_image *si)
image_fallback(&im->fallback, im->sx, im->sy);
TAILQ_INSERT_TAIL(&s->images, im, entry);
im->list = &s->images;
TAILQ_INSERT_TAIL(im->list, im, entry);
TAILQ_INSERT_TAIL(&all_images, im, all_entry);
if (++all_images_count == 10/*XXX*/)
if (++all_images_count == MAX_IMAGE_COUNT)
image_free(TAILQ_FIRST(&all_images));
return (im);

View File

@@ -441,7 +441,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

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

View File

@@ -1028,6 +1028,11 @@ screen_redraw_draw_scrollbar(struct screen_redraw_ctx *ctx,
int sx = ctx->sx, sy = ctx->sy, xoff = wp->xoff;
int yoff = wp->yoff;
if (ctx->statustop) {
sb_y += ctx->statuslines;
sy += ctx->statuslines;
}
/* Set up style for slider. */
gc = sb_style->gc;
memcpy(&slgc, &gc, sizeof slgc);

View File

@@ -2152,6 +2152,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. */
@@ -629,7 +633,10 @@ screen_reflow(struct screen *s, u_int new_x, u_int *cx, u_int *cy, int cursor)
void
screen_alternate_on(struct screen *s, struct grid_cell *gc, int cursor)
{
u_int sx, sy;
u_int sx, sy;
#ifdef ENABLE_SIXEL
struct image *im;
#endif
if (SCREEN_IS_ALTERNATE(s))
return;
@@ -646,6 +653,8 @@ screen_alternate_on(struct screen *s, struct grid_cell *gc, int cursor)
#ifdef ENABLE_SIXEL
TAILQ_CONCAT(&s->saved_images, &s->images, entry);
TAILQ_FOREACH(im, &s->saved_images, entry)
im->list = &s->saved_images;
#endif
grid_view_clear(s->grid, 0, 0, sx, sy, 8);
@@ -658,7 +667,10 @@ screen_alternate_on(struct screen *s, struct grid_cell *gc, int cursor)
void
screen_alternate_off(struct screen *s, struct grid_cell *gc, int cursor)
{
u_int sx = screen_size_x(s), sy = screen_size_y(s);
u_int sx = screen_size_x(s), sy = screen_size_y(s);
#ifdef ENABLE_SIXEL
struct image *im;
#endif
/*
* If the current size is different, temporarily resize to the old size
@@ -705,6 +717,8 @@ screen_alternate_off(struct screen *s, struct grid_cell *gc, int cursor)
#ifdef ENABLE_SIXEL
image_free_all(s);
TAILQ_CONCAT(&s->images, &s->saved_images, entry);
TAILQ_FOREACH(im, &s->images, entry)
im->list = &s->images;
#endif
if (s->cx > screen_size_x(s) - 1)

View File

@@ -613,7 +613,8 @@ server_client_check_mouse_in_pane(struct window_pane *wp, u_int px, u_int py,
line = wp->yoff + wp->sy;
/* Check if point is within the pane or scrollbar. */
if (((pane_status != PANE_STATUS_OFF && py != line) ||
if (((pane_status != PANE_STATUS_OFF &&
py != line && py != wp->yoff + wp->sy) ||
(wp->yoff == 0 && py < wp->sy) ||
(py >= wp->yoff && py < wp->yoff + wp->sy)) &&
((sb_pos == PANE_SCROLLBARS_RIGHT &&
@@ -1270,7 +1271,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:
@@ -2901,8 +2906,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;
@@ -2934,13 +2939,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 = ",";
}

6
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 \
@@ -935,8 +936,10 @@ struct image {
u_int sx;
u_int sy;
TAILQ_ENTRY (image) all_entry;
struct images *list;
TAILQ_ENTRY (image) entry;
TAILQ_ENTRY (image) all_entry;
};
TAILQ_HEAD(images, image);
#endif
@@ -2943,6 +2946,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);

7
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;
@@ -3228,6 +3232,5 @@ tty_clipboard_query(struct tty *tty)
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);
}

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

@@ -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 ||