mirror of
https://github.com/tmux/tmux.git
synced 2024-12-24 01:58:46 +00:00
Merge branch 'master' into sixel
This commit is contained in:
commit
40ad01073d
8
cfg.c
8
cfg.c
@ -184,9 +184,9 @@ load_cfg(const char *path, struct client *c, struct cmdq_item *item, int flags,
|
||||
|
||||
new_item0 = cmdq_get_command(pr->cmdlist, NULL, NULL, 0);
|
||||
if (item != NULL)
|
||||
cmdq_insert_after(item, new_item0);
|
||||
new_item0 = cmdq_insert_after(item, new_item0);
|
||||
else
|
||||
cmdq_append(NULL, new_item0);
|
||||
new_item0 = cmdq_append(NULL, new_item0);
|
||||
cmd_list_free(pr->cmdlist);
|
||||
|
||||
if (new_item != NULL)
|
||||
@ -230,9 +230,9 @@ load_cfg_from_buffer(const void *buf, size_t len, const char *path,
|
||||
|
||||
new_item0 = cmdq_get_command(pr->cmdlist, NULL, NULL, 0);
|
||||
if (item != NULL)
|
||||
cmdq_insert_after(item, new_item0);
|
||||
new_item0 = cmdq_insert_after(item, new_item0);
|
||||
else
|
||||
cmdq_append(NULL, new_item0);
|
||||
new_item0 = cmdq_append(NULL, new_item0);
|
||||
cmd_list_free(pr->cmdlist);
|
||||
|
||||
if (new_item != NULL)
|
||||
|
@ -52,7 +52,7 @@ const struct cmd_entry cmd_move_pane_entry = {
|
||||
.args = { "bdhvp:l:s:t:", 0, 0 },
|
||||
.usage = "[-bdhv] [-p percentage|-l size] " CMD_SRCDST_PANE_USAGE,
|
||||
|
||||
.source = { 's', CMD_FIND_PANE, 0 },
|
||||
.source = { 's', CMD_FIND_PANE, CMD_FIND_DEFAULT_MARKED },
|
||||
.target = { 't', CMD_FIND_PANE, 0 },
|
||||
|
||||
.flags = 0,
|
||||
|
28
cmd-queue.c
28
cmd-queue.c
@ -53,12 +53,16 @@ cmdq_get(struct client *c)
|
||||
}
|
||||
|
||||
/* Append an item. */
|
||||
void
|
||||
struct cmdq_item *
|
||||
cmdq_append(struct client *c, struct cmdq_item *item)
|
||||
{
|
||||
struct cmdq_list *queue = cmdq_get(c);
|
||||
struct cmdq_item *next;
|
||||
|
||||
TAILQ_FOREACH(next, queue, entry) {
|
||||
log_debug("%s %s: queue %s (%u)", __func__, cmdq_name(c),
|
||||
next->name, next->group);
|
||||
}
|
||||
do {
|
||||
next = item->next;
|
||||
item->next = NULL;
|
||||
@ -73,16 +77,21 @@ cmdq_append(struct client *c, struct cmdq_item *item)
|
||||
|
||||
item = next;
|
||||
} while (item != NULL);
|
||||
return (TAILQ_LAST(queue, cmdq_list));
|
||||
}
|
||||
|
||||
/* Insert an item. */
|
||||
void
|
||||
struct cmdq_item *
|
||||
cmdq_insert_after(struct cmdq_item *after, struct cmdq_item *item)
|
||||
{
|
||||
struct client *c = after->client;
|
||||
struct cmdq_list *queue = after->queue;
|
||||
struct cmdq_item *next;
|
||||
|
||||
TAILQ_FOREACH(next, queue, entry) {
|
||||
log_debug("%s %s: queue %s (%u)", __func__, cmdq_name(c),
|
||||
next->name, next->group);
|
||||
}
|
||||
do {
|
||||
next = item->next;
|
||||
item->next = after->next;
|
||||
@ -100,6 +109,7 @@ cmdq_insert_after(struct cmdq_item *after, struct cmdq_item *item)
|
||||
after = item;
|
||||
item = next;
|
||||
} while (item != NULL);
|
||||
return (after);
|
||||
}
|
||||
|
||||
/* Insert a hook. */
|
||||
@ -143,11 +153,10 @@ cmdq_insert_hook(struct session *s, struct cmdq_item *item,
|
||||
|
||||
new_item = cmdq_get_command(cmdlist, fs, NULL, CMDQ_NOHOOKS);
|
||||
cmdq_format(new_item, "hook", "%s", name);
|
||||
if (item != NULL) {
|
||||
cmdq_insert_after(item, new_item);
|
||||
item = new_item;
|
||||
} else
|
||||
cmdq_append(NULL, new_item);
|
||||
if (item != NULL)
|
||||
item = cmdq_insert_after(item, new_item);
|
||||
else
|
||||
item = cmdq_append(NULL, new_item);
|
||||
|
||||
a = options_array_next(a);
|
||||
}
|
||||
@ -542,7 +551,10 @@ cmdq_error(struct cmdq_item *item, const char *fmt, ...)
|
||||
msg = utf8_sanitize(tmp);
|
||||
free(tmp);
|
||||
}
|
||||
file_error(c, "%s\n", msg);
|
||||
if (c->flags & CLIENT_CONTROL)
|
||||
file_print(c, "%s\n", msg);
|
||||
else
|
||||
file_error(c, "%s\n", msg);
|
||||
c->retval = 1;
|
||||
} else {
|
||||
*msg = toupper((u_char) *msg);
|
||||
|
@ -113,6 +113,7 @@ cmd_source_file_done(struct client *c, const char *path, int error,
|
||||
static void
|
||||
cmd_source_file_add(struct cmd_source_file_data *cdata, const char *path)
|
||||
{
|
||||
log_debug("%s: %s", __func__, path);
|
||||
cdata->files = xreallocarray(cdata->files, cdata->nfiles + 1,
|
||||
sizeof *cdata->files);
|
||||
cdata->files[cdata->nfiles++] = xstrdup(path);
|
||||
@ -123,7 +124,6 @@ cmd_source_file_exec(struct cmd *self, struct cmdq_item *item)
|
||||
{
|
||||
struct args *args = self->args;
|
||||
struct cmd_source_file_data *cdata;
|
||||
int flags = 0;
|
||||
struct client *c = item->client;
|
||||
enum cmd_retval retval = CMD_RETURN_NORMAL;
|
||||
char *pattern, *cwd;
|
||||
@ -159,7 +159,7 @@ cmd_source_file_exec(struct cmd *self, struct cmdq_item *item)
|
||||
|
||||
if ((result = glob(pattern, 0, NULL, &g)) != 0) {
|
||||
if (result != GLOB_NOMATCH ||
|
||||
(~flags & CMD_PARSE_QUIET)) {
|
||||
(~cdata->flags & CMD_PARSE_QUIET)) {
|
||||
if (result == GLOB_NOMATCH)
|
||||
error = strerror(ENOENT);
|
||||
else if (result == GLOB_NOSPACE)
|
||||
|
2
cmd.c
2
cmd.c
@ -660,7 +660,7 @@ char *
|
||||
cmd_template_replace(const char *template, const char *s, int idx)
|
||||
{
|
||||
char ch, *buf;
|
||||
const char *ptr, *cp, quote[] = "\"\\$;";
|
||||
const char *ptr, *cp, quote[] = "\"\\$;~";
|
||||
int replaced, quoted;
|
||||
size_t len;
|
||||
|
||||
|
@ -849,8 +849,10 @@ format_trim_left(const char *expanded, u_int limit)
|
||||
out += ud.size;
|
||||
}
|
||||
width += ud.width;
|
||||
} else
|
||||
} else {
|
||||
cp -= ud.have;
|
||||
cp++;
|
||||
}
|
||||
} else if (*cp > 0x1f && *cp < 0x7f) {
|
||||
if (width + 1 <= limit)
|
||||
*out++ = *cp;
|
||||
@ -896,8 +898,10 @@ format_trim_right(const char *expanded, u_int limit)
|
||||
out += ud.size;
|
||||
}
|
||||
width += ud.width;
|
||||
} else
|
||||
} else {
|
||||
cp -= ud.have;
|
||||
cp++;
|
||||
}
|
||||
} else if (*cp > 0x1f && *cp < 0x7f) {
|
||||
if (width >= skip)
|
||||
*out++ = *cp;
|
||||
|
220
format.c
220
format.c
@ -456,6 +456,35 @@ format_cb_pid(__unused struct format_tree *ft, struct format_entry *fe)
|
||||
xasprintf(&fe->value, "%ld", (long)getpid());
|
||||
}
|
||||
|
||||
/* Callback for session_attached_list. */
|
||||
static void
|
||||
format_cb_session_attached_list(struct format_tree *ft, struct format_entry *fe)
|
||||
{
|
||||
struct session *s = ft->s;
|
||||
struct client *loop;
|
||||
struct evbuffer *buffer;
|
||||
int size;
|
||||
|
||||
if (s == NULL)
|
||||
return;
|
||||
|
||||
buffer = evbuffer_new();
|
||||
if (buffer == NULL)
|
||||
fatalx("out of memory");
|
||||
|
||||
TAILQ_FOREACH(loop, &clients, entry) {
|
||||
if (loop->session == s) {
|
||||
if (EVBUFFER_LENGTH(buffer) > 0)
|
||||
evbuffer_add(buffer, ",", 1);
|
||||
evbuffer_add_printf(buffer, "%s", loop->name);
|
||||
}
|
||||
}
|
||||
|
||||
if ((size = EVBUFFER_LENGTH(buffer)) != 0)
|
||||
xasprintf(&fe->value, "%.*s", size, EVBUFFER_DATA(buffer));
|
||||
evbuffer_free(buffer);
|
||||
}
|
||||
|
||||
/* Callback for session_alerts. */
|
||||
static void
|
||||
format_cb_session_alerts(struct format_tree *ft, struct format_entry *fe)
|
||||
@ -528,6 +557,128 @@ format_cb_window_stack_index(struct format_tree *ft, struct format_entry *fe)
|
||||
fe->value = xstrdup("0");
|
||||
}
|
||||
|
||||
/* Callback for window_linked_sessions_list. */
|
||||
static void
|
||||
format_cb_window_linked_sessions_list(struct format_tree *ft,
|
||||
struct format_entry *fe)
|
||||
{
|
||||
struct window *w = ft->wl->window;
|
||||
struct winlink *wl;
|
||||
struct evbuffer *buffer;
|
||||
int size;
|
||||
|
||||
buffer = evbuffer_new();
|
||||
if (buffer == NULL)
|
||||
fatalx("out of memory");
|
||||
|
||||
TAILQ_FOREACH(wl, &w->winlinks, wentry) {
|
||||
if (EVBUFFER_LENGTH(buffer) > 0)
|
||||
evbuffer_add(buffer, ",", 1);
|
||||
evbuffer_add_printf(buffer, "%s", wl->session->name);
|
||||
}
|
||||
|
||||
if ((size = EVBUFFER_LENGTH(buffer)) != 0)
|
||||
xasprintf(&fe->value, "%.*s", size, EVBUFFER_DATA(buffer));
|
||||
evbuffer_free(buffer);
|
||||
}
|
||||
|
||||
/* Callback for window_active_sessions. */
|
||||
static void
|
||||
format_cb_window_active_sessions(struct format_tree *ft,
|
||||
struct format_entry *fe)
|
||||
{
|
||||
struct window *w = ft->wl->window;
|
||||
struct winlink *wl;
|
||||
u_int n = 0;
|
||||
|
||||
TAILQ_FOREACH(wl, &w->winlinks, wentry) {
|
||||
if (wl->session->curw == wl)
|
||||
n++;
|
||||
}
|
||||
|
||||
xasprintf(&fe->value, "%u", n);
|
||||
}
|
||||
|
||||
/* Callback for window_active_sessions_list. */
|
||||
static void
|
||||
format_cb_window_active_sessions_list(struct format_tree *ft,
|
||||
struct format_entry *fe)
|
||||
{
|
||||
struct window *w = ft->wl->window;
|
||||
struct winlink *wl;
|
||||
struct evbuffer *buffer;
|
||||
int size;
|
||||
|
||||
buffer = evbuffer_new();
|
||||
if (buffer == NULL)
|
||||
fatalx("out of memory");
|
||||
|
||||
TAILQ_FOREACH(wl, &w->winlinks, wentry) {
|
||||
if (wl->session->curw == wl) {
|
||||
if (EVBUFFER_LENGTH(buffer) > 0)
|
||||
evbuffer_add(buffer, ",", 1);
|
||||
evbuffer_add_printf(buffer, "%s", wl->session->name);
|
||||
}
|
||||
}
|
||||
|
||||
if ((size = EVBUFFER_LENGTH(buffer)) != 0)
|
||||
xasprintf(&fe->value, "%.*s", size, EVBUFFER_DATA(buffer));
|
||||
evbuffer_free(buffer);
|
||||
}
|
||||
|
||||
/* Callback for window_active_clients. */
|
||||
static void
|
||||
format_cb_window_active_clients(struct format_tree *ft, struct format_entry *fe)
|
||||
{
|
||||
struct window *w = ft->wl->window;
|
||||
struct client *loop;
|
||||
struct session *client_session;
|
||||
u_int n = 0;
|
||||
|
||||
TAILQ_FOREACH(loop, &clients, entry) {
|
||||
client_session = loop->session;
|
||||
if (client_session == NULL)
|
||||
continue;
|
||||
|
||||
if (w == client_session->curw->window)
|
||||
n++;
|
||||
}
|
||||
|
||||
xasprintf(&fe->value, "%u", n);
|
||||
}
|
||||
|
||||
/* Callback for window_active_clients_list. */
|
||||
static void
|
||||
format_cb_window_active_clients_list(struct format_tree *ft,
|
||||
struct format_entry *fe)
|
||||
{
|
||||
struct window *w = ft->wl->window;
|
||||
struct client *loop;
|
||||
struct session *client_session;
|
||||
struct evbuffer *buffer;
|
||||
int size;
|
||||
|
||||
buffer = evbuffer_new();
|
||||
if (buffer == NULL)
|
||||
fatalx("out of memory");
|
||||
|
||||
TAILQ_FOREACH(loop, &clients, entry) {
|
||||
client_session = loop->session;
|
||||
if (client_session == NULL)
|
||||
continue;
|
||||
|
||||
if (w == client_session->curw->window) {
|
||||
if (EVBUFFER_LENGTH(buffer) > 0)
|
||||
evbuffer_add(buffer, ",", 1);
|
||||
evbuffer_add_printf(buffer, "%s", loop->name);
|
||||
}
|
||||
}
|
||||
|
||||
if ((size = EVBUFFER_LENGTH(buffer)) != 0)
|
||||
xasprintf(&fe->value, "%.*s", size, EVBUFFER_DATA(buffer));
|
||||
evbuffer_free(buffer);
|
||||
}
|
||||
|
||||
/* Callback for window_layout. */
|
||||
static void
|
||||
format_cb_window_layout(struct format_tree *ft, struct format_entry *fe)
|
||||
@ -677,11 +828,52 @@ format_cb_session_group_list(struct format_tree *ft, struct format_entry *fe)
|
||||
buffer = evbuffer_new();
|
||||
if (buffer == NULL)
|
||||
fatalx("out of memory");
|
||||
|
||||
TAILQ_FOREACH(loop, &sg->sessions, gentry) {
|
||||
if (EVBUFFER_LENGTH(buffer) > 0)
|
||||
evbuffer_add(buffer, ",", 1);
|
||||
evbuffer_add_printf(buffer, "%s", loop->name);
|
||||
}
|
||||
|
||||
if ((size = EVBUFFER_LENGTH(buffer)) != 0)
|
||||
xasprintf(&fe->value, "%.*s", size, EVBUFFER_DATA(buffer));
|
||||
evbuffer_free(buffer);
|
||||
}
|
||||
|
||||
/* Callback for session_group_attached_list. */
|
||||
static void
|
||||
format_cb_session_group_attached_list(struct format_tree *ft,
|
||||
struct format_entry *fe)
|
||||
{
|
||||
struct session *s = ft->s, *client_session, *session_loop;
|
||||
struct session_group *sg;
|
||||
struct client *loop;
|
||||
struct evbuffer *buffer;
|
||||
int size;
|
||||
|
||||
if (s == NULL)
|
||||
return;
|
||||
sg = session_group_contains(s);
|
||||
if (sg == NULL)
|
||||
return;
|
||||
|
||||
buffer = evbuffer_new();
|
||||
if (buffer == NULL)
|
||||
fatalx("out of memory");
|
||||
|
||||
TAILQ_FOREACH(loop, &clients, entry) {
|
||||
client_session = loop->session;
|
||||
if (client_session == NULL)
|
||||
continue;
|
||||
TAILQ_FOREACH(session_loop, &sg->sessions, gentry) {
|
||||
if (session_loop == client_session){
|
||||
if (EVBUFFER_LENGTH(buffer) > 0)
|
||||
evbuffer_add(buffer, ",", 1);
|
||||
evbuffer_add_printf(buffer, "%s", loop->name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ((size = EVBUFFER_LENGTH(buffer)) != 0)
|
||||
xasprintf(&fe->value, "%.*s", size, EVBUFFER_DATA(buffer));
|
||||
evbuffer_free(buffer);
|
||||
@ -974,12 +1166,12 @@ format_each(struct format_tree *ft, void (*cb)(const char *, const char *,
|
||||
void *), void *arg)
|
||||
{
|
||||
struct format_entry *fe;
|
||||
static char s[64];
|
||||
char s[64];
|
||||
|
||||
RB_FOREACH(fe, format_entry_tree, &ft->tree) {
|
||||
if (fe->t != 0) {
|
||||
xsnprintf(s, sizeof s, "%lld", (long long)fe->t);
|
||||
cb(fe->key, fe->value, s);
|
||||
cb(fe->key, s, arg);
|
||||
} else {
|
||||
if (fe->value == NULL && fe->cb != NULL) {
|
||||
fe->cb(ft, fe);
|
||||
@ -1022,8 +1214,7 @@ format_add(struct format_tree *ft, const char *key, const char *fmt, ...)
|
||||
static void
|
||||
format_add_tv(struct format_tree *ft, const char *key, struct timeval *tv)
|
||||
{
|
||||
struct format_entry *fe;
|
||||
struct format_entry *fe_now;
|
||||
struct format_entry *fe, *fe_now;
|
||||
|
||||
fe = xmalloc(sizeof *fe);
|
||||
fe->key = xstrdup(key);
|
||||
@ -2141,8 +2332,14 @@ format_defaults_session(struct format_tree *ft, struct session *s)
|
||||
format_add(ft, "session_group", "%s", sg->name);
|
||||
format_add(ft, "session_group_size", "%u",
|
||||
session_group_count (sg));
|
||||
format_add(ft, "session_group_attached", "%u",
|
||||
session_group_attached_count (sg));
|
||||
format_add(ft, "session_group_many_attached", "%u",
|
||||
session_group_attached_count (sg) > 1);
|
||||
format_add_cb(ft, "session_group_list",
|
||||
format_cb_session_group_list);
|
||||
format_add_cb(ft, "session_group_attached_list",
|
||||
format_cb_session_group_attached_list);
|
||||
}
|
||||
|
||||
format_add_tv(ft, "session_created", &s->creation_time);
|
||||
@ -2151,6 +2348,8 @@ format_defaults_session(struct format_tree *ft, struct session *s)
|
||||
|
||||
format_add(ft, "session_attached", "%u", s->attached);
|
||||
format_add(ft, "session_many_attached", "%d", s->attached > 1);
|
||||
format_add_cb(ft, "session_attached_list",
|
||||
format_cb_session_attached_list);
|
||||
|
||||
format_add_cb(ft, "session_alerts", format_cb_session_alerts);
|
||||
format_add_cb(ft, "session_stack", format_cb_session_stack);
|
||||
@ -2265,6 +2464,14 @@ format_defaults_winlink(struct format_tree *ft, struct winlink *wl)
|
||||
format_add_cb(ft, "window_stack_index", format_cb_window_stack_index);
|
||||
format_add(ft, "window_flags", "%s", window_printable_flags(wl));
|
||||
format_add(ft, "window_active", "%d", wl == s->curw);
|
||||
format_add_cb(ft, "window_active_sessions",
|
||||
format_cb_window_active_sessions);
|
||||
format_add_cb(ft, "window_active_sessions_list",
|
||||
format_cb_window_active_sessions_list);
|
||||
format_add_cb(ft, "window_active_clients",
|
||||
format_cb_window_active_clients);
|
||||
format_add_cb(ft, "window_active_clients_list",
|
||||
format_cb_window_active_clients_list);
|
||||
|
||||
format_add(ft, "window_start_flag", "%d",
|
||||
!!(wl == RB_MIN(winlinks, &s->windows)));
|
||||
@ -2285,6 +2492,11 @@ format_defaults_winlink(struct format_tree *ft, struct winlink *wl)
|
||||
format_add(ft, "window_last_flag", "%d",
|
||||
!!(wl == TAILQ_FIRST(&s->lastw)));
|
||||
format_add(ft, "window_linked", "%d", session_is_linked(s, wl->window));
|
||||
|
||||
format_add_cb(ft, "window_linked_sessions_list",
|
||||
format_cb_window_linked_sessions_list);
|
||||
format_add(ft, "window_linked_sessions", "%u",
|
||||
wl->window->references);
|
||||
}
|
||||
|
||||
/* Set default format keys for a window pane. */
|
||||
|
@ -85,6 +85,14 @@ key_bindings_cmp(struct key_binding *bd1, struct key_binding *bd2)
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void
|
||||
key_bindings_free(struct key_table *table, struct key_binding *bd)
|
||||
{
|
||||
RB_REMOVE(key_bindings, &table->key_bindings, bd);
|
||||
cmd_list_free(bd->cmdlist);
|
||||
free(bd);
|
||||
}
|
||||
|
||||
struct key_table *
|
||||
key_bindings_get_table(const char *name, int create)
|
||||
{
|
||||
@ -126,11 +134,8 @@ key_bindings_unref_table(struct key_table *table)
|
||||
if (--table->references != 0)
|
||||
return;
|
||||
|
||||
RB_FOREACH_SAFE(bd, key_bindings, &table->key_bindings, bd1) {
|
||||
RB_REMOVE(key_bindings, &table->key_bindings, bd);
|
||||
cmd_list_free(bd->cmdlist);
|
||||
free(bd);
|
||||
}
|
||||
RB_FOREACH_SAFE(bd, key_bindings, &table->key_bindings, bd1)
|
||||
key_bindings_free(table, bd);
|
||||
|
||||
free((void *)table->name);
|
||||
free(table);
|
||||
@ -162,17 +167,13 @@ key_bindings_add(const char *name, key_code key, int repeat,
|
||||
struct cmd_list *cmdlist)
|
||||
{
|
||||
struct key_table *table;
|
||||
struct key_binding bd_find, *bd;
|
||||
struct key_binding *bd;
|
||||
|
||||
table = key_bindings_get_table(name, 1);
|
||||
|
||||
bd_find.key = (key & ~KEYC_XTERM);
|
||||
bd = RB_FIND(key_bindings, &table->key_bindings, &bd_find);
|
||||
if (bd != NULL) {
|
||||
RB_REMOVE(key_bindings, &table->key_bindings, bd);
|
||||
cmd_list_free(bd->cmdlist);
|
||||
free(bd);
|
||||
}
|
||||
bd = key_bindings_get(table, key & ~KEYC_XTERM);
|
||||
if (bd != NULL)
|
||||
key_bindings_free(table, bd);
|
||||
|
||||
bd = xcalloc(1, sizeof *bd);
|
||||
bd->key = key;
|
||||
@ -187,20 +188,16 @@ void
|
||||
key_bindings_remove(const char *name, key_code key)
|
||||
{
|
||||
struct key_table *table;
|
||||
struct key_binding bd_find, *bd;
|
||||
struct key_binding *bd;
|
||||
|
||||
table = key_bindings_get_table(name, 0);
|
||||
if (table == NULL)
|
||||
return;
|
||||
|
||||
bd_find.key = (key & ~KEYC_XTERM);
|
||||
bd = RB_FIND(key_bindings, &table->key_bindings, &bd_find);
|
||||
bd = key_bindings_get(table, key & ~KEYC_XTERM);
|
||||
if (bd == NULL)
|
||||
return;
|
||||
|
||||
RB_REMOVE(key_bindings, &table->key_bindings, bd);
|
||||
cmd_list_free(bd->cmdlist);
|
||||
free(bd);
|
||||
key_bindings_free(table, bd);
|
||||
|
||||
if (RB_EMPTY(&table->key_bindings)) {
|
||||
RB_REMOVE(key_tables, &key_tables, table);
|
||||
@ -520,8 +517,8 @@ key_bindings_dispatch(struct key_binding *bd, struct cmdq_item *item,
|
||||
new_item->shared->flags |= CMDQ_SHARED_REPEAT;
|
||||
}
|
||||
if (item != NULL)
|
||||
cmdq_insert_after(item, new_item);
|
||||
new_item = cmdq_insert_after(item, new_item);
|
||||
else
|
||||
cmdq_append(c, new_item);
|
||||
new_item = cmdq_append(c, new_item);
|
||||
return (new_item);
|
||||
}
|
||||
|
4
notify.c
4
notify.c
@ -89,9 +89,7 @@ notify_insert_hook(struct cmdq_item *item, struct notify_entry *ne)
|
||||
new_item = cmdq_get_command(cmdlist, &fs, NULL, CMDQ_NOHOOKS);
|
||||
cmdq_format(new_item, "hook", "%s", ne->name);
|
||||
notify_hook_formats(new_item, s, w, ne->pane);
|
||||
|
||||
cmdq_insert_after(item, new_item);
|
||||
item = new_item;
|
||||
item = cmdq_insert_after(item, new_item);
|
||||
|
||||
a = options_array_next(a);
|
||||
}
|
||||
|
15
session.c
15
session.c
@ -568,7 +568,20 @@ session_group_count(struct session_group *sg)
|
||||
|
||||
n = 0;
|
||||
TAILQ_FOREACH(s, &sg->sessions, gentry)
|
||||
n++;
|
||||
n++;
|
||||
return (n);
|
||||
}
|
||||
|
||||
/* Count number of clients attached to sessions in session group. */
|
||||
u_int
|
||||
session_group_attached_count(struct session_group *sg)
|
||||
{
|
||||
struct session *s;
|
||||
u_int n;
|
||||
|
||||
n = 0;
|
||||
TAILQ_FOREACH(s, &sg->sessions, gentry)
|
||||
n += s->attached;
|
||||
return (n);
|
||||
}
|
||||
|
||||
|
5
spawn.c
5
spawn.c
@ -78,6 +78,8 @@ spawn_log(const char *from, struct spawn_context *sc)
|
||||
struct winlink *
|
||||
spawn_window(struct spawn_context *sc, char **cause)
|
||||
{
|
||||
struct cmdq_item *item = sc->item;
|
||||
struct client *c = item->client;
|
||||
struct session *s = sc->s;
|
||||
struct window *w;
|
||||
struct window_pane *wp;
|
||||
@ -180,7 +182,8 @@ spawn_window(struct spawn_context *sc, char **cause)
|
||||
/* Set the name of the new window. */
|
||||
if (~sc->flags & SPAWN_RESPAWN) {
|
||||
if (sc->name != NULL) {
|
||||
w->name = xstrdup(sc->name);
|
||||
w->name = format_single(item, sc->name, c, s, NULL,
|
||||
NULL);
|
||||
options_set_number(w->options, "automatic-rename", 0);
|
||||
} else
|
||||
w->name = xstrdup(default_window_name(w));
|
||||
|
51
tmux.1
51
tmux.1
@ -938,7 +938,9 @@ If
|
||||
is specified, any other clients attached to the session are detached.
|
||||
If
|
||||
.Fl x
|
||||
is given, send SIGHUP to the parent process of the client as well as
|
||||
is given, send
|
||||
.Dv SIGHUP
|
||||
to the parent process of the client as well as
|
||||
detaching the client, typically causing it to exit.
|
||||
.Fl r
|
||||
signifies the client is read-only (only keys bound to the
|
||||
@ -989,7 +991,9 @@ option kills all but the client given with
|
||||
.Fl t .
|
||||
If
|
||||
.Fl P
|
||||
is given, send SIGHUP to the parent process of the client, typically causing it
|
||||
is given, send
|
||||
.Dv SIGHUP
|
||||
to the parent process of the client, typically causing it
|
||||
to exit.
|
||||
With
|
||||
.Fl E ,
|
||||
@ -4316,10 +4320,14 @@ The following variables are available, where appropriate:
|
||||
.It Li "session_activity" Ta "" Ta "Time of session last activity"
|
||||
.It Li "session_alerts" Ta "" Ta "List of window indexes with alerts"
|
||||
.It Li "session_attached" Ta "" Ta "Number of clients session is attached to"
|
||||
.It Li "session_attached_list" Ta "" Ta "List of clients session is attached to"
|
||||
.It Li "session_created" Ta "" Ta "Time session created"
|
||||
.It Li "session_format" Ta "" Ta "1 if format is for a session"
|
||||
.It Li "session_group" Ta "" Ta "Name of session group"
|
||||
.It Li "session_group_attached" Ta "" Ta "Number of clients sessions in group are attached to"
|
||||
.It Li "session_group_attached_list" Ta "" Ta "List of clients sessions in group are attached to"
|
||||
.It Li "session_group_list" Ta "" Ta "List of sessions in group"
|
||||
.It Li "session_group_many_attached" Ta "" Ta "1 if multiple clients attached to sessions in group"
|
||||
.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"
|
||||
@ -4332,6 +4340,10 @@ The following variables are available, where appropriate:
|
||||
.It Li "start_time" Ta "" Ta "Server start time"
|
||||
.It Li "version" Ta "" Ta "Server version"
|
||||
.It Li "window_active" Ta "" Ta "1 if window active"
|
||||
.It Li "window_active_clients" Ta "" Ta "Number of clients viewing this window"
|
||||
.It Li "window_active_clients_list" Ta "" Ta "List of clients viewing this window"
|
||||
.It Li "window_active_sessions" Ta "" Ta "Number of sessions on which this window is active"
|
||||
.It Li "window_active_sessions_list" Ta "" Ta "List of sessions on which this window is active"
|
||||
.It Li "window_activity" Ta "" Ta "Time of window last activity"
|
||||
.It Li "window_activity_flag" Ta "" Ta "1 if window has activity"
|
||||
.It Li "window_bell_flag" Ta "" Ta "1 if window has bell"
|
||||
@ -4347,6 +4359,8 @@ The following variables are available, where appropriate:
|
||||
.It Li "window_last_flag" Ta "" Ta "1 if window is the last used"
|
||||
.It Li "window_layout" Ta "" Ta "Window layout description, ignoring zoomed window panes"
|
||||
.It Li "window_linked" Ta "" Ta "1 if window is linked across sessions"
|
||||
.It Li "window_linked_sessions" Ta "" Ta "Number of sessions this window is linked to"
|
||||
.It Li "window_linked_sessions_list" Ta "" Ta "List of sessions this window is linked to"
|
||||
.It Li "window_marked_flag" Ta "" Ta "1 if window contains the marked pane"
|
||||
.It Li "window_name" Ta "#W" Ta "Name of window"
|
||||
.It Li "window_offset_x" Ta "" Ta "X offset into window if larger than client"
|
||||
@ -4367,7 +4381,7 @@ interface, for example
|
||||
.Ic status-style
|
||||
for the status line.
|
||||
In addition, embedded styles may be specified in format options, such as
|
||||
.Ic status-left-format ,
|
||||
.Ic status-left ,
|
||||
by enclosing them in
|
||||
.Ql #[
|
||||
and
|
||||
@ -5145,6 +5159,37 @@ channel are made to wait until the channel is unlocked with
|
||||
.Ic wait-for
|
||||
.Fl U .
|
||||
.El
|
||||
.Sh EXIT MESSAGES
|
||||
When a
|
||||
.Nm
|
||||
client detaches, it prints a message.
|
||||
This may be one of:
|
||||
.Bl -tag -width Ds
|
||||
.It [detached (from session ...)]
|
||||
The client was detached normally.
|
||||
.It [detached and SIGHUP]
|
||||
The client was detached and its parent sent the
|
||||
.Dv SIGHUP
|
||||
signal (for example with
|
||||
.Ic detach-client
|
||||
.Fl P ) .
|
||||
.It [lost tty]
|
||||
The client's
|
||||
.Xr tty 4
|
||||
or
|
||||
.Xr pty 4
|
||||
was unexpectedly destroyed.
|
||||
.It [terminated]
|
||||
The client was killed with
|
||||
.Dv SIGTERM .
|
||||
.It [exited]
|
||||
The server exited when it had no sessions.
|
||||
.It [server exited]
|
||||
The server exited when it received
|
||||
.Dv SIGTERM .
|
||||
.It [server exited unexpectedly]
|
||||
The server crashed or otherwise exited without telling the client the reason.
|
||||
.El
|
||||
.Sh TERMINFO EXTENSIONS
|
||||
.Nm
|
||||
understands some unofficial extensions to
|
||||
|
8
tmux.h
8
tmux.h
@ -1620,7 +1620,8 @@ struct client {
|
||||
#define CLIENT_NOSIZEFLAGS \
|
||||
(CLIENT_DEAD| \
|
||||
CLIENT_SUSPENDED| \
|
||||
CLIENT_DETACHING)
|
||||
CLIENT_DETACHING| \
|
||||
CLIENT_READONLY)
|
||||
int flags;
|
||||
struct key_table *keytable;
|
||||
|
||||
@ -2157,8 +2158,8 @@ struct cmdq_item *cmdq_get_command(struct cmd_list *, struct cmd_find_state *,
|
||||
#define cmdq_get_callback(cb, data) cmdq_get_callback1(#cb, cb, data)
|
||||
struct cmdq_item *cmdq_get_callback1(const char *, cmdq_cb, void *);
|
||||
struct cmdq_item *cmdq_get_error(const char *);
|
||||
void cmdq_insert_after(struct cmdq_item *, struct cmdq_item *);
|
||||
void cmdq_append(struct client *, struct cmdq_item *);
|
||||
struct cmdq_item *cmdq_insert_after(struct cmdq_item *, struct cmdq_item *);
|
||||
struct cmdq_item *cmdq_append(struct client *, struct cmdq_item *);
|
||||
void cmdq_insert_hook(struct session *, struct cmdq_item *,
|
||||
struct cmd_find_state *, const char *, ...);
|
||||
void cmdq_continue(struct cmdq_item *);
|
||||
@ -2714,6 +2715,7 @@ void session_group_add(struct session_group *, struct session *);
|
||||
void session_group_synchronize_to(struct session *);
|
||||
void session_group_synchronize_from(struct session *);
|
||||
u_int session_group_count(struct session_group *);
|
||||
u_int session_group_attached_count(struct session_group *);
|
||||
void session_renumber_windows(struct session *);
|
||||
|
||||
/* utf8.c */
|
||||
|
397
window-copy.c
397
window-copy.c
@ -19,6 +19,7 @@
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <ctype.h>
|
||||
#include <regex.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
@ -57,18 +58,29 @@ static int window_copy_search_lr(struct grid *, struct grid *, u_int *,
|
||||
u_int, u_int, u_int, int);
|
||||
static int window_copy_search_rl(struct grid *, struct grid *, u_int *,
|
||||
u_int, u_int, u_int, int);
|
||||
static int window_copy_search_lr_regex(struct grid *, struct grid *,
|
||||
u_int *, u_int *, u_int, u_int, u_int, int);
|
||||
static int window_copy_search_rl_regex(struct grid *, struct grid *,
|
||||
u_int *, u_int *, u_int, u_int, u_int, int);
|
||||
static int window_copy_last_regex(struct grid *gd, u_int py, u_int first,
|
||||
u_int last, u_int len, u_int *ppx, u_int *psx,
|
||||
const char *buf, const regex_t *preg, int eflags);
|
||||
static char *window_copy_stringify(struct grid *, u_int, u_int, u_int,
|
||||
char *, u_int *);
|
||||
static void window_copy_cstrtocellpos(struct grid *, u_int, u_int *, u_int *,
|
||||
const char *str);
|
||||
static int window_copy_search_marks(struct window_mode_entry *,
|
||||
struct screen *);
|
||||
struct screen *, int);
|
||||
static void window_copy_clear_marks(struct window_mode_entry *);
|
||||
static void window_copy_move_left(struct screen *, u_int *, u_int *, int);
|
||||
static void window_copy_move_right(struct screen *, u_int *, u_int *, int);
|
||||
static int window_copy_is_lowercase(const char *);
|
||||
static int window_copy_search_jump(struct window_mode_entry *,
|
||||
struct grid *, struct grid *, u_int, u_int, u_int, int, int,
|
||||
int);
|
||||
static int window_copy_search(struct window_mode_entry *, int);
|
||||
static int window_copy_search_up(struct window_mode_entry *);
|
||||
static int window_copy_search_down(struct window_mode_entry *);
|
||||
int, int);
|
||||
static int window_copy_search(struct window_mode_entry *, int, int);
|
||||
static int window_copy_search_up(struct window_mode_entry *, int);
|
||||
static int window_copy_search_down(struct window_mode_entry *, int);
|
||||
static void window_copy_goto_line(struct window_mode_entry *, const char *);
|
||||
static void window_copy_update_cursor(struct window_mode_entry *, u_int,
|
||||
u_int);
|
||||
@ -622,7 +634,7 @@ window_copy_resize(struct window_mode_entry *wme, u_int sx, u_int sy)
|
||||
screen_write_stop(&ctx);
|
||||
|
||||
if (search)
|
||||
window_copy_search_marks(wme, NULL);
|
||||
window_copy_search_marks(wme, NULL, 1);
|
||||
data->searchx = data->cx;
|
||||
data->searchy = data->cy;
|
||||
data->searcho = data->oy;
|
||||
@ -1458,10 +1470,10 @@ window_copy_cmd_search_again(struct window_copy_cmd_state *cs)
|
||||
|
||||
if (data->searchtype == WINDOW_COPY_SEARCHUP) {
|
||||
for (; np != 0; np--)
|
||||
window_copy_search_up(wme);
|
||||
window_copy_search_up(wme, 1);
|
||||
} else if (data->searchtype == WINDOW_COPY_SEARCHDOWN) {
|
||||
for (; np != 0; np--)
|
||||
window_copy_search_down(wme);
|
||||
window_copy_search_down(wme, 1);
|
||||
}
|
||||
return (WINDOW_COPY_CMD_NOTHING);
|
||||
}
|
||||
@ -1475,10 +1487,10 @@ window_copy_cmd_search_reverse(struct window_copy_cmd_state *cs)
|
||||
|
||||
if (data->searchtype == WINDOW_COPY_SEARCHUP) {
|
||||
for (; np != 0; np--)
|
||||
window_copy_search_down(wme);
|
||||
window_copy_search_down(wme, 1);
|
||||
} else if (data->searchtype == WINDOW_COPY_SEARCHDOWN) {
|
||||
for (; np != 0; np--)
|
||||
window_copy_search_up(wme);
|
||||
window_copy_search_up(wme, 1);
|
||||
}
|
||||
return (WINDOW_COPY_CMD_NOTHING);
|
||||
}
|
||||
@ -1696,7 +1708,7 @@ window_copy_cmd_search_backward(struct window_copy_cmd_state *cs)
|
||||
if (data->searchstr != NULL) {
|
||||
data->searchtype = WINDOW_COPY_SEARCHUP;
|
||||
for (; np != 0; np--)
|
||||
window_copy_search_up(wme);
|
||||
window_copy_search_up(wme, 1);
|
||||
}
|
||||
return (WINDOW_COPY_CMD_NOTHING);
|
||||
}
|
||||
@ -1731,7 +1743,7 @@ window_copy_cmd_search_forward(struct window_copy_cmd_state *cs)
|
||||
if (data->searchstr != NULL) {
|
||||
data->searchtype = WINDOW_COPY_SEARCHDOWN;
|
||||
for (; np != 0; np--)
|
||||
window_copy_search_down(wme);
|
||||
window_copy_search_down(wme, 1);
|
||||
}
|
||||
return (WINDOW_COPY_CMD_NOTHING);
|
||||
}
|
||||
@ -1767,7 +1779,7 @@ window_copy_cmd_search_backward_incremental(struct window_copy_cmd_state *cs)
|
||||
data->searchtype = WINDOW_COPY_SEARCHUP;
|
||||
free(data->searchstr);
|
||||
data->searchstr = xstrdup(argument);
|
||||
if (!window_copy_search_up(wme)) {
|
||||
if (!window_copy_search_up(wme, 0)) {
|
||||
window_copy_clear_marks(wme);
|
||||
return (WINDOW_COPY_CMD_REDRAW);
|
||||
}
|
||||
@ -1776,7 +1788,7 @@ window_copy_cmd_search_backward_incremental(struct window_copy_cmd_state *cs)
|
||||
data->searchtype = WINDOW_COPY_SEARCHDOWN;
|
||||
free(data->searchstr);
|
||||
data->searchstr = xstrdup(argument);
|
||||
if (!window_copy_search_down(wme)) {
|
||||
if (!window_copy_search_down(wme, 0)) {
|
||||
window_copy_clear_marks(wme);
|
||||
return (WINDOW_COPY_CMD_REDRAW);
|
||||
}
|
||||
@ -1816,7 +1828,7 @@ window_copy_cmd_search_forward_incremental(struct window_copy_cmd_state *cs)
|
||||
data->searchtype = WINDOW_COPY_SEARCHDOWN;
|
||||
free(data->searchstr);
|
||||
data->searchstr = xstrdup(argument);
|
||||
if (!window_copy_search_down(wme)) {
|
||||
if (!window_copy_search_down(wme, 0)) {
|
||||
window_copy_clear_marks(wme);
|
||||
return (WINDOW_COPY_CMD_REDRAW);
|
||||
}
|
||||
@ -1825,7 +1837,7 @@ window_copy_cmd_search_forward_incremental(struct window_copy_cmd_state *cs)
|
||||
data->searchtype = WINDOW_COPY_SEARCHUP;
|
||||
free(data->searchstr);
|
||||
data->searchstr = xstrdup(argument);
|
||||
if (!window_copy_search_up(wme)) {
|
||||
if (!window_copy_search_up(wme, 0)) {
|
||||
window_copy_clear_marks(wme);
|
||||
return (WINDOW_COPY_CMD_REDRAW);
|
||||
}
|
||||
@ -2152,6 +2164,297 @@ window_copy_search_rl(struct grid *gd,
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
window_copy_search_lr_regex(struct grid *gd, struct grid *sgd,
|
||||
u_int *ppx, u_int *psx, u_int py, u_int first, u_int last, int cis)
|
||||
{
|
||||
int cflags = REG_EXTENDED, eflags = 0;
|
||||
u_int endline, foundx, foundy, len, pywrap, size = 1;
|
||||
u_int ssize = 1;
|
||||
char *buf, *sbuf;
|
||||
regex_t reg;
|
||||
regmatch_t regmatch;
|
||||
struct grid_line *gl;
|
||||
|
||||
/*
|
||||
* This can happen during search if the last match was the last
|
||||
* character on a line.
|
||||
*/
|
||||
if (first >= last)
|
||||
return (0);
|
||||
|
||||
sbuf = xmalloc(ssize);
|
||||
sbuf[0] = '\0';
|
||||
sbuf = window_copy_stringify(sgd, 0, 0, sgd->sx, sbuf, &ssize);
|
||||
if (sbuf == NULL)
|
||||
return (0);
|
||||
|
||||
/* Set flags for regex search. */
|
||||
if (cis)
|
||||
cflags |= REG_ICASE;
|
||||
if (regcomp(®, sbuf, cflags) != 0) {
|
||||
free(sbuf);
|
||||
return (0);
|
||||
}
|
||||
if (first != 0)
|
||||
eflags |= REG_NOTBOL;
|
||||
|
||||
/* Need to look at the entire string. */
|
||||
buf = xmalloc(size);
|
||||
buf[0] = '\0';
|
||||
buf = window_copy_stringify(gd, py, first, gd->sx, buf, &size);
|
||||
len = gd->sx - first;
|
||||
endline = gd->hsize + gd->sy - 1;
|
||||
pywrap = py;
|
||||
while (buf != NULL && pywrap <= endline) {
|
||||
gl = grid_get_line(gd, pywrap);
|
||||
if (~gl->flags & GRID_LINE_WRAPPED)
|
||||
break;
|
||||
pywrap++;
|
||||
buf = window_copy_stringify(gd, pywrap, 0, gd->sx, buf, &size);
|
||||
len += gd->sx;
|
||||
}
|
||||
|
||||
if (regexec(®, buf, 1, ®match, eflags) == 0) {
|
||||
foundx = first;
|
||||
foundy = py;
|
||||
window_copy_cstrtocellpos(gd, len, &foundx, &foundy,
|
||||
buf + regmatch.rm_so);
|
||||
if (foundy == py && foundx < last) {
|
||||
*ppx = foundx;
|
||||
len -= foundx - first;
|
||||
window_copy_cstrtocellpos(gd, len, &foundx, &foundy,
|
||||
buf + regmatch.rm_eo);
|
||||
*psx = foundx;
|
||||
while (foundy > py) {
|
||||
*psx += gd->sx;
|
||||
foundy--;
|
||||
}
|
||||
*psx -= *ppx;
|
||||
regfree(®);
|
||||
free(sbuf);
|
||||
free(buf);
|
||||
return (1);
|
||||
}
|
||||
}
|
||||
|
||||
regfree(®);
|
||||
free(sbuf);
|
||||
free(buf);
|
||||
*ppx = 0;
|
||||
*psx = 0;
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
window_copy_search_rl_regex(struct grid *gd, struct grid *sgd,
|
||||
u_int *ppx, u_int *psx, u_int py, u_int first, u_int last, int cis)
|
||||
{
|
||||
int cflags = REG_EXTENDED, eflags = 0;
|
||||
u_int endline, len, pywrap, size = 1, ssize = 1;
|
||||
char *buf, *sbuf;
|
||||
regex_t reg;
|
||||
struct grid_line *gl;
|
||||
|
||||
sbuf = xmalloc(ssize);
|
||||
sbuf[0] = '\0';
|
||||
sbuf = window_copy_stringify(sgd, 0, 0, sgd->sx, sbuf, &ssize);
|
||||
if (sbuf == NULL)
|
||||
return (0);
|
||||
|
||||
/* Set flags for regex search. */
|
||||
if (cis)
|
||||
cflags |= REG_ICASE;
|
||||
if (regcomp(®, sbuf, cflags) != 0) {
|
||||
free(sbuf);
|
||||
return (0);
|
||||
}
|
||||
if (first != 0)
|
||||
eflags |= REG_NOTBOL;
|
||||
|
||||
/* Need to look at the entire string. */
|
||||
buf = xmalloc(size);
|
||||
buf[0] = '\0';
|
||||
buf = window_copy_stringify(gd, py, first, gd->sx, buf, &size);
|
||||
len = gd->sx - first;
|
||||
endline = gd->hsize + gd->sy - 1;
|
||||
pywrap = py;
|
||||
while (buf != NULL && (pywrap <= endline)) {
|
||||
gl = grid_get_line(gd, pywrap);
|
||||
if (~gl->flags & GRID_LINE_WRAPPED)
|
||||
break;
|
||||
pywrap++;
|
||||
buf = window_copy_stringify(gd, pywrap, 0, gd->sx, buf, &size);
|
||||
len += gd->sx;
|
||||
}
|
||||
|
||||
if (window_copy_last_regex(gd, py, first, last, len, ppx, psx, buf,
|
||||
®, eflags))
|
||||
{
|
||||
regfree(®);
|
||||
free(sbuf);
|
||||
free(buf);
|
||||
return (1);
|
||||
}
|
||||
|
||||
regfree(®);
|
||||
free(sbuf);
|
||||
free(buf);
|
||||
*ppx = 0;
|
||||
*psx = 0;
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* Find last match in given range. */
|
||||
static int
|
||||
window_copy_last_regex(struct grid *gd, u_int py, u_int first, u_int last,
|
||||
u_int len, u_int *ppx, u_int *psx, const char *buf, const regex_t *preg,
|
||||
int eflags)
|
||||
{
|
||||
u_int foundx, foundy, oldx, px = 0, savepx, savesx = 0;
|
||||
regmatch_t regmatch;
|
||||
|
||||
foundx = first;
|
||||
foundy = py;
|
||||
oldx = first;
|
||||
while (regexec(preg, buf + px, 1, ®match, eflags) == 0) {
|
||||
window_copy_cstrtocellpos(gd, len, &foundx, &foundy,
|
||||
buf + px + regmatch.rm_so);
|
||||
if (foundy > py || foundx >= last)
|
||||
break;
|
||||
len -= foundx - oldx;
|
||||
savepx = foundx;
|
||||
window_copy_cstrtocellpos(gd, len, &foundx, &foundy,
|
||||
buf + px + regmatch.rm_eo);
|
||||
if (foundy > py || foundx >= last) {
|
||||
*ppx = savepx;
|
||||
*psx = foundx;
|
||||
while (foundy > py) {
|
||||
*psx += gd->sx;
|
||||
foundy--;
|
||||
}
|
||||
*psx -= *ppx;
|
||||
return (1);
|
||||
} else {
|
||||
savesx = foundx - savepx;
|
||||
len -= savesx;
|
||||
oldx = foundx;
|
||||
}
|
||||
px += regmatch.rm_eo;
|
||||
}
|
||||
|
||||
if (savesx > 0) {
|
||||
*ppx = savepx;
|
||||
*psx = savesx;
|
||||
return (1);
|
||||
} else {
|
||||
*ppx = 0;
|
||||
*psx = 0;
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
|
||||
/* Stringify line and append to input buffer. Caller frees. */
|
||||
static char *
|
||||
window_copy_stringify(struct grid *gd, u_int py, u_int first, u_int last,
|
||||
char *buf, u_int *size)
|
||||
{
|
||||
u_int ax, bx, newsize;
|
||||
struct grid_cell gc;
|
||||
|
||||
bx = *size - 1;
|
||||
newsize = *size;
|
||||
for (ax = first; ax < last; ax++) {
|
||||
grid_get_cell(gd, ax, py, &gc);
|
||||
newsize += gc.data.size;
|
||||
buf = xrealloc(buf, newsize);
|
||||
memcpy(buf + bx, gc.data.data, gc.data.size);
|
||||
bx += gc.data.size;
|
||||
}
|
||||
|
||||
buf[newsize - 1] = '\0';
|
||||
*size = newsize;
|
||||
return (buf);
|
||||
}
|
||||
|
||||
/* Map start of C string containing UTF-8 data to grid cell position. */
|
||||
static void
|
||||
window_copy_cstrtocellpos(struct grid *gd, u_int ncells, u_int *ppx, u_int *ppy,
|
||||
const char *str)
|
||||
{
|
||||
u_int cell, ccell, px, pywrap;
|
||||
int match;
|
||||
const char *cstr;
|
||||
char *celldata, **cells;
|
||||
struct grid_cell gc;
|
||||
|
||||
/* Set up staggered array of cell contents. This speeds up search. */
|
||||
cells = xreallocarray(NULL, ncells, sizeof cells[0]);
|
||||
|
||||
/* Populate the array of cell data. */
|
||||
cell = 0;
|
||||
px = *ppx;
|
||||
pywrap = *ppy;
|
||||
while (cell < ncells) {
|
||||
grid_get_cell(gd, px, pywrap, &gc);
|
||||
celldata = xmalloc(gc.data.size + 1);
|
||||
memcpy(celldata, gc.data.data, gc.data.size);
|
||||
celldata[gc.data.size] = '\0';
|
||||
cells[cell] = celldata;
|
||||
cell++;
|
||||
px = (px + 1) % gd->sx;
|
||||
if (px == 0)
|
||||
pywrap++;
|
||||
}
|
||||
|
||||
/* Locate starting cell. */
|
||||
cell = 0;
|
||||
while (cell < ncells) {
|
||||
ccell = cell;
|
||||
cstr = str;
|
||||
match = 1;
|
||||
while (ccell < ncells) {
|
||||
/* Anchor found to the end. */
|
||||
if (*cstr == '\0') {
|
||||
match = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
celldata = cells[ccell];
|
||||
while (*celldata != '\0' && *cstr != '\0') {
|
||||
if (*celldata++ != *cstr++) {
|
||||
match = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!match)
|
||||
break;
|
||||
ccell++;
|
||||
}
|
||||
|
||||
if (match)
|
||||
break;
|
||||
cell++;
|
||||
}
|
||||
|
||||
/* If not found this will be one past the end. */
|
||||
px = *ppx + cell;
|
||||
pywrap = *ppy;
|
||||
while (px >= gd->sx) {
|
||||
px -= gd->sx;
|
||||
pywrap++;
|
||||
}
|
||||
|
||||
*ppx = px;
|
||||
*ppy = pywrap;
|
||||
|
||||
/* Free cell data. */
|
||||
for (cell = 0; cell < ncells; cell++)
|
||||
free(cells[cell]);
|
||||
free(cells);
|
||||
}
|
||||
|
||||
static void
|
||||
window_copy_move_left(struct screen *s, u_int *fx, u_int *fy, int wrapflag)
|
||||
{
|
||||
@ -2206,24 +2509,31 @@ window_copy_is_lowercase(const char *ptr)
|
||||
static int
|
||||
window_copy_search_jump(struct window_mode_entry *wme, struct grid *gd,
|
||||
struct grid *sgd, u_int fx, u_int fy, u_int endline, int cis, int wrap,
|
||||
int direction)
|
||||
int direction, int regex)
|
||||
{
|
||||
u_int i, px;
|
||||
int found;
|
||||
u_int i, px, sx;
|
||||
int found = 0;
|
||||
|
||||
found = 0;
|
||||
if (direction) {
|
||||
for (i = fy; i <= endline; i++) {
|
||||
found = window_copy_search_lr(gd, sgd, &px, i, fx,
|
||||
gd->sx, cis);
|
||||
if (regex)
|
||||
found = window_copy_search_lr_regex(gd, sgd,
|
||||
&px, &sx, i, fx, gd->sx, cis);
|
||||
else
|
||||
found = window_copy_search_lr(gd, sgd,
|
||||
&px, i, fx, gd->sx, cis);
|
||||
if (found)
|
||||
break;
|
||||
fx = 0;
|
||||
}
|
||||
} else {
|
||||
for (i = fy + 1; endline < i; i--) {
|
||||
found = window_copy_search_rl(gd, sgd, &px, i - 1, 0,
|
||||
fx + 1, cis);
|
||||
if (regex)
|
||||
found = window_copy_search_rl_regex(gd, sgd,
|
||||
&px, &sx, i - 1, 0, fx + 1, cis);
|
||||
else
|
||||
found = window_copy_search_rl(gd, sgd,
|
||||
&px, i - 1, 0, fx + 1, cis);
|
||||
if (found) {
|
||||
i--;
|
||||
break;
|
||||
@ -2240,7 +2550,7 @@ window_copy_search_jump(struct window_mode_entry *wme, struct grid *gd,
|
||||
return (window_copy_search_jump(wme, gd, sgd,
|
||||
direction ? 0 : gd->sx - 1,
|
||||
direction ? 0 : gd->hsize + gd->sy - 1, fy, cis, 0,
|
||||
direction));
|
||||
direction, regex));
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
@ -2250,7 +2560,7 @@ window_copy_search_jump(struct window_mode_entry *wme, struct grid *gd,
|
||||
* down.
|
||||
*/
|
||||
static int
|
||||
window_copy_search(struct window_mode_entry *wme, int direction)
|
||||
window_copy_search(struct window_mode_entry *wme, int direction, int regex)
|
||||
{
|
||||
struct window_pane *wp = wme->wp;
|
||||
struct window_copy_mode_data *data = wme->data;
|
||||
@ -2281,10 +2591,11 @@ window_copy_search(struct window_mode_entry *wme, int direction)
|
||||
window_copy_move_left(s, &fx, &fy, wrapflag);
|
||||
endline = 0;
|
||||
}
|
||||
found = window_copy_search_jump(wme, gd, ss.grid, fx, fy, endline, cis,
|
||||
wrapflag, direction);
|
||||
|
||||
if (window_copy_search_marks(wme, &ss))
|
||||
found = window_copy_search_jump(wme, gd, ss.grid, fx, fy, endline, cis,
|
||||
wrapflag, direction, regex);
|
||||
|
||||
if (window_copy_search_marks(wme, &ss, regex))
|
||||
window_copy_redraw_screen(wme);
|
||||
|
||||
screen_free(&ss);
|
||||
@ -2292,7 +2603,8 @@ window_copy_search(struct window_mode_entry *wme, int direction)
|
||||
}
|
||||
|
||||
static int
|
||||
window_copy_search_marks(struct window_mode_entry *wme, struct screen *ssp)
|
||||
window_copy_search_marks(struct window_mode_entry *wme, struct screen *ssp,
|
||||
int regex)
|
||||
{
|
||||
struct window_copy_mode_data *data = wme->data;
|
||||
struct screen *s = data->backing, ss;
|
||||
@ -2320,10 +2632,19 @@ window_copy_search_marks(struct window_mode_entry *wme, struct screen *ssp)
|
||||
for (py = 0; py < gd->hsize + gd->sy; py++) {
|
||||
px = 0;
|
||||
for (;;) {
|
||||
found = window_copy_search_lr(gd, ssp->grid, &px, py,
|
||||
px, gd->sx, cis);
|
||||
if (!found)
|
||||
break;
|
||||
if (regex) {
|
||||
found = window_copy_search_lr_regex(gd,
|
||||
ssp->grid, &px, &width, py, px,
|
||||
gd->sx, cis);
|
||||
if (!found)
|
||||
break;
|
||||
}
|
||||
else {
|
||||
found = window_copy_search_lr(gd, ssp->grid,
|
||||
&px, py, px, gd->sx, cis);
|
||||
if (!found)
|
||||
break;
|
||||
}
|
||||
|
||||
nfound++;
|
||||
if (px == data->cx && py == gd->hsize + data->cy - data->oy)
|
||||
@ -2357,15 +2678,15 @@ window_copy_clear_marks(struct window_mode_entry *wme)
|
||||
}
|
||||
|
||||
static int
|
||||
window_copy_search_up(struct window_mode_entry *wme)
|
||||
window_copy_search_up(struct window_mode_entry *wme, int regex)
|
||||
{
|
||||
return (window_copy_search(wme, 0));
|
||||
return (window_copy_search(wme, 0, regex));
|
||||
}
|
||||
|
||||
static int
|
||||
window_copy_search_down(struct window_mode_entry *wme)
|
||||
window_copy_search_down(struct window_mode_entry *wme, int regex)
|
||||
{
|
||||
return (window_copy_search(wme, 1));
|
||||
return (window_copy_search(wme, 1, regex));
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -33,7 +33,7 @@ static void window_tree_key(struct window_mode_entry *,
|
||||
struct client *, struct session *,
|
||||
struct winlink *, key_code, struct mouse_event *);
|
||||
|
||||
#define WINDOW_TREE_DEFAULT_COMMAND "switch-client -t '%%'"
|
||||
#define WINDOW_TREE_DEFAULT_COMMAND "switch-client -Zt '%%'"
|
||||
|
||||
#define WINDOW_TREE_DEFAULT_FORMAT \
|
||||
"#{?pane_format," \
|
||||
|
Loading…
Reference in New Issue
Block a user