mirror of
https://github.com/tmux/tmux.git
synced 2024-12-24 10:08:48 +00:00
Merge branch 'obsd-master'
This commit is contained in:
commit
1aec420465
@ -1,4 +1,4 @@
|
||||
# Makefile.am
|
||||
Makefile.am
|
||||
|
||||
# Obvious program stuff.
|
||||
bin_PROGRAMS = tmux
|
||||
@ -191,6 +191,7 @@ dist_tmux_SOURCES = \
|
||||
tty-keys.c \
|
||||
tty-term.c \
|
||||
tty.c \
|
||||
utf8-combined.c \
|
||||
utf8.c \
|
||||
window-buffer.c \
|
||||
window-client.c \
|
||||
|
@ -60,7 +60,7 @@ cmd_new_window_exec(struct cmd *self, struct cmdq_item *item)
|
||||
struct session *s = target->s;
|
||||
struct winlink *wl = target->wl, *new_wl = NULL;
|
||||
int idx = target->idx, before;
|
||||
char *cause = NULL, *cp;
|
||||
char *cause = NULL, *cp, *expanded;
|
||||
const char *template, *name;
|
||||
struct cmd_find_state fs;
|
||||
struct args_value *av;
|
||||
@ -71,16 +71,19 @@ cmd_new_window_exec(struct cmd *self, struct cmdq_item *item)
|
||||
*/
|
||||
name = args_get(args, 'n');
|
||||
if (args_has(args, 'S') && name != NULL && target->idx == -1) {
|
||||
expanded = format_single(item, name, c, s, NULL, NULL);
|
||||
RB_FOREACH(wl, winlinks, &s->windows) {
|
||||
if (strcmp(wl->window->name, name) != 0)
|
||||
if (strcmp(wl->window->name, expanded) != 0)
|
||||
continue;
|
||||
if (new_wl == NULL) {
|
||||
new_wl = wl;
|
||||
continue;
|
||||
}
|
||||
cmdq_error(item, "multiple windows named %s", name);
|
||||
free(expanded);
|
||||
return (CMD_RETURN_ERROR);
|
||||
}
|
||||
free(expanded);
|
||||
if (new_wl != NULL) {
|
||||
if (args_has(args, 'd'))
|
||||
return (CMD_RETURN_NORMAL);
|
||||
|
@ -85,7 +85,7 @@ static const char *options_table_remain_on_exit_list[] = {
|
||||
"off", "on", "failed", NULL
|
||||
};
|
||||
static const char *options_table_detach_on_destroy_list[] = {
|
||||
"off", "on", "no-detached", NULL
|
||||
"off", "on", "no-detached", "previous", "next", NULL
|
||||
};
|
||||
static const char *options_table_extended_keys_list[] = {
|
||||
"off", "on", "always", NULL
|
||||
|
@ -1935,46 +1935,37 @@ screen_write_cell(struct screen_write_ctx *ctx, const struct grid_cell *gc)
|
||||
{
|
||||
struct screen *s = ctx->s;
|
||||
struct grid *gd = s->grid;
|
||||
const struct utf8_data *ud = &gc->data;
|
||||
const struct utf8_data zwj = { "\342\200\215", 0, 3, 0 };
|
||||
struct grid_cell copy;
|
||||
const struct utf8_data *ud = &gc->data, *previous = NULL, *combine;
|
||||
struct grid_line *gl;
|
||||
struct grid_cell_entry *gce;
|
||||
struct grid_cell tmp_gc, now_gc;
|
||||
struct tty_ctx ttyctx;
|
||||
u_int sx = screen_size_x(s), sy = screen_size_y(s);
|
||||
u_int width = gc->data.width, xx, last, cx, cy;
|
||||
u_int width = ud->width, xx, last, cx, cy;
|
||||
int selected, skip = 1;
|
||||
|
||||
/* Ignore padding cells. */
|
||||
if (gc->flags & GRID_FLAG_PADDING)
|
||||
return;
|
||||
|
||||
/*
|
||||
* If this is a zero width joiner, set the flag so the next character
|
||||
* will be treated as zero width and appended. Note that we assume a
|
||||
* ZWJ will not change the width - the width of the first character is
|
||||
* used.
|
||||
*/
|
||||
if (ud->size == 3 && memcmp(ud->data, "\342\200\215", 3) == 0) {
|
||||
log_debug("zero width joiner at %u,%u", s->cx, s->cy);
|
||||
ctx->flags |= SCREEN_WRITE_ZWJ;
|
||||
/* Check if this cell needs to be combined with the previous cell. */
|
||||
if (ctx->flags & SCREEN_WRITE_COMBINE)
|
||||
previous = &ctx->previous;
|
||||
switch (utf8_try_combined(ud, previous, &combine, &width)) {
|
||||
case UTF8_DISCARD_NOW:
|
||||
log_debug("%s: UTF8_DISCARD_NOW (width %u)", __func__, width);
|
||||
ctx->flags &= ~SCREEN_WRITE_COMBINE;
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* If the width is zero, combine onto the previous character. We always
|
||||
* combine with the cell to the left of the cursor position. In theory,
|
||||
* the application could have moved the cursor somewhere else, but if
|
||||
* they are silly enough to do that, who cares?
|
||||
*/
|
||||
if (ctx->flags & SCREEN_WRITE_ZWJ) {
|
||||
case UTF8_WRITE_NOW:
|
||||
log_debug("%s: UTF8_WRITE_NOW (width %u)", __func__, width);
|
||||
ctx->flags &= ~SCREEN_WRITE_COMBINE;
|
||||
break;
|
||||
case UTF8_COMBINE_NOW:
|
||||
log_debug("%s: UTF8_COMBINE_NOW (width %u)", __func__, width);
|
||||
screen_write_collect_flush(ctx, 0, __func__);
|
||||
screen_write_combine(ctx, &zwj, &xx, &cx);
|
||||
}
|
||||
if (width == 0 || (ctx->flags & SCREEN_WRITE_ZWJ)) {
|
||||
ctx->flags &= ~SCREEN_WRITE_ZWJ;
|
||||
screen_write_collect_flush(ctx, 0, __func__);
|
||||
if ((gc = screen_write_combine(ctx, ud, &xx, &cx)) != NULL) {
|
||||
gc = screen_write_combine(ctx, combine, &xx, &cx);
|
||||
if (gc != NULL) {
|
||||
cy = s->cy;
|
||||
screen_write_set_cursor(ctx, xx, s->cy);
|
||||
screen_write_initctx(ctx, &ttyctx, 0);
|
||||
@ -1982,8 +1973,27 @@ screen_write_cell(struct screen_write_ctx *ctx, const struct grid_cell *gc)
|
||||
tty_write(tty_cmd_cell, &ttyctx);
|
||||
s->cx = cx; s->cy = cy;
|
||||
}
|
||||
ctx->flags &= ~SCREEN_WRITE_COMBINE;
|
||||
return;
|
||||
case UTF8_WRITE_MAYBE_COMBINE:
|
||||
log_debug("%s: UTF8_WRITE_MAYBE_COMBINE (width %u)", __func__,
|
||||
width);
|
||||
utf8_copy(&ctx->previous, ud);
|
||||
ctx->flags |= SCREEN_WRITE_COMBINE;
|
||||
break;
|
||||
case UTF8_DISCARD_MAYBE_COMBINE:
|
||||
log_debug("%s: UTF8_DISCARD_MAYBE_COMBINE (width %u)", __func__,
|
||||
width);
|
||||
utf8_copy(&ctx->previous, ud);
|
||||
ctx->flags |= SCREEN_WRITE_COMBINE;
|
||||
return;
|
||||
}
|
||||
if (width != ud->width) {
|
||||
memcpy(©, gc, sizeof copy);
|
||||
copy.data.width = width;
|
||||
gc = ©
|
||||
}
|
||||
ud = NULL;
|
||||
|
||||
/* Flush any existing scrolling. */
|
||||
screen_write_collect_flush(ctx, 1, __func__);
|
||||
|
51
server-fn.c
51
server-fn.c
@ -27,7 +27,6 @@
|
||||
|
||||
#include "tmux.h"
|
||||
|
||||
static struct session *server_next_session(struct session *);
|
||||
static void server_destroy_session_group(struct session *);
|
||||
|
||||
void
|
||||
@ -207,7 +206,7 @@ server_kill_window(struct window *w, int renumber)
|
||||
if (session_detach(s, wl)) {
|
||||
server_destroy_session_group(s);
|
||||
break;
|
||||
} else
|
||||
}
|
||||
server_redraw_session_group(s);
|
||||
}
|
||||
|
||||
@ -385,9 +384,10 @@ server_destroy_session_group(struct session *s)
|
||||
struct session_group *sg;
|
||||
struct session *s1;
|
||||
|
||||
if ((sg = session_group_contains(s)) == NULL)
|
||||
if ((sg = session_group_contains(s)) == NULL) {
|
||||
server_destroy_session(s);
|
||||
else {
|
||||
session_destroy(s, 1, __func__);
|
||||
} else {
|
||||
TAILQ_FOREACH_SAFE(s, &sg->sessions, gentry, s1) {
|
||||
server_destroy_session(s);
|
||||
session_destroy(s, 1, __func__);
|
||||
@ -396,52 +396,55 @@ server_destroy_session_group(struct session *s)
|
||||
}
|
||||
|
||||
static struct session *
|
||||
server_next_session(struct session *s)
|
||||
server_find_session(struct session *s,
|
||||
int (*f)(struct session *, struct session *))
|
||||
{
|
||||
struct session *s_loop, *s_out = NULL;
|
||||
|
||||
RB_FOREACH(s_loop, sessions, &sessions) {
|
||||
if (s_loop == s)
|
||||
continue;
|
||||
if (s_out == NULL ||
|
||||
timercmp(&s_loop->activity_time, &s_out->activity_time, <))
|
||||
if (s_loop != s && (s_out == NULL || f(s_loop, s_out)))
|
||||
s_out = s_loop;
|
||||
}
|
||||
return (s_out);
|
||||
}
|
||||
|
||||
static struct session *
|
||||
server_next_detached_session(struct session *s)
|
||||
static int
|
||||
server_newer_session(struct session *s_loop, struct session *s_out)
|
||||
{
|
||||
struct session *s_loop, *s_out = NULL;
|
||||
|
||||
RB_FOREACH(s_loop, sessions, &sessions) {
|
||||
if (s_loop == s || s_loop->attached)
|
||||
continue;
|
||||
if (s_out == NULL ||
|
||||
timercmp(&s_loop->activity_time, &s_out->activity_time, <))
|
||||
s_out = s_loop;
|
||||
return (timercmp(&s_loop->activity_time, &s_out->activity_time, <));
|
||||
}
|
||||
return (s_out);
|
||||
|
||||
static int
|
||||
server_newer_detached_session(struct session *s_loop, struct session *s_out)
|
||||
{
|
||||
if (s_loop->attached)
|
||||
return (0);
|
||||
return (server_newer_session(s_loop, s_out));
|
||||
}
|
||||
|
||||
void
|
||||
server_destroy_session(struct session *s)
|
||||
{
|
||||
struct client *c;
|
||||
struct session *s_new;
|
||||
struct session *s_new = NULL;
|
||||
int detach_on_destroy;
|
||||
|
||||
detach_on_destroy = options_get_number(s->options, "detach-on-destroy");
|
||||
if (detach_on_destroy == 0)
|
||||
s_new = server_next_session(s);
|
||||
s_new = server_find_session(s, server_newer_session);
|
||||
else if (detach_on_destroy == 2)
|
||||
s_new = server_next_detached_session(s);
|
||||
else
|
||||
s_new = server_find_session(s, server_newer_detached_session);
|
||||
else if (detach_on_destroy == 3)
|
||||
s_new = session_previous_session(s);
|
||||
else if (detach_on_destroy == 4)
|
||||
s_new = session_next_session(s);
|
||||
if (s_new == s)
|
||||
s_new = NULL;
|
||||
TAILQ_FOREACH(c, &clients, entry) {
|
||||
if (c->session != s)
|
||||
continue;
|
||||
c->session = NULL;
|
||||
c->last_session = NULL;
|
||||
server_client_set_session(c, s_new);
|
||||
if (s_new == NULL)
|
||||
c->flags |= CLIENT_EXIT;
|
||||
|
1
server.c
1
server.c
@ -207,6 +207,7 @@ server_start(struct tmuxproc *client, int flags, struct event_base *base,
|
||||
fatal("pledge failed");
|
||||
|
||||
input_key_build();
|
||||
utf8_build_combined();
|
||||
RB_INIT(&windows);
|
||||
RB_INIT(&all_window_panes);
|
||||
TAILQ_INIT(&clients);
|
||||
|
@ -365,10 +365,8 @@ session_detach(struct session *s, struct winlink *wl)
|
||||
|
||||
session_group_synchronize_from(s);
|
||||
|
||||
if (RB_EMPTY(&s->windows)) {
|
||||
session_destroy(s, 1, __func__);
|
||||
if (RB_EMPTY(&s->windows))
|
||||
return (1);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
15
tmux.1
15
tmux.1
@ -4042,16 +4042,25 @@ The default is 80x24.
|
||||
If enabled and the session is no longer attached to any clients, it is
|
||||
destroyed.
|
||||
.It Xo Ic detach-on-destroy
|
||||
.Op Ic off | on | no-detached
|
||||
.Op Ic off | on | no-detached | previous | next
|
||||
.Xc
|
||||
If on (the default), the client is detached when the session it is attached to
|
||||
If
|
||||
.Ic on
|
||||
(the default), the client is detached when the session it is attached to
|
||||
is destroyed.
|
||||
If off, the client is switched to the most recently active of the remaining
|
||||
If
|
||||
.Ic off ,
|
||||
the client is switched to the most recently active of the remaining
|
||||
sessions.
|
||||
If
|
||||
.Ic no-detached ,
|
||||
the client is detached only if there are no detached sessions; if detached
|
||||
sessions exist, the client is switched to the most recently active.
|
||||
If
|
||||
.Ic previous
|
||||
or
|
||||
.Ic next ,
|
||||
the client is switched to the previous or next session in alphabetical order.
|
||||
.It Ic display-panes-active-colour Ar colour
|
||||
Set the colour used by the
|
||||
.Ic display-panes
|
||||
|
21
tmux.h
21
tmux.h
@ -627,6 +627,15 @@ enum utf8_state {
|
||||
UTF8_ERROR
|
||||
};
|
||||
|
||||
/* UTF-8 combine state. */
|
||||
enum utf8_combine_state {
|
||||
UTF8_DISCARD_NOW, /* discard immediately */
|
||||
UTF8_WRITE_NOW, /* do not combine, write immediately */
|
||||
UTF8_COMBINE_NOW, /* combine immediately */
|
||||
UTF8_WRITE_MAYBE_COMBINE, /* write but try to combine the next */
|
||||
UTF8_DISCARD_MAYBE_COMBINE /* discard but try to combine the next */
|
||||
};
|
||||
|
||||
/* Colour flags. */
|
||||
#define COLOUR_FLAG_256 0x01000000
|
||||
#define COLOUR_FLAG_RGB 0x02000000
|
||||
@ -921,7 +930,7 @@ struct screen_write_ctx {
|
||||
|
||||
int flags;
|
||||
#define SCREEN_WRITE_SYNC 0x1
|
||||
#define SCREEN_WRITE_ZWJ 0x2
|
||||
#define SCREEN_WRITE_COMBINE 0x2
|
||||
|
||||
screen_write_init_ctx_cb init_ctx_cb;
|
||||
void *arg;
|
||||
@ -929,6 +938,7 @@ struct screen_write_ctx {
|
||||
struct screen_write_citem *item;
|
||||
u_int scrolled;
|
||||
u_int bg;
|
||||
struct utf8_data previous;
|
||||
};
|
||||
|
||||
/* Box border lines option. */
|
||||
@ -3338,6 +3348,15 @@ int utf8_cstrhas(const char *, const struct utf8_data *);
|
||||
char *osdep_get_name(int, char *);
|
||||
char *osdep_get_cwd(int);
|
||||
struct event_base *osdep_event_init(void);
|
||||
/* utf8-combined.c */
|
||||
void utf8_build_combined(void);
|
||||
int utf8_try_combined(const struct utf8_data *,
|
||||
const struct utf8_data *, const struct utf8_data **,
|
||||
u_int *width);
|
||||
|
||||
/* procname.c */
|
||||
char *get_proc_name(int, char *);
|
||||
char *get_proc_cwd(int);
|
||||
|
||||
/* log.c */
|
||||
void log_add_level(void);
|
||||
|
1135
utf8-combined.c
Normal file
1135
utf8-combined.c
Normal file
File diff suppressed because it is too large
Load Diff
2
utf8.c
2
utf8.c
@ -235,7 +235,7 @@ utf8_width(struct utf8_data *ud, int *width)
|
||||
log_debug("utf8proc_wcwidth(%08X) returned %d", (u_int)wc, *width);
|
||||
#else
|
||||
*width = wcwidth(wc);
|
||||
log_debug("wcwidth(%08X) returned %d", (u_int)wc, *width);
|
||||
log_debug("wcwidth(%05X) returned %d", (u_int)wc, *width);
|
||||
if (*width < 0) {
|
||||
/*
|
||||
* C1 control characters are nonprintable, so they are always
|
||||
|
@ -3763,8 +3763,7 @@ window_copy_search(struct window_mode_entry *wme, int direction, int regex)
|
||||
}
|
||||
}
|
||||
endline = gd->hsize + gd->sy - 1;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
window_copy_move_left(s, &fx, &fy, wrapflag);
|
||||
endline = 0;
|
||||
}
|
||||
@ -3806,8 +3805,7 @@ window_copy_search(struct window_mode_entry *wme, int direction, int regex)
|
||||
data->cy = fy - screen_hsize(data->backing) +
|
||||
data-> oy;
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
/*
|
||||
* When searching backward, position the cursor at the
|
||||
* beginning of the mark.
|
||||
|
Loading…
Reference in New Issue
Block a user