mirror of
https://github.com/tmate-io/tmate.git
synced 2024-11-08 01:04:06 +01:00
Merge branch 'master' of ssh://git.code.sf.net/p/tmux/tmux-code
This commit is contained in:
commit
77f582ff13
@ -38,7 +38,7 @@ char *cmd_capture_pane_history(struct args *, struct cmd_q *,
|
||||
const struct cmd_entry cmd_capture_pane_entry = {
|
||||
"capture-pane", "capturep",
|
||||
"ab:CeE:JpPqS:t:", 0, 0,
|
||||
"[-aCeJpPq] [-b buffer-index] [-E end-line] [-S start-line]"
|
||||
"[-aCeJpPq] " CMD_BUFFER_USAGE " [-E end-line] [-S start-line]"
|
||||
CMD_TARGET_PANE_USAGE,
|
||||
0,
|
||||
NULL,
|
||||
@ -165,8 +165,7 @@ cmd_capture_pane_exec(struct cmd *self, struct cmd_q *cmdq)
|
||||
struct client *c;
|
||||
struct window_pane *wp;
|
||||
char *buf, *cause;
|
||||
int buffer;
|
||||
u_int limit;
|
||||
const char *bufname;
|
||||
size_t len;
|
||||
|
||||
if (cmd_find_pane(cmdq, args_get(args, 't'), NULL, &wp) == NULL)
|
||||
@ -192,25 +191,17 @@ cmd_capture_pane_exec(struct cmd *self, struct cmd_q *cmdq)
|
||||
evbuffer_add(c->stdout_data, "\n", 1);
|
||||
server_push_stdout(c);
|
||||
} else {
|
||||
limit = options_get_number(&global_options, "buffer-limit");
|
||||
if (!args_has(args, 'b')) {
|
||||
paste_add(buf, len, limit);
|
||||
return (CMD_RETURN_NORMAL);
|
||||
}
|
||||
|
||||
buffer = args_strtonum(args, 'b', 0, INT_MAX, &cause);
|
||||
if (cause != NULL) {
|
||||
cmdq_error(cmdq, "buffer %s", cause);
|
||||
bufname = NULL;
|
||||
if (args_has(args, 'b'))
|
||||
bufname = args_get(args, 'b');
|
||||
|
||||
if (paste_set(buf, len, bufname, &cause) != 0) {
|
||||
cmdq_error(cmdq, "%s", cause);
|
||||
free(buf);
|
||||
free(cause);
|
||||
return (CMD_RETURN_ERROR);
|
||||
}
|
||||
|
||||
if (paste_replace(buffer, buf, len) != 0) {
|
||||
cmdq_error(cmdq, "no buffer %d", buffer);
|
||||
free(buf);
|
||||
return (CMD_RETURN_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
return (CMD_RETURN_NORMAL);
|
||||
|
@ -75,19 +75,20 @@ cmd_choose_buffer_exec(struct cmd *self, struct cmd_q *cmdq)
|
||||
action = xstrdup("paste-buffer -b '%%'");
|
||||
|
||||
idx = 0;
|
||||
while ((pb = paste_walk_stack(&idx)) != NULL) {
|
||||
pb = NULL;
|
||||
while ((pb = paste_walk(pb)) != NULL) {
|
||||
cdata = window_choose_data_create(TREE_OTHER, c, c->session);
|
||||
cdata->idx = idx - 1;
|
||||
cdata->idx = idx;
|
||||
|
||||
cdata->ft_template = xstrdup(template);
|
||||
format_add(cdata->ft, "line", "%u", idx - 1);
|
||||
format_paste_buffer(cdata->ft, pb, utf8flag);
|
||||
|
||||
xasprintf(&action_data, "%u", idx - 1);
|
||||
xasprintf(&action_data, "%s", pb->name);
|
||||
cdata->command = cmd_template_replace(action, action_data, 1);
|
||||
free(action_data);
|
||||
|
||||
window_choose_add(wl->window->active, cdata);
|
||||
idx++;
|
||||
}
|
||||
free(action);
|
||||
|
||||
|
@ -41,23 +41,16 @@ enum cmd_retval
|
||||
cmd_delete_buffer_exec(struct cmd *self, struct cmd_q *cmdq)
|
||||
{
|
||||
struct args *args = self->args;
|
||||
char *cause;
|
||||
int buffer;
|
||||
const char *bufname;
|
||||
|
||||
if (!args_has(args, 'b')) {
|
||||
paste_free_top();
|
||||
return (CMD_RETURN_NORMAL);
|
||||
}
|
||||
bufname = args_get(args, 'b');
|
||||
|
||||
buffer = args_strtonum(args, 'b', 0, INT_MAX, &cause);
|
||||
if (cause != NULL) {
|
||||
cmdq_error(cmdq, "buffer %s", cause);
|
||||
free(cause);
|
||||
return (CMD_RETURN_ERROR);
|
||||
}
|
||||
|
||||
if (paste_free_index(buffer) != 0) {
|
||||
cmdq_error(cmdq, "no buffer %d", buffer);
|
||||
if (paste_free_name(bufname) != 0) {
|
||||
cmdq_error(cmdq, "no buffer %s", bufname);
|
||||
return (CMD_RETURN_ERROR);
|
||||
}
|
||||
|
||||
|
@ -200,6 +200,8 @@ cmd_find_window_exec(struct cmd *self, struct cmd_q *cmdq)
|
||||
window_choose_ready(wl->window->active, 0, cmd_find_window_callback);
|
||||
|
||||
out:
|
||||
for (i = 0; i < ARRAY_LENGTH(&find_list); i++)
|
||||
free(ARRAY_ITEM(&find_list, i).list_ctx);
|
||||
ARRAY_FREE(&find_list);
|
||||
return (CMD_RETURN_NORMAL);
|
||||
}
|
||||
|
@ -44,17 +44,15 @@ cmd_list_buffers_exec(unused struct cmd *self, struct cmd_q *cmdq)
|
||||
struct args *args = self->args;
|
||||
struct paste_buffer *pb;
|
||||
struct format_tree *ft;
|
||||
u_int idx;
|
||||
char *line;
|
||||
const char *template;
|
||||
|
||||
if ((template = args_get(args, 'F')) == NULL)
|
||||
template = LIST_BUFFERS_TEMPLATE;
|
||||
|
||||
idx = 0;
|
||||
while ((pb = paste_walk_stack(&idx)) != NULL) {
|
||||
pb = NULL;
|
||||
while ((pb = paste_walk(pb)) != NULL) {
|
||||
ft = format_create();
|
||||
format_add(ft, "line", "%u", idx - 1);
|
||||
format_paste_buffer(ft, pb, 0);
|
||||
|
||||
line = format_expand(ft, template);
|
||||
|
@ -50,30 +50,19 @@ cmd_load_buffer_exec(struct cmd *self, struct cmd_q *cmdq)
|
||||
struct client *c = cmdq->client;
|
||||
struct session *s;
|
||||
FILE *f;
|
||||
const char *path;
|
||||
const char *path, *bufname;
|
||||
char *pdata, *new_pdata, *cause;
|
||||
size_t psize;
|
||||
u_int limit;
|
||||
int ch, error, buffer, *buffer_ptr, cwd, fd;
|
||||
int ch, error, cwd, fd;
|
||||
|
||||
if (!args_has(args, 'b'))
|
||||
buffer = -1;
|
||||
else {
|
||||
buffer = args_strtonum(args, 'b', 0, INT_MAX, &cause);
|
||||
if (cause != NULL) {
|
||||
cmdq_error(cmdq, "buffer %s", cause);
|
||||
free(cause);
|
||||
return (CMD_RETURN_ERROR);
|
||||
}
|
||||
}
|
||||
bufname = NULL;
|
||||
if (args_has(args, 'b'))
|
||||
bufname = args_get(args, 'b');
|
||||
|
||||
path = args->argv[0];
|
||||
if (strcmp(path, "-") == 0) {
|
||||
buffer_ptr = xmalloc(sizeof *buffer_ptr);
|
||||
*buffer_ptr = buffer;
|
||||
|
||||
error = server_set_stdin_callback(c, cmd_load_buffer_callback,
|
||||
buffer_ptr, &cause);
|
||||
(void*)bufname, &cause);
|
||||
if (error != 0) {
|
||||
cmdq_error(cmdq, "%s: %s", path, cause);
|
||||
free(cause);
|
||||
@ -117,14 +106,10 @@ cmd_load_buffer_exec(struct cmd *self, struct cmd_q *cmdq)
|
||||
|
||||
fclose(f);
|
||||
|
||||
limit = options_get_number(&global_options, "buffer-limit");
|
||||
if (buffer == -1) {
|
||||
paste_add(pdata, psize, limit);
|
||||
return (CMD_RETURN_NORMAL);
|
||||
}
|
||||
if (paste_replace(buffer, pdata, psize) != 0) {
|
||||
cmdq_error(cmdq, "no buffer %d", buffer);
|
||||
if (paste_set(pdata, psize, bufname, &cause) != 0) {
|
||||
cmdq_error(cmdq, "%s", cause);
|
||||
free(pdata);
|
||||
free(cause);
|
||||
return (CMD_RETURN_ERROR);
|
||||
}
|
||||
|
||||
@ -140,10 +125,9 @@ error:
|
||||
void
|
||||
cmd_load_buffer_callback(struct client *c, int closed, void *data)
|
||||
{
|
||||
int *buffer = data;
|
||||
char *pdata;
|
||||
size_t psize;
|
||||
u_int limit;
|
||||
const char *bufname = data;
|
||||
char *pdata, *cause;
|
||||
size_t psize;
|
||||
|
||||
if (!closed)
|
||||
return;
|
||||
@ -154,26 +138,21 @@ cmd_load_buffer_callback(struct client *c, int closed, void *data)
|
||||
return;
|
||||
|
||||
psize = EVBUFFER_LENGTH(c->stdin_data);
|
||||
if (psize == 0 || (pdata = malloc(psize + 1)) == NULL) {
|
||||
free(data);
|
||||
if (psize == 0 || (pdata = malloc(psize + 1)) == NULL)
|
||||
goto out;
|
||||
}
|
||||
|
||||
memcpy(pdata, EVBUFFER_DATA(c->stdin_data), psize);
|
||||
pdata[psize] = '\0';
|
||||
evbuffer_drain(c->stdin_data, psize);
|
||||
|
||||
limit = options_get_number(&global_options, "buffer-limit");
|
||||
if (*buffer == -1)
|
||||
paste_add(pdata, psize, limit);
|
||||
else if (paste_replace(*buffer, pdata, psize) != 0) {
|
||||
if (paste_set(pdata, psize, bufname, &cause) != 0) {
|
||||
/* No context so can't use server_client_msg_error. */
|
||||
evbuffer_add_printf(c->stderr_data, "no buffer %d\n", *buffer);
|
||||
evbuffer_add_printf(c->stderr_data, "%s", cause);
|
||||
server_push_stderr(c);
|
||||
free(pdata);
|
||||
free(cause);
|
||||
}
|
||||
|
||||
free(data);
|
||||
|
||||
out:
|
||||
cmdq_continue(c->cmdq);
|
||||
}
|
||||
|
@ -35,10 +35,10 @@ enum cmd_retval cmd_new_session_exec(struct cmd *, struct cmd_q *);
|
||||
|
||||
const struct cmd_entry cmd_new_session_entry = {
|
||||
"new-session", "new",
|
||||
"Ac:dDF:n:Ps:t:x:y:", 0, 1,
|
||||
"Ac:dDF:n:Ps:t:x:y:", 0, -1,
|
||||
"[-AdDP] [-c start-directory] [-F format] [-n window-name] "
|
||||
"[-s session-name] " CMD_TARGET_SESSION_USAGE " [-x width] [-y height] "
|
||||
"[command]",
|
||||
"[-s session-name] " CMD_TARGET_SESSION_USAGE " [-x width] "
|
||||
"[-y height] [command]",
|
||||
CMD_STARTSERVER|CMD_CANTNEST,
|
||||
NULL,
|
||||
cmd_new_session_exec
|
||||
@ -55,8 +55,9 @@ cmd_new_session_exec(struct cmd *self, struct cmd_q *cmdq)
|
||||
struct termios tio, *tiop;
|
||||
const char *newname, *target, *update, *errstr, *template;
|
||||
const char *path;
|
||||
char *cmd, *cause, *cp;
|
||||
char **argv, *cmd, *cause, *cp;
|
||||
int detached, already_attached, idx, cwd, fd = -1;
|
||||
int argc;
|
||||
u_int sx, sy;
|
||||
struct format_tree *ft;
|
||||
struct environ_entry *envent;
|
||||
@ -183,12 +184,21 @@ cmd_new_session_exec(struct cmd *self, struct cmd_q *cmdq)
|
||||
sy = 1;
|
||||
|
||||
/* Figure out the command for the new window. */
|
||||
if (target != NULL)
|
||||
cmd = NULL;
|
||||
else if (args->argc != 0)
|
||||
cmd = args->argv[0];
|
||||
else
|
||||
argc = -1;
|
||||
argv = NULL;
|
||||
if (target == NULL && args->argc != 0) {
|
||||
argc = args->argc;
|
||||
argv = args->argv;
|
||||
} else if (target == NULL) {
|
||||
cmd = options_get_string(&global_s_options, "default-command");
|
||||
if (cmd != NULL && *cmd != '\0') {
|
||||
argc = 1;
|
||||
argv = &cmd;
|
||||
} else {
|
||||
argc = 0;
|
||||
argv = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
path = NULL;
|
||||
if (c != NULL && c->session == NULL)
|
||||
@ -206,8 +216,8 @@ cmd_new_session_exec(struct cmd *self, struct cmd_q *cmdq)
|
||||
|
||||
/* Create the new session. */
|
||||
idx = -1 - options_get_number(&global_s_options, "base-index");
|
||||
s = session_create(newname, cmd, path, cwd, &env, tiop, idx, sx, sy,
|
||||
&cause);
|
||||
s = session_create(newname, argc, argv, path, cwd, &env, tiop, idx, sx,
|
||||
sy, &cause);
|
||||
if (s == NULL) {
|
||||
cmdq_error(cmdq, "create session failed: %s", cause);
|
||||
free(cause);
|
||||
@ -216,7 +226,7 @@ cmd_new_session_exec(struct cmd *self, struct cmd_q *cmdq)
|
||||
environ_free(&env);
|
||||
|
||||
/* Set the initial window name if one given. */
|
||||
if (cmd != NULL && args_has(args, 'n')) {
|
||||
if (argc >= 0 && args_has(args, 'n')) {
|
||||
w = s->curw->window;
|
||||
window_set_name(w, args_get(args, 'n'));
|
||||
options_set_number(&w->options, "automatic-rename", 0);
|
||||
|
@ -34,7 +34,7 @@ enum cmd_retval cmd_new_window_exec(struct cmd *, struct cmd_q *);
|
||||
|
||||
const struct cmd_entry cmd_new_window_entry = {
|
||||
"new-window", "neww",
|
||||
"ac:dF:kn:Pt:", 0, 1,
|
||||
"ac:dF:kn:Pt:", 0, -1,
|
||||
"[-adkP] [-c start-directory] [-F format] [-n window-name] "
|
||||
CMD_TARGET_WINDOW_USAGE " [command]",
|
||||
0,
|
||||
@ -50,8 +50,8 @@ cmd_new_window_exec(struct cmd *self, struct cmd_q *cmdq)
|
||||
struct winlink *wl;
|
||||
struct client *c;
|
||||
const char *cmd, *path, *template;
|
||||
char *cause, *cp;
|
||||
int idx, last, detached, cwd, fd = -1;
|
||||
char **argv, *cause, *cp;
|
||||
int argc, idx, last, detached, cwd, fd = -1;
|
||||
struct format_tree *ft;
|
||||
struct environ_entry *envent;
|
||||
|
||||
@ -84,10 +84,19 @@ cmd_new_window_exec(struct cmd *self, struct cmd_q *cmdq)
|
||||
}
|
||||
detached = args_has(args, 'd');
|
||||
|
||||
if (args->argc == 0)
|
||||
if (args->argc == 0) {
|
||||
cmd = options_get_string(&s->options, "default-command");
|
||||
else
|
||||
cmd = args->argv[0];
|
||||
if (cmd != NULL && *cmd != '\0') {
|
||||
argc = 1;
|
||||
argv = (char**)&cmd;
|
||||
} else {
|
||||
argc = 0;
|
||||
argv = NULL;
|
||||
}
|
||||
} else {
|
||||
argc = args->argc;
|
||||
argv = args->argv;
|
||||
}
|
||||
|
||||
path = NULL;
|
||||
if (cmdq->client != NULL && cmdq->client->session == NULL)
|
||||
@ -145,7 +154,8 @@ cmd_new_window_exec(struct cmd *self, struct cmd_q *cmdq)
|
||||
|
||||
if (idx == -1)
|
||||
idx = -1 - options_get_number(&s->options, "base-index");
|
||||
wl = session_new(s, args_get(args, 'n'), cmd, path, cwd, idx, &cause);
|
||||
wl = session_new(s, args_get(args, 'n'), argc, argv, path, cwd, idx,
|
||||
&cause);
|
||||
if (wl == NULL) {
|
||||
cmdq_error(cmdq, "create window failed: %s", cause);
|
||||
free(cause);
|
||||
|
@ -35,7 +35,7 @@ void cmd_paste_buffer_filter(struct window_pane *,
|
||||
const struct cmd_entry cmd_paste_buffer_entry = {
|
||||
"paste-buffer", "pasteb",
|
||||
"db:prs:t:", 0, 0,
|
||||
"[-dpr] [-s separator] [-b buffer-index] " CMD_TARGET_PANE_USAGE,
|
||||
"[-dpr] [-s separator] " CMD_BUFFER_USAGE " " CMD_TARGET_PANE_USAGE,
|
||||
0,
|
||||
NULL,
|
||||
cmd_paste_buffer_exec
|
||||
@ -48,31 +48,22 @@ cmd_paste_buffer_exec(struct cmd *self, struct cmd_q *cmdq)
|
||||
struct window_pane *wp;
|
||||
struct session *s;
|
||||
struct paste_buffer *pb;
|
||||
const char *sepstr;
|
||||
char *cause;
|
||||
int buffer;
|
||||
const char *sepstr, *bufname;
|
||||
int pflag;
|
||||
|
||||
if (cmd_find_pane(cmdq, args_get(args, 't'), &s, &wp) == NULL)
|
||||
return (CMD_RETURN_ERROR);
|
||||
|
||||
if (!args_has(args, 'b'))
|
||||
buffer = -1;
|
||||
else {
|
||||
buffer = args_strtonum(args, 'b', 0, INT_MAX, &cause);
|
||||
if (cause != NULL) {
|
||||
cmdq_error(cmdq, "buffer %s", cause);
|
||||
free(cause);
|
||||
return (CMD_RETURN_ERROR);
|
||||
}
|
||||
}
|
||||
bufname = NULL;
|
||||
if (args_has(args, 'b'))
|
||||
bufname = args_get(args, 'b');
|
||||
|
||||
if (buffer == -1)
|
||||
if (bufname == NULL)
|
||||
pb = paste_get_top();
|
||||
else {
|
||||
pb = paste_get_index(buffer);
|
||||
pb = paste_get_name(bufname);
|
||||
if (pb == NULL) {
|
||||
cmdq_error(cmdq, "no buffer %d", buffer);
|
||||
cmdq_error(cmdq, "no buffer %s", bufname);
|
||||
return (CMD_RETURN_ERROR);
|
||||
}
|
||||
}
|
||||
@ -91,10 +82,10 @@ cmd_paste_buffer_exec(struct cmd *self, struct cmd_q *cmdq)
|
||||
|
||||
/* Delete the buffer if -d. */
|
||||
if (args_has(args, 'd')) {
|
||||
if (buffer == -1)
|
||||
if (bufname == NULL)
|
||||
paste_free_top();
|
||||
else
|
||||
paste_free_index(buffer);
|
||||
paste_free_name(bufname);
|
||||
}
|
||||
|
||||
return (CMD_RETURN_NORMAL);
|
||||
|
@ -32,7 +32,7 @@ enum cmd_retval cmd_respawn_pane_exec(struct cmd *, struct cmd_q *);
|
||||
|
||||
const struct cmd_entry cmd_respawn_pane_entry = {
|
||||
"respawn-pane", "respawnp",
|
||||
"kt:", 0, 1,
|
||||
"kt:", 0, -1,
|
||||
"[-k] " CMD_TARGET_PANE_USAGE " [command]",
|
||||
0,
|
||||
NULL,
|
||||
@ -48,7 +48,7 @@ cmd_respawn_pane_exec(struct cmd *self, struct cmd_q *cmdq)
|
||||
struct window_pane *wp;
|
||||
struct session *s;
|
||||
struct environ env;
|
||||
const char *cmd, *path;
|
||||
const char *path;
|
||||
char *cause;
|
||||
u_int idx;
|
||||
struct environ_entry *envent;
|
||||
@ -74,11 +74,6 @@ cmd_respawn_pane_exec(struct cmd *self, struct cmd_q *cmdq)
|
||||
screen_reinit(&wp->base);
|
||||
input_init(wp);
|
||||
|
||||
if (args->argc != 0)
|
||||
cmd = args->argv[0];
|
||||
else
|
||||
cmd = NULL;
|
||||
|
||||
path = NULL;
|
||||
if (cmdq->client != NULL && cmdq->client->session == NULL)
|
||||
envent = environ_find(&cmdq->client->environ, "PATH");
|
||||
@ -87,8 +82,8 @@ cmd_respawn_pane_exec(struct cmd *self, struct cmd_q *cmdq)
|
||||
if (envent != NULL)
|
||||
path = envent->value;
|
||||
|
||||
if (window_pane_spawn(wp, cmd, path, NULL, -1, &env, s->tio,
|
||||
&cause) != 0) {
|
||||
if (window_pane_spawn(wp, args->argc, args->argv, path, NULL, -1, &env,
|
||||
s->tio, &cause) != 0) {
|
||||
cmdq_error(cmdq, "respawn pane failed: %s", cause);
|
||||
free(cause);
|
||||
environ_free(&env);
|
||||
|
@ -31,7 +31,7 @@ enum cmd_retval cmd_respawn_window_exec(struct cmd *, struct cmd_q *);
|
||||
|
||||
const struct cmd_entry cmd_respawn_window_entry = {
|
||||
"respawn-window", "respawnw",
|
||||
"kt:", 0, 1,
|
||||
"kt:", 0, -1,
|
||||
"[-k] " CMD_TARGET_WINDOW_USAGE " [command]",
|
||||
0,
|
||||
NULL,
|
||||
@ -47,7 +47,7 @@ cmd_respawn_window_exec(struct cmd *self, struct cmd_q *cmdq)
|
||||
struct window_pane *wp;
|
||||
struct session *s;
|
||||
struct environ env;
|
||||
const char *cmd, *path;
|
||||
const char *path;
|
||||
char *cause;
|
||||
struct environ_entry *envent;
|
||||
|
||||
@ -76,10 +76,6 @@ cmd_respawn_window_exec(struct cmd *self, struct cmd_q *cmdq)
|
||||
window_destroy_panes(w);
|
||||
TAILQ_INSERT_HEAD(&w->panes, wp, entry);
|
||||
window_pane_resize(wp, w->sx, w->sy);
|
||||
if (args->argc != 0)
|
||||
cmd = args->argv[0];
|
||||
else
|
||||
cmd = NULL;
|
||||
|
||||
path = NULL;
|
||||
if (cmdq->client != NULL && cmdq->client->session == NULL)
|
||||
@ -89,8 +85,8 @@ cmd_respawn_window_exec(struct cmd *self, struct cmd_q *cmdq)
|
||||
if (envent != NULL)
|
||||
path = envent->value;
|
||||
|
||||
if (window_pane_spawn(wp, cmd, path, NULL, -1, &env, s->tio,
|
||||
&cause) != 0) {
|
||||
if (window_pane_spawn(wp, args->argc, args->argv, path, NULL, -1, &env,
|
||||
s->tio, &cause) != 0) {
|
||||
cmdq_error(cmdq, "respawn window failed: %s", cause);
|
||||
free(cause);
|
||||
environ_free(&env);
|
||||
|
@ -58,10 +58,10 @@ cmd_save_buffer_exec(struct cmd *self, struct cmd_q *cmdq)
|
||||
struct client *c = cmdq->client;
|
||||
struct session *s;
|
||||
struct paste_buffer *pb;
|
||||
const char *path;
|
||||
char *cause, *start, *end, *msg;
|
||||
const char *path, *bufname;
|
||||
char *start, *end, *msg;
|
||||
size_t size, used, msglen;
|
||||
int cwd, fd, buffer;
|
||||
int cwd, fd;
|
||||
FILE *f;
|
||||
|
||||
if (!args_has(args, 'b')) {
|
||||
@ -70,16 +70,10 @@ cmd_save_buffer_exec(struct cmd *self, struct cmd_q *cmdq)
|
||||
return (CMD_RETURN_ERROR);
|
||||
}
|
||||
} else {
|
||||
buffer = args_strtonum(args, 'b', 0, INT_MAX, &cause);
|
||||
if (cause != NULL) {
|
||||
cmdq_error(cmdq, "buffer %s", cause);
|
||||
free(cause);
|
||||
return (CMD_RETURN_ERROR);
|
||||
}
|
||||
|
||||
pb = paste_get_index(buffer);
|
||||
bufname = args_get(args, 'b');
|
||||
pb = paste_get_name(bufname);
|
||||
if (pb == NULL) {
|
||||
cmdq_error(cmdq, "no buffer %d", buffer);
|
||||
cmdq_error(cmdq, "no buffer %s", bufname);
|
||||
return (CMD_RETURN_ERROR);
|
||||
}
|
||||
}
|
||||
|
@ -31,8 +31,8 @@ enum cmd_retval cmd_set_buffer_exec(struct cmd *, struct cmd_q *);
|
||||
|
||||
const struct cmd_entry cmd_set_buffer_entry = {
|
||||
"set-buffer", "setb",
|
||||
"ab:", 1, 1,
|
||||
"[-a] " CMD_BUFFER_USAGE " data",
|
||||
"ab:n:", 0, 1,
|
||||
"[-a] " CMD_BUFFER_USAGE " [-n new-buffer-name] data",
|
||||
0,
|
||||
NULL,
|
||||
cmd_set_buffer_exec
|
||||
@ -43,38 +43,59 @@ cmd_set_buffer_exec(struct cmd *self, struct cmd_q *cmdq)
|
||||
{
|
||||
struct args *args = self->args;
|
||||
struct paste_buffer *pb;
|
||||
u_int limit;
|
||||
char *pdata, *cause;
|
||||
const char *bufname;
|
||||
size_t psize, newsize;
|
||||
int buffer;
|
||||
|
||||
limit = options_get_number(&global_options, "buffer-limit");
|
||||
bufname = NULL;
|
||||
|
||||
if (args_has(args, 'n')) {
|
||||
if (args->argc > 0) {
|
||||
cmdq_error(cmdq, "don't provide data with n flag");
|
||||
return (CMD_RETURN_ERROR);
|
||||
}
|
||||
|
||||
if (args_has(args, 'b'))
|
||||
bufname = args_get(args, 'b');
|
||||
|
||||
if (bufname == NULL) {
|
||||
pb = paste_get_top();
|
||||
if (pb == NULL) {
|
||||
cmdq_error(cmdq, "no buffer");
|
||||
return (CMD_RETURN_ERROR);
|
||||
}
|
||||
bufname = pb->name;
|
||||
}
|
||||
|
||||
if (paste_rename(bufname, args_get(args, 'n'), &cause) != 0) {
|
||||
cmdq_error(cmdq, "%s", cause);
|
||||
free(cause);
|
||||
return (CMD_RETURN_ERROR);
|
||||
}
|
||||
|
||||
return (CMD_RETURN_NORMAL);
|
||||
}
|
||||
|
||||
if (args->argc != 1) {
|
||||
cmdq_error(cmdq, "no data specified");
|
||||
return (CMD_RETURN_ERROR);
|
||||
}
|
||||
|
||||
psize = 0;
|
||||
pdata = NULL;
|
||||
|
||||
pb = NULL;
|
||||
buffer = -1;
|
||||
|
||||
if ((newsize = strlen(args->argv[0])) == 0)
|
||||
return (CMD_RETURN_NORMAL);
|
||||
|
||||
if (args_has(args, 'b')) {
|
||||
buffer = args_strtonum(args, 'b', 0, INT_MAX, &cause);
|
||||
if (cause != NULL) {
|
||||
cmdq_error(cmdq, "buffer %s", cause);
|
||||
free(cause);
|
||||
return (CMD_RETURN_ERROR);
|
||||
}
|
||||
pb = paste_get_index(buffer);
|
||||
if (pb == NULL) {
|
||||
cmdq_error(cmdq, "no buffer %d", buffer);
|
||||
return (CMD_RETURN_ERROR);
|
||||
}
|
||||
bufname = args_get(args, 'b');
|
||||
pb = paste_get_name(bufname);
|
||||
} else if (args_has(args, 'a')) {
|
||||
pb = paste_get_top();
|
||||
if (pb != NULL)
|
||||
buffer = 0;
|
||||
bufname = pb->name;
|
||||
}
|
||||
|
||||
if (args_has(args, 'a') && pb != NULL) {
|
||||
@ -87,10 +108,12 @@ cmd_set_buffer_exec(struct cmd *self, struct cmd_q *cmdq)
|
||||
memcpy(pdata + psize, args->argv[0], newsize);
|
||||
psize += newsize;
|
||||
|
||||
if (buffer == -1)
|
||||
paste_add(pdata, psize, limit);
|
||||
else
|
||||
paste_replace(buffer, pdata, psize);
|
||||
if (paste_set(pdata, psize, bufname, &cause) != 0) {
|
||||
cmdq_error(cmdq, "%s", cause);
|
||||
free(pdata);
|
||||
free(cause);
|
||||
return (CMD_RETURN_ERROR);
|
||||
}
|
||||
|
||||
return (CMD_RETURN_NORMAL);
|
||||
}
|
||||
|
@ -35,7 +35,7 @@ enum cmd_retval cmd_split_window_exec(struct cmd *, struct cmd_q *);
|
||||
|
||||
const struct cmd_entry cmd_split_window_entry = {
|
||||
"split-window", "splitw",
|
||||
"c:dF:l:hp:Pt:v", 0, 1,
|
||||
"c:dF:l:hp:Pt:v", 0, -1,
|
||||
"[-dhvP] [-c start-directory] [-F format] [-p percentage|-l size] "
|
||||
CMD_TARGET_PANE_USAGE " [command]",
|
||||
0,
|
||||
@ -61,9 +61,9 @@ cmd_split_window_exec(struct cmd *self, struct cmd_q *cmdq)
|
||||
struct window_pane *wp, *new_wp = NULL;
|
||||
struct environ env;
|
||||
const char *cmd, *path, *shell, *template;
|
||||
char *cause, *new_cause, *cp;
|
||||
char **argv, *cause, *new_cause, *cp;
|
||||
u_int hlimit;
|
||||
int size, percentage, cwd, fd = -1;
|
||||
int argc, size, percentage, cwd, fd = -1;
|
||||
enum layout_type type;
|
||||
struct layout_cell *lc;
|
||||
struct client *c;
|
||||
@ -80,10 +80,19 @@ cmd_split_window_exec(struct cmd *self, struct cmd_q *cmdq)
|
||||
environ_copy(&s->environ, &env);
|
||||
server_fill_environ(s, &env);
|
||||
|
||||
if (args->argc == 0)
|
||||
if (args->argc == 0) {
|
||||
cmd = options_get_string(&s->options, "default-command");
|
||||
else
|
||||
cmd = args->argv[0];
|
||||
if (cmd != NULL && *cmd != '\0') {
|
||||
argc = 1;
|
||||
argv = (char**)&cmd;
|
||||
} else {
|
||||
argc = 0;
|
||||
argv = NULL;
|
||||
}
|
||||
} else {
|
||||
argc = args->argc;
|
||||
argv = args->argv;
|
||||
}
|
||||
|
||||
if (args_has(args, 'c')) {
|
||||
ft = format_create();
|
||||
@ -157,8 +166,8 @@ cmd_split_window_exec(struct cmd *self, struct cmd_q *cmdq)
|
||||
if (envent != NULL)
|
||||
path = envent->value;
|
||||
|
||||
if (window_pane_spawn(
|
||||
new_wp, cmd, path, shell, cwd, &env, s->tio, &cause) != 0)
|
||||
if (window_pane_spawn(new_wp, argc, argv, path, shell, cwd, &env,
|
||||
s->tio, &cause) != 0)
|
||||
goto error;
|
||||
layout_assign_pane(lc, new_wp);
|
||||
|
||||
|
30
cmd.c
30
cmd.c
@ -179,14 +179,14 @@ cmd_unpack_argv(char *buf, size_t len, int argc, char ***argv)
|
||||
}
|
||||
|
||||
char **
|
||||
cmd_copy_argv(int argc, char *const *argv)
|
||||
cmd_copy_argv(int argc, char **argv)
|
||||
{
|
||||
char **new_argv;
|
||||
int i;
|
||||
|
||||
if (argc == 0)
|
||||
return (NULL);
|
||||
new_argv = xcalloc(argc, sizeof *new_argv);
|
||||
new_argv = xcalloc(argc + 1, sizeof *new_argv);
|
||||
for (i = 0; i < argc; i++) {
|
||||
if (argv[i] != NULL)
|
||||
new_argv[i] = xstrdup(argv[i]);
|
||||
@ -206,6 +206,32 @@ cmd_free_argv(int argc, char **argv)
|
||||
free(argv);
|
||||
}
|
||||
|
||||
char *
|
||||
cmd_stringify_argv(int argc, char **argv)
|
||||
{
|
||||
char *buf;
|
||||
int i;
|
||||
size_t len;
|
||||
|
||||
if (argc == 0)
|
||||
return (xstrdup(""));
|
||||
|
||||
len = 0;
|
||||
buf = NULL;
|
||||
|
||||
for (i = 0; i < argc; i++) {
|
||||
len += strlen(argv[i]) + 1;
|
||||
buf = xrealloc(buf, 1, len);
|
||||
|
||||
if (i == 0)
|
||||
*buf = '\0';
|
||||
else
|
||||
strlcat(buf, " ", len);
|
||||
strlcat(buf, argv[i], len);
|
||||
}
|
||||
return (buf);
|
||||
}
|
||||
|
||||
struct cmd *
|
||||
cmd_parse(int argc, char **argv, const char *file, u_int line, char **cause)
|
||||
{
|
||||
|
9
format.c
9
format.c
@ -368,7 +368,7 @@ format_get_command(struct window_pane *wp)
|
||||
cmd = osdep_get_name(wp->fd, wp->tty);
|
||||
if (cmd == NULL || *cmd == '\0') {
|
||||
free(cmd);
|
||||
cmd = xstrdup(wp->cmd);
|
||||
cmd = cmd_stringify_argv(wp->argc, wp->argv);
|
||||
if (cmd == NULL || *cmd == '\0') {
|
||||
free(cmd);
|
||||
cmd = xstrdup(wp->shell);
|
||||
@ -559,10 +559,12 @@ format_window_pane(struct format_tree *ft, struct window_pane *wp)
|
||||
if (wp->tty != NULL)
|
||||
format_add(ft, "pane_tty", "%s", wp->tty);
|
||||
format_add(ft, "pane_pid", "%ld", (long) wp->pid);
|
||||
if (wp->cmd != NULL)
|
||||
format_add(ft, "pane_start_command", "%s", wp->cmd);
|
||||
if ((cwd = osdep_get_cwd(wp->fd)) != NULL)
|
||||
format_add(ft, "pane_current_path", "%s", cwd);
|
||||
if ((cmd = cmd_stringify_argv(wp->argc, wp->argv)) != NULL) {
|
||||
format_add(ft, "pane_start_command", "%s", cmd);
|
||||
free(cmd);
|
||||
}
|
||||
if ((cmd = format_get_command(wp)) != NULL) {
|
||||
format_add(ft, "pane_current_command", "%s", cmd);
|
||||
free(cmd);
|
||||
@ -610,6 +612,7 @@ format_paste_buffer(struct format_tree *ft, struct paste_buffer *pb,
|
||||
char *s;
|
||||
|
||||
format_add(ft, "buffer_size", "%zu", pb->size);
|
||||
format_add(ft, "buffer_name", "%s", pb->name);
|
||||
|
||||
s = paste_make_sample(pb, utf8flag);
|
||||
format_add(ft, "buffer_sample", "%s", s);
|
||||
|
15
input-keys.c
15
input-keys.c
@ -204,6 +204,21 @@ input_mouse(struct window_pane *wp, struct session *s, struct mouse_event *m)
|
||||
char buf[40];
|
||||
size_t len;
|
||||
struct paste_buffer *pb;
|
||||
u_int i;
|
||||
|
||||
/*
|
||||
* If the alternate screen is active and hasn't enabled the mouse, send
|
||||
* up and down key presses for the mouse wheel.
|
||||
*/
|
||||
if (wp->saved_grid != NULL && !(wp->screen->mode & ALL_MOUSE_MODES)) {
|
||||
for (i = 0; i < m->scroll; i++) {
|
||||
if (m->wheel == MOUSE_WHEEL_UP)
|
||||
input_key(wp, KEYC_UP);
|
||||
else
|
||||
input_key(wp, KEYC_DOWN);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (wp->screen->mode & ALL_MOUSE_MODES) {
|
||||
/*
|
||||
|
1
layout.c
1
layout.c
@ -53,7 +53,6 @@ layout_create_cell(struct layout_cell *lcparent)
|
||||
lc->yoff = UINT_MAX;
|
||||
|
||||
lc->wp = NULL;
|
||||
lc->lastwp = NULL;
|
||||
|
||||
return (lc);
|
||||
}
|
||||
|
1
log.c
1
log.c
@ -17,6 +17,7 @@
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <time.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
|
@ -141,6 +141,7 @@ const struct mode_key_cmdstr mode_key_cmdstr_copy[] = {
|
||||
{ MODEKEYCOPY_SEARCHREVERSE, "search-reverse" },
|
||||
{ MODEKEYCOPY_SEARCHUP, "search-backward" },
|
||||
{ MODEKEYCOPY_SELECTLINE, "select-line" },
|
||||
{ MODEKEYCOPY_STARTNAMEDBUFFER, "start-named-buffer" },
|
||||
{ MODEKEYCOPY_STARTNUMBERPREFIX, "start-number-prefix" },
|
||||
{ MODEKEYCOPY_STARTOFLINE, "start-of-line" },
|
||||
{ MODEKEYCOPY_STARTSELECTION, "begin-selection" },
|
||||
@ -257,6 +258,7 @@ struct mode_key_tree mode_key_tree_vi_choice;
|
||||
/* vi copy mode keys. */
|
||||
const struct mode_key_entry mode_key_vi_copy[] = {
|
||||
{ ' ', 0, MODEKEYCOPY_STARTSELECTION },
|
||||
{ '"', 0, MODEKEYCOPY_STARTNAMEDBUFFER },
|
||||
{ '$', 0, MODEKEYCOPY_ENDOFLINE },
|
||||
{ ',', 0, MODEKEYCOPY_JUMPREVERSE },
|
||||
{ ';', 0, MODEKEYCOPY_JUMPAGAIN },
|
||||
|
12
names.c
12
names.c
@ -68,9 +68,15 @@ window_name_callback(unused int fd, unused short events, void *data)
|
||||
char *
|
||||
default_window_name(struct window *w)
|
||||
{
|
||||
if (w->active->cmd != NULL && *w->active->cmd != '\0')
|
||||
return (parse_window_name(w->active->cmd));
|
||||
return (parse_window_name(w->active->shell));
|
||||
char *cmd, *s;
|
||||
|
||||
cmd = cmd_stringify_argv(w->active->argc, w->active->argv);
|
||||
if (cmd != NULL && *cmd != '\0')
|
||||
s = parse_window_name(cmd);
|
||||
else
|
||||
s = parse_window_name(w->active->shell);
|
||||
free(cmd);
|
||||
return (s);
|
||||
}
|
||||
|
||||
char *
|
||||
|
218
paste.c
218
paste.c
@ -25,127 +25,237 @@
|
||||
#include "tmux.h"
|
||||
|
||||
/*
|
||||
* Stack of paste buffers. Note that paste buffer data is not necessarily a C
|
||||
* Set of paste buffers. Note that paste buffer data is not necessarily a C
|
||||
* string!
|
||||
*/
|
||||
|
||||
ARRAY_DECL(, struct paste_buffer *) paste_buffers = ARRAY_INITIALIZER;
|
||||
u_int paste_next_index;
|
||||
u_int paste_next_order;
|
||||
u_int paste_num_automatic;
|
||||
RB_HEAD(paste_name_tree, paste_buffer) paste_by_name;
|
||||
RB_HEAD(paste_time_tree, paste_buffer) paste_by_time;
|
||||
|
||||
/* Return each item of the stack in turn. */
|
||||
struct paste_buffer *
|
||||
paste_walk_stack(u_int *idx)
|
||||
int paste_cmp_names(const struct paste_buffer *, const struct paste_buffer *);
|
||||
RB_PROTOTYPE(paste_name_tree, paste_buffer, name_entry, paste_cmp_names);
|
||||
RB_GENERATE(paste_name_tree, paste_buffer, name_entry, paste_cmp_names);
|
||||
|
||||
int paste_cmp_times(const struct paste_buffer *, const struct paste_buffer *);
|
||||
RB_PROTOTYPE(paste_time_tree, paste_buffer, time_entry, paste_cmp_times);
|
||||
RB_GENERATE(paste_time_tree, paste_buffer, time_entry, paste_cmp_times);
|
||||
|
||||
int
|
||||
paste_cmp_names(const struct paste_buffer *a, const struct paste_buffer *b)
|
||||
{
|
||||
struct paste_buffer *pb;
|
||||
|
||||
pb = paste_get_index(*idx);
|
||||
(*idx)++;
|
||||
return (pb);
|
||||
return (strcmp(a->name, b->name));
|
||||
}
|
||||
|
||||
/* Get the top item on the stack. */
|
||||
int
|
||||
paste_cmp_times(const struct paste_buffer *a, const struct paste_buffer *b)
|
||||
{
|
||||
if (a->order > b->order)
|
||||
return (-1);
|
||||
if (a->order < b->order)
|
||||
return (1);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* Walk paste buffers by name. */
|
||||
struct paste_buffer *
|
||||
paste_walk(struct paste_buffer *pb)
|
||||
{
|
||||
if (pb == NULL)
|
||||
return (RB_MIN(paste_time_tree, &paste_by_time));
|
||||
return (RB_NEXT(paste_time_tree, &paste_by_time, pb));
|
||||
}
|
||||
|
||||
/* Get the most recent automatic buffer */
|
||||
struct paste_buffer *
|
||||
paste_get_top(void)
|
||||
{
|
||||
if (ARRAY_LENGTH(&paste_buffers) == 0)
|
||||
struct paste_buffer *pb;
|
||||
|
||||
pb = RB_MIN(paste_time_tree, &paste_by_time);
|
||||
if (pb == NULL)
|
||||
return (NULL);
|
||||
return (ARRAY_FIRST(&paste_buffers));
|
||||
return (pb);
|
||||
}
|
||||
|
||||
/* Get an item by its index. */
|
||||
struct paste_buffer *
|
||||
paste_get_index(u_int idx)
|
||||
{
|
||||
if (idx >= ARRAY_LENGTH(&paste_buffers))
|
||||
return (NULL);
|
||||
return (ARRAY_ITEM(&paste_buffers, idx));
|
||||
}
|
||||
|
||||
/* Free the top item on the stack. */
|
||||
/* Free the most recent buffer */
|
||||
int
|
||||
paste_free_top(void)
|
||||
{
|
||||
struct paste_buffer *pb;
|
||||
|
||||
if (ARRAY_LENGTH(&paste_buffers) == 0)
|
||||
pb = paste_get_top();
|
||||
if (pb == NULL)
|
||||
return (-1);
|
||||
|
||||
pb = ARRAY_FIRST(&paste_buffers);
|
||||
ARRAY_REMOVE(&paste_buffers, 0);
|
||||
|
||||
free(pb->data);
|
||||
free(pb);
|
||||
|
||||
return (0);
|
||||
return (paste_free_name(pb->name));
|
||||
}
|
||||
|
||||
/* Free an item by index. */
|
||||
int
|
||||
paste_free_index(u_int idx)
|
||||
/* Get a paste buffer by name. */
|
||||
struct paste_buffer *
|
||||
paste_get_name(const char *name)
|
||||
{
|
||||
struct paste_buffer *pb;
|
||||
struct paste_buffer pbfind;
|
||||
|
||||
if (idx >= ARRAY_LENGTH(&paste_buffers))
|
||||
if (name == NULL || *name == '\0')
|
||||
return (NULL);
|
||||
|
||||
pbfind.name = (char*)name;
|
||||
return (RB_FIND(paste_name_tree, &paste_by_name, &pbfind));
|
||||
}
|
||||
|
||||
/* Free a paste buffer by name. */
|
||||
int
|
||||
paste_free_name(const char *name)
|
||||
{
|
||||
struct paste_buffer *pb, pbfind;
|
||||
|
||||
if (name == NULL || *name == '\0')
|
||||
return (-1);
|
||||
|
||||
pb = ARRAY_ITEM(&paste_buffers, idx);
|
||||
ARRAY_REMOVE(&paste_buffers, idx);
|
||||
pbfind.name = (char*)name;
|
||||
pb = RB_FIND(paste_name_tree, &paste_by_name, &pbfind);
|
||||
if (pb == NULL)
|
||||
return (-1);
|
||||
|
||||
RB_REMOVE(paste_name_tree, &paste_by_name, pb);
|
||||
RB_REMOVE(paste_time_tree, &paste_by_time, pb);
|
||||
if (pb->automatic)
|
||||
paste_num_automatic--;
|
||||
|
||||
free(pb->data);
|
||||
free(pb->name);
|
||||
free(pb);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Add an item onto the top of the stack, freeing the bottom if at limit. Note
|
||||
* Add an automatic buffer, freeing the oldest automatic item if at limit. Note
|
||||
* that the caller is responsible for allocating data.
|
||||
*/
|
||||
void
|
||||
paste_add(char *data, size_t size, u_int limit)
|
||||
paste_add(char *data, size_t size)
|
||||
{
|
||||
struct paste_buffer *pb;
|
||||
struct paste_buffer *pb, *pb1;
|
||||
u_int limit;
|
||||
|
||||
if (size == 0)
|
||||
return;
|
||||
|
||||
while (ARRAY_LENGTH(&paste_buffers) >= limit) {
|
||||
pb = ARRAY_LAST(&paste_buffers);
|
||||
free(pb->data);
|
||||
free(pb);
|
||||
ARRAY_TRUNC(&paste_buffers, 1);
|
||||
limit = options_get_number(&global_options, "buffer-limit");
|
||||
RB_FOREACH_REVERSE_SAFE(pb, paste_time_tree, &paste_by_time, pb1) {
|
||||
if (paste_num_automatic < limit)
|
||||
break;
|
||||
if (pb->automatic)
|
||||
paste_free_name(pb->name);
|
||||
}
|
||||
|
||||
pb = xmalloc(sizeof *pb);
|
||||
ARRAY_INSERT(&paste_buffers, 0, pb);
|
||||
|
||||
pb->name = NULL;
|
||||
do {
|
||||
free(pb->name);
|
||||
xasprintf(&pb->name, "buffer%04u", paste_next_index);
|
||||
paste_next_index++;
|
||||
} while (paste_get_name(pb->name) != NULL);
|
||||
|
||||
pb->data = data;
|
||||
pb->size = size;
|
||||
|
||||
pb->automatic = 1;
|
||||
paste_num_automatic++;
|
||||
|
||||
pb->order = paste_next_order++;
|
||||
RB_INSERT(paste_name_tree, &paste_by_name, pb);
|
||||
RB_INSERT(paste_time_tree, &paste_by_time, pb);
|
||||
}
|
||||
|
||||
/* Rename a paste buffer. */
|
||||
int
|
||||
paste_rename(const char *oldname, const char *newname, char **cause)
|
||||
{
|
||||
struct paste_buffer *pb;
|
||||
|
||||
if (cause != NULL)
|
||||
*cause = NULL;
|
||||
|
||||
if (oldname == NULL || *oldname == '\0') {
|
||||
if (cause != NULL)
|
||||
*cause = xstrdup("no buffer");
|
||||
return (-1);
|
||||
}
|
||||
if (newname == NULL || *newname == '\0') {
|
||||
if (cause != NULL)
|
||||
*cause = xstrdup("new name is empty");
|
||||
return (-1);
|
||||
}
|
||||
|
||||
pb = paste_get_name(oldname);
|
||||
if (pb == NULL) {
|
||||
if (cause != NULL)
|
||||
xasprintf(cause, "no buffer %s", oldname);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
RB_REMOVE(paste_name_tree, &paste_by_name, pb);
|
||||
|
||||
free(pb->name);
|
||||
pb->name = xstrdup(newname);
|
||||
|
||||
if (pb->automatic)
|
||||
paste_num_automatic--;
|
||||
pb->automatic = 0;
|
||||
|
||||
RB_INSERT(paste_name_tree, &paste_by_name, pb);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Replace an item on the stack. Note that the caller is responsible for
|
||||
* Add or replace an item in the store. Note that the caller is responsible for
|
||||
* allocating data.
|
||||
*/
|
||||
int
|
||||
paste_replace(u_int idx, char *data, size_t size)
|
||||
paste_set(char *data, size_t size, const char *name, char **cause)
|
||||
{
|
||||
struct paste_buffer *pb;
|
||||
|
||||
if (cause != NULL)
|
||||
*cause = NULL;
|
||||
|
||||
if (size == 0) {
|
||||
free(data);
|
||||
return (0);
|
||||
}
|
||||
if (name == NULL) {
|
||||
paste_add(data, size);
|
||||
return (0);
|
||||
}
|
||||
|
||||
if (idx >= ARRAY_LENGTH(&paste_buffers))
|
||||
if (*name == '\0') {
|
||||
if (cause != NULL)
|
||||
*cause = xstrdup("empty buffer name");
|
||||
return (-1);
|
||||
}
|
||||
|
||||
pb = ARRAY_ITEM(&paste_buffers, idx);
|
||||
free(pb->data);
|
||||
pb = paste_get_name(name);
|
||||
if (pb != NULL)
|
||||
paste_free_name(name);
|
||||
|
||||
pb = xmalloc(sizeof *pb);
|
||||
|
||||
pb->name = xstrdup(name);
|
||||
|
||||
pb->data = data;
|
||||
pb->size = size;
|
||||
|
||||
pb->automatic = 0;
|
||||
pb->order = paste_next_order++;
|
||||
|
||||
RB_INSERT(paste_name_tree, &paste_by_name, pb);
|
||||
RB_INSERT(paste_time_tree, &paste_by_time, pb);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
18
session.c
18
session.c
@ -84,11 +84,12 @@ session_find_by_id(u_int id)
|
||||
|
||||
/* Create a new session. */
|
||||
struct session *
|
||||
session_create(const char *name, const char *cmd, const char *path, int cwd,
|
||||
struct environ *env, struct termios *tio, int idx, u_int sx, u_int sy,
|
||||
char **cause)
|
||||
session_create(const char *name, int argc, char **argv, const char *path,
|
||||
int cwd, struct environ *env, struct termios *tio, int idx, u_int sx,
|
||||
u_int sy, char **cause)
|
||||
{
|
||||
struct session *s;
|
||||
struct winlink *wl;
|
||||
|
||||
s = xmalloc(sizeof *s);
|
||||
s->references = 0;
|
||||
@ -131,8 +132,9 @@ session_create(const char *name, const char *cmd, const char *path, int cwd,
|
||||
}
|
||||
RB_INSERT(sessions, &sessions, s);
|
||||
|
||||
if (cmd != NULL) {
|
||||
if (session_new(s, NULL, cmd, path, cwd, idx, cause) == NULL) {
|
||||
if (argc >= 0) {
|
||||
wl = session_new(s, NULL, argc, argv, path, cwd, idx, cause);
|
||||
if (wl == NULL) {
|
||||
session_destroy(s);
|
||||
return (NULL);
|
||||
}
|
||||
@ -226,7 +228,7 @@ session_previous_session(struct session *s)
|
||||
|
||||
/* Create a new window on a session. */
|
||||
struct winlink *
|
||||
session_new(struct session *s, const char *name, const char *cmd,
|
||||
session_new(struct session *s, const char *name, int argc, char **argv,
|
||||
const char *path, int cwd, int idx, char **cause)
|
||||
{
|
||||
struct window *w;
|
||||
@ -250,8 +252,8 @@ session_new(struct session *s, const char *name, const char *cmd,
|
||||
shell = _PATH_BSHELL;
|
||||
|
||||
hlimit = options_get_number(&s->options, "history-limit");
|
||||
w = window_create(name, cmd, path, shell, cwd, &env, s->tio, s->sx,
|
||||
s->sy, hlimit, cause);
|
||||
w = window_create(name, argc, argv, path, shell, cwd, &env, s->tio,
|
||||
s->sx, s->sy, hlimit, cause);
|
||||
if (w == NULL) {
|
||||
winlink_remove(&s->windows, wl);
|
||||
environ_free(&env);
|
||||
|
8
style.c
8
style.c
@ -117,7 +117,7 @@ style_tostring(struct grid_cell *gc)
|
||||
|
||||
*s = '\0';
|
||||
|
||||
if (gc->fg != 8) {
|
||||
if (gc->fg != 8 || gc->flags & GRID_FLAG_FG256) {
|
||||
if (gc->flags & GRID_FLAG_FG256)
|
||||
c = gc->fg | 0x100;
|
||||
else
|
||||
@ -126,7 +126,7 @@ style_tostring(struct grid_cell *gc)
|
||||
comma = 1;
|
||||
}
|
||||
|
||||
if (gc->bg != 8) {
|
||||
if (gc->bg != 8 || gc->flags & GRID_FLAG_BG256) {
|
||||
if (gc->flags & GRID_FLAG_BG256)
|
||||
c = gc->bg | 0x100;
|
||||
else
|
||||
@ -221,13 +221,13 @@ style_apply_update(struct grid_cell *gc, struct options *oo, const char *name)
|
||||
struct grid_cell *gcp;
|
||||
|
||||
gcp = options_get_style(oo, name);
|
||||
if (gcp->fg != 8) {
|
||||
if (gcp->fg != 8 || gcp->flags & GRID_FLAG_FG256) {
|
||||
if (gcp->flags & GRID_FLAG_FG256)
|
||||
colour_set_fg(gc, gcp->fg | 0x100);
|
||||
else
|
||||
colour_set_fg(gc, gcp->fg);
|
||||
}
|
||||
if (gcp->bg != 8) {
|
||||
if (gcp->bg != 8 || gcp->flags & GRID_FLAG_BG256) {
|
||||
if (gcp->flags & GRID_FLAG_BG256)
|
||||
colour_set_bg(gc, gcp->bg | 0x100);
|
||||
else
|
||||
|
93
tmux.1
93
tmux.1
@ -482,12 +482,37 @@ It may be used alone to target a pane or the window containing it.
|
||||
arguments are
|
||||
.Xr sh 1
|
||||
commands.
|
||||
These must be passed as a single item, which typically means quoting them, for
|
||||
example:
|
||||
This may be a single argument passed to the shell, for example:
|
||||
.Bd -literal -offset indent
|
||||
new-window 'vi /etc/passwd'
|
||||
.Ed
|
||||
.Pp
|
||||
Will run:
|
||||
.Bd -literal -offset indent
|
||||
/bin/sh -c 'vi /etc/passwd'
|
||||
.Ed
|
||||
.Pp
|
||||
Additionally, the
|
||||
.Ic new-window ,
|
||||
.Ic new-session ,
|
||||
.Ic split-window ,
|
||||
.Ic respawn-window
|
||||
and
|
||||
.Ic respawn-pane
|
||||
commands allow
|
||||
.Ar shell-command
|
||||
to be given as multiple arguments and executed directly (without
|
||||
.Ql sh -c ) .
|
||||
This can avoid issues with shell quoting.
|
||||
For example:
|
||||
.Bd -literal -offset indent
|
||||
$ tmux new-window vi /etc/passwd
|
||||
.Ed
|
||||
.Pp
|
||||
Will run
|
||||
.Xr vi 1
|
||||
directly without invoking the shell.
|
||||
.Pp
|
||||
.Ar command
|
||||
.Op Ar arguments
|
||||
refers to a
|
||||
@ -853,6 +878,7 @@ The following keys are supported as appropriate for the mode:
|
||||
.It Sy "Function" Ta Sy "vi" Ta Sy "emacs"
|
||||
.It Li "Append selection" Ta "A" Ta ""
|
||||
.It Li "Back to indentation" Ta "^" Ta "M-m"
|
||||
.It Li "Copy to named buffer" Ta \&" Ta ""
|
||||
.It Li "Bottom of history" Ta "G" Ta "M-<"
|
||||
.It Li "Clear selection" Ta "Escape" Ta "C-g"
|
||||
.It Li "Copy selection" Ta "Enter" Ta "M-w"
|
||||
@ -934,9 +960,6 @@ in emacs mode, and
|
||||
.Ql 10w
|
||||
in vi.
|
||||
.Pp
|
||||
When copying the selection, the repeat count indicates the buffer index to
|
||||
replace, if used.
|
||||
.Pp
|
||||
Mode key bindings are defined in a set of named tables:
|
||||
.Em vi-edit
|
||||
and
|
||||
@ -1094,7 +1117,7 @@ but a different format may be specified with
|
||||
.Fl F .
|
||||
.It Xo Ic capture-pane
|
||||
.Op Fl aepPq
|
||||
.Op Fl b Ar buffer-index
|
||||
.Op Fl b Ar buffer-name
|
||||
.Op Fl E Ar end-line
|
||||
.Op Fl S Ar start-line
|
||||
.Op Fl t Ar target-pane
|
||||
@ -3371,19 +3394,40 @@ is given, otherwise the active pane for the session attached to
|
||||
.El
|
||||
.Sh BUFFERS
|
||||
.Nm
|
||||
maintains a stack of
|
||||
maintains a set of named
|
||||
.Em paste buffers .
|
||||
Up to the value of the
|
||||
Each buffer may be either explicitly or automatically named.
|
||||
Explicitly named buffers are named when created with the
|
||||
.Ic set-buffer
|
||||
or
|
||||
.Ic load-buffer
|
||||
commands, or by renaming an automatically named buffer with
|
||||
.Ic set-buffer
|
||||
.Fl n .
|
||||
Automatically named buffers are given a name such as
|
||||
.Ql buffer0001 ,
|
||||
.Ql buffer0002
|
||||
and so on.
|
||||
When the
|
||||
.Ic buffer-limit
|
||||
option are kept; when a new buffer is added, the buffer at the bottom of the
|
||||
stack is removed.
|
||||
option is reached, the oldest automatically named buffer is deleted.
|
||||
Explicitly named are not subject to
|
||||
.Ic buffer-limit
|
||||
and may be deleted with
|
||||
.Ic delete-buffer
|
||||
command.
|
||||
.Pp
|
||||
Buffers may be added using
|
||||
.Ic copy-mode
|
||||
or the
|
||||
.Ic set-buffer
|
||||
command, and pasted into a window using the
|
||||
and
|
||||
.Ic load-buffer
|
||||
commands, and pasted into a window using the
|
||||
.Ic paste-buffer
|
||||
command.
|
||||
If a buffer command is used and no buffer is specified, the most
|
||||
recently added automatically named buffer is assumed.
|
||||
.Pp
|
||||
A configurable history buffer is also maintained for each window.
|
||||
By default, up to 2000 lines are kept; this can be altered with the
|
||||
@ -3404,7 +3448,7 @@ Put a window into buffer choice mode, where a buffer may be chosen
|
||||
interactively from a list.
|
||||
After a buffer is selected,
|
||||
.Ql %%
|
||||
is replaced by the buffer index in
|
||||
is replaced by the buffer name in
|
||||
.Ar template
|
||||
and the result executed as a command.
|
||||
If
|
||||
@ -3419,11 +3463,11 @@ This command works only if at least one client is attached.
|
||||
.It Ic clear-history Op Fl t Ar target-pane
|
||||
.D1 (alias: Ic clearhist )
|
||||
Remove and free the history for the specified pane.
|
||||
.It Ic delete-buffer Op Fl b Ar buffer-index
|
||||
.It Ic delete-buffer Op Fl b Ar buffer-name
|
||||
.D1 (alias: Ic deleteb )
|
||||
Delete the buffer at
|
||||
.Ar buffer-index ,
|
||||
or the top buffer if not specified.
|
||||
Delete the buffer named
|
||||
.Ar buffer-name ,
|
||||
or the most recently added automatically named buffer if not specified.
|
||||
.It Xo Ic list-buffers
|
||||
.Op Fl F Ar format
|
||||
.Xc
|
||||
@ -3435,7 +3479,7 @@ flag, see the
|
||||
.Sx FORMATS
|
||||
section.
|
||||
.It Xo Ic load-buffer
|
||||
.Op Fl b Ar buffer-index
|
||||
.Op Fl b Ar buffer-name
|
||||
.Ar path
|
||||
.Xc
|
||||
.D1 (alias: Ic loadb )
|
||||
@ -3443,7 +3487,7 @@ Load the contents of the specified paste buffer from
|
||||
.Ar path .
|
||||
.It Xo Ic paste-buffer
|
||||
.Op Fl dpr
|
||||
.Op Fl b Ar buffer-index
|
||||
.Op Fl b Ar buffer-name
|
||||
.Op Fl s Ar separator
|
||||
.Op Fl t Ar target-pane
|
||||
.Xc
|
||||
@ -3452,7 +3496,7 @@ Insert the contents of a paste buffer into the specified pane.
|
||||
If not specified, paste into the current one.
|
||||
With
|
||||
.Fl d ,
|
||||
also delete the paste buffer from the stack.
|
||||
also delete the paste buffer.
|
||||
When output, any linefeed (LF) characters in the paste buffer are replaced with
|
||||
a separator, by default carriage return (CR).
|
||||
A custom separator may be specified using the
|
||||
@ -3467,7 +3511,7 @@ is specified, paste bracket control codes are inserted around the
|
||||
buffer if the application has requested bracketed paste mode.
|
||||
.It Xo Ic save-buffer
|
||||
.Op Fl a
|
||||
.Op Fl b Ar buffer-index
|
||||
.Op Fl b Ar buffer-name
|
||||
.Ar path
|
||||
.Xc
|
||||
.D1 (alias: Ic saveb )
|
||||
@ -3478,7 +3522,8 @@ The
|
||||
option appends to rather than overwriting the file.
|
||||
.It Xo Ic set-buffer
|
||||
.Op Fl a
|
||||
.Op Fl b Ar buffer-index
|
||||
.Op Fl b Ar buffer-name
|
||||
.Op Fl n Ar new-buffer-name
|
||||
.Ar data
|
||||
.Xc
|
||||
.D1 (alias: Ic setb )
|
||||
@ -3487,8 +3532,12 @@ Set the contents of the specified buffer to
|
||||
The
|
||||
.Fl a
|
||||
option appends to rather than overwriting the buffer.
|
||||
The
|
||||
.Fl n
|
||||
option renames the buffer to
|
||||
.Ar new-buffer-name .
|
||||
.It Xo Ic show-buffer
|
||||
.Op Fl b Ar buffer-index
|
||||
.Op Fl b Ar buffer-name
|
||||
.Xc
|
||||
.D1 (alias: Ic showb )
|
||||
Display the contents of the specified buffer.
|
||||
|
55
tmux.h
55
tmux.h
@ -82,7 +82,7 @@ extern char **environ;
|
||||
|
||||
/* Default template for choose-buffer. */
|
||||
#define CHOOSE_BUFFER_TEMPLATE \
|
||||
"#{line}: #{buffer_size} bytes: #{buffer_sample}"
|
||||
"#{buffer_name}: #{buffer_size} bytes: #{buffer_sample}"
|
||||
|
||||
/* Default template for choose-client. */
|
||||
#define CHOOSE_CLIENT_TEMPLATE \
|
||||
@ -115,7 +115,8 @@ extern char **environ;
|
||||
|
||||
/* Default template for list-buffers. */
|
||||
#define LIST_BUFFERS_TEMPLATE \
|
||||
"#{line}: #{buffer_size} bytes: \"#{buffer_sample}\""
|
||||
"#{buffer_name}: #{buffer_size} bytes: " \
|
||||
"\"#{buffer_sample}\""
|
||||
|
||||
/* Default template for list-clients. */
|
||||
#define LIST_CLIENTS_TEMPLATE \
|
||||
@ -579,6 +580,7 @@ enum mode_key_cmd {
|
||||
MODEKEYCOPY_SEARCHREVERSE,
|
||||
MODEKEYCOPY_SEARCHUP,
|
||||
MODEKEYCOPY_SELECTLINE,
|
||||
MODEKEYCOPY_STARTNAMEDBUFFER,
|
||||
MODEKEYCOPY_STARTNUMBERPREFIX,
|
||||
MODEKEYCOPY_STARTOFLINE,
|
||||
MODEKEYCOPY_STARTSELECTION,
|
||||
@ -889,6 +891,7 @@ struct window_choose_mode_item {
|
||||
/* Child window structure. */
|
||||
struct window_pane {
|
||||
u_int id;
|
||||
u_int active_point;
|
||||
|
||||
struct window *window;
|
||||
|
||||
@ -908,7 +911,8 @@ struct window_pane {
|
||||
#define PANE_RESIZE 0x8
|
||||
#define PANE_FOCUSPUSH 0x10
|
||||
|
||||
char *cmd;
|
||||
int argc;
|
||||
char **argv;
|
||||
char *shell;
|
||||
int cwd;
|
||||
|
||||
@ -945,6 +949,7 @@ struct window_pane {
|
||||
};
|
||||
TAILQ_HEAD(window_panes, window_pane);
|
||||
RB_HEAD(window_pane_tree, window_pane);
|
||||
ARRAY_DECL(window_pane_list, struct window_pane *);
|
||||
|
||||
/* Window structure. */
|
||||
struct window {
|
||||
@ -1022,8 +1027,6 @@ struct layout_cell {
|
||||
u_int yoff;
|
||||
|
||||
struct window_pane *wp;
|
||||
struct window_pane *lastwp;
|
||||
|
||||
struct layout_cells cells;
|
||||
|
||||
TAILQ_ENTRY(layout_cell) entry;
|
||||
@ -1033,6 +1036,13 @@ struct layout_cell {
|
||||
struct paste_buffer {
|
||||
char *data;
|
||||
size_t size;
|
||||
|
||||
char *name;
|
||||
int automatic;
|
||||
u_int order;
|
||||
|
||||
RB_ENTRY(paste_buffer) name_entry;
|
||||
RB_ENTRY(paste_buffer) time_entry;
|
||||
};
|
||||
|
||||
/* Environment variable. */
|
||||
@ -1127,6 +1137,9 @@ LIST_HEAD(tty_terms, tty_term);
|
||||
#define MOUSE_WHEEL_UP 0
|
||||
#define MOUSE_WHEEL_DOWN 1
|
||||
|
||||
/* Mouse wheel multipler. */
|
||||
#define MOUSE_WHEEL_SCALE 3
|
||||
|
||||
/* Mouse event bits. */
|
||||
#define MOUSE_EVENT_DOWN 0x1
|
||||
#define MOUSE_EVENT_DRAG 0x2
|
||||
@ -1493,7 +1506,7 @@ RB_HEAD(format_tree, format_entry);
|
||||
#define CMD_SRCDST_WINDOW_USAGE "[-s src-window] [-t dst-window]"
|
||||
#define CMD_SRCDST_SESSION_USAGE "[-s src-session] [-t dst-session]"
|
||||
#define CMD_SRCDST_CLIENT_USAGE "[-s src-client] [-t dst-client]"
|
||||
#define CMD_BUFFER_USAGE "[-b buffer-index]"
|
||||
#define CMD_BUFFER_USAGE "[-b buffer-name]"
|
||||
|
||||
/* tmux.c */
|
||||
extern struct options global_options;
|
||||
@ -1705,13 +1718,14 @@ void tty_keys_free(struct tty *);
|
||||
int tty_keys_next(struct tty *);
|
||||
|
||||
/* paste.c */
|
||||
struct paste_buffer *paste_walk_stack(u_int *);
|
||||
struct paste_buffer *paste_walk(struct paste_buffer *);
|
||||
struct paste_buffer *paste_get_top(void);
|
||||
struct paste_buffer *paste_get_index(u_int);
|
||||
struct paste_buffer *paste_get_name(const char *);
|
||||
int paste_free_top(void);
|
||||
int paste_free_index(u_int);
|
||||
void paste_add(char *, size_t, u_int);
|
||||
int paste_replace(u_int, char *, size_t);
|
||||
int paste_free_name(const char *);
|
||||
void paste_add(char *, size_t);
|
||||
int paste_rename(const char *, const char *, char **);
|
||||
int paste_set(char *, size_t, const char *, char **);
|
||||
char *paste_make_sample(struct paste_buffer *, int);
|
||||
void paste_send_pane(struct paste_buffer *, struct window_pane *,
|
||||
const char *, int);
|
||||
@ -1732,8 +1746,9 @@ long long args_strtonum(
|
||||
/* cmd.c */
|
||||
int cmd_pack_argv(int, char **, char *, size_t);
|
||||
int cmd_unpack_argv(char *, size_t, int, char ***);
|
||||
char **cmd_copy_argv(int, char *const *);
|
||||
char **cmd_copy_argv(int, char **);
|
||||
void cmd_free_argv(int, char **);
|
||||
char *cmd_stringify_argv(int, char **);
|
||||
struct cmd *cmd_parse(int, char **, const char *, u_int, char **);
|
||||
size_t cmd_print(struct cmd *, char *, size_t);
|
||||
struct session *cmd_current_session(struct cmd_q *, int);
|
||||
@ -2124,7 +2139,7 @@ void winlink_stack_remove(struct winlink_stack *, struct winlink *);
|
||||
int window_index(struct window *, u_int *);
|
||||
struct window *window_find_by_id(u_int);
|
||||
struct window *window_create1(u_int, u_int);
|
||||
struct window *window_create(const char *, const char *, const char *,
|
||||
struct window *window_create(const char *, int, char **, const char *,
|
||||
const char *, int, struct environ *, struct termios *,
|
||||
u_int, u_int, u_int, char **);
|
||||
void window_destroy(struct window *);
|
||||
@ -2150,7 +2165,7 @@ struct window_pane *window_pane_find_by_id(u_int);
|
||||
struct window_pane *window_pane_create(struct window *, u_int, u_int, u_int);
|
||||
void window_pane_destroy(struct window_pane *);
|
||||
void window_pane_timer_start(struct window_pane *);
|
||||
int window_pane_spawn(struct window_pane *, const char *,
|
||||
int window_pane_spawn(struct window_pane *, int, char **,
|
||||
const char *, const char *, int, struct environ *,
|
||||
struct termios *, char **);
|
||||
void window_pane_resize(struct window_pane *, u_int, u_int);
|
||||
@ -2288,18 +2303,18 @@ RB_PROTOTYPE(sessions, session, entry, session_cmp);
|
||||
int session_alive(struct session *);
|
||||
struct session *session_find(const char *);
|
||||
struct session *session_find_by_id(u_int);
|
||||
struct session *session_create(const char *, const char *, const char *, int,
|
||||
struct environ *, struct termios *, int, u_int, u_int,
|
||||
char **);
|
||||
struct session *session_create(const char *, int, char **, const char *,
|
||||
int, struct environ *, struct termios *, int, u_int,
|
||||
u_int, char **);
|
||||
void session_destroy(struct session *);
|
||||
int session_check_name(const char *);
|
||||
void session_update_activity(struct session *);
|
||||
struct session *session_next_session(struct session *);
|
||||
struct session *session_previous_session(struct session *);
|
||||
struct winlink *session_new(struct session *, const char *, const char *,
|
||||
struct winlink *session_new(struct session *, const char *, int, char **,
|
||||
const char *, int, int, char **);
|
||||
struct winlink *session_attach(
|
||||
struct session *, struct window *, int, char **);
|
||||
struct winlink *session_attach(struct session *, struct window *, int,
|
||||
char **);
|
||||
int session_detach(struct session *, struct winlink *);
|
||||
struct winlink *session_has(struct session *, struct window *);
|
||||
int session_next(struct session *, int);
|
||||
|
@ -752,11 +752,11 @@ tty_keys_mouse(struct tty *tty, const char *buf, size_t len, size_t *size)
|
||||
if (b & MOUSE_MASK_SHIFT)
|
||||
m->scroll = 1;
|
||||
else
|
||||
m->scroll = 3;
|
||||
m->scroll = MOUSE_WHEEL_SCALE;
|
||||
if (b & MOUSE_MASK_META)
|
||||
m->scroll *= 3;
|
||||
m->scroll *= MOUSE_WHEEL_SCALE;
|
||||
if (b & MOUSE_MASK_CTRL)
|
||||
m->scroll *= 3;
|
||||
m->scroll *= MOUSE_WHEEL_SCALE;
|
||||
|
||||
b &= MOUSE_MASK_BUTTONS;
|
||||
if (b == 0)
|
||||
|
@ -721,17 +721,22 @@ window_choose_mouse(struct window_pane *wp, struct session *sess,
|
||||
struct window_choose_mode_data *data = wp->modedata;
|
||||
struct screen *s = &data->screen;
|
||||
struct window_choose_mode_item *item;
|
||||
u_int idx;
|
||||
u_int idx, i, n;
|
||||
|
||||
if (m->event == MOUSE_EVENT_WHEEL) {
|
||||
/*
|
||||
* Don't use m->scroll and just move line-by-line or it's
|
||||
* annoying.
|
||||
* Multiple line scrolling by default is annoying, so scale
|
||||
* m->scroll back down.
|
||||
*/
|
||||
if (m->wheel == MOUSE_WHEEL_UP)
|
||||
window_choose_key(wp, sess, KEYC_UP);
|
||||
else
|
||||
window_choose_key(wp, sess, KEYC_DOWN);
|
||||
n = m->scroll;
|
||||
if (n >= MOUSE_WHEEL_SCALE)
|
||||
n /= MOUSE_WHEEL_SCALE;
|
||||
for (i = 0; i < n; i++) {
|
||||
if (m->wheel == MOUSE_WHEEL_UP)
|
||||
window_choose_key(wp, sess, KEYC_UP);
|
||||
else
|
||||
window_choose_key(wp, sess, KEYC_DOWN);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -54,14 +54,15 @@ void window_copy_update_cursor(struct window_pane *, u_int, u_int);
|
||||
void window_copy_start_selection(struct window_pane *);
|
||||
int window_copy_update_selection(struct window_pane *, int);
|
||||
void *window_copy_get_selection(struct window_pane *, size_t *);
|
||||
void window_copy_copy_buffer(struct window_pane *, int, void *, size_t);
|
||||
void window_copy_copy_pipe(
|
||||
struct window_pane *, struct session *, int, const char *);
|
||||
void window_copy_copy_selection(struct window_pane *, int);
|
||||
void window_copy_append_selection(struct window_pane *, int);
|
||||
void window_copy_copy_buffer(struct window_pane *, const char *, void *,
|
||||
size_t);
|
||||
void window_copy_copy_pipe(struct window_pane *, struct session *,
|
||||
const char *, const char *);
|
||||
void window_copy_copy_selection(struct window_pane *, const char *);
|
||||
void window_copy_append_selection(struct window_pane *, const char *);
|
||||
void window_copy_clear_selection(struct window_pane *);
|
||||
void window_copy_copy_line(
|
||||
struct window_pane *, char **, size_t *, u_int, u_int, u_int);
|
||||
void window_copy_copy_line(struct window_pane *, char **, size_t *, u_int,
|
||||
u_int, u_int);
|
||||
int window_copy_in_set(struct window_pane *, u_int, u_int, const char *);
|
||||
u_int window_copy_find_length(struct window_pane *, u_int);
|
||||
void window_copy_cursor_start_of_line(struct window_pane *);
|
||||
@ -94,6 +95,7 @@ const struct window_mode window_copy_mode = {
|
||||
|
||||
enum window_copy_input_type {
|
||||
WINDOW_COPY_OFF,
|
||||
WINDOW_COPY_NAMEDBUFFER,
|
||||
WINDOW_COPY_NUMERICPREFIX,
|
||||
WINDOW_COPY_SEARCHUP,
|
||||
WINDOW_COPY_SEARCHDOWN,
|
||||
@ -417,7 +419,7 @@ window_copy_key(struct window_pane *wp, struct session *sess, int key)
|
||||
switch (cmd) {
|
||||
case MODEKEYCOPY_APPENDSELECTION:
|
||||
if (sess != NULL) {
|
||||
window_copy_append_selection(wp, data->numprefix);
|
||||
window_copy_append_selection(wp, NULL);
|
||||
window_pane_reset_mode(wp);
|
||||
return;
|
||||
}
|
||||
@ -543,7 +545,7 @@ window_copy_key(struct window_pane *wp, struct session *sess, int key)
|
||||
if (sess != NULL &&
|
||||
(cmd == MODEKEYCOPY_COPYLINE ||
|
||||
cmd == MODEKEYCOPY_COPYENDOFLINE)) {
|
||||
window_copy_copy_selection(wp, -1);
|
||||
window_copy_copy_selection(wp, NULL);
|
||||
window_pane_reset_mode(wp);
|
||||
return;
|
||||
}
|
||||
@ -554,14 +556,14 @@ window_copy_key(struct window_pane *wp, struct session *sess, int key)
|
||||
break;
|
||||
case MODEKEYCOPY_COPYPIPE:
|
||||
if (sess != NULL) {
|
||||
window_copy_copy_pipe(wp, sess, data->numprefix, arg);
|
||||
window_copy_copy_pipe(wp, sess, NULL, arg);
|
||||
window_pane_reset_mode(wp);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case MODEKEYCOPY_COPYSELECTION:
|
||||
if (sess != NULL) {
|
||||
window_copy_copy_selection(wp, data->numprefix);
|
||||
window_copy_copy_selection(wp, NULL);
|
||||
window_pane_reset_mode(wp);
|
||||
return;
|
||||
}
|
||||
@ -676,6 +678,7 @@ window_copy_key(struct window_pane *wp, struct session *sess, int key)
|
||||
case WINDOW_COPY_JUMPBACK:
|
||||
case WINDOW_COPY_JUMPTOFORWARD:
|
||||
case WINDOW_COPY_JUMPTOBACK:
|
||||
case WINDOW_COPY_NAMEDBUFFER:
|
||||
case WINDOW_COPY_NUMERICPREFIX:
|
||||
break;
|
||||
case WINDOW_COPY_SEARCHUP:
|
||||
@ -711,6 +714,11 @@ window_copy_key(struct window_pane *wp, struct session *sess, int key)
|
||||
data->inputprompt = "Goto Line";
|
||||
*data->inputstr = '\0';
|
||||
goto input_on;
|
||||
case MODEKEYCOPY_STARTNAMEDBUFFER:
|
||||
data->inputtype = WINDOW_COPY_NAMEDBUFFER;
|
||||
data->inputprompt = "Buffer";
|
||||
*data->inputstr = '\0';
|
||||
goto input_on;
|
||||
case MODEKEYCOPY_STARTNUMBERPREFIX:
|
||||
key &= KEYC_MASK_KEY;
|
||||
if (key >= '0' && key <= '9') {
|
||||
@ -814,6 +822,11 @@ window_copy_key_input(struct window_pane *wp, int key)
|
||||
data->searchtype = data->inputtype;
|
||||
data->searchstr = xstrdup(data->inputstr);
|
||||
break;
|
||||
case WINDOW_COPY_NAMEDBUFFER:
|
||||
window_copy_copy_selection(wp, data->inputstr);
|
||||
*data->inputstr = '\0';
|
||||
window_pane_reset_mode(wp);
|
||||
return (0);
|
||||
case WINDOW_COPY_GOTOLINE:
|
||||
window_copy_goto_line(wp, data->inputstr);
|
||||
*data->inputstr = '\0';
|
||||
@ -918,7 +931,7 @@ reset_mode:
|
||||
s->mode &= ~MODE_MOUSE_BUTTON;
|
||||
s->mode |= MODE_MOUSE_STANDARD;
|
||||
if (sess != NULL) {
|
||||
window_copy_copy_selection(wp, -1);
|
||||
window_copy_copy_selection(wp, NULL);
|
||||
window_pane_reset_mode(wp);
|
||||
}
|
||||
}
|
||||
@ -1452,9 +1465,9 @@ window_copy_get_selection(struct window_pane *wp, size_t *len)
|
||||
}
|
||||
|
||||
void
|
||||
window_copy_copy_buffer(struct window_pane *wp, int idx, void *buf, size_t len)
|
||||
window_copy_copy_buffer(struct window_pane *wp, const char *bufname, void *buf,
|
||||
size_t len)
|
||||
{
|
||||
u_int limit;
|
||||
struct screen_write_ctx ctx;
|
||||
|
||||
if (options_get_number(&global_options, "set-clipboard")) {
|
||||
@ -1463,16 +1476,13 @@ window_copy_copy_buffer(struct window_pane *wp, int idx, void *buf, size_t len)
|
||||
screen_write_stop(&ctx);
|
||||
}
|
||||
|
||||
if (idx == -1) {
|
||||
limit = options_get_number(&global_options, "buffer-limit");
|
||||
paste_add(buf, len, limit);
|
||||
} else if (paste_replace(idx, buf, len) != 0)
|
||||
if (paste_set(buf, len, bufname, NULL) != 0)
|
||||
free(buf);
|
||||
}
|
||||
|
||||
void
|
||||
window_copy_copy_pipe(
|
||||
struct window_pane *wp, struct session *sess, int idx, const char *arg)
|
||||
window_copy_copy_pipe(struct window_pane *wp, struct session *sess,
|
||||
const char *bufname, const char *arg)
|
||||
{
|
||||
void *buf;
|
||||
size_t len;
|
||||
@ -1486,11 +1496,11 @@ window_copy_copy_pipe(
|
||||
job = job_run(arg, sess, NULL, NULL, NULL);
|
||||
bufferevent_write(job->event, buf, len);
|
||||
|
||||
window_copy_copy_buffer(wp, idx, buf, len);
|
||||
window_copy_copy_buffer(wp, bufname, buf, len);
|
||||
}
|
||||
|
||||
void
|
||||
window_copy_copy_selection(struct window_pane *wp, int idx)
|
||||
window_copy_copy_selection(struct window_pane *wp, const char *bufname)
|
||||
{
|
||||
void* buf;
|
||||
size_t len;
|
||||
@ -1499,17 +1509,16 @@ window_copy_copy_selection(struct window_pane *wp, int idx)
|
||||
if (buf == NULL)
|
||||
return;
|
||||
|
||||
window_copy_copy_buffer(wp, idx, buf, len);
|
||||
window_copy_copy_buffer(wp, bufname, buf, len);
|
||||
}
|
||||
|
||||
void
|
||||
window_copy_append_selection(struct window_pane *wp, int idx)
|
||||
window_copy_append_selection(struct window_pane *wp, const char *bufname)
|
||||
{
|
||||
char *buf;
|
||||
struct paste_buffer *pb;
|
||||
size_t len;
|
||||
u_int limit;
|
||||
struct screen_write_ctx ctx;
|
||||
char *buf;
|
||||
struct paste_buffer *pb;
|
||||
size_t len;
|
||||
struct screen_write_ctx ctx;
|
||||
|
||||
buf = window_copy_get_selection(wp, &len);
|
||||
if (buf == NULL)
|
||||
@ -1521,24 +1530,19 @@ window_copy_append_selection(struct window_pane *wp, int idx)
|
||||
screen_write_stop(&ctx);
|
||||
}
|
||||
|
||||
if (idx == -1)
|
||||
idx = 0;
|
||||
|
||||
if (idx == 0 && paste_get_top() == NULL) {
|
||||
limit = options_get_number(&global_options, "buffer-limit");
|
||||
paste_add(buf, len, limit);
|
||||
return;
|
||||
}
|
||||
|
||||
pb = paste_get_index(idx);
|
||||
if (bufname == NULL || *bufname == '\0') {
|
||||
pb = paste_get_top();
|
||||
if (pb != NULL)
|
||||
bufname = pb->name;
|
||||
} else
|
||||
pb = paste_get_name(bufname);
|
||||
if (pb != NULL) {
|
||||
buf = xrealloc(buf, 1, len + pb->size);
|
||||
memmove(buf + pb->size, buf, len);
|
||||
memcpy(buf, pb->data, pb->size);
|
||||
len += pb->size;
|
||||
}
|
||||
|
||||
if (paste_replace(idx, buf, len) != 0)
|
||||
if (paste_set(buf, len, bufname, NULL) != 0)
|
||||
free(buf);
|
||||
}
|
||||
|
||||
|
327
window.c
327
window.c
@ -55,15 +55,14 @@ struct windows windows;
|
||||
struct window_pane_tree all_window_panes;
|
||||
u_int next_window_pane_id;
|
||||
u_int next_window_id;
|
||||
|
||||
struct window_pane *window_pane_active_set(struct window_pane *,
|
||||
struct window_pane *);
|
||||
void window_pane_active_lost(struct window_pane *, struct window_pane *);
|
||||
u_int next_active_point;
|
||||
|
||||
void window_pane_timer_callback(int, short, void *);
|
||||
void window_pane_read_callback(struct bufferevent *, void *);
|
||||
void window_pane_error_callback(struct bufferevent *, short, void *);
|
||||
|
||||
struct window_pane *window_pane_choose_best(struct window_pane_list *);
|
||||
|
||||
RB_GENERATE(winlinks, winlink, entry, winlink_cmp);
|
||||
|
||||
int
|
||||
@ -307,7 +306,7 @@ window_create1(u_int sx, u_int sy)
|
||||
}
|
||||
|
||||
struct window *
|
||||
window_create(const char *name, const char *cmd, const char *path,
|
||||
window_create(const char *name, int argc, char **argv, const char *path,
|
||||
const char *shell, int cwd, struct environ *env, struct termios *tio,
|
||||
u_int sx, u_int sy, u_int hlimit, char **cause)
|
||||
{
|
||||
@ -318,7 +317,7 @@ window_create(const char *name, const char *cmd, const char *path,
|
||||
wp = window_add_pane(w, hlimit);
|
||||
layout_init(w, wp);
|
||||
|
||||
if (window_pane_spawn(wp, cmd, path, shell, cwd, env, tio,
|
||||
if (window_pane_spawn(wp, argc, argv, path, shell, cwd, env, tio,
|
||||
cause) != 0) {
|
||||
window_destroy(w);
|
||||
return (NULL);
|
||||
@ -386,64 +385,6 @@ window_resize(struct window *w, u_int sx, u_int sy)
|
||||
w->sy = sy;
|
||||
}
|
||||
|
||||
/*
|
||||
* Restore previously active pane when changing from wp to nextwp. The intended
|
||||
* pane is in nextwp and it returns the previously focused pane.
|
||||
*/
|
||||
struct window_pane *
|
||||
window_pane_active_set(struct window_pane *wp, struct window_pane *nextwp)
|
||||
{
|
||||
struct layout_cell *lc;
|
||||
struct window_pane *lastwp;
|
||||
|
||||
/* Target pane's parent must not be an ancestor of source pane. */
|
||||
for (lc = wp->layout_cell->parent; lc != NULL; lc = lc->parent) {
|
||||
if (lc == nextwp->layout_cell->parent)
|
||||
return (nextwp);
|
||||
}
|
||||
|
||||
/*
|
||||
* Previously active pane, if any, must not be the same as the source
|
||||
* pane.
|
||||
*/
|
||||
lc = nextwp->layout_cell->parent;
|
||||
if (lc != NULL && lc->lastwp != NULL) {
|
||||
lastwp = lc->lastwp;
|
||||
if (lastwp != wp && window_pane_visible(lastwp))
|
||||
return (lastwp);
|
||||
}
|
||||
return (nextwp);
|
||||
}
|
||||
|
||||
/* Remember previously active pane when changing from wp to nextwp. */
|
||||
void
|
||||
window_pane_active_lost(struct window_pane *wp, struct window_pane *nextwp)
|
||||
{
|
||||
struct layout_cell *lc, *lc2, *lcparent;
|
||||
|
||||
/* Get the parent cell. */
|
||||
lcparent = nextwp->layout_cell->parent;
|
||||
if (lcparent == NULL)
|
||||
return;
|
||||
|
||||
/* Save the target pane in its parent. */
|
||||
lcparent->lastwp = nextwp;
|
||||
|
||||
/*
|
||||
* Save the source pane in all of its parents up to, but not including,
|
||||
* the common ancestor of itself and the target panes.
|
||||
*/
|
||||
if (wp == NULL)
|
||||
return;
|
||||
for (lc = wp->layout_cell->parent; lc != NULL; lc = lc->parent) {
|
||||
for (lc2 = lcparent; lc2 != NULL; lc2 = lc2->parent) {
|
||||
if (lc == lc2)
|
||||
return;
|
||||
}
|
||||
lc->lastwp = wp;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
window_set_active_pane(struct window *w, struct window_pane *wp)
|
||||
{
|
||||
@ -451,7 +392,6 @@ window_set_active_pane(struct window *w, struct window_pane *wp)
|
||||
return;
|
||||
w->last = w->active;
|
||||
w->active = wp;
|
||||
window_pane_active_lost(w->last, wp);
|
||||
while (!window_pane_visible(w->active)) {
|
||||
w->active = TAILQ_PREV(w->active, window_panes, entry);
|
||||
if (w->active == NULL)
|
||||
@ -459,6 +399,7 @@ window_set_active_pane(struct window *w, struct window_pane *wp)
|
||||
if (w->active == wp)
|
||||
return;
|
||||
}
|
||||
w->active->active_point = next_active_point++;
|
||||
}
|
||||
|
||||
struct window_pane *
|
||||
@ -736,7 +677,8 @@ window_pane_create(struct window *w, u_int sx, u_int sy, u_int hlimit)
|
||||
wp->id = next_window_pane_id++;
|
||||
RB_INSERT(window_pane_tree, &all_window_panes, wp);
|
||||
|
||||
wp->cmd = NULL;
|
||||
wp->argc = 0;
|
||||
wp->argv = NULL;
|
||||
wp->shell = NULL;
|
||||
wp->cwd = -1;
|
||||
|
||||
@ -770,16 +712,6 @@ window_pane_create(struct window *w, u_int sx, u_int sy, u_int hlimit)
|
||||
void
|
||||
window_pane_destroy(struct window_pane *wp)
|
||||
{
|
||||
struct window_pane *wp2;
|
||||
|
||||
/* Forget removed pane in all layout cells that remember it. */
|
||||
RB_FOREACH(wp2, window_pane_tree, &all_window_panes) {
|
||||
if (wp2->layout_cell != NULL &&
|
||||
wp2->layout_cell->parent != NULL &&
|
||||
wp2->layout_cell->parent->lastwp == wp)
|
||||
wp2->layout_cell->parent->lastwp = NULL;
|
||||
}
|
||||
|
||||
window_pane_reset_mode(wp);
|
||||
|
||||
if (event_initialized(&wp->changes_timer))
|
||||
@ -808,30 +740,32 @@ window_pane_destroy(struct window_pane *wp)
|
||||
|
||||
close(wp->cwd);
|
||||
free(wp->shell);
|
||||
free(wp->cmd);
|
||||
cmd_free_argv(wp->argc, wp->argv);
|
||||
free(wp);
|
||||
}
|
||||
|
||||
int
|
||||
window_pane_spawn(struct window_pane *wp, const char *cmd, const char *path,
|
||||
const char *shell, int cwd, struct environ *env, struct termios *tio,
|
||||
char **cause)
|
||||
window_pane_spawn(struct window_pane *wp, int argc, char **argv,
|
||||
const char *path, const char *shell, int cwd, struct environ *env,
|
||||
struct termios *tio, char **cause)
|
||||
{
|
||||
struct winsize ws;
|
||||
char *argv0, paneid[16];
|
||||
const char *ptr;
|
||||
char *argv0, *cmd, **argvp, paneid[16];
|
||||
const char *ptr, *first;
|
||||
struct termios tio2;
|
||||
#ifdef HAVE_UTEMPTER
|
||||
char s[32];
|
||||
#endif
|
||||
int i;
|
||||
|
||||
if (wp->fd != -1) {
|
||||
bufferevent_free(wp->event);
|
||||
close(wp->fd);
|
||||
}
|
||||
if (cmd != NULL) {
|
||||
free(wp->cmd);
|
||||
wp->cmd = xstrdup(cmd);
|
||||
if (argc > 0) {
|
||||
cmd_free_argv(wp->argc, wp->argv);
|
||||
wp->argc = argc;
|
||||
wp->argv = cmd_copy_argv(argc, argv);
|
||||
}
|
||||
if (shell != NULL) {
|
||||
free(wp->shell);
|
||||
@ -842,7 +776,10 @@ window_pane_spawn(struct window_pane *wp, const char *cmd, const char *path,
|
||||
wp->cwd = dup(cwd);
|
||||
}
|
||||
|
||||
log_debug("spawn: %s -- %s", wp->shell, wp->cmd);
|
||||
cmd = cmd_stringify_argv(wp->argc, wp->argv);
|
||||
log_debug("spawn: %s -- %s", wp->shell, cmd);
|
||||
for (i = 0; i < wp->argc; i++)
|
||||
log_debug("spawn: argv[%d] = %s", i, wp->argv[i]);
|
||||
|
||||
memset(&ws, 0, sizeof ws);
|
||||
ws.ws_col = screen_size_x(&wp->base);
|
||||
@ -852,6 +789,7 @@ window_pane_spawn(struct window_pane *wp, const char *cmd, const char *path,
|
||||
case -1:
|
||||
wp->fd = -1;
|
||||
xasprintf(cause, "%s: %s", cmd, strerror(errno));
|
||||
free(cmd);
|
||||
return (-1);
|
||||
case 0:
|
||||
if (fchdir(wp->cwd) != 0)
|
||||
@ -883,22 +821,32 @@ window_pane_spawn(struct window_pane *wp, const char *cmd, const char *path,
|
||||
setenv("SHELL", wp->shell, 1);
|
||||
ptr = strrchr(wp->shell, '/');
|
||||
|
||||
if (*wp->cmd != '\0') {
|
||||
/* Use the command. */
|
||||
/*
|
||||
* If given one argument, assume it should be passed to sh -c;
|
||||
* with more than one argument, use execvp(). If there is no
|
||||
* arguments, create a login shell.
|
||||
*/
|
||||
if (wp->argc > 0) {
|
||||
if (wp->argc != 1) {
|
||||
/* Copy to ensure argv ends in NULL. */
|
||||
argvp = cmd_copy_argv(wp->argc, wp->argv);
|
||||
execvp(argvp[0], argvp);
|
||||
fatal("execvp failed");
|
||||
}
|
||||
first = wp->argv[0];
|
||||
|
||||
if (ptr != NULL && *(ptr + 1) != '\0')
|
||||
xasprintf(&argv0, "%s", ptr + 1);
|
||||
else
|
||||
xasprintf(&argv0, "%s", wp->shell);
|
||||
execl(wp->shell, argv0, "-c", wp->cmd, (char *) NULL);
|
||||
execl(wp->shell, argv0, "-c", first, (char *)NULL);
|
||||
fatal("execl failed");
|
||||
}
|
||||
|
||||
/* No command; fork a login shell. */
|
||||
if (ptr != NULL && *(ptr + 1) != '\0')
|
||||
xasprintf(&argv0, "-%s", ptr + 1);
|
||||
else
|
||||
xasprintf(&argv0, "-%s", wp->shell);
|
||||
execl(wp->shell, argv0, (char *) NULL);
|
||||
execl(wp->shell, argv0, (char *)NULL);
|
||||
fatal("execl failed");
|
||||
}
|
||||
|
||||
@ -909,10 +857,11 @@ window_pane_spawn(struct window_pane *wp, const char *cmd, const char *path,
|
||||
|
||||
setblocking(wp->fd, 0);
|
||||
|
||||
wp->event = bufferevent_new(wp->fd,
|
||||
window_pane_read_callback, NULL, window_pane_error_callback, wp);
|
||||
wp->event = bufferevent_new(wp->fd, window_pane_read_callback, NULL,
|
||||
window_pane_error_callback, wp);
|
||||
bufferevent_enable(wp->event, EV_READ|EV_WRITE);
|
||||
|
||||
free(cmd);
|
||||
return (0);
|
||||
}
|
||||
|
||||
@ -1201,114 +1150,198 @@ window_pane_search(struct window_pane *wp, const char *searchstr,
|
||||
return (msg);
|
||||
}
|
||||
|
||||
/* Find the pane directly above another. */
|
||||
/* Get MRU pane from a list. */
|
||||
struct window_pane *
|
||||
window_pane_choose_best(struct window_pane_list *list)
|
||||
{
|
||||
struct window_pane *next, *best;
|
||||
u_int i;
|
||||
|
||||
if (ARRAY_LENGTH(list) == 0)
|
||||
return (NULL);
|
||||
|
||||
best = ARRAY_FIRST(list);
|
||||
for (i = 1; i < ARRAY_LENGTH(list); i++) {
|
||||
next = ARRAY_ITEM(list, i);
|
||||
if (next->active_point > best->active_point)
|
||||
best = next;
|
||||
}
|
||||
return (best);
|
||||
}
|
||||
|
||||
/*
|
||||
* Find the pane directly above another. We build a list of those adjacent to
|
||||
* top edge and then choose the best.
|
||||
*/
|
||||
struct window_pane *
|
||||
window_pane_find_up(struct window_pane *wp)
|
||||
{
|
||||
struct window_pane *wp2;
|
||||
u_int left, top;
|
||||
struct window_pane *next, *best;
|
||||
u_int edge, left, right, end;
|
||||
struct window_pane_list list;
|
||||
int found;
|
||||
|
||||
if (wp == NULL || !window_pane_visible(wp))
|
||||
return (NULL);
|
||||
ARRAY_INIT(&list);
|
||||
|
||||
edge = wp->yoff;
|
||||
if (edge == 0)
|
||||
edge = wp->window->sy + 1;
|
||||
|
||||
top = wp->yoff;
|
||||
if (top == 0)
|
||||
top = wp->window->sy + 1;
|
||||
left = wp->xoff;
|
||||
right = wp->xoff + wp->sx;
|
||||
|
||||
TAILQ_FOREACH(wp2, &wp->window->panes, entry) {
|
||||
if (!window_pane_visible(wp2))
|
||||
TAILQ_FOREACH(next, &wp->window->panes, entry) {
|
||||
if (next == wp || !window_pane_visible(next))
|
||||
continue;
|
||||
if (wp2->yoff + wp2->sy + 1 != top)
|
||||
if (next->yoff + next->sy + 1 != edge)
|
||||
continue;
|
||||
if (left >= wp2->xoff && left <= wp2->xoff + wp2->sx)
|
||||
return (window_pane_active_set(wp, wp2));
|
||||
end = next->xoff + next->sx - 1;
|
||||
|
||||
found = 0;
|
||||
if (next->xoff < left && end > right)
|
||||
found = 1;
|
||||
else if (next->xoff >= left && next->xoff <= right)
|
||||
found = 1;
|
||||
else if (end >= left && end <= right)
|
||||
found = 1;
|
||||
if (found)
|
||||
ARRAY_ADD(&list, next);
|
||||
}
|
||||
return (NULL);
|
||||
|
||||
best = window_pane_choose_best(&list);
|
||||
ARRAY_FREE(&list);
|
||||
return (best);
|
||||
}
|
||||
|
||||
/* Find the pane directly below another. */
|
||||
struct window_pane *
|
||||
window_pane_find_down(struct window_pane *wp)
|
||||
{
|
||||
struct window_pane *wp2;
|
||||
u_int left, bottom;
|
||||
struct window_pane *next, *best;
|
||||
u_int edge, left, right, end;
|
||||
struct window_pane_list list;
|
||||
int found;
|
||||
|
||||
if (wp == NULL || !window_pane_visible(wp))
|
||||
return (NULL);
|
||||
ARRAY_INIT(&list);
|
||||
|
||||
edge = wp->yoff + wp->sy + 1;
|
||||
if (edge >= wp->window->sy)
|
||||
edge = 0;
|
||||
|
||||
bottom = wp->yoff + wp->sy + 1;
|
||||
if (bottom >= wp->window->sy)
|
||||
bottom = 0;
|
||||
left = wp->xoff;
|
||||
right = wp->xoff + wp->sx;
|
||||
|
||||
TAILQ_FOREACH(wp2, &wp->window->panes, entry) {
|
||||
if (!window_pane_visible(wp2))
|
||||
TAILQ_FOREACH(next, &wp->window->panes, entry) {
|
||||
if (next == wp || !window_pane_visible(next))
|
||||
continue;
|
||||
if (wp2->yoff != bottom)
|
||||
if (next->yoff != edge)
|
||||
continue;
|
||||
if (left >= wp2->xoff && left <= wp2->xoff + wp2->sx)
|
||||
return (window_pane_active_set(wp, wp2));
|
||||
end = next->xoff + next->sx - 1;
|
||||
|
||||
found = 0;
|
||||
if (next->xoff < left && end > right)
|
||||
found = 1;
|
||||
else if (next->xoff >= left && next->xoff <= right)
|
||||
found = 1;
|
||||
else if (end >= left && end <= right)
|
||||
found = 1;
|
||||
if (found)
|
||||
ARRAY_ADD(&list, next);
|
||||
}
|
||||
return (NULL);
|
||||
|
||||
best = window_pane_choose_best(&list);
|
||||
ARRAY_FREE(&list);
|
||||
return (best);
|
||||
}
|
||||
|
||||
/*
|
||||
* Find the pane directly to the left of another, adjacent to the left side and
|
||||
* containing the top edge.
|
||||
*/
|
||||
/* Find the pane directly to the left of another. */
|
||||
struct window_pane *
|
||||
window_pane_find_left(struct window_pane *wp)
|
||||
{
|
||||
struct window_pane *wp2;
|
||||
u_int left, top;
|
||||
struct window_pane *next, *best;
|
||||
u_int edge, top, bottom, end;
|
||||
struct window_pane_list list;
|
||||
int found;
|
||||
|
||||
if (wp == NULL || !window_pane_visible(wp))
|
||||
return (NULL);
|
||||
ARRAY_INIT(&list);
|
||||
|
||||
edge = wp->xoff;
|
||||
if (edge == 0)
|
||||
edge = wp->window->sx + 1;
|
||||
|
||||
left = wp->xoff;
|
||||
if (left == 0)
|
||||
left = wp->window->sx + 1;
|
||||
top = wp->yoff;
|
||||
bottom = wp->yoff + wp->sy;
|
||||
|
||||
TAILQ_FOREACH(wp2, &wp->window->panes, entry) {
|
||||
if (!window_pane_visible(wp2))
|
||||
TAILQ_FOREACH(next, &wp->window->panes, entry) {
|
||||
if (next == wp || !window_pane_visible(next))
|
||||
continue;
|
||||
if (wp2->xoff + wp2->sx + 1 != left)
|
||||
if (next->xoff + next->sx + 1 != edge)
|
||||
continue;
|
||||
if (top >= wp2->yoff && top <= wp2->yoff + wp2->sy)
|
||||
return (window_pane_active_set(wp, wp2));
|
||||
end = next->yoff + next->sy - 1;
|
||||
|
||||
found = 0;
|
||||
if (next->yoff < top && end > bottom)
|
||||
found = 1;
|
||||
else if (next->yoff >= top && next->yoff <= bottom)
|
||||
found = 1;
|
||||
else if (end >= top && end <= bottom)
|
||||
found = 1;
|
||||
if (found)
|
||||
ARRAY_ADD(&list, next);
|
||||
}
|
||||
return (NULL);
|
||||
|
||||
best = window_pane_choose_best(&list);
|
||||
ARRAY_FREE(&list);
|
||||
return (best);
|
||||
}
|
||||
|
||||
/*
|
||||
* Find the pane directly to the right of another, that is adjacent to the
|
||||
* right edge and including the top edge.
|
||||
*/
|
||||
/* Find the pane directly to the right of another. */
|
||||
struct window_pane *
|
||||
window_pane_find_right(struct window_pane *wp)
|
||||
{
|
||||
struct window_pane *wp2;
|
||||
u_int right, top;
|
||||
struct window_pane *next, *best;
|
||||
u_int edge, top, bottom, end;
|
||||
struct window_pane_list list;
|
||||
int found;
|
||||
|
||||
if (wp == NULL || !window_pane_visible(wp))
|
||||
return (NULL);
|
||||
ARRAY_INIT(&list);
|
||||
|
||||
edge = wp->xoff + wp->sx + 1;
|
||||
if (edge >= wp->window->sx)
|
||||
edge = 0;
|
||||
|
||||
right = wp->xoff + wp->sx + 1;
|
||||
if (right >= wp->window->sx)
|
||||
right = 0;
|
||||
top = wp->yoff;
|
||||
bottom = wp->yoff + wp->sy;
|
||||
|
||||
TAILQ_FOREACH(wp2, &wp->window->panes, entry) {
|
||||
if (!window_pane_visible(wp2))
|
||||
TAILQ_FOREACH(next, &wp->window->panes, entry) {
|
||||
if (next == wp || !window_pane_visible(next))
|
||||
continue;
|
||||
if (wp2->xoff != right)
|
||||
if (next->xoff != edge)
|
||||
continue;
|
||||
if (top >= wp2->yoff && top <= wp2->yoff + wp2->sy)
|
||||
return (window_pane_active_set(wp, wp2));
|
||||
end = next->yoff + next->sy - 1;
|
||||
|
||||
found = 0;
|
||||
if (next->yoff < top && end > bottom)
|
||||
found = 1;
|
||||
else if (next->yoff >= top && next->yoff <= bottom)
|
||||
found = 1;
|
||||
else if (end >= top && end <= bottom)
|
||||
found = 1;
|
||||
if (found)
|
||||
ARRAY_ADD(&list, next);
|
||||
}
|
||||
return (NULL);
|
||||
|
||||
best = window_pane_choose_best(&list);
|
||||
ARRAY_FREE(&list);
|
||||
return (best);
|
||||
}
|
||||
|
||||
/* Clear alert flags for a winlink */
|
||||
|
Loading…
Reference in New Issue
Block a user