mirror of
https://github.com/tmux/tmux.git
synced 2025-03-29 10:18:49 +00:00
Merge branch 'obsd-master'
Conflicts: Makefile tmux.1
This commit is contained in:
commit
94a8ef1cae
@ -80,6 +80,7 @@ dist_tmux_SOURCES = \
|
|||||||
cmd-detach-client.c \
|
cmd-detach-client.c \
|
||||||
cmd-display-message.c \
|
cmd-display-message.c \
|
||||||
cmd-display-panes.c \
|
cmd-display-panes.c \
|
||||||
|
cmd-find.c \
|
||||||
cmd-find-window.c \
|
cmd-find-window.c \
|
||||||
cmd-if-shell.c \
|
cmd-if-shell.c \
|
||||||
cmd-join-pane.c \
|
cmd-join-pane.c \
|
||||||
|
18
cfg.c
18
cfg.c
@ -26,12 +26,12 @@
|
|||||||
|
|
||||||
#include "tmux.h"
|
#include "tmux.h"
|
||||||
|
|
||||||
struct cmd_q *cfg_cmd_q;
|
struct cmd_q *cfg_cmd_q;
|
||||||
int cfg_finished;
|
int cfg_finished;
|
||||||
int cfg_references;
|
int cfg_references;
|
||||||
char** cfg_causes;
|
char **cfg_causes;
|
||||||
u_int cfg_ncauses;
|
u_int cfg_ncauses;
|
||||||
struct client *cfg_client;
|
struct client *cfg_client;
|
||||||
|
|
||||||
int
|
int
|
||||||
load_cfg(const char *path, struct cmd_q *cmdq, char **cause)
|
load_cfg(const char *path, struct cmd_q *cmdq, char **cause)
|
||||||
@ -113,10 +113,10 @@ cfg_default_done(unused struct cmd_q *cmdq)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
cfg_add_cause(const char* fmt, ...)
|
cfg_add_cause(const char *fmt, ...)
|
||||||
{
|
{
|
||||||
va_list ap;
|
va_list ap;
|
||||||
char* msg;
|
char *msg;
|
||||||
|
|
||||||
va_start(ap, fmt);
|
va_start(ap, fmt);
|
||||||
xvasprintf(&msg, fmt, ap);
|
xvasprintf(&msg, fmt, ap);
|
||||||
|
@ -53,7 +53,7 @@ cmd_choose_buffer_exec(struct cmd *self, struct cmd_q *cmdq)
|
|||||||
u_int idx;
|
u_int idx;
|
||||||
int utf8flag;
|
int utf8flag;
|
||||||
|
|
||||||
if ((c = cmd_current_client(cmdq)) == NULL) {
|
if ((c = cmd_find_client(cmdq, NULL, 1)) == NULL) {
|
||||||
cmdq_error(cmdq, "no client available");
|
cmdq_error(cmdq, "no client available");
|
||||||
return (CMD_RETURN_ERROR);
|
return (CMD_RETURN_ERROR);
|
||||||
}
|
}
|
||||||
|
@ -61,7 +61,7 @@ cmd_choose_client_exec(struct cmd *self, struct cmd_q *cmdq)
|
|||||||
char *action;
|
char *action;
|
||||||
u_int idx, cur;
|
u_int idx, cur;
|
||||||
|
|
||||||
if ((c = cmd_current_client(cmdq)) == NULL) {
|
if ((c = cmd_find_client(cmdq, NULL, 1)) == NULL) {
|
||||||
cmdq_error(cmdq, "no client available");
|
cmdq_error(cmdq, "no client available");
|
||||||
return (CMD_RETURN_ERROR);
|
return (CMD_RETURN_ERROR);
|
||||||
}
|
}
|
||||||
|
@ -87,7 +87,7 @@ cmd_choose_tree_exec(struct cmd *self, struct cmd_q *cmdq)
|
|||||||
ses_template = win_template = NULL;
|
ses_template = win_template = NULL;
|
||||||
ses_action = win_action = NULL;
|
ses_action = win_action = NULL;
|
||||||
|
|
||||||
if ((c = cmd_current_client(cmdq)) == NULL) {
|
if ((c = cmd_find_client(cmdq, NULL, 1)) == NULL) {
|
||||||
cmdq_error(cmdq, "no client available");
|
cmdq_error(cmdq, "no client available");
|
||||||
return (CMD_RETURN_ERROR);
|
return (CMD_RETURN_ERROR);
|
||||||
}
|
}
|
||||||
|
@ -78,7 +78,7 @@ cmd_display_message_exec(struct cmd *self, struct cmd_q *cmdq)
|
|||||||
if (c == NULL)
|
if (c == NULL)
|
||||||
return (CMD_RETURN_ERROR);
|
return (CMD_RETURN_ERROR);
|
||||||
} else {
|
} else {
|
||||||
c = cmd_current_client(cmdq);
|
c = cmd_find_client(cmdq, NULL, 1);
|
||||||
if (c == NULL && !args_has(self->args, 'p')) {
|
if (c == NULL && !args_has(self->args, 'p')) {
|
||||||
cmdq_error(cmdq, "no client available");
|
cmdq_error(cmdq, "no client available");
|
||||||
return (CMD_RETURN_ERROR);
|
return (CMD_RETURN_ERROR);
|
||||||
|
@ -143,7 +143,7 @@ cmd_find_window_exec(struct cmd *self, struct cmd_q *cmdq)
|
|||||||
const char *template;
|
const char *template;
|
||||||
u_int i, match_flags;
|
u_int i, match_flags;
|
||||||
|
|
||||||
if ((c = cmd_current_client(cmdq)) == NULL) {
|
if ((c = cmd_find_client(cmdq, NULL, 1)) == NULL) {
|
||||||
cmdq_error(cmdq, "no client available");
|
cmdq_error(cmdq, "no client available");
|
||||||
return (CMD_RETURN_ERROR);
|
return (CMD_RETURN_ERROR);
|
||||||
}
|
}
|
||||||
|
1114
cmd-find.c
Normal file
1114
cmd-find.c
Normal file
File diff suppressed because it is too large
Load Diff
@ -72,7 +72,7 @@ cmd_load_buffer_exec(struct cmd *self, struct cmd_q *cmdq)
|
|||||||
|
|
||||||
if (c != NULL && c->session == NULL)
|
if (c != NULL && c->session == NULL)
|
||||||
cwd = c->cwd;
|
cwd = c->cwd;
|
||||||
else if ((s = cmd_current_session(cmdq, 0)) != NULL)
|
else if ((s = cmd_find_current(cmdq)) != NULL)
|
||||||
cwd = s->cwd;
|
cwd = s->cwd;
|
||||||
else
|
else
|
||||||
cwd = AT_FDCWD;
|
cwd = AT_FDCWD;
|
||||||
|
@ -137,7 +137,7 @@ cmd_new_session_exec(struct cmd *self, struct cmd_q *cmdq)
|
|||||||
cwd = fd;
|
cwd = fd;
|
||||||
} else if (c != NULL && c->session == NULL)
|
} else if (c != NULL && c->session == NULL)
|
||||||
cwd = c->cwd;
|
cwd = c->cwd;
|
||||||
else if ((c0 = cmd_current_client(cmdq)) != NULL)
|
else if ((c0 = cmd_find_client(cmdq, NULL, 1)) != NULL)
|
||||||
cwd = c0->session->cwd;
|
cwd = c0->session->cwd;
|
||||||
else {
|
else {
|
||||||
fd = open(".", O_RDONLY);
|
fd = open(".", O_RDONLY);
|
||||||
|
@ -92,7 +92,7 @@ cmd_save_buffer_exec(struct cmd *self, struct cmd_q *cmdq)
|
|||||||
|
|
||||||
if (c != NULL && c->session == NULL)
|
if (c != NULL && c->session == NULL)
|
||||||
cwd = c->cwd;
|
cwd = c->cwd;
|
||||||
else if ((s = cmd_current_session(cmdq, 0)) != NULL)
|
else if ((s = cmd_find_current(cmdq)) != NULL)
|
||||||
cwd = s->cwd;
|
cwd = s->cwd;
|
||||||
else
|
else
|
||||||
cwd = AT_FDCWD;
|
cwd = AT_FDCWD;
|
||||||
|
@ -77,12 +77,6 @@ cmd_select_pane_exec(struct cmd *self, struct cmd_q *cmdq)
|
|||||||
if ((wl = cmd_find_pane(cmdq, args_get(args, 't'), NULL, &wp)) == NULL)
|
if ((wl = cmd_find_pane(cmdq, args_get(args, 't'), NULL, &wp)) == NULL)
|
||||||
return (CMD_RETURN_ERROR);
|
return (CMD_RETURN_ERROR);
|
||||||
|
|
||||||
server_unzoom_window(wp->window);
|
|
||||||
if (!window_pane_visible(wp)) {
|
|
||||||
cmdq_error(cmdq, "pane not visible");
|
|
||||||
return (CMD_RETURN_ERROR);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (args_has(self->args, 'P') || args_has(self->args, 'g')) {
|
if (args_has(self->args, 'P') || args_has(self->args, 'g')) {
|
||||||
if (args_has(args, 'P')) {
|
if (args_has(args, 'P')) {
|
||||||
style = args_get(args, 'P');
|
style = args_get(args, 'P');
|
||||||
@ -111,11 +105,23 @@ cmd_select_pane_exec(struct cmd *self, struct cmd_q *cmdq)
|
|||||||
return (CMD_RETURN_ERROR);
|
return (CMD_RETURN_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (args_has(self->args, 'e'))
|
if (args_has(self->args, 'e')) {
|
||||||
wp->flags &= ~PANE_INPUTOFF;
|
wp->flags &= ~PANE_INPUTOFF;
|
||||||
else if (args_has(self->args, 'd'))
|
return (CMD_RETURN_NORMAL);
|
||||||
|
}
|
||||||
|
if (args_has(self->args, 'd')) {
|
||||||
wp->flags |= PANE_INPUTOFF;
|
wp->flags |= PANE_INPUTOFF;
|
||||||
else if (window_set_active_pane(wl->window, wp)) {
|
return (CMD_RETURN_NORMAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (wp == wl->window->active)
|
||||||
|
return (CMD_RETURN_NORMAL);
|
||||||
|
server_unzoom_window(wp->window);
|
||||||
|
if (!window_pane_visible(wp)) {
|
||||||
|
cmdq_error(cmdq, "pane not visible");
|
||||||
|
return (CMD_RETURN_ERROR);
|
||||||
|
}
|
||||||
|
if (window_set_active_pane(wl->window, wp)) {
|
||||||
server_status_window(wl->window);
|
server_status_window(wl->window);
|
||||||
server_redraw_window_borders(wl->window);
|
server_redraw_window_borders(wl->window);
|
||||||
}
|
}
|
||||||
|
@ -146,6 +146,7 @@ cmd_split_window_exec(struct cmd *self, struct cmd_q *cmdq)
|
|||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
new_wp = window_add_pane(w, hlimit);
|
new_wp = window_add_pane(w, hlimit);
|
||||||
|
layout_assign_pane(lc, new_wp);
|
||||||
|
|
||||||
path = NULL;
|
path = NULL;
|
||||||
if (cmdq->client != NULL && cmdq->client->session == NULL)
|
if (cmdq->client != NULL && cmdq->client->session == NULL)
|
||||||
@ -158,7 +159,6 @@ cmd_split_window_exec(struct cmd *self, struct cmd_q *cmdq)
|
|||||||
if (window_pane_spawn(new_wp, argc, argv, path, shell, cwd, &env,
|
if (window_pane_spawn(new_wp, argc, argv, path, shell, cwd, &env,
|
||||||
s->tio, &cause) != 0)
|
s->tio, &cause) != 0)
|
||||||
goto error;
|
goto error;
|
||||||
layout_assign_pane(lc, new_wp);
|
|
||||||
|
|
||||||
server_redraw_window(w);
|
server_redraw_window(w);
|
||||||
|
|
||||||
@ -193,8 +193,10 @@ cmd_split_window_exec(struct cmd *self, struct cmd_q *cmdq)
|
|||||||
|
|
||||||
error:
|
error:
|
||||||
environ_free(&env);
|
environ_free(&env);
|
||||||
if (new_wp != NULL)
|
if (new_wp != NULL) {
|
||||||
|
layout_close_pane(new_wp);
|
||||||
window_remove_pane(w, new_wp);
|
window_remove_pane(w, new_wp);
|
||||||
|
}
|
||||||
cmdq_error(cmdq, "create pane failed: %s", cause);
|
cmdq_error(cmdq, "create pane failed: %s", cause);
|
||||||
free(cause);
|
free(cause);
|
||||||
if (fd != -1)
|
if (fd != -1)
|
||||||
|
937
cmd.c
937
cmd.c
@ -115,24 +115,6 @@ const struct cmd_entry *cmd_table[] = {
|
|||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
ARRAY_DECL(client_list, struct client *);
|
|
||||||
ARRAY_DECL(sessionslist, struct session *);
|
|
||||||
|
|
||||||
int cmd_session_better(struct session *, struct session *, int);
|
|
||||||
struct session *cmd_choose_session_list(struct sessionslist *);
|
|
||||||
struct session *cmd_choose_session(int);
|
|
||||||
struct client *cmd_choose_client(struct client_list *);
|
|
||||||
struct client *cmd_lookup_client(const char *);
|
|
||||||
struct session *cmd_lookup_session(struct cmd_q *, const char *, int *);
|
|
||||||
struct winlink *cmd_lookup_window(struct session *, const char *, int *);
|
|
||||||
int cmd_lookup_index(struct session *, const char *, int *);
|
|
||||||
struct winlink *cmd_lookup_winlink_windowid(struct session *, const char *);
|
|
||||||
struct session *cmd_window_session(struct cmd_q *, struct window *,
|
|
||||||
struct winlink **);
|
|
||||||
struct winlink *cmd_find_window_offset(const char *, struct session *, int *);
|
|
||||||
int cmd_find_index_offset(const char *, struct session *, int *);
|
|
||||||
struct window_pane *cmd_find_pane_offset(const char *, struct winlink *);
|
|
||||||
|
|
||||||
int
|
int
|
||||||
cmd_pack_argv(int argc, char **argv, char *buf, size_t len)
|
cmd_pack_argv(int argc, char **argv, char *buf, size_t len)
|
||||||
{
|
{
|
||||||
@ -331,183 +313,6 @@ cmd_print(struct cmd *cmd, char *buf, size_t len)
|
|||||||
return (off);
|
return (off);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Figure out the current session. Use: 1) the current session, if the command
|
|
||||||
* context has one; 2) the most recently used session containing the pty of the
|
|
||||||
* calling client, if any; 3) the session specified in the TMUX variable from
|
|
||||||
* the environment (as passed from the client); 4) the most recently used
|
|
||||||
* session from all sessions.
|
|
||||||
*/
|
|
||||||
struct session *
|
|
||||||
cmd_current_session(struct cmd_q *cmdq, int prefer_unattached)
|
|
||||||
{
|
|
||||||
struct client *c = cmdq->client;
|
|
||||||
struct session *s;
|
|
||||||
struct sessionslist ss;
|
|
||||||
struct winlink *wl;
|
|
||||||
struct window_pane *wp;
|
|
||||||
const char *path;
|
|
||||||
int found;
|
|
||||||
|
|
||||||
/* Try the queue session. */
|
|
||||||
if (c != NULL && c->session != NULL)
|
|
||||||
return (c->session);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If the name of the calling client's pty is known, build a list of
|
|
||||||
* the sessions that contain it and if any choose either the first or
|
|
||||||
* the newest.
|
|
||||||
*/
|
|
||||||
path = c == NULL ? NULL : c->tty.path;
|
|
||||||
if (path != NULL) {
|
|
||||||
ARRAY_INIT(&ss);
|
|
||||||
RB_FOREACH(s, sessions, &sessions) {
|
|
||||||
found = 0;
|
|
||||||
RB_FOREACH(wl, winlinks, &s->windows) {
|
|
||||||
TAILQ_FOREACH(wp, &wl->window->panes, entry) {
|
|
||||||
if (strcmp(wp->tty, path) == 0) {
|
|
||||||
found = 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (found)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (found)
|
|
||||||
ARRAY_ADD(&ss, s);
|
|
||||||
}
|
|
||||||
|
|
||||||
s = cmd_choose_session_list(&ss);
|
|
||||||
ARRAY_FREE(&ss);
|
|
||||||
if (s != NULL)
|
|
||||||
return (s);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (cmd_choose_session(prefer_unattached));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Is this session better? */
|
|
||||||
int
|
|
||||||
cmd_session_better(struct session *s, struct session *best,
|
|
||||||
int prefer_unattached)
|
|
||||||
{
|
|
||||||
if (best == NULL)
|
|
||||||
return (1);
|
|
||||||
if (prefer_unattached) {
|
|
||||||
if (!(best->flags & SESSION_UNATTACHED) &&
|
|
||||||
(s->flags & SESSION_UNATTACHED))
|
|
||||||
return (1);
|
|
||||||
else if ((best->flags & SESSION_UNATTACHED) &&
|
|
||||||
!(s->flags & SESSION_UNATTACHED))
|
|
||||||
return (0);
|
|
||||||
}
|
|
||||||
return (timercmp(&s->activity_time, &best->activity_time, >));
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Find the most recently used session, preferring unattached if the flag is
|
|
||||||
* set.
|
|
||||||
*/
|
|
||||||
struct session *
|
|
||||||
cmd_choose_session(int prefer_unattached)
|
|
||||||
{
|
|
||||||
struct session *s, *best;
|
|
||||||
|
|
||||||
best = NULL;
|
|
||||||
RB_FOREACH(s, sessions, &sessions) {
|
|
||||||
if (cmd_session_better(s, best, prefer_unattached))
|
|
||||||
best = s;
|
|
||||||
}
|
|
||||||
return (best);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Find the most recently used session from a list. */
|
|
||||||
struct session *
|
|
||||||
cmd_choose_session_list(struct sessionslist *ss)
|
|
||||||
{
|
|
||||||
struct session *s, *sbest;
|
|
||||||
struct timeval *tv = NULL;
|
|
||||||
u_int i;
|
|
||||||
|
|
||||||
sbest = NULL;
|
|
||||||
for (i = 0; i < ARRAY_LENGTH(ss); i++) {
|
|
||||||
if ((s = ARRAY_ITEM(ss, i)) == NULL)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (tv == NULL || timercmp(&s->activity_time, tv, >)) {
|
|
||||||
sbest = s;
|
|
||||||
tv = &s->activity_time;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return (sbest);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Find the current client. First try the current client if set, then pick the
|
|
||||||
* most recently used of the clients attached to the current session if any,
|
|
||||||
* then of all clients.
|
|
||||||
*/
|
|
||||||
struct client *
|
|
||||||
cmd_current_client(struct cmd_q *cmdq)
|
|
||||||
{
|
|
||||||
struct session *s;
|
|
||||||
struct client *c;
|
|
||||||
struct client_list cc;
|
|
||||||
|
|
||||||
if (cmdq->client != NULL && cmdq->client->session != NULL)
|
|
||||||
return (cmdq->client);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* No current client set. Find the current session and return the
|
|
||||||
* newest of its clients.
|
|
||||||
*/
|
|
||||||
s = cmd_current_session(cmdq, 0);
|
|
||||||
if (s != NULL && !(s->flags & SESSION_UNATTACHED)) {
|
|
||||||
ARRAY_INIT(&cc);
|
|
||||||
TAILQ_FOREACH(c, &clients, entry) {
|
|
||||||
if (s == c->session)
|
|
||||||
ARRAY_ADD(&cc, c);
|
|
||||||
}
|
|
||||||
|
|
||||||
c = cmd_choose_client(&cc);
|
|
||||||
ARRAY_FREE(&cc);
|
|
||||||
if (c != NULL)
|
|
||||||
return (c);
|
|
||||||
}
|
|
||||||
|
|
||||||
ARRAY_INIT(&cc);
|
|
||||||
TAILQ_FOREACH(c, &clients, entry)
|
|
||||||
ARRAY_ADD(&cc, c);
|
|
||||||
c = cmd_choose_client(&cc);
|
|
||||||
ARRAY_FREE(&cc);
|
|
||||||
return (c);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Choose the most recently used client from a list. */
|
|
||||||
struct client *
|
|
||||||
cmd_choose_client(struct client_list *cc)
|
|
||||||
{
|
|
||||||
struct client *c, *cbest;
|
|
||||||
struct timeval *tv = NULL;
|
|
||||||
u_int i;
|
|
||||||
|
|
||||||
cbest = NULL;
|
|
||||||
for (i = 0; i < ARRAY_LENGTH(cc); i++) {
|
|
||||||
if ((c = ARRAY_ITEM(cc, i)) == NULL)
|
|
||||||
continue;
|
|
||||||
if (c->session == NULL)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (tv == NULL || timercmp(&c->activity_time, tv, >)) {
|
|
||||||
cbest = c;
|
|
||||||
tv = &c->activity_time;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return (cbest);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Adjust current mouse position for a pane. */
|
/* Adjust current mouse position for a pane. */
|
||||||
int
|
int
|
||||||
cmd_mouse_at(struct window_pane *wp, struct mouse_event *m, u_int *xp,
|
cmd_mouse_at(struct window_pane *wp, struct mouse_event *m, u_int *xp,
|
||||||
@ -559,7 +364,8 @@ cmd_mouse_window(struct mouse_event *m, struct session **sp)
|
|||||||
|
|
||||||
/* Get current mouse pane if any. */
|
/* Get current mouse pane if any. */
|
||||||
struct window_pane *
|
struct window_pane *
|
||||||
cmd_mouse_pane(struct mouse_event *m, struct session **sp, struct winlink **wlp)
|
cmd_mouse_pane(struct mouse_event *m, struct session **sp,
|
||||||
|
struct winlink **wlp)
|
||||||
{
|
{
|
||||||
struct winlink *wl;
|
struct winlink *wl;
|
||||||
struct window_pane *wp;
|
struct window_pane *wp;
|
||||||
@ -576,745 +382,6 @@ cmd_mouse_pane(struct mouse_event *m, struct session **sp, struct winlink **wlp)
|
|||||||
return (wp);
|
return (wp);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Find the target client or report an error and return NULL. */
|
|
||||||
struct client *
|
|
||||||
cmd_find_client(struct cmd_q *cmdq, const char *arg, int quiet)
|
|
||||||
{
|
|
||||||
struct client *c;
|
|
||||||
char *tmparg;
|
|
||||||
size_t arglen;
|
|
||||||
|
|
||||||
/* A NULL argument means the current client. */
|
|
||||||
if (arg == NULL) {
|
|
||||||
c = cmd_current_client(cmdq);
|
|
||||||
if (c == NULL && !quiet)
|
|
||||||
cmdq_error(cmdq, "no clients");
|
|
||||||
return (c);
|
|
||||||
}
|
|
||||||
tmparg = xstrdup(arg);
|
|
||||||
|
|
||||||
/* Trim a single trailing colon if any. */
|
|
||||||
arglen = strlen(tmparg);
|
|
||||||
if (arglen != 0 && tmparg[arglen - 1] == ':')
|
|
||||||
tmparg[arglen - 1] = '\0';
|
|
||||||
|
|
||||||
/* Find the client, if any. */
|
|
||||||
c = cmd_lookup_client(tmparg);
|
|
||||||
|
|
||||||
/* If no client found, report an error. */
|
|
||||||
if (c == NULL && !quiet)
|
|
||||||
cmdq_error(cmdq, "client not found: %s", tmparg);
|
|
||||||
|
|
||||||
free(tmparg);
|
|
||||||
return (c);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Lookup a client by device path. Either of a full match and a match without a
|
|
||||||
* leading _PATH_DEV ("/dev/") is accepted.
|
|
||||||
*/
|
|
||||||
struct client *
|
|
||||||
cmd_lookup_client(const char *name)
|
|
||||||
{
|
|
||||||
struct client *c;
|
|
||||||
const char *path;
|
|
||||||
|
|
||||||
TAILQ_FOREACH(c, &clients, entry) {
|
|
||||||
if (c->session == NULL || c->tty.path == NULL)
|
|
||||||
continue;
|
|
||||||
path = c->tty.path;
|
|
||||||
|
|
||||||
/* Check for exact matches. */
|
|
||||||
if (strcmp(name, path) == 0)
|
|
||||||
return (c);
|
|
||||||
|
|
||||||
/* Check without leading /dev if present. */
|
|
||||||
if (strncmp(path, _PATH_DEV, (sizeof _PATH_DEV) - 1) != 0)
|
|
||||||
continue;
|
|
||||||
if (strcmp(name, path + (sizeof _PATH_DEV) - 1) == 0)
|
|
||||||
return (c);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Lookup a session by name. If no session is found, NULL is returned. */
|
|
||||||
struct session *
|
|
||||||
cmd_lookup_session(struct cmd_q *cmdq, const char *name, int *ambiguous)
|
|
||||||
{
|
|
||||||
struct session *s, *sfound;
|
|
||||||
struct window *w;
|
|
||||||
struct window_pane *wp;
|
|
||||||
|
|
||||||
*ambiguous = 0;
|
|
||||||
|
|
||||||
/* Look for $id first. */
|
|
||||||
if ((s = session_find_by_id_str(name)) != NULL)
|
|
||||||
return (s);
|
|
||||||
|
|
||||||
/* Try as pane or window id. */
|
|
||||||
if ((wp = window_pane_find_by_id_str(name)) != NULL)
|
|
||||||
return (cmd_window_session(cmdq, wp->window, NULL));
|
|
||||||
if ((w = window_find_by_id_str(name)) != NULL)
|
|
||||||
return (cmd_window_session(cmdq, w, NULL));
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Look for matches. First look for exact matches - session names must
|
|
||||||
* be unique so an exact match can't be ambigious and can just be
|
|
||||||
* returned.
|
|
||||||
*/
|
|
||||||
if ((s = session_find(name)) != NULL)
|
|
||||||
return (s);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Otherwise look for partial matches, returning early if it is found to
|
|
||||||
* be ambiguous.
|
|
||||||
*/
|
|
||||||
sfound = NULL;
|
|
||||||
RB_FOREACH(s, sessions, &sessions) {
|
|
||||||
if (strncmp(name, s->name, strlen(name)) == 0 ||
|
|
||||||
fnmatch(name, s->name, 0) == 0) {
|
|
||||||
if (sfound != NULL) {
|
|
||||||
*ambiguous = 1;
|
|
||||||
return (NULL);
|
|
||||||
}
|
|
||||||
sfound = s;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return (sfound);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Lookup a window or return -1 if not found or ambigious. First try as an
|
|
||||||
* index and if invalid, use fnmatch or leading prefix. Return NULL but fill in
|
|
||||||
* idx if the window index is a valid number but there is no window with that
|
|
||||||
* index.
|
|
||||||
*/
|
|
||||||
struct winlink *
|
|
||||||
cmd_lookup_window(struct session *s, const char *name, int *ambiguous)
|
|
||||||
{
|
|
||||||
struct winlink *wl, *wlfound;
|
|
||||||
struct window *w;
|
|
||||||
struct window_pane *wp;
|
|
||||||
const char *errstr;
|
|
||||||
u_int idx;
|
|
||||||
|
|
||||||
*ambiguous = 0;
|
|
||||||
|
|
||||||
/* Try as pane or window id. */
|
|
||||||
if ((wl = cmd_lookup_winlink_windowid(s, name)) != NULL)
|
|
||||||
return (wl);
|
|
||||||
|
|
||||||
/* Lookup as pane or window id. */
|
|
||||||
if ((wp = window_pane_find_by_id_str(name)) != NULL) {
|
|
||||||
wl = winlink_find_by_window(&s->windows, wp->window);
|
|
||||||
if (wl != NULL)
|
|
||||||
return (wl);
|
|
||||||
}
|
|
||||||
if ((w = window_find_by_id_str(name)) != NULL) {
|
|
||||||
wl = winlink_find_by_window(&s->windows, w);
|
|
||||||
if (wl != NULL)
|
|
||||||
return (wl);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* First see if this is a valid window index in this session. */
|
|
||||||
idx = strtonum(name, 0, INT_MAX, &errstr);
|
|
||||||
if (errstr == NULL) {
|
|
||||||
if ((wl = winlink_find_by_index(&s->windows, idx)) != NULL)
|
|
||||||
return (wl);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Look for exact matches, error if more than one. */
|
|
||||||
wlfound = NULL;
|
|
||||||
RB_FOREACH(wl, winlinks, &s->windows) {
|
|
||||||
if (strcmp(name, wl->window->name) == 0) {
|
|
||||||
if (wlfound != NULL) {
|
|
||||||
*ambiguous = 1;
|
|
||||||
return (NULL);
|
|
||||||
}
|
|
||||||
wlfound = wl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (wlfound != NULL)
|
|
||||||
return (wlfound);
|
|
||||||
|
|
||||||
/* Now look for pattern matches, again error if multiple. */
|
|
||||||
wlfound = NULL;
|
|
||||||
RB_FOREACH(wl, winlinks, &s->windows) {
|
|
||||||
if (strncmp(name, wl->window->name, strlen(name)) == 0 ||
|
|
||||||
fnmatch(name, wl->window->name, 0) == 0) {
|
|
||||||
if (wlfound != NULL) {
|
|
||||||
*ambiguous = 1;
|
|
||||||
return (NULL);
|
|
||||||
}
|
|
||||||
wlfound = wl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (wlfound != NULL)
|
|
||||||
return (wlfound);
|
|
||||||
|
|
||||||
return (NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Find a window index - if the window doesn't exist, check if it is a
|
|
||||||
* potential index and return it anyway.
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
cmd_lookup_index(struct session *s, const char *name, int *ambiguous)
|
|
||||||
{
|
|
||||||
struct winlink *wl;
|
|
||||||
const char *errstr;
|
|
||||||
u_int idx;
|
|
||||||
|
|
||||||
idx = strtonum(name, 0, INT_MAX, &errstr);
|
|
||||||
if (errstr == NULL)
|
|
||||||
return (idx);
|
|
||||||
|
|
||||||
if ((wl = cmd_lookup_window(s, name, ambiguous)) != NULL)
|
|
||||||
return (wl->idx);
|
|
||||||
if (*ambiguous)
|
|
||||||
return (-1);
|
|
||||||
|
|
||||||
return (-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Lookup window id in a session. An initial @ means a window id. */
|
|
||||||
struct winlink *
|
|
||||||
cmd_lookup_winlink_windowid(struct session *s, const char *arg)
|
|
||||||
{
|
|
||||||
const char *errstr;
|
|
||||||
u_int windowid;
|
|
||||||
|
|
||||||
if (*arg != '@')
|
|
||||||
return (NULL);
|
|
||||||
|
|
||||||
windowid = strtonum(arg + 1, 0, UINT_MAX, &errstr);
|
|
||||||
if (errstr != NULL)
|
|
||||||
return (NULL);
|
|
||||||
return (winlink_find_by_window_id(&s->windows, windowid));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Find session and winlink for window. */
|
|
||||||
struct session *
|
|
||||||
cmd_window_session(struct cmd_q *cmdq, struct window *w, struct winlink **wlp)
|
|
||||||
{
|
|
||||||
struct session *s;
|
|
||||||
struct sessionslist ss;
|
|
||||||
struct winlink *wl;
|
|
||||||
|
|
||||||
/* If this window is in the current session, return that winlink. */
|
|
||||||
s = cmd_current_session(cmdq, 0);
|
|
||||||
if (s != NULL) {
|
|
||||||
wl = winlink_find_by_window(&s->windows, w);
|
|
||||||
if (wl != NULL) {
|
|
||||||
if (wlp != NULL)
|
|
||||||
*wlp = wl;
|
|
||||||
return (s);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Otherwise choose from all sessions with this window. */
|
|
||||||
ARRAY_INIT(&ss);
|
|
||||||
RB_FOREACH(s, sessions, &sessions) {
|
|
||||||
if (winlink_find_by_window(&s->windows, w) != NULL)
|
|
||||||
ARRAY_ADD(&ss, s);
|
|
||||||
}
|
|
||||||
s = cmd_choose_session_list(&ss);
|
|
||||||
ARRAY_FREE(&ss);
|
|
||||||
if (wlp != NULL)
|
|
||||||
*wlp = winlink_find_by_window(&s->windows, w);
|
|
||||||
return (s);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Find the target session or report an error and return NULL. */
|
|
||||||
struct session *
|
|
||||||
cmd_find_session(struct cmd_q *cmdq, const char *arg, int prefer_unattached)
|
|
||||||
{
|
|
||||||
struct session *s;
|
|
||||||
struct client *c;
|
|
||||||
char *tmparg;
|
|
||||||
size_t arglen;
|
|
||||||
int ambiguous;
|
|
||||||
|
|
||||||
/* A NULL argument means the current session. */
|
|
||||||
if (arg == NULL) {
|
|
||||||
if ((s = cmd_current_session(cmdq, prefer_unattached)) == NULL)
|
|
||||||
cmdq_error(cmdq, "can't establish current session");
|
|
||||||
return (s);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Trim a single trailing colon if any. */
|
|
||||||
tmparg = xstrdup(arg);
|
|
||||||
arglen = strlen(tmparg);
|
|
||||||
if (arglen != 0 && tmparg[arglen - 1] == ':')
|
|
||||||
tmparg[arglen - 1] = '\0';
|
|
||||||
|
|
||||||
/* An empty session name is the current session. */
|
|
||||||
if (*tmparg == '\0') {
|
|
||||||
free(tmparg);
|
|
||||||
if ((s = cmd_current_session(cmdq, prefer_unattached)) == NULL)
|
|
||||||
cmdq_error(cmdq, "can't establish current session");
|
|
||||||
return (s);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Find the session, if any. */
|
|
||||||
s = cmd_lookup_session(cmdq, tmparg, &ambiguous);
|
|
||||||
|
|
||||||
/* If it doesn't, try to match it as a client. */
|
|
||||||
if (s == NULL && (c = cmd_lookup_client(tmparg)) != NULL)
|
|
||||||
s = c->session;
|
|
||||||
|
|
||||||
/* If no session found, report an error. */
|
|
||||||
if (s == NULL) {
|
|
||||||
if (ambiguous)
|
|
||||||
cmdq_error(cmdq, "more than one session: %s", tmparg);
|
|
||||||
else
|
|
||||||
cmdq_error(cmdq, "session not found: %s", tmparg);
|
|
||||||
}
|
|
||||||
|
|
||||||
free(tmparg);
|
|
||||||
return (s);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Find the target session and window or report an error and return NULL. */
|
|
||||||
struct winlink *
|
|
||||||
cmd_find_window(struct cmd_q *cmdq, const char *arg, struct session **sp)
|
|
||||||
{
|
|
||||||
struct session *s;
|
|
||||||
struct winlink *wl;
|
|
||||||
const char *winptr;
|
|
||||||
char *sessptr = NULL;
|
|
||||||
int ambiguous = 0;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Find the current session. There must always be a current session, if
|
|
||||||
* it can't be found, report an error.
|
|
||||||
*/
|
|
||||||
if ((s = cmd_current_session(cmdq, 0)) == NULL) {
|
|
||||||
cmdq_error(cmdq, "can't establish current session");
|
|
||||||
return (NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* A NULL argument means the current session and window. */
|
|
||||||
if (arg == NULL) {
|
|
||||||
if (sp != NULL)
|
|
||||||
*sp = s;
|
|
||||||
return (s->curw);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Time to look at the argument. If it is empty, that is an error. */
|
|
||||||
if (*arg == '\0')
|
|
||||||
goto not_found;
|
|
||||||
|
|
||||||
/* Find the separating colon and split into window and session. */
|
|
||||||
winptr = strchr(arg, ':');
|
|
||||||
if (winptr == NULL)
|
|
||||||
goto no_colon;
|
|
||||||
winptr++; /* skip : */
|
|
||||||
sessptr = xstrdup(arg);
|
|
||||||
*strchr(sessptr, ':') = '\0';
|
|
||||||
|
|
||||||
/* Try to lookup the session if present. */
|
|
||||||
if (*sessptr != '\0') {
|
|
||||||
if ((s = cmd_lookup_session(cmdq, sessptr, &ambiguous)) == NULL)
|
|
||||||
goto no_session;
|
|
||||||
}
|
|
||||||
if (sp != NULL)
|
|
||||||
*sp = s;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Then work out the window. An empty string is the current window,
|
|
||||||
* otherwise try special cases then to look it up in the session.
|
|
||||||
*/
|
|
||||||
if (*winptr == '\0')
|
|
||||||
wl = s->curw;
|
|
||||||
else if (winptr[0] == '!' && winptr[1] == '\0')
|
|
||||||
wl = TAILQ_FIRST(&s->lastw);
|
|
||||||
else if (winptr[0] == '^' && winptr[1] == '\0')
|
|
||||||
wl = RB_MIN(winlinks, &s->windows);
|
|
||||||
else if (winptr[0] == '$' && winptr[1] == '\0')
|
|
||||||
wl = RB_MAX(winlinks, &s->windows);
|
|
||||||
else if (winptr[0] == '+' || winptr[0] == '-')
|
|
||||||
wl = cmd_find_window_offset(winptr, s, &ambiguous);
|
|
||||||
else
|
|
||||||
wl = cmd_lookup_window(s, winptr, &ambiguous);
|
|
||||||
if (wl == NULL)
|
|
||||||
goto not_found;
|
|
||||||
|
|
||||||
if (sessptr != NULL)
|
|
||||||
free(sessptr);
|
|
||||||
return (wl);
|
|
||||||
|
|
||||||
no_colon:
|
|
||||||
/*
|
|
||||||
* No colon in the string, first try special cases, then as a window
|
|
||||||
* and lastly as a session.
|
|
||||||
*/
|
|
||||||
if (arg[0] == '=' && arg[1] == '\0') {
|
|
||||||
if ((wl = cmd_mouse_window(&cmdq->item->mouse, &s)) == NULL) {
|
|
||||||
cmdq_error(cmdq, "no mouse target");
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
} else if (arg[0] == '!' && arg[1] == '\0') {
|
|
||||||
if ((wl = TAILQ_FIRST(&s->lastw)) == NULL)
|
|
||||||
goto not_found;
|
|
||||||
} else if (arg[0] == '+' || arg[0] == '-') {
|
|
||||||
if ((wl = cmd_find_window_offset(arg, s, &ambiguous)) == NULL)
|
|
||||||
goto lookup_session;
|
|
||||||
} else if ((wl = cmd_lookup_window(s, arg, &ambiguous)) == NULL)
|
|
||||||
goto lookup_session;
|
|
||||||
|
|
||||||
if (sp != NULL)
|
|
||||||
*sp = s;
|
|
||||||
|
|
||||||
return (wl);
|
|
||||||
|
|
||||||
lookup_session:
|
|
||||||
if (ambiguous)
|
|
||||||
goto not_found;
|
|
||||||
if (*arg != '\0' &&
|
|
||||||
(s = cmd_lookup_session(cmdq, arg, &ambiguous)) == NULL)
|
|
||||||
goto no_session;
|
|
||||||
|
|
||||||
if (sp != NULL)
|
|
||||||
*sp = s;
|
|
||||||
|
|
||||||
return (s->curw);
|
|
||||||
|
|
||||||
no_session:
|
|
||||||
if (ambiguous)
|
|
||||||
cmdq_error(cmdq, "multiple sessions: %s", arg);
|
|
||||||
else
|
|
||||||
cmdq_error(cmdq, "session not found: %s", arg);
|
|
||||||
goto error;
|
|
||||||
|
|
||||||
not_found:
|
|
||||||
if (ambiguous)
|
|
||||||
cmdq_error(cmdq, "multiple windows: %s", arg);
|
|
||||||
else
|
|
||||||
cmdq_error(cmdq, "window not found: %s", arg);
|
|
||||||
goto error;
|
|
||||||
|
|
||||||
error:
|
|
||||||
free(sessptr);
|
|
||||||
return (NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct winlink *
|
|
||||||
cmd_find_window_offset(const char *winptr, struct session *s, int *ambiguous)
|
|
||||||
{
|
|
||||||
struct winlink *wl;
|
|
||||||
int offset = 1;
|
|
||||||
|
|
||||||
if (winptr[1] != '\0')
|
|
||||||
offset = strtonum(winptr + 1, 1, INT_MAX, NULL);
|
|
||||||
if (offset == 0)
|
|
||||||
wl = cmd_lookup_window(s, winptr, ambiguous);
|
|
||||||
else {
|
|
||||||
if (winptr[0] == '+')
|
|
||||||
wl = winlink_next_by_number(s->curw, s, offset);
|
|
||||||
else
|
|
||||||
wl = winlink_previous_by_number(s->curw, s, offset);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (wl);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Find the target session and window index, whether or not it exists in the
|
|
||||||
* session. Return -2 on error or -1 if no window index is specified. This is
|
|
||||||
* used when parsing an argument for a window target that may not exist (for
|
|
||||||
* example if it is going to be created).
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
cmd_find_index(struct cmd_q *cmdq, const char *arg, struct session **sp)
|
|
||||||
{
|
|
||||||
struct session *s;
|
|
||||||
struct winlink *wl;
|
|
||||||
const char *winptr;
|
|
||||||
char *sessptr = NULL;
|
|
||||||
int idx, ambiguous = 0;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Find the current session. There must always be a current session, if
|
|
||||||
* it can't be found, report an error.
|
|
||||||
*/
|
|
||||||
if ((s = cmd_current_session(cmdq, 0)) == NULL) {
|
|
||||||
cmdq_error(cmdq, "can't establish current session");
|
|
||||||
return (-2);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* A NULL argument means the current session and "no window" (-1). */
|
|
||||||
if (arg == NULL) {
|
|
||||||
if (sp != NULL)
|
|
||||||
*sp = s;
|
|
||||||
return (-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Time to look at the argument. If it is empty, that is an error. */
|
|
||||||
if (*arg == '\0')
|
|
||||||
goto not_found;
|
|
||||||
|
|
||||||
/* Find the separating colon. If none, assume the current session. */
|
|
||||||
winptr = strchr(arg, ':');
|
|
||||||
if (winptr == NULL)
|
|
||||||
goto no_colon;
|
|
||||||
winptr++; /* skip : */
|
|
||||||
sessptr = xstrdup(arg);
|
|
||||||
*strchr(sessptr, ':') = '\0';
|
|
||||||
|
|
||||||
/* Try to lookup the session if present. */
|
|
||||||
if (sessptr != NULL && *sessptr != '\0') {
|
|
||||||
if ((s = cmd_lookup_session(cmdq, sessptr, &ambiguous)) == NULL)
|
|
||||||
goto no_session;
|
|
||||||
}
|
|
||||||
if (sp != NULL)
|
|
||||||
*sp = s;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Then work out the window. An empty string is a new window otherwise
|
|
||||||
* try to look it up in the session.
|
|
||||||
*/
|
|
||||||
if (*winptr == '\0')
|
|
||||||
idx = -1;
|
|
||||||
else if (winptr[0] == '!' && winptr[1] == '\0') {
|
|
||||||
if ((wl = TAILQ_FIRST(&s->lastw)) == NULL)
|
|
||||||
goto not_found;
|
|
||||||
idx = wl->idx;
|
|
||||||
} else if (winptr[0] == '+' || winptr[0] == '-') {
|
|
||||||
if ((idx = cmd_find_index_offset(winptr, s, &ambiguous)) < 0)
|
|
||||||
goto invalid_index;
|
|
||||||
} else if ((idx = cmd_lookup_index(s, winptr, &ambiguous)) == -1)
|
|
||||||
goto invalid_index;
|
|
||||||
|
|
||||||
free(sessptr);
|
|
||||||
return (idx);
|
|
||||||
|
|
||||||
no_colon:
|
|
||||||
/*
|
|
||||||
* No colon in the string, first try special cases, then as a window
|
|
||||||
* and lastly as a session.
|
|
||||||
*/
|
|
||||||
if (arg[0] == '!' && arg[1] == '\0') {
|
|
||||||
if ((wl = TAILQ_FIRST(&s->lastw)) == NULL)
|
|
||||||
goto not_found;
|
|
||||||
idx = wl->idx;
|
|
||||||
} else if (arg[0] == '+' || arg[0] == '-') {
|
|
||||||
if ((idx = cmd_find_index_offset(arg, s, &ambiguous)) < 0)
|
|
||||||
goto lookup_session;
|
|
||||||
} else if ((idx = cmd_lookup_index(s, arg, &ambiguous)) == -1)
|
|
||||||
goto lookup_session;
|
|
||||||
|
|
||||||
if (sp != NULL)
|
|
||||||
*sp = s;
|
|
||||||
|
|
||||||
return (idx);
|
|
||||||
|
|
||||||
lookup_session:
|
|
||||||
if (ambiguous)
|
|
||||||
goto not_found;
|
|
||||||
if (*arg != '\0' &&
|
|
||||||
(s = cmd_lookup_session(cmdq, arg, &ambiguous)) == NULL)
|
|
||||||
goto no_session;
|
|
||||||
|
|
||||||
if (sp != NULL)
|
|
||||||
*sp = s;
|
|
||||||
|
|
||||||
return (-1);
|
|
||||||
|
|
||||||
no_session:
|
|
||||||
if (ambiguous)
|
|
||||||
cmdq_error(cmdq, "multiple sessions: %s", arg);
|
|
||||||
else
|
|
||||||
cmdq_error(cmdq, "session not found: %s", arg);
|
|
||||||
free(sessptr);
|
|
||||||
return (-2);
|
|
||||||
|
|
||||||
invalid_index:
|
|
||||||
if (ambiguous)
|
|
||||||
goto not_found;
|
|
||||||
cmdq_error(cmdq, "invalid index: %s", arg);
|
|
||||||
|
|
||||||
free(sessptr);
|
|
||||||
return (-2);
|
|
||||||
|
|
||||||
not_found:
|
|
||||||
if (ambiguous)
|
|
||||||
cmdq_error(cmdq, "multiple windows: %s", arg);
|
|
||||||
else
|
|
||||||
cmdq_error(cmdq, "window not found: %s", arg);
|
|
||||||
free(sessptr);
|
|
||||||
return (-2);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
cmd_find_index_offset(const char *winptr, struct session *s, int *ambiguous)
|
|
||||||
{
|
|
||||||
int idx, offset = 1;
|
|
||||||
|
|
||||||
if (winptr[1] != '\0')
|
|
||||||
offset = strtonum(winptr + 1, 1, INT_MAX, NULL);
|
|
||||||
if (offset == 0)
|
|
||||||
idx = cmd_lookup_index(s, winptr, ambiguous);
|
|
||||||
else {
|
|
||||||
if (winptr[0] == '+') {
|
|
||||||
if (s->curw->idx == INT_MAX)
|
|
||||||
idx = cmd_lookup_index(s, winptr, ambiguous);
|
|
||||||
else
|
|
||||||
idx = s->curw->idx + offset;
|
|
||||||
} else {
|
|
||||||
if (s->curw->idx == 0)
|
|
||||||
idx = cmd_lookup_index(s, winptr, ambiguous);
|
|
||||||
else
|
|
||||||
idx = s->curw->idx - offset;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return (idx);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Find the target session, window and pane number or report an error and
|
|
||||||
* return NULL. The pane number is separated from the session:window by a .,
|
|
||||||
* such as mysession:mywindow.0.
|
|
||||||
*/
|
|
||||||
struct winlink *
|
|
||||||
cmd_find_pane(struct cmd_q *cmdq,
|
|
||||||
const char *arg, struct session **sp, struct window_pane **wpp)
|
|
||||||
{
|
|
||||||
struct session *s;
|
|
||||||
struct winlink *wl;
|
|
||||||
const char *period, *errstr;
|
|
||||||
char *winptr, *paneptr;
|
|
||||||
u_int idx;
|
|
||||||
|
|
||||||
/* Get the current session. */
|
|
||||||
if ((s = cmd_current_session(cmdq, 0)) == NULL) {
|
|
||||||
cmdq_error(cmdq, "can't establish current session");
|
|
||||||
return (NULL);
|
|
||||||
}
|
|
||||||
if (sp != NULL)
|
|
||||||
*sp = s;
|
|
||||||
|
|
||||||
/* A NULL argument means the current session, window and pane. */
|
|
||||||
if (arg == NULL) {
|
|
||||||
*wpp = s->curw->window->active;
|
|
||||||
return (s->curw);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Lookup as pane id. */
|
|
||||||
if ((*wpp = window_pane_find_by_id_str(arg)) != NULL) {
|
|
||||||
s = cmd_window_session(cmdq, (*wpp)->window, &wl);
|
|
||||||
if (sp != NULL)
|
|
||||||
*sp = s;
|
|
||||||
return (wl);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Look for a separating period. */
|
|
||||||
if ((period = strrchr(arg, '.')) == NULL)
|
|
||||||
goto no_period;
|
|
||||||
|
|
||||||
/* Pull out the window part and parse it. */
|
|
||||||
winptr = xstrdup(arg);
|
|
||||||
winptr[period - arg] = '\0';
|
|
||||||
if (*winptr == '\0')
|
|
||||||
wl = s->curw;
|
|
||||||
else if ((wl = cmd_find_window(cmdq, winptr, sp)) == NULL)
|
|
||||||
goto error;
|
|
||||||
|
|
||||||
/* Find the pane section and look it up. */
|
|
||||||
paneptr = winptr + (period - arg) + 1;
|
|
||||||
if (*paneptr == '\0')
|
|
||||||
*wpp = wl->window->active;
|
|
||||||
else if (paneptr[0] == '+' || paneptr[0] == '-')
|
|
||||||
*wpp = cmd_find_pane_offset(paneptr, wl);
|
|
||||||
else if (paneptr[0] == '!' && paneptr[1] == '\0') {
|
|
||||||
if (wl->window->last == NULL) {
|
|
||||||
cmdq_error(cmdq, "no last pane");
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
*wpp = wl->window->last;
|
|
||||||
} else {
|
|
||||||
idx = strtonum(paneptr, 0, INT_MAX, &errstr);
|
|
||||||
if (errstr != NULL)
|
|
||||||
goto lookup_string;
|
|
||||||
*wpp = window_pane_at_index(wl->window, idx);
|
|
||||||
if (*wpp == NULL)
|
|
||||||
goto lookup_string;
|
|
||||||
}
|
|
||||||
|
|
||||||
free(winptr);
|
|
||||||
return (wl);
|
|
||||||
|
|
||||||
lookup_string:
|
|
||||||
/* Try pane string description. */
|
|
||||||
if ((*wpp = window_find_string(wl->window, paneptr)) == NULL) {
|
|
||||||
cmdq_error(cmdq, "can't find pane: %s", paneptr);
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
free(winptr);
|
|
||||||
return (wl);
|
|
||||||
|
|
||||||
no_period:
|
|
||||||
/* Check mouse event. */
|
|
||||||
if (arg[0] == '=' && arg[1] == '\0') {
|
|
||||||
*wpp = cmd_mouse_pane(&cmdq->item->mouse, &s, &wl);
|
|
||||||
if (*wpp == NULL) {
|
|
||||||
cmdq_error(cmdq, "no mouse target");
|
|
||||||
return (NULL);
|
|
||||||
}
|
|
||||||
if (sp != NULL)
|
|
||||||
*sp = s;
|
|
||||||
return (wl);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Try as a pane number alone. */
|
|
||||||
idx = strtonum(arg, 0, INT_MAX, &errstr);
|
|
||||||
if (errstr != NULL)
|
|
||||||
goto lookup_window;
|
|
||||||
|
|
||||||
/* Try index in the current session and window. */
|
|
||||||
if ((*wpp = window_pane_at_index(s->curw->window, idx)) == NULL)
|
|
||||||
goto lookup_window;
|
|
||||||
|
|
||||||
return (s->curw);
|
|
||||||
|
|
||||||
lookup_window:
|
|
||||||
/* Try pane string description. */
|
|
||||||
if ((*wpp = window_find_string(s->curw->window, arg)) != NULL)
|
|
||||||
return (s->curw);
|
|
||||||
|
|
||||||
/* Try as a window and use the active pane. */
|
|
||||||
if ((wl = cmd_find_window(cmdq, arg, sp)) != NULL)
|
|
||||||
*wpp = wl->window->active;
|
|
||||||
return (wl);
|
|
||||||
|
|
||||||
error:
|
|
||||||
free(winptr);
|
|
||||||
return (NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct window_pane *
|
|
||||||
cmd_find_pane_offset(const char *paneptr, struct winlink *wl)
|
|
||||||
{
|
|
||||||
struct window *w = wl->window;
|
|
||||||
struct window_pane *wp = w->active;
|
|
||||||
u_int offset = 1;
|
|
||||||
|
|
||||||
if (paneptr[1] != '\0')
|
|
||||||
offset = strtonum(paneptr + 1, 1, INT_MAX, NULL);
|
|
||||||
if (offset > 0) {
|
|
||||||
if (paneptr[0] == '+')
|
|
||||||
wp = window_pane_next_by_number(w, wp, offset);
|
|
||||||
else
|
|
||||||
wp = window_pane_previous_by_number(w, wp, offset);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (wp);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Replace the first %% or %idx in template by s. */
|
/* Replace the first %% or %idx in template by s. */
|
||||||
char *
|
char *
|
||||||
cmd_template_replace(const char *template, const char *s, int idx)
|
cmd_template_replace(const char *template, const char *s, int idx)
|
||||||
|
@ -144,7 +144,7 @@ key_bindings_remove_table(const char *name)
|
|||||||
void
|
void
|
||||||
key_bindings_init(void)
|
key_bindings_init(void)
|
||||||
{
|
{
|
||||||
static const char* defaults[] = {
|
static const char *defaults[] = {
|
||||||
"bind C-b send-prefix",
|
"bind C-b send-prefix",
|
||||||
"bind C-o rotate-window",
|
"bind C-o rotate-window",
|
||||||
"bind C-z suspend-client",
|
"bind C-z suspend-client",
|
||||||
@ -225,7 +225,7 @@ key_bindings_init(void)
|
|||||||
};
|
};
|
||||||
u_int i;
|
u_int i;
|
||||||
struct cmd_list *cmdlist;
|
struct cmd_list *cmdlist;
|
||||||
char* cause;
|
char *cause;
|
||||||
int error;
|
int error;
|
||||||
struct cmd_q *cmdq;
|
struct cmd_q *cmdq;
|
||||||
|
|
||||||
|
182
tmux.1
182
tmux.1
@ -362,6 +362,7 @@ argument with one of
|
|||||||
or
|
or
|
||||||
.Ar target-pane .
|
.Ar target-pane .
|
||||||
These specify the client, session, window or pane which a command should affect.
|
These specify the client, session, window or pane which a command should affect.
|
||||||
|
.Pp
|
||||||
.Ar target-client
|
.Ar target-client
|
||||||
is the name of the
|
is the name of the
|
||||||
.Xr pty 7
|
.Xr pty 7
|
||||||
@ -371,27 +372,35 @@ or
|
|||||||
.Pa ttyp1
|
.Pa ttyp1
|
||||||
for the client attached to
|
for the client attached to
|
||||||
.Pa /dev/ttyp1 .
|
.Pa /dev/ttyp1 .
|
||||||
If no client is specified, the current client is chosen, if possible, or an
|
If no client is specified,
|
||||||
error is reported.
|
.Nm
|
||||||
|
attempts to work out the client currently in use; if that fails, an error is
|
||||||
|
reported.
|
||||||
Clients may be listed with the
|
Clients may be listed with the
|
||||||
.Ic list-clients
|
.Ic list-clients
|
||||||
command.
|
command.
|
||||||
.Pp
|
.Pp
|
||||||
.Ar target-session
|
.Ar target-session
|
||||||
is the session id prefixed with a $, the name of a session (as listed by the
|
is tried as, in order:
|
||||||
|
.Bl -enum -offset Ds
|
||||||
|
.It
|
||||||
|
A session ID prefixed with a $.
|
||||||
|
.It
|
||||||
|
An exact name of a session (as listed by the
|
||||||
.Ic list-sessions
|
.Ic list-sessions
|
||||||
command), or the name of a client with the same syntax as
|
command).
|
||||||
.Ar target-client ,
|
.It
|
||||||
in which case the session attached to the client is used.
|
The start of a session name, for example
|
||||||
When looking for the session name,
|
.Ql mysess
|
||||||
.Nm
|
would match a session named
|
||||||
initially searches for an exact match; if none is found, the session names
|
.Ql mysession .
|
||||||
are checked for any for which
|
.It
|
||||||
.Ar target-session
|
An
|
||||||
is a prefix or for which it matches as an
|
|
||||||
.Xr fnmatch 3
|
.Xr fnmatch 3
|
||||||
pattern.
|
pattern which is matched against the session name.
|
||||||
If a single match is found, it is used as the target session; multiple matches
|
.El
|
||||||
|
.Pp
|
||||||
|
If a single session is found, it is used as the target session; multiple matches
|
||||||
produce an error.
|
produce an error.
|
||||||
If a session is omitted, the current session is used if available; if no
|
If a session is omitted, the current session is used if available; if no
|
||||||
current session is available, the most recently used is chosen.
|
current session is available, the most recently used is chosen.
|
||||||
@ -404,12 +413,29 @@ follows the same rules as for
|
|||||||
.Ar target-session ,
|
.Ar target-session ,
|
||||||
and
|
and
|
||||||
.Em window
|
.Em window
|
||||||
is looked for in order: as a window index, for example mysession:1;
|
is looked for in order as:
|
||||||
as a window ID, such as @1;
|
.Bl -enum -offset Ds
|
||||||
as an exact window name, such as mysession:mywindow; then as an
|
.It
|
||||||
|
A special token, listed below.
|
||||||
|
.It
|
||||||
|
A window index, for example
|
||||||
|
.Ql mysession:1
|
||||||
|
is window 1 in session
|
||||||
|
.Ql mysession .
|
||||||
|
.It
|
||||||
|
A window ID, such as @1.
|
||||||
|
.It
|
||||||
|
An exact window name, such as
|
||||||
|
.Ql mysession:mywindow .
|
||||||
|
.It
|
||||||
|
The start of a window name, such as
|
||||||
|
.Ql mysession:mywin .
|
||||||
|
.It
|
||||||
|
As an
|
||||||
.Xr fnmatch 3
|
.Xr fnmatch 3
|
||||||
pattern or the start of a window name, such as mysession:mywin* or
|
pattern matched against the window name.
|
||||||
mysession:mywin.
|
.El
|
||||||
|
.Pp
|
||||||
An empty window name specifies the next unused index if appropriate (for
|
An empty window name specifies the next unused index if appropriate (for
|
||||||
example the
|
example the
|
||||||
.Ic new-window
|
.Ic new-window
|
||||||
@ -419,53 +445,50 @@ commands)
|
|||||||
otherwise the current window in
|
otherwise the current window in
|
||||||
.Em session
|
.Em session
|
||||||
is chosen.
|
is chosen.
|
||||||
The special character
|
.Pp
|
||||||
.Ql \&!
|
The following special tokens are available to indicate particular windows. Each
|
||||||
uses the last (previously current) window,
|
has a single-character alternative form.
|
||||||
.Ql ^
|
.Bl -column "XXXXXXXXXX" "X"
|
||||||
selects the highest numbered window,
|
.It Sy "Token" Ta Sy "" Ta Sy "Meaning"
|
||||||
.Ql $
|
.It Li "{start}" Ta "^" Ta "The lowest-numbered window"
|
||||||
selects the lowest numbered window, and
|
.It Li "{end}" Ta "$" Ta "The highest-numbered window"
|
||||||
.Ql +
|
.It Li "{last}" Ta "!" Ta "The last (previously current) window"
|
||||||
and
|
.It Li "{next}" Ta "+" Ta "The next window by number"
|
||||||
.Ql -
|
.It Li "{previous}" Ta "-" Ta "The previous window by number"
|
||||||
select the next window or the previous window by number.
|
.It Li "{mouse}" Ta "=" Ta "The window where the mouse event happened"
|
||||||
When the argument does not contain a colon,
|
.El
|
||||||
.Nm
|
|
||||||
first attempts to parse it as window; if that fails, an attempt is made to
|
|
||||||
match a session.
|
|
||||||
.Pp
|
.Pp
|
||||||
.Ar target-pane
|
.Ar target-pane
|
||||||
takes a similar form to
|
may be a
|
||||||
|
pane ID or takes a similar form to
|
||||||
.Ar target-window
|
.Ar target-window
|
||||||
but with the optional addition of a period followed by a pane index, for
|
but with the optional addition of a period followed by a pane index or pane ID,
|
||||||
example: mysession:mywindow.1.
|
for example:
|
||||||
|
.Ql mysession:mywindow.1 .
|
||||||
If the pane index is omitted, the currently active pane in the specified
|
If the pane index is omitted, the currently active pane in the specified
|
||||||
window is used.
|
window is used.
|
||||||
If neither a colon nor period appears,
|
The following special tokens are available for the pane index:
|
||||||
.Nm
|
.Bl -column "XXXXXXXXXXXXXX" "X"
|
||||||
first attempts to use the argument as a pane index; if that fails, it is looked
|
.It Sy "Token" Ta Sy "" Ta Sy "Meaning"
|
||||||
up as for
|
.It Li "{last}" Ta "!" Ta "The last (previously active) pane"
|
||||||
.Ar target-window .
|
.It Li "{next}" Ta "+" Ta "The next pane by number"
|
||||||
A
|
.It Li "{previous}" Ta "-" Ta "The previous pane by number"
|
||||||
.Ql + ,
|
.It Li "{top}" Ta "" Ta "The top pane"
|
||||||
.Ql -
|
.It Li "{bottom}" Ta "" Ta "The bottom pane"
|
||||||
or
|
.It Li "{left}" Ta "" Ta "The leftmost pane"
|
||||||
.Ql \&!
|
.It Li "{right}" Ta "" Ta "The rightmost pane"
|
||||||
indicate the next, previous or last pane.
|
.It Li "{top-left}" Ta "" Ta "The top-left pane"
|
||||||
One of the strings
|
.It Li "{top-right}" Ta "" Ta "The top-right pane"
|
||||||
.Em top ,
|
.It Li "{bottom-left}" Ta "" Ta "The bottom-left pane"
|
||||||
.Em bottom ,
|
.It Li "{bottom-right}" Ta "" Ta "The bottom-right pane"
|
||||||
.Em left ,
|
.It Li "{up}" Ta "" Ta "The pane above the active pane"
|
||||||
.Em right ,
|
.It Li "{down}" Ta "" Ta "The pane below the active pane"
|
||||||
.Em top-left ,
|
.It Li "{left}" Ta "" Ta "The pane to the left of the active pane"
|
||||||
.Em top-right ,
|
.It Li "{right}" Ta "" Ta "The pane to the right of the active pane"
|
||||||
.Em bottom-left
|
.It Li "{mouse}" Ta "=" Ta "The pane where the mouse event happened"
|
||||||
or
|
.El
|
||||||
.Em bottom-right
|
|
||||||
may be used instead of a pane index.
|
|
||||||
.Pp
|
.Pp
|
||||||
The special characters
|
The tokens
|
||||||
.Ql +
|
.Ql +
|
||||||
and
|
and
|
||||||
.Ql -
|
.Ql -
|
||||||
@ -474,19 +497,34 @@ may be followed by an offset, for example:
|
|||||||
select-window -t:+2
|
select-window -t:+2
|
||||||
.Ed
|
.Ed
|
||||||
.Pp
|
.Pp
|
||||||
When dealing with a session that doesn't contain sequential window indexes,
|
Sessions, window and panes are each numbered with a unique ID; session IDs are
|
||||||
they will be correctly skipped.
|
prefixed with a
|
||||||
.Pp
|
.Ql $ ,
|
||||||
|
windows with a
|
||||||
|
.Ql @ ,
|
||||||
|
and panes with a
|
||||||
|
.Ql % .
|
||||||
|
These are unique and are unchanged for the life of the session, window or pane
|
||||||
|
in the
|
||||||
.Nm
|
.Nm
|
||||||
also gives each pane created in a server an identifier consisting of a
|
server.
|
||||||
.Ql %
|
The pane ID is passed to the child process of the pane in the
|
||||||
and a number, starting from zero.
|
|
||||||
A pane's identifier is unique for the life of the
|
|
||||||
.Nm
|
|
||||||
server and is passed to the child process of the pane in the
|
|
||||||
.Ev TMUX_PANE
|
.Ev TMUX_PANE
|
||||||
environment variable.
|
environment variable.
|
||||||
It may be used alone to target a pane or the window containing it.
|
IDs may be displayed using the
|
||||||
|
.Ql session_id ,
|
||||||
|
.Ql window_id ,
|
||||||
|
or
|
||||||
|
.Ql pane_id
|
||||||
|
formats (see the
|
||||||
|
.Sx FORMATS
|
||||||
|
section) and the
|
||||||
|
.Ic display-message ,
|
||||||
|
.Ic list-sessions ,
|
||||||
|
.Ic list-windows
|
||||||
|
or
|
||||||
|
.Ic list-panes
|
||||||
|
commands.
|
||||||
.Pp
|
.Pp
|
||||||
.Ar shell-command
|
.Ar shell-command
|
||||||
arguments are
|
arguments are
|
||||||
@ -3148,7 +3186,9 @@ The following mouse events are available:
|
|||||||
Each should be suffixed with a location, for example
|
Each should be suffixed with a location, for example
|
||||||
.Ql MouseDown1Status .
|
.Ql MouseDown1Status .
|
||||||
.Pp
|
.Pp
|
||||||
The special character
|
The special token
|
||||||
|
.Ql {mouse}
|
||||||
|
or
|
||||||
.Ql =
|
.Ql =
|
||||||
may be used as
|
may be used as
|
||||||
.Ar target-window
|
.Ar target-window
|
||||||
|
25
tmux.h
25
tmux.h
@ -1738,8 +1738,19 @@ size_t args_print(struct args *, char *, size_t);
|
|||||||
int args_has(struct args *, u_char);
|
int args_has(struct args *, u_char);
|
||||||
void args_set(struct args *, u_char, const char *);
|
void args_set(struct args *, u_char, const char *);
|
||||||
const char *args_get(struct args *, u_char);
|
const char *args_get(struct args *, u_char);
|
||||||
long long args_strtonum(
|
long long args_strtonum(struct args *, u_char, long long, long long,
|
||||||
struct args *, u_char, long long, long long, char **);
|
char **);
|
||||||
|
|
||||||
|
/* cmd-find.c */
|
||||||
|
struct session *cmd_find_current(struct cmd_q *);
|
||||||
|
struct session *cmd_find_session(struct cmd_q *, const char *, int);
|
||||||
|
struct winlink *cmd_find_window(struct cmd_q *, const char *,
|
||||||
|
struct session **);
|
||||||
|
struct winlink *cmd_find_pane(struct cmd_q *, const char *, struct session **,
|
||||||
|
struct window_pane **);
|
||||||
|
struct client *cmd_find_client(struct cmd_q *, const char *, int);
|
||||||
|
int cmd_find_index(struct cmd_q *, const char *,
|
||||||
|
struct session **);
|
||||||
|
|
||||||
/* cmd.c */
|
/* cmd.c */
|
||||||
int cmd_pack_argv(int, char **, char *, size_t);
|
int cmd_pack_argv(int, char **, char *, size_t);
|
||||||
@ -1754,16 +1765,6 @@ int cmd_mouse_at(struct window_pane *, struct mouse_event *,
|
|||||||
struct winlink *cmd_mouse_window(struct mouse_event *, struct session **);
|
struct winlink *cmd_mouse_window(struct mouse_event *, struct session **);
|
||||||
struct window_pane *cmd_mouse_pane(struct mouse_event *, struct session **,
|
struct window_pane *cmd_mouse_pane(struct mouse_event *, struct session **,
|
||||||
struct winlink **);
|
struct winlink **);
|
||||||
struct session *cmd_current_session(struct cmd_q *, int);
|
|
||||||
struct client *cmd_current_client(struct cmd_q *);
|
|
||||||
struct client *cmd_find_client(struct cmd_q *, const char *, int);
|
|
||||||
struct session *cmd_find_session(struct cmd_q *, const char *, int);
|
|
||||||
struct winlink *cmd_find_window(struct cmd_q *, const char *,
|
|
||||||
struct session **);
|
|
||||||
int cmd_find_index(struct cmd_q *, const char *,
|
|
||||||
struct session **);
|
|
||||||
struct winlink *cmd_find_pane(struct cmd_q *, const char *, struct session **,
|
|
||||||
struct window_pane **);
|
|
||||||
char *cmd_template_replace(const char *, const char *, int);
|
char *cmd_template_replace(const char *, const char *, int);
|
||||||
extern const struct cmd_entry *cmd_table[];
|
extern const struct cmd_entry *cmd_table[];
|
||||||
extern const struct cmd_entry cmd_attach_session_entry;
|
extern const struct cmd_entry cmd_attach_session_entry;
|
||||||
|
92
window.c
92
window.c
@ -48,8 +48,6 @@
|
|||||||
* it reaches zero.
|
* it reaches zero.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
ARRAY_DECL(window_pane_list, struct window_pane *);
|
|
||||||
|
|
||||||
/* Global window list. */
|
/* Global window list. */
|
||||||
struct windows windows;
|
struct windows windows;
|
||||||
|
|
||||||
@ -63,7 +61,7 @@ void window_pane_timer_callback(int, short, void *);
|
|||||||
void window_pane_read_callback(struct bufferevent *, void *);
|
void window_pane_read_callback(struct bufferevent *, void *);
|
||||||
void window_pane_error_callback(struct bufferevent *, short, void *);
|
void window_pane_error_callback(struct bufferevent *, short, void *);
|
||||||
|
|
||||||
struct window_pane *window_pane_choose_best(struct window_pane_list *);
|
struct window_pane *window_pane_choose_best(struct window_pane **, u_int);
|
||||||
|
|
||||||
RB_GENERATE(windows, window, entry, window_cmp);
|
RB_GENERATE(windows, window, entry, window_cmp);
|
||||||
|
|
||||||
@ -255,7 +253,7 @@ winlink_stack_remove(struct winlink_stack *stack, struct winlink *wl)
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct window *
|
struct window *
|
||||||
window_find_by_id_str(const char* s)
|
window_find_by_id_str(const char *s)
|
||||||
{
|
{
|
||||||
const char *errstr;
|
const char *errstr;
|
||||||
u_int id;
|
u_int id;
|
||||||
@ -1163,17 +1161,17 @@ window_pane_search(struct window_pane *wp, const char *searchstr,
|
|||||||
|
|
||||||
/* Get MRU pane from a list. */
|
/* Get MRU pane from a list. */
|
||||||
struct window_pane *
|
struct window_pane *
|
||||||
window_pane_choose_best(struct window_pane_list *list)
|
window_pane_choose_best(struct window_pane **list, u_int size)
|
||||||
{
|
{
|
||||||
struct window_pane *next, *best;
|
struct window_pane *next, *best;
|
||||||
u_int i;
|
u_int i;
|
||||||
|
|
||||||
if (ARRAY_LENGTH(list) == 0)
|
if (size == 0)
|
||||||
return (NULL);
|
return (NULL);
|
||||||
|
|
||||||
best = ARRAY_FIRST(list);
|
best = list[0];
|
||||||
for (i = 1; i < ARRAY_LENGTH(list); i++) {
|
for (i = 1; i < size; i++) {
|
||||||
next = ARRAY_ITEM(list, i);
|
next = list[i];
|
||||||
if (next->active_point > best->active_point)
|
if (next->active_point > best->active_point)
|
||||||
best = next;
|
best = next;
|
||||||
}
|
}
|
||||||
@ -1187,14 +1185,15 @@ window_pane_choose_best(struct window_pane_list *list)
|
|||||||
struct window_pane *
|
struct window_pane *
|
||||||
window_pane_find_up(struct window_pane *wp)
|
window_pane_find_up(struct window_pane *wp)
|
||||||
{
|
{
|
||||||
struct window_pane *next, *best;
|
struct window_pane *next, *best, **list;
|
||||||
u_int edge, left, right, end;
|
u_int edge, left, right, end, size;
|
||||||
struct window_pane_list list;
|
|
||||||
int found;
|
int found;
|
||||||
|
|
||||||
if (wp == NULL || !window_pane_visible(wp))
|
if (wp == NULL || !window_pane_visible(wp))
|
||||||
return (NULL);
|
return (NULL);
|
||||||
ARRAY_INIT(&list);
|
|
||||||
|
list = NULL;
|
||||||
|
size = 0;
|
||||||
|
|
||||||
edge = wp->yoff;
|
edge = wp->yoff;
|
||||||
if (edge == 0)
|
if (edge == 0)
|
||||||
@ -1217,12 +1216,14 @@ window_pane_find_up(struct window_pane *wp)
|
|||||||
found = 1;
|
found = 1;
|
||||||
else if (end >= left && end <= right)
|
else if (end >= left && end <= right)
|
||||||
found = 1;
|
found = 1;
|
||||||
if (found)
|
if (!found)
|
||||||
ARRAY_ADD(&list, next);
|
continue;
|
||||||
|
list = xreallocarray(list, size + 1, sizeof *list);
|
||||||
|
list[size++] = next;
|
||||||
}
|
}
|
||||||
|
|
||||||
best = window_pane_choose_best(&list);
|
best = window_pane_choose_best(list, size);
|
||||||
ARRAY_FREE(&list);
|
free(list);
|
||||||
return (best);
|
return (best);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1230,14 +1231,15 @@ window_pane_find_up(struct window_pane *wp)
|
|||||||
struct window_pane *
|
struct window_pane *
|
||||||
window_pane_find_down(struct window_pane *wp)
|
window_pane_find_down(struct window_pane *wp)
|
||||||
{
|
{
|
||||||
struct window_pane *next, *best;
|
struct window_pane *next, *best, **list;
|
||||||
u_int edge, left, right, end;
|
u_int edge, left, right, end, size;
|
||||||
struct window_pane_list list;
|
|
||||||
int found;
|
int found;
|
||||||
|
|
||||||
if (wp == NULL || !window_pane_visible(wp))
|
if (wp == NULL || !window_pane_visible(wp))
|
||||||
return (NULL);
|
return (NULL);
|
||||||
ARRAY_INIT(&list);
|
|
||||||
|
list = NULL;
|
||||||
|
size = 0;
|
||||||
|
|
||||||
edge = wp->yoff + wp->sy + 1;
|
edge = wp->yoff + wp->sy + 1;
|
||||||
if (edge >= wp->window->sy)
|
if (edge >= wp->window->sy)
|
||||||
@ -1260,12 +1262,14 @@ window_pane_find_down(struct window_pane *wp)
|
|||||||
found = 1;
|
found = 1;
|
||||||
else if (end >= left && end <= right)
|
else if (end >= left && end <= right)
|
||||||
found = 1;
|
found = 1;
|
||||||
if (found)
|
if (!found)
|
||||||
ARRAY_ADD(&list, next);
|
continue;
|
||||||
|
list = xreallocarray(list, size + 1, sizeof *list);
|
||||||
|
list[size++] = next;
|
||||||
}
|
}
|
||||||
|
|
||||||
best = window_pane_choose_best(&list);
|
best = window_pane_choose_best(list, size);
|
||||||
ARRAY_FREE(&list);
|
free(list);
|
||||||
return (best);
|
return (best);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1273,14 +1277,15 @@ window_pane_find_down(struct window_pane *wp)
|
|||||||
struct window_pane *
|
struct window_pane *
|
||||||
window_pane_find_left(struct window_pane *wp)
|
window_pane_find_left(struct window_pane *wp)
|
||||||
{
|
{
|
||||||
struct window_pane *next, *best;
|
struct window_pane *next, *best, **list;
|
||||||
u_int edge, top, bottom, end;
|
u_int edge, top, bottom, end, size;
|
||||||
struct window_pane_list list;
|
|
||||||
int found;
|
int found;
|
||||||
|
|
||||||
if (wp == NULL || !window_pane_visible(wp))
|
if (wp == NULL || !window_pane_visible(wp))
|
||||||
return (NULL);
|
return (NULL);
|
||||||
ARRAY_INIT(&list);
|
|
||||||
|
list = NULL;
|
||||||
|
size = 0;
|
||||||
|
|
||||||
edge = wp->xoff;
|
edge = wp->xoff;
|
||||||
if (edge == 0)
|
if (edge == 0)
|
||||||
@ -1303,12 +1308,14 @@ window_pane_find_left(struct window_pane *wp)
|
|||||||
found = 1;
|
found = 1;
|
||||||
else if (end >= top && end <= bottom)
|
else if (end >= top && end <= bottom)
|
||||||
found = 1;
|
found = 1;
|
||||||
if (found)
|
if (!found)
|
||||||
ARRAY_ADD(&list, next);
|
continue;
|
||||||
|
list = xreallocarray(list, size + 1, sizeof *list);
|
||||||
|
list[size++] = next;
|
||||||
}
|
}
|
||||||
|
|
||||||
best = window_pane_choose_best(&list);
|
best = window_pane_choose_best(list, size);
|
||||||
ARRAY_FREE(&list);
|
free(list);
|
||||||
return (best);
|
return (best);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1316,14 +1323,15 @@ window_pane_find_left(struct window_pane *wp)
|
|||||||
struct window_pane *
|
struct window_pane *
|
||||||
window_pane_find_right(struct window_pane *wp)
|
window_pane_find_right(struct window_pane *wp)
|
||||||
{
|
{
|
||||||
struct window_pane *next, *best;
|
struct window_pane *next, *best, **list;
|
||||||
u_int edge, top, bottom, end;
|
u_int edge, top, bottom, end, size;
|
||||||
struct window_pane_list list;
|
|
||||||
int found;
|
int found;
|
||||||
|
|
||||||
if (wp == NULL || !window_pane_visible(wp))
|
if (wp == NULL || !window_pane_visible(wp))
|
||||||
return (NULL);
|
return (NULL);
|
||||||
ARRAY_INIT(&list);
|
|
||||||
|
list = NULL;
|
||||||
|
size = 0;
|
||||||
|
|
||||||
edge = wp->xoff + wp->sx + 1;
|
edge = wp->xoff + wp->sx + 1;
|
||||||
if (edge >= wp->window->sx)
|
if (edge >= wp->window->sx)
|
||||||
@ -1346,12 +1354,14 @@ window_pane_find_right(struct window_pane *wp)
|
|||||||
found = 1;
|
found = 1;
|
||||||
else if (end >= top && end <= bottom)
|
else if (end >= top && end <= bottom)
|
||||||
found = 1;
|
found = 1;
|
||||||
if (found)
|
if (!found)
|
||||||
ARRAY_ADD(&list, next);
|
continue;
|
||||||
|
list = xreallocarray(list, size + 1, sizeof *list);
|
||||||
|
list[size++] = next;
|
||||||
}
|
}
|
||||||
|
|
||||||
best = window_pane_choose_best(&list);
|
best = window_pane_choose_best(list, size);
|
||||||
ARRAY_FREE(&list);
|
free(list);
|
||||||
return (best);
|
return (best);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user