mirror of
https://github.com/tmux/tmux.git
synced 2025-01-05 23:38:48 +00:00
Merge branch 'obsd-master'
Conflicts: Makefile.am cfg.c server-client.c
This commit is contained in:
commit
f17ecaa495
@ -66,8 +66,6 @@ dist_tmux_SOURCES = \
|
||||
cmd-bind-key.c \
|
||||
cmd-break-pane.c \
|
||||
cmd-capture-pane.c \
|
||||
cmd-choose-buffer.c \
|
||||
cmd-choose-client.c \
|
||||
cmd-choose-tree.c \
|
||||
cmd-command-prompt.c \
|
||||
cmd-confirm-before.c \
|
||||
@ -145,6 +143,7 @@ dist_tmux_SOURCES = \
|
||||
layout-set.c \
|
||||
layout.c \
|
||||
log.c \
|
||||
mode-tree.c \
|
||||
names.c \
|
||||
notify.c \
|
||||
options-table.c \
|
||||
@ -169,9 +168,11 @@ dist_tmux_SOURCES = \
|
||||
tty-term.c \
|
||||
tty.c \
|
||||
utf8.c \
|
||||
window-choose.c \
|
||||
window-buffer.c \
|
||||
window-client.c \
|
||||
window-clock.c \
|
||||
window-copy.c \
|
||||
window-tree.c \
|
||||
window.c \
|
||||
xmalloc.c \
|
||||
xmalloc.h \
|
||||
|
@ -34,7 +34,6 @@ struct args_entry {
|
||||
RB_ENTRY(args_entry) entry;
|
||||
};
|
||||
|
||||
static void args_set(struct args *, u_char, const char *);
|
||||
static struct args_entry *args_find(struct args *, u_char);
|
||||
|
||||
static int args_cmp(struct args_entry *, struct args_entry *);
|
||||
@ -195,7 +194,7 @@ args_has(struct args *args, u_char ch)
|
||||
}
|
||||
|
||||
/* Set argument value in the arguments tree. */
|
||||
static void
|
||||
void
|
||||
args_set(struct args *args, u_char ch, const char *value)
|
||||
{
|
||||
struct args_entry *entry;
|
||||
|
2
cfg.c
2
cfg.c
@ -233,7 +233,7 @@ cfg_show_causes(struct session *s)
|
||||
return;
|
||||
wp = s->curw->window->active;
|
||||
|
||||
window_pane_set_mode(wp, &window_copy_mode);
|
||||
window_pane_set_mode(wp, &window_copy_mode, NULL, NULL);
|
||||
window_copy_init_for_output(wp);
|
||||
for (i = 0; i < cfg_ncauses; i++) {
|
||||
window_copy_add(wp, "%s", cfg_causes[i]);
|
||||
|
@ -1,101 +0,0 @@
|
||||
/* $OpenBSD$ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2010 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
|
||||
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <ctype.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "tmux.h"
|
||||
|
||||
/*
|
||||
* Enter choice mode to choose a buffer.
|
||||
*/
|
||||
|
||||
#define CHOOSE_BUFFER_TEMPLATE \
|
||||
"#{buffer_name}: #{buffer_size} bytes: #{buffer_sample}"
|
||||
|
||||
static enum cmd_retval cmd_choose_buffer_exec(struct cmd *,
|
||||
struct cmdq_item *);
|
||||
|
||||
const struct cmd_entry cmd_choose_buffer_entry = {
|
||||
.name = "choose-buffer",
|
||||
.alias = NULL,
|
||||
|
||||
.args = { "F:t:", 0, 1 },
|
||||
.usage = CMD_TARGET_WINDOW_USAGE " [-F format] [template]",
|
||||
|
||||
.target = { 't', CMD_FIND_WINDOW, 0 },
|
||||
|
||||
.flags = 0,
|
||||
.exec = cmd_choose_buffer_exec
|
||||
};
|
||||
|
||||
static enum cmd_retval
|
||||
cmd_choose_buffer_exec(struct cmd *self, struct cmdq_item *item)
|
||||
{
|
||||
struct args *args = self->args;
|
||||
struct client *c = cmd_find_client(item, NULL, 1);
|
||||
struct winlink *wl = item->target.wl;
|
||||
struct window_choose_data *cdata;
|
||||
struct paste_buffer *pb;
|
||||
char *action, *action_data;
|
||||
const char *template;
|
||||
u_int idx;
|
||||
|
||||
if (c == NULL) {
|
||||
cmdq_error(item, "no client available");
|
||||
return (CMD_RETURN_ERROR);
|
||||
}
|
||||
|
||||
if ((template = args_get(args, 'F')) == NULL)
|
||||
template = CHOOSE_BUFFER_TEMPLATE;
|
||||
|
||||
if (paste_get_top(NULL) == NULL)
|
||||
return (CMD_RETURN_NORMAL);
|
||||
|
||||
if (window_pane_set_mode(wl->window->active, &window_choose_mode) != 0)
|
||||
return (CMD_RETURN_NORMAL);
|
||||
|
||||
if (args->argc != 0)
|
||||
action = xstrdup(args->argv[0]);
|
||||
else
|
||||
action = xstrdup("paste-buffer -b '%%'");
|
||||
|
||||
idx = 0;
|
||||
pb = NULL;
|
||||
while ((pb = paste_walk(pb)) != NULL) {
|
||||
cdata = window_choose_data_create(TREE_OTHER, c, c->session);
|
||||
cdata->idx = idx;
|
||||
|
||||
cdata->ft_template = xstrdup(template);
|
||||
format_defaults_paste_buffer(cdata->ft, pb);
|
||||
|
||||
xasprintf(&action_data, "%s", paste_buffer_name(pb));
|
||||
cdata->command = cmd_template_replace(action, action_data, 1);
|
||||
free(action_data);
|
||||
|
||||
window_choose_add(wl->window->active, cdata);
|
||||
idx++;
|
||||
}
|
||||
free(action);
|
||||
|
||||
window_choose_ready(wl->window->active, 0, NULL);
|
||||
|
||||
return (CMD_RETURN_NORMAL);
|
||||
}
|
@ -1,135 +0,0 @@
|
||||
/* $OpenBSD$ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2009 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
|
||||
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <ctype.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "tmux.h"
|
||||
|
||||
/*
|
||||
* Enter choice mode to choose a client.
|
||||
*/
|
||||
|
||||
#define CHOOSE_CLIENT_TEMPLATE \
|
||||
"#{client_name}: #{session_name} " \
|
||||
"[#{client_width}x#{client_height} #{client_termname}]" \
|
||||
"#{?client_utf8, (utf8),}#{?client_readonly, (ro),} " \
|
||||
"(last used #{t:client_activity})"
|
||||
|
||||
static enum cmd_retval cmd_choose_client_exec(struct cmd *,
|
||||
struct cmdq_item *);
|
||||
|
||||
static void cmd_choose_client_callback(struct window_choose_data *);
|
||||
|
||||
const struct cmd_entry cmd_choose_client_entry = {
|
||||
.name = "choose-client",
|
||||
.alias = NULL,
|
||||
|
||||
.args = { "F:t:", 0, 1 },
|
||||
.usage = CMD_TARGET_WINDOW_USAGE " [-F format] [template]",
|
||||
|
||||
.target = { 't', CMD_FIND_WINDOW, 0 },
|
||||
|
||||
.flags = 0,
|
||||
.exec = cmd_choose_client_exec
|
||||
};
|
||||
|
||||
struct cmd_choose_client_data {
|
||||
struct client *client;
|
||||
};
|
||||
|
||||
static enum cmd_retval
|
||||
cmd_choose_client_exec(struct cmd *self, struct cmdq_item *item)
|
||||
{
|
||||
struct args *args = self->args;
|
||||
struct client *c = cmd_find_client(item, NULL, 1);
|
||||
struct client *c1;
|
||||
struct window_choose_data *cdata;
|
||||
struct winlink *wl = item->target.wl;
|
||||
const char *template;
|
||||
char *action;
|
||||
u_int idx, cur;
|
||||
|
||||
if (c == NULL) {
|
||||
cmdq_error(item, "no client available");
|
||||
return (CMD_RETURN_ERROR);
|
||||
}
|
||||
|
||||
if (window_pane_set_mode(wl->window->active, &window_choose_mode) != 0)
|
||||
return (CMD_RETURN_NORMAL);
|
||||
|
||||
if ((template = args_get(args, 'F')) == NULL)
|
||||
template = CHOOSE_CLIENT_TEMPLATE;
|
||||
|
||||
if (args->argc != 0)
|
||||
action = xstrdup(args->argv[0]);
|
||||
else
|
||||
action = xstrdup("detach-client -t '%%'");
|
||||
|
||||
cur = idx = 0;
|
||||
TAILQ_FOREACH(c1, &clients, entry) {
|
||||
if (c1->session == NULL)
|
||||
continue;
|
||||
if (c1 == item->client)
|
||||
cur = idx;
|
||||
|
||||
cdata = window_choose_data_create(TREE_OTHER, c, c->session);
|
||||
cdata->idx = idx;
|
||||
|
||||
cdata->ft_template = xstrdup(template);
|
||||
format_add(cdata->ft, "line", "%u", idx);
|
||||
format_defaults(cdata->ft, c1, NULL, NULL, NULL);
|
||||
|
||||
cdata->command = cmd_template_replace(action, c1->name, 1);
|
||||
|
||||
window_choose_add(wl->window->active, cdata);
|
||||
|
||||
idx++;
|
||||
}
|
||||
free(action);
|
||||
|
||||
window_choose_ready(wl->window->active, cur,
|
||||
cmd_choose_client_callback);
|
||||
|
||||
return (CMD_RETURN_NORMAL);
|
||||
}
|
||||
|
||||
static void
|
||||
cmd_choose_client_callback(struct window_choose_data *cdata)
|
||||
{
|
||||
struct client *c;
|
||||
u_int idx;
|
||||
|
||||
if (cdata == NULL)
|
||||
return;
|
||||
if (cdata->start_client->flags & CLIENT_DEAD)
|
||||
return;
|
||||
|
||||
idx = 0;
|
||||
TAILQ_FOREACH(c, &clients, entry) {
|
||||
if (idx == cdata->idx)
|
||||
break;
|
||||
idx++;
|
||||
}
|
||||
if (c == NULL || c->session == NULL)
|
||||
return;
|
||||
|
||||
window_choose_data_run(cdata);
|
||||
}
|
@ -18,66 +18,48 @@
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <ctype.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "tmux.h"
|
||||
|
||||
#define CMD_CHOOSE_TREE_WINDOW_ACTION "select-window -t '%%'"
|
||||
#define CMD_CHOOSE_TREE_SESSION_ACTION "switch-client -t '%%'"
|
||||
|
||||
/*
|
||||
* Enter choice mode to choose a session and/or window.
|
||||
* Enter a mode.
|
||||
*/
|
||||
|
||||
#define CHOOSE_TREE_SESSION_TEMPLATE \
|
||||
"#{session_name}: #{session_windows} windows" \
|
||||
"#{?session_grouped, (group ,}" \
|
||||
"#{session_group}#{?session_grouped,),}" \
|
||||
"#{?session_attached, (attached),}"
|
||||
#define CHOOSE_TREE_WINDOW_TEMPLATE \
|
||||
"#{window_index}: #{window_name}#{window_flags} " \
|
||||
"\"#{pane_title}\""
|
||||
|
||||
static enum cmd_retval cmd_choose_tree_exec(struct cmd *, struct cmdq_item *);
|
||||
|
||||
const struct cmd_entry cmd_choose_tree_entry = {
|
||||
.name = "choose-tree",
|
||||
.alias = NULL,
|
||||
|
||||
.args = { "S:W:swub:c:t:", 0, 1 },
|
||||
.usage = "[-suw] [-b session-template] [-c window template] "
|
||||
"[-S format] [-W format] " CMD_TARGET_WINDOW_USAGE,
|
||||
.args = { "st:w", 0, 1 },
|
||||
.usage = "[-sw] " CMD_TARGET_PANE_USAGE,
|
||||
|
||||
.target = { 't', CMD_FIND_WINDOW, 0 },
|
||||
.target = { 't', CMD_FIND_PANE, 0 },
|
||||
|
||||
.flags = 0,
|
||||
.exec = cmd_choose_tree_exec
|
||||
};
|
||||
|
||||
const struct cmd_entry cmd_choose_session_entry = {
|
||||
.name = "choose-session",
|
||||
const struct cmd_entry cmd_choose_client_entry = {
|
||||
.name = "choose-client",
|
||||
.alias = NULL,
|
||||
|
||||
.args = { "F:t:", 0, 1 },
|
||||
.usage = CMD_TARGET_WINDOW_USAGE " [-F format] [template]",
|
||||
.args = { "t:", 0, 1 },
|
||||
.usage = CMD_TARGET_PANE_USAGE,
|
||||
|
||||
.target = { 't', CMD_FIND_WINDOW, 0 },
|
||||
.target = { 't', CMD_FIND_PANE, 0 },
|
||||
|
||||
.flags = 0,
|
||||
.exec = cmd_choose_tree_exec
|
||||
};
|
||||
|
||||
const struct cmd_entry cmd_choose_window_entry = {
|
||||
.name = "choose-window",
|
||||
const struct cmd_entry cmd_choose_buffer_entry = {
|
||||
.name = "choose-buffer",
|
||||
.alias = NULL,
|
||||
|
||||
.args = { "F:t:", 0, 1 },
|
||||
.usage = CMD_TARGET_WINDOW_USAGE "[-F format] [template]",
|
||||
.args = { "t:", 0, 1 },
|
||||
.usage = CMD_TARGET_PANE_USAGE,
|
||||
|
||||
.target = { 't', CMD_FIND_WINDOW, 0 },
|
||||
.target = { 't', CMD_FIND_PANE, 0 },
|
||||
|
||||
.flags = 0,
|
||||
.exec = cmd_choose_tree_exec
|
||||
@ -87,167 +69,20 @@ static enum cmd_retval
|
||||
cmd_choose_tree_exec(struct cmd *self, struct cmdq_item *item)
|
||||
{
|
||||
struct args *args = self->args;
|
||||
struct client *c = cmd_find_client(item, NULL, 1);
|
||||
struct winlink *wl = item->target.wl, *wm;
|
||||
struct session *s = item->target.s, *s2;
|
||||
struct window_choose_data *wcd = NULL;
|
||||
const char *ses_template, *win_template;
|
||||
char *final_win_action, *cur_win_template;
|
||||
char *final_win_template_middle;
|
||||
char *final_win_template_last;
|
||||
const char *ses_action, *win_action;
|
||||
u_int cur_win, idx_ses, win_ses, win_max;
|
||||
u_int wflag, sflag;
|
||||
struct window_pane *wp = item->target.wp;
|
||||
const struct window_mode *mode;
|
||||
|
||||
ses_template = win_template = NULL;
|
||||
ses_action = win_action = NULL;
|
||||
|
||||
if (c == NULL) {
|
||||
cmdq_error(item, "no client available");
|
||||
return (CMD_RETURN_ERROR);
|
||||
}
|
||||
|
||||
if (window_pane_set_mode(wl->window->active, &window_choose_mode) != 0)
|
||||
return (CMD_RETURN_NORMAL);
|
||||
|
||||
/* Sort out which command this is. */
|
||||
wflag = sflag = 0;
|
||||
if (self->entry == &cmd_choose_session_entry) {
|
||||
sflag = 1;
|
||||
if ((ses_template = args_get(args, 'F')) == NULL)
|
||||
ses_template = CHOOSE_TREE_SESSION_TEMPLATE;
|
||||
|
||||
if (args->argc != 0)
|
||||
ses_action = args->argv[0];
|
||||
else
|
||||
ses_action = CMD_CHOOSE_TREE_SESSION_ACTION;
|
||||
} else if (self->entry == &cmd_choose_window_entry) {
|
||||
wflag = 1;
|
||||
if ((win_template = args_get(args, 'F')) == NULL)
|
||||
win_template = CHOOSE_TREE_WINDOW_TEMPLATE;
|
||||
|
||||
if (args->argc != 0)
|
||||
win_action = args->argv[0];
|
||||
else
|
||||
win_action = CMD_CHOOSE_TREE_WINDOW_ACTION;
|
||||
} else {
|
||||
wflag = args_has(args, 'w');
|
||||
sflag = args_has(args, 's');
|
||||
|
||||
if ((ses_action = args_get(args, 'b')) == NULL)
|
||||
ses_action = CMD_CHOOSE_TREE_SESSION_ACTION;
|
||||
|
||||
if ((win_action = args_get(args, 'c')) == NULL)
|
||||
win_action = CMD_CHOOSE_TREE_WINDOW_ACTION;
|
||||
|
||||
if ((ses_template = args_get(args, 'S')) == NULL)
|
||||
ses_template = CHOOSE_TREE_SESSION_TEMPLATE;
|
||||
|
||||
if ((win_template = args_get(args, 'W')) == NULL)
|
||||
win_template = CHOOSE_TREE_WINDOW_TEMPLATE;
|
||||
}
|
||||
|
||||
/*
|
||||
* If not asking for windows and sessions, assume no "-ws" given and
|
||||
* hence display the entire tree outright.
|
||||
*/
|
||||
if (!wflag && !sflag)
|
||||
wflag = sflag = 1;
|
||||
|
||||
/*
|
||||
* If we're drawing in tree mode, including sessions, then pad the
|
||||
* window template, otherwise just render the windows as a flat list
|
||||
* without any padding.
|
||||
*/
|
||||
if (wflag && sflag) {
|
||||
xasprintf(&final_win_template_middle,
|
||||
" \001tq\001> %s", win_template);
|
||||
xasprintf(&final_win_template_last,
|
||||
" \001mq\001> %s", win_template);
|
||||
} else if (wflag) {
|
||||
final_win_template_middle = xstrdup(win_template);
|
||||
final_win_template_last = xstrdup(win_template);
|
||||
if (self->entry == &cmd_choose_buffer_entry) {
|
||||
if (paste_get_top(NULL) == NULL)
|
||||
return (CMD_RETURN_NORMAL);
|
||||
mode = &window_buffer_mode;
|
||||
} else if (self->entry == &cmd_choose_client_entry) {
|
||||
if (server_client_how_many() == 0)
|
||||
return (CMD_RETURN_NORMAL);
|
||||
mode = &window_client_mode;
|
||||
} else
|
||||
final_win_template_middle = final_win_template_last = NULL;
|
||||
|
||||
idx_ses = cur_win = -1;
|
||||
RB_FOREACH(s2, sessions, &sessions) {
|
||||
idx_ses++;
|
||||
|
||||
/*
|
||||
* If we're just choosing windows, jump straight there. Note
|
||||
* that this implies the current session, so only choose
|
||||
* windows when the session matches this one.
|
||||
*/
|
||||
if (wflag && !sflag) {
|
||||
if (s != s2)
|
||||
continue;
|
||||
goto windows_only;
|
||||
}
|
||||
|
||||
wcd = window_choose_add_session(wl->window->active,
|
||||
c, s2, ses_template, ses_action, idx_ses);
|
||||
|
||||
/* If we're just choosing sessions, skip choosing windows. */
|
||||
if (sflag && !wflag) {
|
||||
if (s == s2)
|
||||
cur_win = idx_ses;
|
||||
continue;
|
||||
}
|
||||
windows_only:
|
||||
win_ses = win_max = -1;
|
||||
RB_FOREACH(wm, winlinks, &s2->windows)
|
||||
win_max++;
|
||||
RB_FOREACH(wm, winlinks, &s2->windows) {
|
||||
win_ses++;
|
||||
if (sflag && wflag)
|
||||
idx_ses++;
|
||||
|
||||
if (wm == s2->curw && s == s2) {
|
||||
if (wflag && !sflag) {
|
||||
/*
|
||||
* Then we're only counting windows.
|
||||
* So remember which is the current
|
||||
* window in the list.
|
||||
*/
|
||||
cur_win = win_ses;
|
||||
} else
|
||||
cur_win = idx_ses;
|
||||
}
|
||||
|
||||
xasprintf(&final_win_action, "%s %s %s",
|
||||
wcd != NULL ? wcd->command : "",
|
||||
wcd != NULL ? ";" : "", win_action);
|
||||
|
||||
if (win_ses != win_max)
|
||||
cur_win_template = final_win_template_middle;
|
||||
else
|
||||
cur_win_template = final_win_template_last;
|
||||
|
||||
window_choose_add_window(wl->window->active,
|
||||
c, s2, wm, cur_win_template,
|
||||
final_win_action,
|
||||
(wflag && !sflag) ? win_ses : idx_ses);
|
||||
|
||||
free(final_win_action);
|
||||
}
|
||||
|
||||
/*
|
||||
* If we're just drawing windows, don't consider moving on to
|
||||
* other sessions as we only list windows in this session.
|
||||
*/
|
||||
if (wflag && !sflag)
|
||||
break;
|
||||
}
|
||||
free(final_win_template_middle);
|
||||
free(final_win_template_last);
|
||||
|
||||
window_choose_ready(wl->window->active, cur_win, NULL);
|
||||
|
||||
if (args_has(args, 'u')) {
|
||||
window_choose_expand_all(wl->window->active);
|
||||
window_choose_set_current(wl->window->active, cur_win);
|
||||
}
|
||||
mode = &window_tree_mode;
|
||||
|
||||
window_pane_set_mode(wp, mode, &item->target, args);
|
||||
return (CMD_RETURN_NORMAL);
|
||||
}
|
||||
|
@ -60,6 +60,7 @@ cmd_copy_mode_exec(struct cmd *self, struct cmdq_item *item)
|
||||
struct client *c = item->client;
|
||||
struct session *s;
|
||||
struct window_pane *wp = item->target.wp;
|
||||
int flag;
|
||||
|
||||
if (args_has(args, 'M')) {
|
||||
if ((wp = cmd_mouse_pane(&shared->mouse, &s, NULL)) == NULL)
|
||||
@ -69,12 +70,13 @@ cmd_copy_mode_exec(struct cmd *self, struct cmdq_item *item)
|
||||
}
|
||||
|
||||
if (self->entry == &cmd_clock_mode_entry) {
|
||||
window_pane_set_mode(wp, &window_clock_mode);
|
||||
window_pane_set_mode(wp, &window_clock_mode, NULL, NULL);
|
||||
return (CMD_RETURN_NORMAL);
|
||||
}
|
||||
|
||||
if (wp->mode != &window_copy_mode) {
|
||||
if (window_pane_set_mode(wp, &window_copy_mode) != 0)
|
||||
flag = window_pane_set_mode(wp, &window_copy_mode, NULL, NULL);
|
||||
if (flag != 0)
|
||||
return (CMD_RETURN_NORMAL);
|
||||
window_copy_init_from_pane(wp, args_has(self->args, 'e'));
|
||||
}
|
||||
|
@ -18,9 +18,7 @@
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <fnmatch.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "tmux.h"
|
||||
|
||||
@ -28,216 +26,69 @@
|
||||
* Find window containing text.
|
||||
*/
|
||||
|
||||
#define FIND_WINDOW_TEMPLATE \
|
||||
"#{window_index}: #{window_name} " \
|
||||
"[#{window_width}x#{window_height}] " \
|
||||
"(#{window_panes} panes) #{window_find_matches}"
|
||||
|
||||
static enum cmd_retval cmd_find_window_exec(struct cmd *, struct cmdq_item *);
|
||||
|
||||
static void cmd_find_window_callback(struct window_choose_data *);
|
||||
|
||||
/* Flags for determining matching behavior. */
|
||||
#define CMD_FIND_WINDOW_BY_TITLE 0x1
|
||||
#define CMD_FIND_WINDOW_BY_CONTENT 0x2
|
||||
#define CMD_FIND_WINDOW_BY_NAME 0x4
|
||||
|
||||
#define CMD_FIND_WINDOW_ALL \
|
||||
(CMD_FIND_WINDOW_BY_TITLE | \
|
||||
CMD_FIND_WINDOW_BY_CONTENT | \
|
||||
CMD_FIND_WINDOW_BY_NAME)
|
||||
|
||||
const struct cmd_entry cmd_find_window_entry = {
|
||||
.name = "find-window",
|
||||
.alias = "findw",
|
||||
|
||||
.args = { "F:CNt:T", 1, 4 },
|
||||
.usage = "[-CNT] [-F format] " CMD_TARGET_WINDOW_USAGE " match-string",
|
||||
.args = { "CNt:T", 1, 1 },
|
||||
.usage = "[-CNT] " CMD_TARGET_PANE_USAGE " match-string",
|
||||
|
||||
.target = { 't', CMD_FIND_WINDOW, 0 },
|
||||
.target = { 't', CMD_FIND_PANE, 0 },
|
||||
|
||||
.flags = 0,
|
||||
.exec = cmd_find_window_exec
|
||||
};
|
||||
|
||||
struct cmd_find_window_data {
|
||||
struct winlink *wl;
|
||||
char *list_ctx;
|
||||
u_int pane_id;
|
||||
TAILQ_ENTRY(cmd_find_window_data) entry;
|
||||
};
|
||||
TAILQ_HEAD(cmd_find_window_list, cmd_find_window_data);
|
||||
|
||||
static u_int cmd_find_window_match_flags(struct args *);
|
||||
static void cmd_find_window_match(struct cmd_find_window_list *, int,
|
||||
struct winlink *, const char *, const char *);
|
||||
|
||||
static u_int
|
||||
cmd_find_window_match_flags(struct args *args)
|
||||
{
|
||||
u_int match_flags = 0;
|
||||
|
||||
/* Turn on flags based on the options. */
|
||||
if (args_has(args, 'T'))
|
||||
match_flags |= CMD_FIND_WINDOW_BY_TITLE;
|
||||
if (args_has(args, 'C'))
|
||||
match_flags |= CMD_FIND_WINDOW_BY_CONTENT;
|
||||
if (args_has(args, 'N'))
|
||||
match_flags |= CMD_FIND_WINDOW_BY_NAME;
|
||||
|
||||
/* If none of the flags were set, default to matching anything. */
|
||||
if (match_flags == 0)
|
||||
match_flags = CMD_FIND_WINDOW_ALL;
|
||||
|
||||
return (match_flags);
|
||||
}
|
||||
|
||||
static void
|
||||
cmd_find_window_match(struct cmd_find_window_list *find_list,
|
||||
int match_flags, struct winlink *wl, const char *str,
|
||||
const char *searchstr)
|
||||
{
|
||||
struct cmd_find_window_data *find_data;
|
||||
struct window_pane *wp;
|
||||
u_int i, line;
|
||||
char *sres;
|
||||
|
||||
find_data = xcalloc(1, sizeof *find_data);
|
||||
|
||||
i = 0;
|
||||
TAILQ_FOREACH(wp, &wl->window->panes, entry) {
|
||||
i++;
|
||||
|
||||
if ((match_flags & CMD_FIND_WINDOW_BY_NAME) &&
|
||||
fnmatch(searchstr, wl->window->name, 0) == 0) {
|
||||
find_data->list_ctx = xstrdup("");
|
||||
break;
|
||||
}
|
||||
|
||||
if ((match_flags & CMD_FIND_WINDOW_BY_TITLE) &&
|
||||
fnmatch(searchstr, wp->base.title, 0) == 0) {
|
||||
xasprintf(&find_data->list_ctx,
|
||||
"pane %u title: \"%s\"", i - 1, wp->base.title);
|
||||
break;
|
||||
}
|
||||
|
||||
if (match_flags & CMD_FIND_WINDOW_BY_CONTENT &&
|
||||
(sres = window_pane_search_old(wp, str, &line)) != NULL) {
|
||||
xasprintf(&find_data->list_ctx,
|
||||
"pane %u line %u: \"%s\"", i - 1, line + 1, sres);
|
||||
free(sres);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (find_data->list_ctx != NULL) {
|
||||
find_data->wl = wl;
|
||||
find_data->pane_id = i - 1;
|
||||
TAILQ_INSERT_TAIL(find_list, find_data, entry);
|
||||
} else
|
||||
free(find_data);
|
||||
}
|
||||
|
||||
static enum cmd_retval
|
||||
cmd_find_window_exec(struct cmd *self, struct cmdq_item *item)
|
||||
{
|
||||
struct args *args = self->args;
|
||||
struct cmd_find_state *current = &item->shared->current;
|
||||
struct client *c = cmd_find_client(item, NULL, 1);
|
||||
struct window_choose_data *cdata;
|
||||
struct session *s = item->target.s;
|
||||
struct winlink *wl = item->target.wl, *wm;
|
||||
struct cmd_find_window_list find_list;
|
||||
struct cmd_find_window_data *find_data;
|
||||
struct cmd_find_window_data *find_data1;
|
||||
char *str, *searchstr;
|
||||
const char *template;
|
||||
u_int i, match_flags;
|
||||
struct args *args = self->args, *new_args;
|
||||
struct window_pane *wp = item->target.wp;
|
||||
const char *s = args->argv[0];
|
||||
char *filter, *argv = { NULL };
|
||||
int C, N, T;
|
||||
|
||||
if (c == NULL) {
|
||||
cmdq_error(item, "no client available");
|
||||
return (CMD_RETURN_ERROR);
|
||||
}
|
||||
C = args_has(args, 'C');
|
||||
N = args_has(args, 'N');
|
||||
T = args_has(args, 'T');
|
||||
|
||||
if ((template = args_get(args, 'F')) == NULL)
|
||||
template = FIND_WINDOW_TEMPLATE;
|
||||
if (!C && !N && !T)
|
||||
C = N = T = 1;
|
||||
|
||||
match_flags = cmd_find_window_match_flags(args);
|
||||
str = args->argv[0];
|
||||
if (C && N && T) {
|
||||
xasprintf(&filter,
|
||||
"#{||:"
|
||||
"#{C:%s},#{||:#{m:*%s*,#{window_name}},"
|
||||
"#{m:*%s*,#{pane_title}}}}",
|
||||
s, s, s);
|
||||
} else if (C && N) {
|
||||
xasprintf(&filter,
|
||||
"#{||:#{C:%s},#{m:*%s*,#{window_name}}}",
|
||||
s, s);
|
||||
} else if (C && T) {
|
||||
xasprintf(&filter,
|
||||
"#{||:#{C:%s},#{m:*%s*,#{pane_title}}}",
|
||||
s, s);
|
||||
} else if (N && T) {
|
||||
xasprintf(&filter,
|
||||
"#{||:#{m:*%s*,#{window_name}},#{m:*%s*,#{pane_title}}}",
|
||||
s, s);
|
||||
} else if (C)
|
||||
xasprintf(&filter, "#{C:%s}", s);
|
||||
else if (N)
|
||||
xasprintf(&filter, "#{m:*%s*,#{window_name}}", s);
|
||||
else if (T)
|
||||
xasprintf(&filter, "#{m:*%s*,#{pane_title}}", s);
|
||||
|
||||
TAILQ_INIT(&find_list);
|
||||
new_args = args_parse("", 1, &argv);
|
||||
args_set(new_args, 'f', filter);
|
||||
|
||||
xasprintf(&searchstr, "*%s*", str);
|
||||
RB_FOREACH(wm, winlinks, &s->windows)
|
||||
cmd_find_window_match(&find_list, match_flags, wm, str, searchstr);
|
||||
free(searchstr);
|
||||
window_pane_set_mode(wp, &window_tree_mode, &item->target, new_args);
|
||||
|
||||
if (TAILQ_EMPTY(&find_list)) {
|
||||
cmdq_error(item, "no windows matching: %s", str);
|
||||
return (CMD_RETURN_ERROR);
|
||||
}
|
||||
args_free(new_args);
|
||||
free(filter);
|
||||
|
||||
if (TAILQ_NEXT(TAILQ_FIRST(&find_list), entry) == NULL) {
|
||||
if (session_select(s, TAILQ_FIRST(&find_list)->wl->idx) == 0) {
|
||||
cmd_find_from_session(current, s);
|
||||
server_redraw_session(s);
|
||||
}
|
||||
recalculate_sizes();
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (window_pane_set_mode(wl->window->active, &window_choose_mode) != 0)
|
||||
goto out;
|
||||
|
||||
i = 0;
|
||||
TAILQ_FOREACH(find_data, &find_list, entry) {
|
||||
cdata = window_choose_data_create(TREE_OTHER, c, c->session);
|
||||
cdata->idx = find_data->wl->idx;
|
||||
cdata->wl = find_data->wl;
|
||||
|
||||
cdata->ft_template = xstrdup(template);
|
||||
cdata->pane_id = find_data->pane_id;
|
||||
|
||||
format_add(cdata->ft, "line", "%u", i);
|
||||
format_add(cdata->ft, "window_find_matches", "%s",
|
||||
find_data->list_ctx);
|
||||
format_defaults(cdata->ft, NULL, s, find_data->wl, NULL);
|
||||
|
||||
window_choose_add(wl->window->active, cdata);
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
window_choose_ready(wl->window->active, 0, cmd_find_window_callback);
|
||||
|
||||
out:
|
||||
TAILQ_FOREACH_SAFE(find_data, &find_list, entry, find_data1) {
|
||||
free(find_data->list_ctx);
|
||||
TAILQ_REMOVE(&find_list, find_data, entry);
|
||||
free(find_data);
|
||||
}
|
||||
return (CMD_RETURN_NORMAL);
|
||||
}
|
||||
|
||||
static void
|
||||
cmd_find_window_callback(struct window_choose_data *cdata)
|
||||
{
|
||||
struct session *s;
|
||||
struct window_pane *wp;
|
||||
|
||||
if (cdata == NULL)
|
||||
return;
|
||||
|
||||
s = cdata->start_session;
|
||||
if (!session_alive(s))
|
||||
return;
|
||||
|
||||
wp = window_pane_at_index(cdata->wl->window, cdata->pane_id);
|
||||
if (wp != NULL && window_pane_visible(wp))
|
||||
window_set_active_pane(cdata->wl->window, wp);
|
||||
|
||||
if (session_select(s, cdata->idx) == 0) {
|
||||
server_redraw_session(s);
|
||||
recalculate_sizes();
|
||||
}
|
||||
}
|
||||
|
@ -428,7 +428,8 @@ cmdq_print(struct cmdq_item *item, const char *fmt, ...)
|
||||
w = c->session->curw->window;
|
||||
if (w->active->mode != &window_copy_mode) {
|
||||
window_pane_reset_mode(w->active);
|
||||
window_pane_set_mode(w->active, &window_copy_mode);
|
||||
window_pane_set_mode(w->active, &window_copy_mode, NULL,
|
||||
NULL);
|
||||
window_copy_init_for_output(w->active);
|
||||
}
|
||||
window_copy_vadd(w->active, fmt, ap);
|
||||
|
@ -75,7 +75,7 @@ cmd_run_shell_print(struct job *job, const char *msg)
|
||||
return;
|
||||
}
|
||||
|
||||
if (window_pane_set_mode(wp, &window_copy_mode) == 0)
|
||||
if (window_pane_set_mode(wp, &window_copy_mode, NULL, NULL) == 0)
|
||||
window_copy_init_for_output(wp);
|
||||
if (wp->mode == &window_copy_mode)
|
||||
window_copy_add(wp, "%s", msg);
|
||||
|
@ -133,7 +133,7 @@ cmd_split_window_exec(struct cmd *self, struct cmdq_item *item)
|
||||
goto error;
|
||||
}
|
||||
new_wp = window_add_pane(w, wp, args_has(args, 'b'), hlimit);
|
||||
layout_assign_pane(lc, new_wp);
|
||||
layout_make_leaf(lc, new_wp);
|
||||
|
||||
path = NULL;
|
||||
if (item->client != NULL && item->client->session == NULL)
|
||||
@ -151,6 +151,7 @@ cmd_split_window_exec(struct cmd *self, struct cmdq_item *item)
|
||||
}
|
||||
environ_free(env);
|
||||
|
||||
layout_fix_panes(w, w->sx, w->sy);
|
||||
server_redraw_window(w);
|
||||
|
||||
if (!args_has(args, 'd')) {
|
||||
|
4
cmd.c
4
cmd.c
@ -33,9 +33,7 @@ extern const struct cmd_entry cmd_break_pane_entry;
|
||||
extern const struct cmd_entry cmd_capture_pane_entry;
|
||||
extern const struct cmd_entry cmd_choose_buffer_entry;
|
||||
extern const struct cmd_entry cmd_choose_client_entry;
|
||||
extern const struct cmd_entry cmd_choose_session_entry;
|
||||
extern const struct cmd_entry cmd_choose_tree_entry;
|
||||
extern const struct cmd_entry cmd_choose_window_entry;
|
||||
extern const struct cmd_entry cmd_clear_history_entry;
|
||||
extern const struct cmd_entry cmd_clock_mode_entry;
|
||||
extern const struct cmd_entry cmd_command_prompt_entry;
|
||||
@ -122,9 +120,7 @@ const struct cmd_entry *cmd_table[] = {
|
||||
&cmd_capture_pane_entry,
|
||||
&cmd_choose_buffer_entry,
|
||||
&cmd_choose_client_entry,
|
||||
&cmd_choose_session_entry,
|
||||
&cmd_choose_tree_entry,
|
||||
&cmd_choose_window_entry,
|
||||
&cmd_clear_history_entry,
|
||||
&cmd_clock_mode_entry,
|
||||
&cmd_command_prompt_entry,
|
||||
|
4
format.c
4
format.c
@ -20,11 +20,9 @@
|
||||
#include <sys/param.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <fnmatch.h>
|
||||
#include <libgen.h>
|
||||
#include <netdb.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
@ -857,7 +855,7 @@ format_choose(char *s, char **left, char **right)
|
||||
}
|
||||
|
||||
/* Is this true? */
|
||||
static int
|
||||
int
|
||||
format_true(const char *s)
|
||||
{
|
||||
if (s != NULL && *s != '\0' && (s[0] != '0' || s[1] != '\0'))
|
||||
|
@ -196,9 +196,9 @@ key_bindings_init(void)
|
||||
"bind p previous-window",
|
||||
"bind q display-panes",
|
||||
"bind r refresh-client",
|
||||
"bind s choose-tree",
|
||||
"bind s choose-tree -s",
|
||||
"bind t clock-mode",
|
||||
"bind w choose-window",
|
||||
"bind w choose-tree -w",
|
||||
"bind x confirm-before -p\"kill-pane #P? (y/n)\" kill-pane",
|
||||
"bind z resize-pane -Z",
|
||||
"bind { swap-pane -U",
|
||||
|
705
mode-tree.c
Normal file
705
mode-tree.c
Normal file
@ -0,0 +1,705 @@
|
||||
/* $OpenBSD$ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2017 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
|
||||
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <ctype.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "tmux.h"
|
||||
|
||||
struct mode_tree_item;
|
||||
TAILQ_HEAD(mode_tree_list, mode_tree_item);
|
||||
|
||||
struct mode_tree_data {
|
||||
struct window_pane *wp;
|
||||
void *modedata;
|
||||
|
||||
const char **sort_list;
|
||||
u_int sort_size;
|
||||
u_int sort_type;
|
||||
|
||||
void (*buildcb)(void *, u_int, uint64_t *);
|
||||
struct screen *(*drawcb)(void *, void *, u_int, u_int);
|
||||
|
||||
struct mode_tree_list children;
|
||||
struct mode_tree_list saved;
|
||||
|
||||
struct mode_tree_line *line_list;
|
||||
u_int line_size;
|
||||
|
||||
u_int depth;
|
||||
|
||||
u_int width;
|
||||
u_int height;
|
||||
|
||||
u_int offset;
|
||||
u_int current;
|
||||
|
||||
struct screen screen;
|
||||
};
|
||||
|
||||
struct mode_tree_item {
|
||||
struct mode_tree_item *parent;
|
||||
void *itemdata;
|
||||
u_int line;
|
||||
|
||||
uint64_t tag;
|
||||
const char *name;
|
||||
const char *text;
|
||||
|
||||
int expanded;
|
||||
int tagged;
|
||||
|
||||
struct mode_tree_list children;
|
||||
TAILQ_ENTRY(mode_tree_item) entry;
|
||||
};
|
||||
|
||||
struct mode_tree_line {
|
||||
struct mode_tree_item *item;
|
||||
u_int depth;
|
||||
int last;
|
||||
int flat;
|
||||
};
|
||||
|
||||
static void mode_tree_free_items(struct mode_tree_list *);
|
||||
|
||||
static struct mode_tree_item *
|
||||
mode_tree_find_item(struct mode_tree_list *mtl, uint64_t tag)
|
||||
{
|
||||
struct mode_tree_item *mti, *child;
|
||||
|
||||
TAILQ_FOREACH(mti, mtl, entry) {
|
||||
if (mti->tag == tag)
|
||||
return (mti);
|
||||
child = mode_tree_find_item(&mti->children, tag);
|
||||
if (child != NULL)
|
||||
return (child);
|
||||
}
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
mode_tree_free_item(struct mode_tree_item *mti)
|
||||
{
|
||||
mode_tree_free_items(&mti->children);
|
||||
|
||||
free((void *)mti->name);
|
||||
free((void *)mti->text);
|
||||
|
||||
free(mti);
|
||||
}
|
||||
|
||||
static void
|
||||
mode_tree_free_items(struct mode_tree_list *mtl)
|
||||
{
|
||||
struct mode_tree_item *mti, *mti1;
|
||||
|
||||
TAILQ_FOREACH_SAFE(mti, mtl, entry, mti1) {
|
||||
TAILQ_REMOVE(mtl, mti, entry);
|
||||
mode_tree_free_item(mti);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
mode_tree_clear_lines(struct mode_tree_data *mtd)
|
||||
{
|
||||
free(mtd->line_list);
|
||||
mtd->line_list = NULL;
|
||||
mtd->line_size = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
mode_tree_build_lines(struct mode_tree_data *mtd,
|
||||
struct mode_tree_list *mtl, u_int depth)
|
||||
{
|
||||
struct mode_tree_item *mti;
|
||||
struct mode_tree_line *line;
|
||||
u_int i;
|
||||
int flat = 1;
|
||||
|
||||
mtd->depth = depth;
|
||||
TAILQ_FOREACH(mti, mtl, entry) {
|
||||
mtd->line_list = xreallocarray(mtd->line_list,
|
||||
mtd->line_size + 1, sizeof *mtd->line_list);
|
||||
|
||||
line = &mtd->line_list[mtd->line_size++];
|
||||
line->item = mti;
|
||||
line->depth = depth;
|
||||
line->last = (mti == TAILQ_LAST(mtl, mode_tree_list));
|
||||
|
||||
mti->line = (mtd->line_size - 1);
|
||||
if (!TAILQ_EMPTY(&mti->children))
|
||||
flat = 0;
|
||||
if (mti->expanded)
|
||||
mode_tree_build_lines(mtd, &mti->children, depth + 1);
|
||||
}
|
||||
TAILQ_FOREACH(mti, mtl, entry) {
|
||||
for (i = 0; i < mtd->line_size; i++) {
|
||||
line = &mtd->line_list[i];
|
||||
if (line->item == mti)
|
||||
line->flat = flat;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
mode_tree_clear_tagged(struct mode_tree_list *mtl)
|
||||
{
|
||||
struct mode_tree_item *mti;
|
||||
|
||||
TAILQ_FOREACH(mti, mtl, entry) {
|
||||
mti->tagged = 0;
|
||||
mode_tree_clear_tagged(&mti->children);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
mode_tree_up(struct mode_tree_data *mtd, int wrap)
|
||||
{
|
||||
if (mtd->current == 0) {
|
||||
if (wrap) {
|
||||
mtd->current = mtd->line_size - 1;
|
||||
if (mtd->line_size >= mtd->height)
|
||||
mtd->offset = mtd->line_size - mtd->height;
|
||||
}
|
||||
} else {
|
||||
mtd->current--;
|
||||
if (mtd->current < mtd->offset)
|
||||
mtd->offset--;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
mode_tree_down(struct mode_tree_data *mtd, int wrap)
|
||||
{
|
||||
if (mtd->current == mtd->line_size - 1) {
|
||||
if (wrap) {
|
||||
mtd->current = 0;
|
||||
mtd->offset = 0;
|
||||
}
|
||||
} else {
|
||||
mtd->current++;
|
||||
if (mtd->current > mtd->offset + mtd->height - 1)
|
||||
mtd->offset++;
|
||||
}
|
||||
}
|
||||
|
||||
void *
|
||||
mode_tree_get_current(struct mode_tree_data *mtd)
|
||||
{
|
||||
return (mtd->line_list[mtd->current].item->itemdata);
|
||||
}
|
||||
|
||||
u_int
|
||||
mode_tree_count_tagged(struct mode_tree_data *mtd)
|
||||
{
|
||||
struct mode_tree_item *mti;
|
||||
u_int i, tagged;
|
||||
|
||||
tagged = 0;
|
||||
for (i = 0; i < mtd->line_size; i++) {
|
||||
mti = mtd->line_list[i].item;
|
||||
if (mti->tagged)
|
||||
tagged++;
|
||||
}
|
||||
return (tagged);
|
||||
}
|
||||
|
||||
void
|
||||
mode_tree_each_tagged(struct mode_tree_data *mtd, void (*cb)(void *, void *,
|
||||
key_code), key_code key, int current)
|
||||
{
|
||||
struct mode_tree_item *mti;
|
||||
u_int i;
|
||||
int fired;
|
||||
|
||||
fired = 0;
|
||||
for (i = 0; i < mtd->line_size; i++) {
|
||||
mti = mtd->line_list[i].item;
|
||||
if (mti->tagged) {
|
||||
fired = 1;
|
||||
cb(mtd->modedata, mti->itemdata, key);
|
||||
}
|
||||
}
|
||||
if (!fired && current) {
|
||||
mti = mtd->line_list[mtd->current].item;
|
||||
cb(mtd->modedata, mti->itemdata, key);
|
||||
}
|
||||
}
|
||||
|
||||
struct mode_tree_data *
|
||||
mode_tree_start(struct window_pane *wp, void (*buildcb)(void *, u_int,
|
||||
uint64_t *), struct screen *(*drawcb)(void *, void *, u_int, u_int),
|
||||
void *modedata, const char **sort_list, u_int sort_size, struct screen **s)
|
||||
{
|
||||
struct mode_tree_data *mtd;
|
||||
|
||||
mtd = xcalloc(1, sizeof *mtd);
|
||||
mtd->wp = wp;
|
||||
mtd->modedata = modedata;
|
||||
|
||||
mtd->sort_list = sort_list;
|
||||
mtd->sort_size = sort_size;
|
||||
mtd->sort_type = 0;
|
||||
|
||||
mtd->buildcb = buildcb;
|
||||
mtd->drawcb = drawcb;
|
||||
|
||||
TAILQ_INIT(&mtd->children);
|
||||
|
||||
*s = &mtd->screen;
|
||||
screen_init(*s, screen_size_x(&wp->base), screen_size_y(&wp->base), 0);
|
||||
(*s)->mode &= ~MODE_CURSOR;
|
||||
|
||||
return (mtd);
|
||||
}
|
||||
|
||||
void
|
||||
mode_tree_build(struct mode_tree_data *mtd)
|
||||
{
|
||||
struct screen *s = &mtd->screen;
|
||||
uint64_t tag;
|
||||
u_int i;
|
||||
|
||||
if (mtd->line_list != NULL)
|
||||
tag = mtd->line_list[mtd->current].item->tag;
|
||||
else
|
||||
tag = 0;
|
||||
|
||||
TAILQ_CONCAT(&mtd->saved, &mtd->children, entry);
|
||||
TAILQ_INIT(&mtd->children);
|
||||
|
||||
mtd->buildcb(mtd->modedata, mtd->sort_type, &tag);
|
||||
|
||||
mode_tree_free_items(&mtd->saved);
|
||||
TAILQ_INIT(&mtd->saved);
|
||||
|
||||
mode_tree_clear_lines(mtd);
|
||||
mode_tree_build_lines(mtd, &mtd->children, 0);
|
||||
|
||||
for (i = 0; i < mtd->line_size; i++) {
|
||||
if (mtd->line_list[i].item->tag == tag)
|
||||
break;
|
||||
}
|
||||
if (i != mtd->line_size)
|
||||
mtd->current = i;
|
||||
else {
|
||||
mtd->current = 0;
|
||||
mtd->offset = 0;
|
||||
}
|
||||
|
||||
mtd->width = screen_size_x(s);
|
||||
mtd->height = (screen_size_y(s) / 3) * 2;
|
||||
if (mtd->height > mtd->line_size)
|
||||
mtd->height = screen_size_y(s) / 2;
|
||||
if (mtd->height < 10)
|
||||
mtd->height = screen_size_y(s);
|
||||
if (screen_size_y(s) - mtd->height < 2)
|
||||
mtd->height = screen_size_y(s);
|
||||
}
|
||||
|
||||
void
|
||||
mode_tree_free(struct mode_tree_data *mtd)
|
||||
{
|
||||
mode_tree_free_items(&mtd->children);
|
||||
mode_tree_clear_lines(mtd);
|
||||
screen_free(&mtd->screen);
|
||||
free(mtd);
|
||||
}
|
||||
|
||||
void
|
||||
mode_tree_resize(struct mode_tree_data *mtd, u_int sx, u_int sy)
|
||||
{
|
||||
struct screen *s = &mtd->screen;
|
||||
|
||||
screen_resize(s, sx, sy, 0);
|
||||
|
||||
mode_tree_build(mtd);
|
||||
mode_tree_draw(mtd);
|
||||
|
||||
mtd->wp->flags |= PANE_REDRAW;
|
||||
}
|
||||
|
||||
struct mode_tree_item *
|
||||
mode_tree_add(struct mode_tree_data *mtd, struct mode_tree_item *parent,
|
||||
void *itemdata, uint64_t tag, const char *name, const char *text,
|
||||
int expanded)
|
||||
{
|
||||
struct mode_tree_item *mti, *saved;
|
||||
|
||||
log_debug("%s: %llu, %s %s", __func__, (unsigned long long)tag,
|
||||
name, text);
|
||||
|
||||
mti = xcalloc(1, sizeof *mti);
|
||||
mti->parent = parent;
|
||||
mti->itemdata = itemdata;
|
||||
|
||||
mti->tag = tag;
|
||||
mti->name = xstrdup(name);
|
||||
mti->text = xstrdup(text);
|
||||
|
||||
saved = mode_tree_find_item(&mtd->saved, tag);
|
||||
if (saved != NULL) {
|
||||
if (parent == NULL || (parent != NULL && parent->expanded))
|
||||
mti->tagged = saved->tagged;
|
||||
mti->expanded = saved->expanded;
|
||||
} else if (expanded == -1)
|
||||
mti->expanded = 1;
|
||||
else
|
||||
mti->expanded = expanded;
|
||||
|
||||
TAILQ_INIT(&mti->children);
|
||||
|
||||
if (parent != NULL)
|
||||
TAILQ_INSERT_TAIL(&parent->children, mti, entry);
|
||||
else
|
||||
TAILQ_INSERT_TAIL(&mtd->children, mti, entry);
|
||||
|
||||
return (mti);
|
||||
}
|
||||
|
||||
void
|
||||
mode_tree_remove(struct mode_tree_data *mtd, struct mode_tree_item *mti)
|
||||
{
|
||||
struct mode_tree_item *parent = mti->parent;
|
||||
|
||||
if (parent != NULL)
|
||||
TAILQ_REMOVE(&parent->children, mti, entry);
|
||||
else
|
||||
TAILQ_REMOVE(&mtd->children, mti, entry);
|
||||
mode_tree_free_item(mti);
|
||||
}
|
||||
|
||||
void
|
||||
mode_tree_draw(struct mode_tree_data *mtd)
|
||||
{
|
||||
struct window_pane *wp = mtd->wp;
|
||||
struct screen *s = &mtd->screen, *box;
|
||||
struct mode_tree_line *line;
|
||||
struct mode_tree_item *mti;
|
||||
struct options *oo = wp->window->options;
|
||||
struct screen_write_ctx ctx;
|
||||
struct grid_cell gc0, gc;
|
||||
u_int w, h, i, j, sy, box_x, box_y;
|
||||
char *text, *start, key[7];
|
||||
const char *tag, *symbol;
|
||||
size_t size;
|
||||
int keylen;
|
||||
|
||||
if (mtd->line_size == 0)
|
||||
return;
|
||||
|
||||
memcpy(&gc0, &grid_default_cell, sizeof gc0);
|
||||
memcpy(&gc, &grid_default_cell, sizeof gc);
|
||||
style_apply(&gc, oo, "mode-style");
|
||||
|
||||
w = mtd->width;
|
||||
h = mtd->height;
|
||||
|
||||
screen_write_start(&ctx, NULL, s);
|
||||
screen_write_clearscreen(&ctx, 8);
|
||||
|
||||
if (mtd->line_size > 10)
|
||||
keylen = 6;
|
||||
else
|
||||
keylen = 4;
|
||||
|
||||
for (i = 0; i < mtd->line_size; i++) {
|
||||
if (i < mtd->offset)
|
||||
continue;
|
||||
if (i > mtd->offset + h - 1)
|
||||
break;
|
||||
|
||||
line = &mtd->line_list[i];
|
||||
mti = line->item;
|
||||
|
||||
screen_write_cursormove(&ctx, 0, i - mtd->offset);
|
||||
|
||||
if (i < 10)
|
||||
snprintf(key, sizeof key, "(%c)", '0' + i);
|
||||
else if (i < 36)
|
||||
snprintf(key, sizeof key, "(M-%c)", 'a' + (i - 10));
|
||||
else
|
||||
*key = '\0';
|
||||
|
||||
if (line->flat)
|
||||
symbol = "";
|
||||
else if (TAILQ_EMPTY(&mti->children))
|
||||
symbol = " ";
|
||||
else if (mti->expanded)
|
||||
symbol = "- ";
|
||||
else
|
||||
symbol = "+ ";
|
||||
|
||||
if (line->depth == 0)
|
||||
start = xstrdup(symbol);
|
||||
else {
|
||||
size = (4 * line->depth) + 32;
|
||||
|
||||
start = xcalloc(1, size);
|
||||
for (j = 1; j < line->depth; j++) {
|
||||
if (mti->parent != NULL &&
|
||||
mtd->line_list[mti->parent->line].last)
|
||||
strlcat(start, " ", size);
|
||||
else
|
||||
strlcat(start, "\001x\001 ", size);
|
||||
}
|
||||
if (line->last)
|
||||
strlcat(start, "\001mq\001> ", size);
|
||||
else
|
||||
strlcat(start, "\001tq\001> ", size);
|
||||
strlcat(start, symbol, size);
|
||||
}
|
||||
|
||||
if (mti->tagged)
|
||||
tag = "*";
|
||||
else
|
||||
tag = "";
|
||||
xasprintf(&text, "%-*s%s%s%s: %s", keylen, key, start,
|
||||
mti->name, tag, mti->text);
|
||||
free(start);
|
||||
|
||||
if (mti->tagged) {
|
||||
gc.attr ^= GRID_ATTR_BRIGHT;
|
||||
gc0.attr ^= GRID_ATTR_BRIGHT;
|
||||
}
|
||||
|
||||
if (i != mtd->current) {
|
||||
screen_write_puts(&ctx, &gc0, "%.*s", w, text);
|
||||
screen_write_clearendofline(&ctx, 8);
|
||||
} else
|
||||
screen_write_puts(&ctx, &gc, "%-*.*s", w, w, text);
|
||||
free(text);
|
||||
|
||||
if (mti->tagged) {
|
||||
gc.attr ^= GRID_ATTR_BRIGHT;
|
||||
gc0.attr ^= GRID_ATTR_BRIGHT;
|
||||
}
|
||||
}
|
||||
|
||||
sy = screen_size_y(s);
|
||||
if (sy <= 4 || h <= 4 || sy - h <= 4 || w <= 4) {
|
||||
screen_write_stop(&ctx);
|
||||
return;
|
||||
}
|
||||
|
||||
line = &mtd->line_list[mtd->current];
|
||||
mti = line->item;
|
||||
|
||||
screen_write_cursormove(&ctx, 0, h);
|
||||
screen_write_box(&ctx, w, sy - h);
|
||||
|
||||
xasprintf(&text, " %s (sort: %s) ", mti->name,
|
||||
mtd->sort_list[mtd->sort_type]);
|
||||
if (w - 2 >= strlen(text)) {
|
||||
screen_write_cursormove(&ctx, 1, h);
|
||||
screen_write_puts(&ctx, &gc0, "%s", text);
|
||||
}
|
||||
free(text);
|
||||
|
||||
box_x = w - 4;
|
||||
box_y = sy - h - 2;
|
||||
|
||||
box = mtd->drawcb(mtd->modedata, mti->itemdata, box_x, box_y);
|
||||
if (box != NULL) {
|
||||
screen_write_cursormove(&ctx, 2, h + 1);
|
||||
screen_write_copy(&ctx, box, 0, 0, box_x, box_y, NULL, NULL);
|
||||
|
||||
screen_free(box);
|
||||
}
|
||||
|
||||
screen_write_stop(&ctx);
|
||||
}
|
||||
|
||||
int
|
||||
mode_tree_key(struct mode_tree_data *mtd, key_code *key, struct mouse_event *m)
|
||||
{
|
||||
struct mode_tree_line *line;
|
||||
struct mode_tree_item *current, *parent;
|
||||
u_int i, x, y;
|
||||
int choice;
|
||||
key_code tmp;
|
||||
|
||||
if (*key == KEYC_MOUSEDOWN1_PANE) {
|
||||
if (cmd_mouse_at(mtd->wp, m, &x, &y, 0) != 0) {
|
||||
*key = KEYC_NONE;
|
||||
return (0);
|
||||
}
|
||||
if (x > mtd->width || y > mtd->height) {
|
||||
*key = KEYC_NONE;
|
||||
return (0);
|
||||
}
|
||||
if (mtd->offset + y < mtd->line_size) {
|
||||
mtd->current = mtd->offset + y;
|
||||
*key = '\r';
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
|
||||
line = &mtd->line_list[mtd->current];
|
||||
current = line->item;
|
||||
|
||||
choice = -1;
|
||||
if (*key >= '0' && *key <= '9')
|
||||
choice = (*key) - '0';
|
||||
else if (((*key) & KEYC_MASK_MOD) == KEYC_ESCAPE) {
|
||||
tmp = (*key) & KEYC_MASK_KEY;
|
||||
if (tmp >= 'a' && tmp <= 'z')
|
||||
choice = 10 + (tmp - 'a');
|
||||
}
|
||||
if (choice != -1) {
|
||||
if ((u_int)choice > mtd->line_size - 1) {
|
||||
*key = KEYC_NONE;
|
||||
return (0);
|
||||
}
|
||||
mtd->current = choice;
|
||||
*key = '\r';
|
||||
return (0);
|
||||
}
|
||||
|
||||
switch (*key) {
|
||||
case 'q':
|
||||
case '\033': /* Escape */
|
||||
return (1);
|
||||
case KEYC_UP:
|
||||
case 'k':
|
||||
case KEYC_WHEELUP_PANE:
|
||||
mode_tree_up(mtd, 1);
|
||||
break;
|
||||
case KEYC_DOWN:
|
||||
case 'j':
|
||||
case KEYC_WHEELDOWN_PANE:
|
||||
mode_tree_down(mtd, 1);
|
||||
break;
|
||||
case KEYC_PPAGE:
|
||||
case '\002': /* C-b */
|
||||
for (i = 0; i < mtd->height; i++) {
|
||||
if (mtd->current == 0)
|
||||
break;
|
||||
mode_tree_up(mtd, 1);
|
||||
}
|
||||
break;
|
||||
case KEYC_NPAGE:
|
||||
case '\006': /* C-f */
|
||||
for (i = 0; i < mtd->height; i++) {
|
||||
if (mtd->current == mtd->line_size - 1)
|
||||
break;
|
||||
mode_tree_down(mtd, 1);
|
||||
}
|
||||
break;
|
||||
case KEYC_HOME:
|
||||
mtd->current = 0;
|
||||
mtd->offset = 0;
|
||||
break;
|
||||
case KEYC_END:
|
||||
mtd->current = mtd->line_size - 1;
|
||||
if (mtd->current > mtd->height - 1)
|
||||
mtd->offset = mtd->current - mtd->height;
|
||||
else
|
||||
mtd->offset = 0;
|
||||
break;
|
||||
case 't':
|
||||
/*
|
||||
* Do not allow parents and children to both be tagged: untag
|
||||
* all parents and children of current.
|
||||
*/
|
||||
if (!current->tagged) {
|
||||
parent = current->parent;
|
||||
while (parent != NULL) {
|
||||
parent->tagged = 0;
|
||||
parent = parent->parent;
|
||||
}
|
||||
mode_tree_clear_tagged(¤t->children);
|
||||
current->tagged = 1;
|
||||
} else
|
||||
current->tagged = 0;
|
||||
mode_tree_down(mtd, 0);
|
||||
break;
|
||||
case 'T':
|
||||
for (i = 0; i < mtd->line_size; i++)
|
||||
mtd->line_list[i].item->tagged = 0;
|
||||
break;
|
||||
case '\024': /* C-t */
|
||||
for (i = 0; i < mtd->line_size; i++) {
|
||||
if (mtd->line_list[i].item->parent == NULL)
|
||||
mtd->line_list[i].item->tagged = 1;
|
||||
else
|
||||
mtd->line_list[i].item->tagged = 0;
|
||||
}
|
||||
break;
|
||||
case 'O':
|
||||
mtd->sort_type++;
|
||||
if (mtd->sort_type == mtd->sort_size)
|
||||
mtd->sort_type = 0;
|
||||
mode_tree_build(mtd);
|
||||
break;
|
||||
case KEYC_LEFT:
|
||||
case '-':
|
||||
if (line->flat || !current->expanded)
|
||||
current = current->parent;
|
||||
if (current == NULL)
|
||||
mode_tree_up(mtd, 0);
|
||||
else {
|
||||
current->expanded = 0;
|
||||
mtd->current = current->line;
|
||||
mode_tree_build(mtd);
|
||||
}
|
||||
break;
|
||||
case KEYC_RIGHT:
|
||||
case '+':
|
||||
if (line->flat || current->expanded)
|
||||
mode_tree_down(mtd, 0);
|
||||
else if (!line->flat) {
|
||||
current->expanded = 1;
|
||||
mode_tree_build(mtd);
|
||||
}
|
||||
break;
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
void
|
||||
mode_tree_run_command(struct client *c, struct cmd_find_state *fs,
|
||||
const char *template, const char *name)
|
||||
{
|
||||
struct cmdq_item *new_item;
|
||||
struct cmd_list *cmdlist;
|
||||
char *command, *cause;
|
||||
|
||||
command = cmd_template_replace(template, name, 1);
|
||||
if (command == NULL || *command == '\0')
|
||||
return;
|
||||
|
||||
cmdlist = cmd_string_parse(command, NULL, 0, &cause);
|
||||
if (cmdlist == NULL) {
|
||||
if (cause != NULL && c != NULL) {
|
||||
*cause = toupper((u_char)*cause);
|
||||
status_message_set(c, "%s", cause);
|
||||
}
|
||||
free(cause);
|
||||
} else {
|
||||
new_item = cmdq_get_command(cmdlist, fs, NULL, 0);
|
||||
cmdq_append(c, new_item);
|
||||
cmd_list_free(cmdlist);
|
||||
}
|
||||
|
||||
free(command);
|
||||
}
|
@ -61,7 +61,7 @@ const struct options_table_entry options_table[] = {
|
||||
.scope = OPTIONS_TABLE_SERVER,
|
||||
.minimum = 1,
|
||||
.maximum = INT_MAX,
|
||||
.default_num = 20
|
||||
.default_num = 50
|
||||
},
|
||||
|
||||
{ .name = "command-alias",
|
||||
@ -70,7 +70,9 @@ const struct options_table_entry options_table[] = {
|
||||
.default_str = "split-pane=split-window,"
|
||||
"splitp=split-window,"
|
||||
"server-info=show-messages -JT,"
|
||||
"info=show-messages -JT",
|
||||
"info=show-messages -JT,"
|
||||
"choose-window=choose-tree -w,"
|
||||
"choose-session=choose-tree -s",
|
||||
.separator = ","
|
||||
},
|
||||
|
||||
|
118
screen-write.c
118
screen-write.c
@ -362,6 +362,9 @@ screen_write_copy(struct screen_write_ctx *ctx, struct screen *src, u_int px,
|
||||
struct grid_cell gc;
|
||||
u_int xx, yy, cx, cy, b;
|
||||
|
||||
if (nx == 0 || ny == 0)
|
||||
return;
|
||||
|
||||
cx = s->cx;
|
||||
cy = s->cy;
|
||||
|
||||
@ -384,6 +387,121 @@ screen_write_copy(struct screen_write_ctx *ctx, struct screen *src, u_int px,
|
||||
}
|
||||
}
|
||||
|
||||
/* Draw a line on screen. */
|
||||
void
|
||||
screen_write_line(struct screen_write_ctx *ctx, u_int nx, int left, int right)
|
||||
{
|
||||
struct screen *s = ctx->s;
|
||||
struct grid_cell gc;
|
||||
u_int cx, cy, i;
|
||||
|
||||
cx = s->cx;
|
||||
cy = s->cy;
|
||||
|
||||
memcpy(&gc, &grid_default_cell, sizeof gc);
|
||||
gc.attr |= GRID_ATTR_CHARSET;
|
||||
|
||||
screen_write_putc(ctx, &gc, left ? 't' : 'q');
|
||||
for (i = 1; i < nx - 1; i++)
|
||||
screen_write_putc(ctx, &gc, 'q');
|
||||
screen_write_putc(ctx, &gc, right ? 'u' : 'q');
|
||||
|
||||
screen_write_cursormove(ctx, cx, cy);
|
||||
}
|
||||
|
||||
/* Draw a box on screen. */
|
||||
void
|
||||
screen_write_box(struct screen_write_ctx *ctx, u_int nx, u_int ny)
|
||||
{
|
||||
struct screen *s = ctx->s;
|
||||
struct grid_cell gc;
|
||||
u_int cx, cy, i;
|
||||
|
||||
cx = s->cx;
|
||||
cy = s->cy;
|
||||
|
||||
memcpy(&gc, &grid_default_cell, sizeof gc);
|
||||
gc.attr |= GRID_ATTR_CHARSET;
|
||||
|
||||
screen_write_putc(ctx, &gc, 'l');
|
||||
for (i = 1; i < nx - 1; i++)
|
||||
screen_write_putc(ctx, &gc, 'q');
|
||||
screen_write_putc(ctx, &gc, 'k');
|
||||
|
||||
screen_write_cursormove(ctx, cx, cy + ny - 1);
|
||||
screen_write_putc(ctx, &gc, 'm');
|
||||
for (i = 1; i < nx - 1; i++)
|
||||
screen_write_putc(ctx, &gc, 'q');
|
||||
screen_write_putc(ctx, &gc, 'j');
|
||||
|
||||
for (i = 1; i < ny - 1; i++) {
|
||||
screen_write_cursormove(ctx, cx, cy + i);
|
||||
screen_write_putc(ctx, &gc, 'x');
|
||||
}
|
||||
for (i = 1; i < ny - 1; i++) {
|
||||
screen_write_cursormove(ctx, cx + nx - 1, cy + i);
|
||||
screen_write_putc(ctx, &gc, 'x');
|
||||
}
|
||||
|
||||
screen_write_cursormove(ctx, cx, cy);
|
||||
}
|
||||
|
||||
/* Write a preview version of a window. */
|
||||
void
|
||||
screen_write_preview(struct screen_write_ctx *ctx, struct screen *src, u_int nx,
|
||||
u_int ny)
|
||||
{
|
||||
struct screen *s = ctx->s;
|
||||
struct grid_cell gc;
|
||||
u_int cx, cy, px, py;
|
||||
|
||||
cx = s->cx;
|
||||
cy = s->cy;
|
||||
|
||||
/*
|
||||
* If the cursor is on, pick the area around the cursor, otherwise use
|
||||
* the top left.
|
||||
*/
|
||||
if (src->mode & MODE_CURSOR) {
|
||||
px = src->cx;
|
||||
if (px < nx / 3)
|
||||
px = 0;
|
||||
else
|
||||
px = px - nx / 3;
|
||||
if (px + nx > screen_size_x(src)) {
|
||||
if (nx > screen_size_x(src))
|
||||
px = 0;
|
||||
else
|
||||
px = screen_size_x(src) - nx;
|
||||
}
|
||||
py = src->cy;
|
||||
if (py < ny / 3)
|
||||
py = 0;
|
||||
else
|
||||
py = py - ny / 3;
|
||||
if (py + ny > screen_size_y(src)) {
|
||||
if (ny > screen_size_y(src))
|
||||
py = 0;
|
||||
else
|
||||
py = screen_size_y(src) - ny;
|
||||
}
|
||||
} else {
|
||||
px = 0;
|
||||
py = 0;
|
||||
}
|
||||
|
||||
screen_write_copy(ctx, src, px, src->grid->hsize + py, nx, ny, NULL,
|
||||
NULL);
|
||||
|
||||
if (src->mode & MODE_CURSOR) {
|
||||
grid_view_get_cell(src->grid, src->cx, src->cy, &gc);
|
||||
gc.attr |= GRID_ATTR_REVERSE;
|
||||
screen_write_cursormove(ctx, cx + (src->cx - px),
|
||||
cy + (src->cy - py));
|
||||
screen_write_cell(ctx, &gc);
|
||||
}
|
||||
}
|
||||
|
||||
/* Set up context for TTY command. */
|
||||
static void
|
||||
screen_write_initctx(struct screen_write_ctx *ctx, struct tty_ctx *ttyctx)
|
||||
|
@ -1036,6 +1036,44 @@ server_client_loop(void)
|
||||
}
|
||||
}
|
||||
|
||||
/* Check if we need to force a resize. */
|
||||
static int
|
||||
server_client_resize_force(struct window_pane *wp)
|
||||
{
|
||||
struct timeval tv = { .tv_usec = 100000 };
|
||||
struct winsize ws;
|
||||
|
||||
/*
|
||||
* If we are resizing to the same size as when we entered the loop
|
||||
* (that is, to the same size the application currently thinks it is),
|
||||
* tmux may have gone through several resizes internally and thrown
|
||||
* away parts of the screen. So we need the application to actually
|
||||
* redraw even though its final size has not changed.
|
||||
*/
|
||||
|
||||
if (wp->flags & PANE_RESIZEFORCE) {
|
||||
wp->flags &= ~PANE_RESIZEFORCE;
|
||||
return (0);
|
||||
}
|
||||
|
||||
if (wp->sx != wp->osx ||
|
||||
wp->sy != wp->osy ||
|
||||
wp->sx <= 1 ||
|
||||
wp->sy <= 1)
|
||||
return (0);
|
||||
|
||||
memset(&ws, 0, sizeof ws);
|
||||
ws.ws_col = wp->sx;
|
||||
ws.ws_row = wp->sy - 1;
|
||||
if (ioctl(wp->fd, TIOCSWINSZ, &ws) == -1)
|
||||
fatal("ioctl failed");
|
||||
log_debug("%s: %%%u forcing resize", __func__, wp->id);
|
||||
|
||||
evtimer_add(&wp->resize_timer, &tv);
|
||||
wp->flags |= PANE_RESIZEFORCE;
|
||||
return (1);
|
||||
}
|
||||
|
||||
/* Resize timer event. */
|
||||
static void
|
||||
server_client_resize_event(__unused int fd, __unused short events, void *data)
|
||||
@ -1047,12 +1085,12 @@ server_client_resize_event(__unused int fd, __unused short events, void *data)
|
||||
|
||||
if (!(wp->flags & PANE_RESIZE))
|
||||
return;
|
||||
if (server_client_resize_force(wp))
|
||||
return;
|
||||
|
||||
memset(&ws, 0, sizeof ws);
|
||||
ws.ws_col = wp->sx;
|
||||
ws.ws_row = wp->sy;
|
||||
|
||||
if (ioctl(wp->fd, TIOCSWINSZ, &ws) == -1) {
|
||||
#ifdef __sun
|
||||
/*
|
||||
* Some versions of Solaris apparently can return an error when
|
||||
@ -1066,6 +1104,9 @@ server_client_resize_event(__unused int fd, __unused short events, void *data)
|
||||
}
|
||||
|
||||
wp->flags &= ~PANE_RESIZE;
|
||||
|
||||
wp->osx = wp->sx;
|
||||
wp->osy = wp->sy;
|
||||
}
|
||||
|
||||
/* Check if pane should be resized. */
|
||||
@ -1076,6 +1117,7 @@ server_client_check_resize(struct window_pane *wp)
|
||||
|
||||
if (!(wp->flags & PANE_RESIZE))
|
||||
return;
|
||||
log_debug("%s: %%%u resize to %u,%u", __func__, wp->id, wp->sx, wp->sy);
|
||||
|
||||
if (!event_initialized(&wp->resize_timer))
|
||||
evtimer_set(&wp->resize_timer, server_client_resize_event, wp);
|
||||
@ -1436,10 +1478,9 @@ server_client_dispatch(struct imsg *imsg, void *arg)
|
||||
|
||||
if (c->flags & CLIENT_CONTROL)
|
||||
break;
|
||||
if (tty_resize(&c->tty)) {
|
||||
recalculate_sizes();
|
||||
server_redraw_client(c);
|
||||
}
|
||||
tty_resize(&c->tty);
|
||||
recalculate_sizes();
|
||||
server_redraw_client(c);
|
||||
if (c->session != NULL)
|
||||
notify_client("client-resized", c);
|
||||
break;
|
||||
|
199
tmux.1
199
tmux.1
@ -1343,136 +1343,76 @@ the end of the visible pane.
|
||||
The default is to capture only the visible contents of the pane.
|
||||
.It Xo
|
||||
.Ic choose-client
|
||||
.Op Fl F Ar format
|
||||
.Op Fl t Ar target-window
|
||||
.Op Fl t Ar target-pane
|
||||
.Op Ar template
|
||||
.Xc
|
||||
Put a window into client choice mode, allowing a client to be selected
|
||||
interactively from a list.
|
||||
Put a pane into client mode, allowing a client to be selected interactively from
|
||||
a list.
|
||||
The following keys may be used in client mode:
|
||||
.Bl -column "Key" "Function" -offset indent
|
||||
.It Sy "Key" Ta Sy "Function"
|
||||
.It Li "Enter" Ta "Choose selected client"
|
||||
.It Li "Up" Ta "Select previous client"
|
||||
.It Li "Down" Ta "Select next client"
|
||||
.It Li "t" Ta "Toggle if client is tagged"
|
||||
.It Li "T" Ta "Tag no clients"
|
||||
.It Li "C-t" Ta "Tag all clients"
|
||||
.It Li "d" Ta "Detach selected client"
|
||||
.It Li "D" Ta "Detach tagged clients"
|
||||
.It Li "x" Ta "Detach and HUP selected client"
|
||||
.It Li "X" Ta "Detach and HUP tagged clients"
|
||||
.It Li "z" Ta "Suspend selected client"
|
||||
.It Li "Z" Ta "Suspend tagged clients"
|
||||
.It Li "O" Ta "Change sort order"
|
||||
.It Li "q" Ta "Exit mode"
|
||||
.El
|
||||
.Pp
|
||||
After a client is chosen,
|
||||
.Ql %%
|
||||
is replaced by the client
|
||||
.Xr pty 4
|
||||
path in
|
||||
is replaced by the client name in
|
||||
.Ar template
|
||||
and the result executed as a command.
|
||||
If
|
||||
.Ar template
|
||||
is not given, "detach-client -t '%%'" is used.
|
||||
For the meaning of the
|
||||
.Fl F
|
||||
flag, see the
|
||||
.Sx FORMATS
|
||||
section.
|
||||
.Pp
|
||||
This command works only if at least one client is attached.
|
||||
.It Xo
|
||||
.Ic choose-session
|
||||
.Op Fl F Ar format
|
||||
.Op Fl t Ar target-window
|
||||
.Ic choose-tree
|
||||
.Op Fl sw
|
||||
.Op Fl t Ar target-pane
|
||||
.Op Ar template
|
||||
.Xc
|
||||
Put a window into session choice mode, where a session may be selected
|
||||
Put a pane into tree mode, where a session, window or pane may be chosen
|
||||
interactively from a list.
|
||||
When one is chosen,
|
||||
.Fl s
|
||||
starts with sessions collapsed and
|
||||
.Fl w
|
||||
with windows collapsed.
|
||||
The following keys may be used in tree mode:
|
||||
.Bl -column "Key" "Function" -offset indent
|
||||
.It Sy "Key" Ta Sy "Function"
|
||||
.It Li "Enter" Ta "Choose selected item"
|
||||
.It Li "Up" Ta "Select previous item"
|
||||
.It Li "Down" Ta "Select next item"
|
||||
.It Li "t" Ta "Toggle if item is tagged"
|
||||
.It Li "T" Ta "Tag no items"
|
||||
.It Li "C-t" Ta "Tag all items"
|
||||
.It Li ":" Ta "Run a command for each tagged item"
|
||||
.It Li "f" Ta "Enter a format to filter items"
|
||||
.It Li "O" Ta "Change sort order"
|
||||
.It Li "q" Ta "Exit mode"
|
||||
.El
|
||||
.Pp
|
||||
After a session, window or pane is chosen,
|
||||
.Ql %%
|
||||
is replaced by the session name in
|
||||
is replaced by the target in
|
||||
.Ar template
|
||||
and the result executed as a command.
|
||||
If
|
||||
.Ar template
|
||||
is not given, "switch-client -t '%%'" is used.
|
||||
For the meaning of the
|
||||
.Fl F
|
||||
flag, see the
|
||||
.Sx FORMATS
|
||||
section.
|
||||
This command works only if at least one client is attached.
|
||||
.It Xo
|
||||
.Ic choose-tree
|
||||
.Op Fl suw
|
||||
.Op Fl b Ar session-template
|
||||
.Op Fl c Ar window-template
|
||||
.Op Fl S Ar format
|
||||
.Op Fl W Ar format
|
||||
.Op Fl t Ar target-window
|
||||
.Xc
|
||||
Put a window into tree choice mode, where either sessions or windows may be
|
||||
selected interactively from a list.
|
||||
By default, windows belonging to a session are indented to show their
|
||||
relationship to a session.
|
||||
.Pp
|
||||
Note that the
|
||||
.Ic choose-window
|
||||
and
|
||||
.Ic choose-session
|
||||
commands are wrappers around
|
||||
.Ic choose-tree .
|
||||
.Pp
|
||||
If
|
||||
.Fl s
|
||||
is given, will show sessions.
|
||||
If
|
||||
.Fl w
|
||||
is given, will show windows.
|
||||
.Pp
|
||||
By default, the tree is collapsed and sessions must be expanded to windows
|
||||
with the right arrow key.
|
||||
The
|
||||
.Fl u
|
||||
option will start with all sessions expanded instead.
|
||||
.Pp
|
||||
If
|
||||
.Fl b
|
||||
is given, will override the default session command.
|
||||
Note that
|
||||
.Ql %%
|
||||
can be used and will be replaced with the session name.
|
||||
The default option if not specified is "switch-client -t '%%'".
|
||||
If
|
||||
.Fl c
|
||||
is given, will override the default window command.
|
||||
Like
|
||||
.Fl b ,
|
||||
.Ql %%
|
||||
can be used and will be replaced with the session name and window index.
|
||||
When a window is chosen from the list, the session command is run before the
|
||||
window command.
|
||||
.Pp
|
||||
.Fl S
|
||||
uses
|
||||
.Ar format
|
||||
instead of the default session
|
||||
format and
|
||||
.Fl W
|
||||
instead of the default window format.
|
||||
For the meaning of
|
||||
.Ar format ,
|
||||
see the
|
||||
.Sx FORMATS
|
||||
section.
|
||||
.Pp
|
||||
This command works only if at least one client is attached.
|
||||
.It Xo
|
||||
.Ic choose-window
|
||||
.Op Fl F Ar format
|
||||
.Op Fl t Ar target-window
|
||||
.Op Ar template
|
||||
.Xc
|
||||
Put a window into window choice mode, where a window may be chosen
|
||||
interactively from a list.
|
||||
After a window is selected,
|
||||
.Ql %%
|
||||
is replaced by the session name and window index in
|
||||
.Ar template
|
||||
and the result executed as a command.
|
||||
If
|
||||
.Ar template
|
||||
is not given, "select-window -t '%%'" is used.
|
||||
For the meaning of the
|
||||
.Fl F
|
||||
flag, see the
|
||||
.Sx FORMATS
|
||||
section.
|
||||
This command works only if at least one client is attached.
|
||||
.It Xo
|
||||
.Ic display-panes
|
||||
@ -1502,8 +1442,7 @@ The default
|
||||
is "select-pane -t '%%'".
|
||||
.It Xo Ic find-window
|
||||
.Op Fl CNT
|
||||
.Op Fl F Ar format
|
||||
.Op Fl t Ar target-window
|
||||
.Op Fl t Ar target-pane
|
||||
.Ar match-string
|
||||
.Xc
|
||||
.D1 (alias: Ic findw )
|
||||
@ -1521,13 +1460,7 @@ matches only the window name and
|
||||
matches only the window title.
|
||||
The default is
|
||||
.Fl CNT .
|
||||
If only one window is matched, it'll be automatically selected,
|
||||
otherwise a choice list is shown.
|
||||
For the meaning of the
|
||||
.Fl F
|
||||
flag, see the
|
||||
.Sx FORMATS
|
||||
section.
|
||||
.Pp
|
||||
This command works only if at least one client is attached.
|
||||
.It Xo Ic join-pane
|
||||
.Op Fl bdhv
|
||||
@ -3988,13 +3921,27 @@ The buffer commands are as follows:
|
||||
.Bl -tag -width Ds
|
||||
.It Xo
|
||||
.Ic choose-buffer
|
||||
.Op Fl F Ar format
|
||||
.Op Fl t Ar target-window
|
||||
.Op Fl t Ar target-pane
|
||||
.Op Ar template
|
||||
.Xc
|
||||
Put a window into buffer choice mode, where a buffer may be chosen
|
||||
interactively from a list.
|
||||
After a buffer is selected,
|
||||
Put a pane into buffer mode, where a buffer may be chosen interactively from
|
||||
a list.
|
||||
The following keys may be used in buffer mode:
|
||||
.Bl -column "Key" "Function" -offset indent
|
||||
.It Sy "Key" Ta Sy "Function"
|
||||
.It Li "Enter" Ta "Choose selected buffer"
|
||||
.It Li "Up" Ta "Select previous buffer"
|
||||
.It Li "Down" Ta "Select next buffer"
|
||||
.It Li "t" Ta "Toggle if buffer is tagged"
|
||||
.It Li "T" Ta "Tag no buffers"
|
||||
.It Li "C-t" Ta "Tag all buffers"
|
||||
.It Li "d" Ta "Delete selected buffer"
|
||||
.It Li "D" Ta "Delete tagged buffers"
|
||||
.It Li "O" Ta "Change sort order"
|
||||
.It Li "q" Ta "Exit mode"
|
||||
.El
|
||||
.Pp
|
||||
After a buffer is chosen,
|
||||
.Ql %%
|
||||
is replaced by the buffer name in
|
||||
.Ar template
|
||||
@ -4002,11 +3949,7 @@ and the result executed as a command.
|
||||
If
|
||||
.Ar template
|
||||
is not given, "paste-buffer -b '%%'" is used.
|
||||
For the meaning of the
|
||||
.Fl F
|
||||
flag, see the
|
||||
.Sx FORMATS
|
||||
section.
|
||||
.Pp
|
||||
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 )
|
||||
|
240
tmux.h
240
tmux.h
@ -42,12 +42,13 @@ extern char **environ;
|
||||
|
||||
struct args;
|
||||
struct client;
|
||||
struct cmd_find_state;
|
||||
struct cmdq_item;
|
||||
struct cmdq_list;
|
||||
struct environ;
|
||||
struct format_job_tree;
|
||||
struct input_ctx;
|
||||
struct mode_key_cmdstr;
|
||||
struct mode_tree_data;
|
||||
struct mouse_event;
|
||||
struct options;
|
||||
struct options_entry;
|
||||
@ -207,67 +208,67 @@ enum {
|
||||
/* Termcap codes. */
|
||||
enum tty_code_code {
|
||||
TTYC_AX = 0,
|
||||
TTYC_ACSC, /* acs_chars, ac */
|
||||
TTYC_BCE, /* back_color_erase, ut */
|
||||
TTYC_BEL, /* bell, bl */
|
||||
TTYC_BLINK, /* enter_blink_mode, mb */
|
||||
TTYC_BOLD, /* enter_bold_mode, md */
|
||||
TTYC_CIVIS, /* cursor_invisible, vi */
|
||||
TTYC_CLEAR, /* clear_screen, cl */
|
||||
TTYC_CNORM, /* cursor_normal, ve */
|
||||
TTYC_COLORS, /* max_colors, Co */
|
||||
TTYC_CR, /* restore cursor colour, Cr */
|
||||
TTYC_CS, /* set cursor colour, Cs */
|
||||
TTYC_CSR, /* change_scroll_region, cs */
|
||||
TTYC_CUB, /* parm_left_cursor, LE */
|
||||
TTYC_CUB1, /* cursor_left, le */
|
||||
TTYC_CUD, /* parm_down_cursor, DO */
|
||||
TTYC_CUD1, /* cursor_down, do */
|
||||
TTYC_CUF, /* parm_right_cursor, RI */
|
||||
TTYC_CUF1, /* cursor_right, nd */
|
||||
TTYC_CUP, /* cursor_address, cm */
|
||||
TTYC_CUU, /* parm_up_cursor, UP */
|
||||
TTYC_CUU1, /* cursor_up, up */
|
||||
TTYC_CVVIS, /* cursor_visible, vs */
|
||||
TTYC_DCH, /* parm_dch, DC */
|
||||
TTYC_DCH1, /* delete_character, dc */
|
||||
TTYC_DIM, /* enter_dim_mode, mh */
|
||||
TTYC_DL, /* parm_delete_line, DL */
|
||||
TTYC_DL1, /* delete_line, dl */
|
||||
TTYC_ACSC,
|
||||
TTYC_BCE,
|
||||
TTYC_BEL,
|
||||
TTYC_BLINK,
|
||||
TTYC_BOLD,
|
||||
TTYC_CIVIS,
|
||||
TTYC_CLEAR,
|
||||
TTYC_CNORM,
|
||||
TTYC_COLORS,
|
||||
TTYC_CR,
|
||||
TTYC_CS,
|
||||
TTYC_CSR,
|
||||
TTYC_CUB,
|
||||
TTYC_CUB1,
|
||||
TTYC_CUD,
|
||||
TTYC_CUD1,
|
||||
TTYC_CUF,
|
||||
TTYC_CUF1,
|
||||
TTYC_CUP,
|
||||
TTYC_CUU,
|
||||
TTYC_CUU1,
|
||||
TTYC_CVVIS,
|
||||
TTYC_DCH,
|
||||
TTYC_DCH1,
|
||||
TTYC_DIM,
|
||||
TTYC_DL,
|
||||
TTYC_DL1,
|
||||
TTYC_E3,
|
||||
TTYC_ECH, /* erase_chars, ec */
|
||||
TTYC_ED, /* clr_eos, cd */
|
||||
TTYC_EL, /* clr_eol, ce */
|
||||
TTYC_EL1, /* clr_bol, cb */
|
||||
TTYC_ENACS, /* ena_acs, eA */
|
||||
TTYC_FSL, /* from_status_line, fsl */
|
||||
TTYC_HOME, /* cursor_home, ho */
|
||||
TTYC_HPA, /* column_address, ch */
|
||||
TTYC_ICH, /* parm_ich, IC */
|
||||
TTYC_ICH1, /* insert_character, ic */
|
||||
TTYC_IL, /* parm_insert_line, IL */
|
||||
TTYC_IL1, /* insert_line, il */
|
||||
TTYC_INDN, /* parm_index, indn */
|
||||
TTYC_INVIS, /* enter_secure_mode, mk */
|
||||
TTYC_KCBT, /* key_btab, kB */
|
||||
TTYC_KCUB1, /* key_left, kl */
|
||||
TTYC_KCUD1, /* key_down, kd */
|
||||
TTYC_KCUF1, /* key_right, kr */
|
||||
TTYC_KCUU1, /* key_up, ku */
|
||||
TTYC_ECH,
|
||||
TTYC_ED,
|
||||
TTYC_EL,
|
||||
TTYC_EL1,
|
||||
TTYC_ENACS,
|
||||
TTYC_FSL,
|
||||
TTYC_HOME,
|
||||
TTYC_HPA,
|
||||
TTYC_ICH,
|
||||
TTYC_ICH1,
|
||||
TTYC_IL,
|
||||
TTYC_IL1,
|
||||
TTYC_INDN,
|
||||
TTYC_INVIS,
|
||||
TTYC_KCBT,
|
||||
TTYC_KCUB1,
|
||||
TTYC_KCUD1,
|
||||
TTYC_KCUF1,
|
||||
TTYC_KCUU1,
|
||||
TTYC_KDC2,
|
||||
TTYC_KDC3,
|
||||
TTYC_KDC4,
|
||||
TTYC_KDC5,
|
||||
TTYC_KDC6,
|
||||
TTYC_KDC7,
|
||||
TTYC_KDCH1, /* key_dc, kD */
|
||||
TTYC_KDCH1,
|
||||
TTYC_KDN2,
|
||||
TTYC_KDN3,
|
||||
TTYC_KDN4,
|
||||
TTYC_KDN5,
|
||||
TTYC_KDN6,
|
||||
TTYC_KDN7,
|
||||
TTYC_KEND, /* key_end, ke */
|
||||
TTYC_KEND,
|
||||
TTYC_KEND2,
|
||||
TTYC_KEND3,
|
||||
TTYC_KEND4,
|
||||
@ -343,29 +344,29 @@ enum tty_code_code {
|
||||
TTYC_KHOM5,
|
||||
TTYC_KHOM6,
|
||||
TTYC_KHOM7,
|
||||
TTYC_KHOME, /* key_home, kh */
|
||||
TTYC_KHOME,
|
||||
TTYC_KIC2,
|
||||
TTYC_KIC3,
|
||||
TTYC_KIC4,
|
||||
TTYC_KIC5,
|
||||
TTYC_KIC6,
|
||||
TTYC_KIC7,
|
||||
TTYC_KICH1, /* key_ic, kI */
|
||||
TTYC_KICH1,
|
||||
TTYC_KLFT2,
|
||||
TTYC_KLFT3,
|
||||
TTYC_KLFT4,
|
||||
TTYC_KLFT5,
|
||||
TTYC_KLFT6,
|
||||
TTYC_KLFT7,
|
||||
TTYC_KMOUS, /* key_mouse, Km */
|
||||
TTYC_KNP, /* key_npage, kN */
|
||||
TTYC_KMOUS,
|
||||
TTYC_KNP,
|
||||
TTYC_KNXT2,
|
||||
TTYC_KNXT3,
|
||||
TTYC_KNXT4,
|
||||
TTYC_KNXT5,
|
||||
TTYC_KNXT6,
|
||||
TTYC_KNXT7,
|
||||
TTYC_KPP, /* key_ppage, kP */
|
||||
TTYC_KPP,
|
||||
TTYC_KPRV2,
|
||||
TTYC_KPRV3,
|
||||
TTYC_KPRV4,
|
||||
@ -384,31 +385,33 @@ enum tty_code_code {
|
||||
TTYC_KUP5,
|
||||
TTYC_KUP6,
|
||||
TTYC_KUP7,
|
||||
TTYC_MS, /* modify xterm(1) selection */
|
||||
TTYC_OP, /* orig_pair, op */
|
||||
TTYC_REV, /* enter_reverse_mode, mr */
|
||||
TTYC_RI, /* scroll_reverse, sr */
|
||||
TTYC_RMACS, /* exit_alt_charset_mode */
|
||||
TTYC_RMCUP, /* exit_ca_mode, te */
|
||||
TTYC_RMKX, /* keypad_local, ke */
|
||||
TTYC_SE, /* reset cursor style, Se */
|
||||
TTYC_SETAB, /* set_a_background, AB */
|
||||
TTYC_SETAF, /* set_a_foreground, AF */
|
||||
TTYC_SGR0, /* exit_attribute_mode, me */
|
||||
TTYC_SITM, /* enter_italics_mode, it */
|
||||
TTYC_SMACS, /* enter_alt_charset_mode, as */
|
||||
TTYC_SMCUP, /* enter_ca_mode, ti */
|
||||
TTYC_SMKX, /* keypad_xmit, ks */
|
||||
TTYC_SMSO, /* enter_standout_mode, so */
|
||||
TTYC_SMUL, /* enter_underline_mode, us */
|
||||
TTYC_MS,
|
||||
TTYC_OP,
|
||||
TTYC_REV,
|
||||
TTYC_RI,
|
||||
TTYC_RMACS,
|
||||
TTYC_RMCUP,
|
||||
TTYC_RMKX,
|
||||
TTYC_SE,
|
||||
TTYC_SETAB,
|
||||
TTYC_SETAF,
|
||||
TTYC_SETRGBB,
|
||||
TTYC_SETRGBF,
|
||||
TTYC_SGR0,
|
||||
TTYC_SITM,
|
||||
TTYC_SMACS,
|
||||
TTYC_SMCUP,
|
||||
TTYC_SMKX,
|
||||
TTYC_SMSO,
|
||||
TTYC_SMUL,
|
||||
TTYC_SMXX,
|
||||
TTYC_SS, /* set cursor style, Ss */
|
||||
TTYC_TC, /* 24-bit "true" colour, Tc */
|
||||
TTYC_TSL, /* to_status_line, tsl */
|
||||
TTYC_SS,
|
||||
TTYC_TC,
|
||||
TTYC_TSL,
|
||||
TTYC_U8,
|
||||
TTYC_VPA, /* row_address, cv */
|
||||
TTYC_XENL, /* eat_newline_glitch, xn */
|
||||
TTYC_XT, /* xterm(1)-compatible title, XT */
|
||||
TTYC_VPA,
|
||||
TTYC_XENL,
|
||||
TTYC_XT,
|
||||
};
|
||||
|
||||
/* Message codes. */
|
||||
@ -697,7 +700,8 @@ struct screen_write_ctx {
|
||||
struct window_mode {
|
||||
const char *name;
|
||||
|
||||
struct screen *(*init)(struct window_pane *);
|
||||
struct screen *(*init)(struct window_pane *, struct cmd_find_state *,
|
||||
struct args *);
|
||||
void (*free)(struct window_pane *);
|
||||
void (*resize)(struct window_pane *, u_int, u_int);
|
||||
void (*key)(struct window_pane *, struct client *,
|
||||
@ -745,6 +749,9 @@ struct window_pane {
|
||||
u_int sx;
|
||||
u_int sy;
|
||||
|
||||
u_int osx;
|
||||
u_int osy;
|
||||
|
||||
u_int xoff;
|
||||
u_int yoff;
|
||||
|
||||
@ -753,9 +760,10 @@ struct window_pane {
|
||||
#define PANE_DROP 0x2
|
||||
#define PANE_FOCUSED 0x4
|
||||
#define PANE_RESIZE 0x8
|
||||
#define PANE_FOCUSPUSH 0x10
|
||||
#define PANE_INPUTOFF 0x20
|
||||
#define PANE_CHANGED 0x40
|
||||
#define PANE_RESIZEFORCE 0x10
|
||||
#define PANE_FOCUSPUSH 0x20
|
||||
#define PANE_INPUTOFF 0x40
|
||||
#define PANE_CHANGED 0x80
|
||||
|
||||
int argc;
|
||||
char **argv;
|
||||
@ -1522,6 +1530,7 @@ char *paste_make_sample(struct paste_buffer *);
|
||||
#define FORMAT_PANE 0x80000000U
|
||||
#define FORMAT_WINDOW 0x40000000U
|
||||
struct format_tree;
|
||||
int format_true(const char *);
|
||||
struct format_tree *format_create(struct client *, struct cmdq_item *, int,
|
||||
int);
|
||||
void format_free(struct format_tree *);
|
||||
@ -1649,6 +1658,7 @@ void tty_cursor(struct tty *, u_int, u_int);
|
||||
void tty_putcode(struct tty *, enum tty_code_code);
|
||||
void tty_putcode1(struct tty *, enum tty_code_code, int);
|
||||
void tty_putcode2(struct tty *, enum tty_code_code, int, int);
|
||||
void tty_putcode3(struct tty *, enum tty_code_code, int, int, int);
|
||||
void tty_putcode_ptr1(struct tty *, enum tty_code_code, const void *);
|
||||
void tty_putcode_ptr2(struct tty *, enum tty_code_code, const void *,
|
||||
const void *);
|
||||
@ -1656,8 +1666,8 @@ void tty_puts(struct tty *, const char *);
|
||||
void tty_putc(struct tty *, u_char);
|
||||
void tty_putn(struct tty *, const void *, size_t, u_int);
|
||||
int tty_init(struct tty *, struct client *, int, char *);
|
||||
int tty_resize(struct tty *);
|
||||
int tty_set_size(struct tty *, u_int, u_int);
|
||||
void tty_resize(struct tty *);
|
||||
void tty_set_size(struct tty *, u_int, u_int);
|
||||
void tty_start_tty(struct tty *);
|
||||
void tty_stop_tty(struct tty *);
|
||||
void tty_set_title(struct tty *, const char *);
|
||||
@ -1703,6 +1713,8 @@ const char *tty_term_string(struct tty_term *, enum tty_code_code);
|
||||
const char *tty_term_string1(struct tty_term *, enum tty_code_code, int);
|
||||
const char *tty_term_string2(struct tty_term *, enum tty_code_code, int,
|
||||
int);
|
||||
const char *tty_term_string3(struct tty_term *, enum tty_code_code, int,
|
||||
int, int);
|
||||
const char *tty_term_ptr1(struct tty_term *, enum tty_code_code,
|
||||
const void *);
|
||||
const char *tty_term_ptr2(struct tty_term *, enum tty_code_code,
|
||||
@ -1721,6 +1733,7 @@ void tty_keys_free(struct tty *);
|
||||
key_code tty_keys_next(struct tty *);
|
||||
|
||||
/* arguments.c */
|
||||
void args_set(struct args *, u_char, const char *);
|
||||
struct args *args_parse(const char *, int, char **);
|
||||
void args_free(struct args *);
|
||||
char *args_print(struct args *);
|
||||
@ -2001,6 +2014,10 @@ void screen_write_putc(struct screen_write_ctx *, const struct grid_cell *,
|
||||
u_char);
|
||||
void screen_write_copy(struct screen_write_ctx *, struct screen *, u_int,
|
||||
u_int, u_int, u_int, bitstr_t *, const struct grid_cell *);
|
||||
void screen_write_line(struct screen_write_ctx *, u_int, int, int);
|
||||
void screen_write_box(struct screen_write_ctx *, u_int, u_int);
|
||||
void screen_write_preview(struct screen_write_ctx *, struct screen *, u_int,
|
||||
u_int);
|
||||
void screen_write_backspace(struct screen_write_ctx *);
|
||||
void screen_write_mode_set(struct screen_write_ctx *, int);
|
||||
void screen_write_mode_clear(struct screen_write_ctx *, int);
|
||||
@ -2123,15 +2140,15 @@ void window_pane_unset_palette(struct window_pane *, u_int);
|
||||
void window_pane_reset_palette(struct window_pane *);
|
||||
int window_pane_get_palette(const struct window_pane *, int);
|
||||
int window_pane_set_mode(struct window_pane *,
|
||||
const struct window_mode *);
|
||||
const struct window_mode *, struct cmd_find_state *,
|
||||
struct args *);
|
||||
void window_pane_reset_mode(struct window_pane *);
|
||||
void window_pane_key(struct window_pane *, struct client *,
|
||||
struct session *, key_code, struct mouse_event *);
|
||||
int window_pane_outside(struct window_pane *);
|
||||
int window_pane_visible(struct window_pane *);
|
||||
u_int window_pane_search(struct window_pane *, const char *);
|
||||
char *window_pane_search_old(struct window_pane *, const char *,
|
||||
u_int *);
|
||||
|
||||
const char *window_printable_flags(struct winlink *);
|
||||
struct window_pane *window_pane_find_up(struct window_pane *);
|
||||
struct window_pane *window_pane_find_down(struct window_pane *);
|
||||
@ -2180,10 +2197,43 @@ u_int layout_set_select(struct window *, u_int);
|
||||
u_int layout_set_next(struct window *);
|
||||
u_int layout_set_previous(struct window *);
|
||||
|
||||
/* mode-tree.c */
|
||||
u_int mode_tree_count_tagged(struct mode_tree_data *);
|
||||
void *mode_tree_get_current(struct mode_tree_data *);
|
||||
void mode_tree_each_tagged(struct mode_tree_data *, void (*)(void *, void *,
|
||||
key_code), key_code, int);
|
||||
void mode_tree_up(struct mode_tree_data *, int);
|
||||
void mode_tree_down(struct mode_tree_data *, int);
|
||||
struct mode_tree_data *mode_tree_start(struct window_pane *,
|
||||
void (*)(void *, u_int, uint64_t *), struct screen *(*)(void *,
|
||||
void *, u_int, u_int), void *, const char **, u_int,
|
||||
struct screen **);
|
||||
void mode_tree_build(struct mode_tree_data *);
|
||||
void mode_tree_free(struct mode_tree_data *);
|
||||
void mode_tree_resize(struct mode_tree_data *, u_int, u_int);
|
||||
struct mode_tree_item *mode_tree_add(struct mode_tree_data *,
|
||||
struct mode_tree_item *, void *, uint64_t, const char *,
|
||||
const char *, int);
|
||||
void mode_tree_remove(struct mode_tree_data *, struct mode_tree_item *);
|
||||
void mode_tree_draw(struct mode_tree_data *);
|
||||
int mode_tree_key(struct mode_tree_data *, key_code *,
|
||||
struct mouse_event *);
|
||||
void mode_tree_run_command(struct client *, struct cmd_find_state *,
|
||||
const char *, const char *);
|
||||
|
||||
/* window-buffer.c */
|
||||
extern const struct window_mode window_buffer_mode;
|
||||
|
||||
/* window-tree.c */
|
||||
extern const struct window_mode window_tree_mode;
|
||||
|
||||
/* window-clock.c */
|
||||
extern const struct window_mode window_clock_mode;
|
||||
extern const char window_clock_table[14][5][5];
|
||||
|
||||
/* window-client.c */
|
||||
extern const struct window_mode window_client_mode;
|
||||
|
||||
/* window-copy.c */
|
||||
extern const struct window_mode window_copy_mode;
|
||||
void window_copy_init_from_pane(struct window_pane *, int);
|
||||
@ -2194,24 +2244,6 @@ void window_copy_pageup(struct window_pane *, int);
|
||||
void window_copy_start_drag(struct client *, struct mouse_event *);
|
||||
int window_copy_scroll_position(struct window_pane *);
|
||||
|
||||
/* window-choose.c */
|
||||
extern const struct window_mode window_choose_mode;
|
||||
void window_choose_add(struct window_pane *,
|
||||
struct window_choose_data *);
|
||||
void window_choose_ready(struct window_pane *,
|
||||
u_int, void (*)(struct window_choose_data *));
|
||||
struct window_choose_data *window_choose_data_create (int,
|
||||
struct client *, struct session *);
|
||||
void window_choose_data_run(struct window_choose_data *);
|
||||
struct window_choose_data *window_choose_add_window(struct window_pane *,
|
||||
struct client *, struct session *, struct winlink *,
|
||||
const char *, const char *, u_int);
|
||||
struct window_choose_data *window_choose_add_session(struct window_pane *,
|
||||
struct client *, struct session *, const char *,
|
||||
const char *, u_int);
|
||||
void window_choose_expand_all(struct window_pane *);
|
||||
void window_choose_set_current(struct window_pane *, u_int);
|
||||
|
||||
/* names.c */
|
||||
void check_window_name(struct window *);
|
||||
char *default_window_name(struct window *);
|
||||
|
20
tty-term.c
20
tty-term.c
@ -245,6 +245,8 @@ static const struct tty_term_code_entry tty_term_codes[] = {
|
||||
[TTYC_SE] = { TTYCODE_STRING, "Se" },
|
||||
[TTYC_SETAB] = { TTYCODE_STRING, "setab" },
|
||||
[TTYC_SETAF] = { TTYCODE_STRING, "setaf" },
|
||||
[TTYC_SETRGBB] = { TTYCODE_STRING, "setrgbb" },
|
||||
[TTYC_SETRGBF] = { TTYCODE_STRING, "setrgbf" },
|
||||
[TTYC_SGR0] = { TTYCODE_STRING, "sgr0" },
|
||||
[TTYC_SITM] = { TTYCODE_STRING, "sitm" },
|
||||
[TTYC_SMACS] = { TTYCODE_STRING, "smacs" },
|
||||
@ -527,6 +529,18 @@ tty_term_find(char *name, int fd, char **cause)
|
||||
code->type = TTYCODE_STRING;
|
||||
}
|
||||
|
||||
/* On terminals with RGB colour (TC), fill in setrgbf and setrgbb. */
|
||||
if (tty_term_flag(term, TTYC_TC) &&
|
||||
!tty_term_has(term, TTYC_SETRGBF) &&
|
||||
!tty_term_has(term, TTYC_SETRGBB)) {
|
||||
code = &term->codes[TTYC_SETRGBF];
|
||||
code->value.string = xstrdup("\033[38;2;%p1%d;%p2%d;%p3%dm");
|
||||
code->type = TTYCODE_STRING;
|
||||
code = &term->codes[TTYC_SETRGBB];
|
||||
code->value.string = xstrdup("\033[48;2;%p1%d;%p2%d;%p3%dm");
|
||||
code->type = TTYCODE_STRING;
|
||||
}
|
||||
|
||||
return (term);
|
||||
|
||||
error:
|
||||
@ -582,6 +596,12 @@ tty_term_string2(struct tty_term *term, enum tty_code_code code, int a, int b)
|
||||
return (tparm((char *) tty_term_string(term, code), a, b, 0, 0, 0, 0, 0, 0, 0));
|
||||
}
|
||||
|
||||
const char *
|
||||
tty_term_string3(struct tty_term *term, enum tty_code_code code, int a, int b, int c)
|
||||
{
|
||||
return (tparm((char *) tty_term_string(term, code), a, b, c));
|
||||
}
|
||||
|
||||
const char *
|
||||
tty_term_ptr1(struct tty_term *term, enum tty_code_code code, const void *a)
|
||||
{
|
||||
|
42
tty.c
42
tty.c
@ -120,7 +120,7 @@ tty_init(struct tty *tty, struct client *c, int fd, char *term)
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
void
|
||||
tty_resize(struct tty *tty)
|
||||
{
|
||||
struct client *c = tty->client;
|
||||
@ -139,21 +139,15 @@ tty_resize(struct tty *tty)
|
||||
sy = 24;
|
||||
}
|
||||
log_debug("%s: %s now %ux%u", __func__, c->name, sx, sy);
|
||||
|
||||
if (!tty_set_size(tty, sx, sy))
|
||||
return (0);
|
||||
tty_set_size(tty, sx, sy);
|
||||
tty_invalidate(tty);
|
||||
return (1);
|
||||
}
|
||||
|
||||
int
|
||||
void
|
||||
tty_set_size(struct tty *tty, u_int sx, u_int sy)
|
||||
{
|
||||
if (sx == tty->sx && sy == tty->sy)
|
||||
return (0);
|
||||
tty->sx = sx;
|
||||
tty->sy = sy;
|
||||
return (1);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -472,6 +466,14 @@ tty_putcode2(struct tty *tty, enum tty_code_code code, int a, int b)
|
||||
tty_puts(tty, tty_term_string2(tty->term, code, a, b));
|
||||
}
|
||||
|
||||
void
|
||||
tty_putcode3(struct tty *tty, enum tty_code_code code, int a, int b, int c)
|
||||
{
|
||||
if (a < 0 || b < 0 || c < 0)
|
||||
return;
|
||||
tty_puts(tty, tty_term_string3(tty->term, code, a, b, c));
|
||||
}
|
||||
|
||||
void
|
||||
tty_putcode_ptr1(struct tty *tty, enum tty_code_code code, const void *a)
|
||||
{
|
||||
@ -1847,7 +1849,7 @@ tty_check_fg(struct tty *tty, const struct window_pane *wp,
|
||||
/* Is this a 24-bit colour? */
|
||||
if (gc->fg & COLOUR_FLAG_RGB) {
|
||||
/* Not a 24-bit terminal? Translate to 256-colour palette. */
|
||||
if (!tty_term_flag(tty->term, TTYC_TC)) {
|
||||
if (!tty_term_has(tty->term, TTYC_SETRGBF)) {
|
||||
colour_split_rgb(gc->fg, &r, &g, &b);
|
||||
gc->fg = colour_find_rgb(r, g, b);
|
||||
} else
|
||||
@ -1900,7 +1902,7 @@ tty_check_bg(struct tty *tty, const struct window_pane *wp,
|
||||
/* Is this a 24-bit colour? */
|
||||
if (gc->bg & COLOUR_FLAG_RGB) {
|
||||
/* Not a 24-bit terminal? Translate to 256-colour palette. */
|
||||
if (!tty_term_flag(tty->term, TTYC_TC)) {
|
||||
if (!tty_term_has(tty->term, TTYC_SETRGBB)) {
|
||||
colour_split_rgb(gc->bg, &r, &g, &b);
|
||||
gc->bg = colour_find_rgb(r, g, b);
|
||||
} else
|
||||
@ -2031,13 +2033,17 @@ tty_try_colour(struct tty *tty, int colour, const char *type)
|
||||
}
|
||||
|
||||
if (colour & COLOUR_FLAG_RGB) {
|
||||
if (!tty_term_flag(tty->term, TTYC_TC))
|
||||
return (-1);
|
||||
|
||||
colour_split_rgb(colour & 0xffffff, &r, &g, &b);
|
||||
xsnprintf(s, sizeof s, "\033[%s;2;%hhu;%hhu;%hhum", type,
|
||||
r, g, b);
|
||||
tty_puts(tty, s);
|
||||
if (*type == '3') {
|
||||
if (!tty_term_has(tty->term, TTYC_SETRGBF))
|
||||
return (-1);
|
||||
colour_split_rgb(colour & 0xffffff, &r, &g, &b);
|
||||
tty_putcode3(tty, TTYC_SETRGBF, r, g, b);
|
||||
} else {
|
||||
if (!tty_term_has(tty->term, TTYC_SETRGBB))
|
||||
return (-1);
|
||||
colour_split_rgb(colour & 0xffffff, &r, &g, &b);
|
||||
tty_putcode3(tty, TTYC_SETRGBB, r, g, b);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
342
window-buffer.c
Normal file
342
window-buffer.c
Normal file
@ -0,0 +1,342 @@
|
||||
/* $OpenBSD$ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2017 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
|
||||
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <vis.h>
|
||||
|
||||
#include "tmux.h"
|
||||
|
||||
static struct screen *window_buffer_init(struct window_pane *,
|
||||
struct cmd_find_state *, struct args *);
|
||||
static void window_buffer_free(struct window_pane *);
|
||||
static void window_buffer_resize(struct window_pane *, u_int,
|
||||
u_int);
|
||||
static void window_buffer_key(struct window_pane *,
|
||||
struct client *, struct session *, key_code,
|
||||
struct mouse_event *);
|
||||
|
||||
#define WINDOW_BUFFER_DEFAULT_COMMAND "paste-buffer -b '%%'"
|
||||
|
||||
const struct window_mode window_buffer_mode = {
|
||||
.name = "buffer-mode",
|
||||
|
||||
.init = window_buffer_init,
|
||||
.free = window_buffer_free,
|
||||
.resize = window_buffer_resize,
|
||||
.key = window_buffer_key,
|
||||
};
|
||||
|
||||
enum window_buffer_sort_type {
|
||||
WINDOW_BUFFER_BY_NAME,
|
||||
WINDOW_BUFFER_BY_TIME,
|
||||
WINDOW_BUFFER_BY_SIZE,
|
||||
};
|
||||
static const char *window_buffer_sort_list[] = {
|
||||
"name",
|
||||
"time",
|
||||
"size"
|
||||
};
|
||||
|
||||
struct window_buffer_itemdata {
|
||||
const char *name;
|
||||
time_t created;
|
||||
u_int order;
|
||||
size_t size;
|
||||
};
|
||||
|
||||
struct window_buffer_modedata {
|
||||
struct mode_tree_data *data;
|
||||
char *command;
|
||||
|
||||
struct window_buffer_itemdata **item_list;
|
||||
u_int item_size;
|
||||
};
|
||||
|
||||
static struct window_buffer_itemdata *
|
||||
window_buffer_add_item(struct window_buffer_modedata *data)
|
||||
{
|
||||
struct window_buffer_itemdata *item;
|
||||
|
||||
data->item_list = xreallocarray(data->item_list, data->item_size + 1,
|
||||
sizeof *data->item_list);
|
||||
item = data->item_list[data->item_size++] = xcalloc(1, sizeof *item);
|
||||
return (item);
|
||||
}
|
||||
|
||||
static void
|
||||
window_buffer_free_item(struct window_buffer_itemdata *item)
|
||||
{
|
||||
free((void *)item->name);
|
||||
free(item);
|
||||
}
|
||||
|
||||
static int
|
||||
window_buffer_cmp_name(const void *a0, const void *b0)
|
||||
{
|
||||
const struct window_buffer_itemdata *const *a = a0;
|
||||
const struct window_buffer_itemdata *const *b = b0;
|
||||
|
||||
return (strcmp((*a)->name, (*b)->name));
|
||||
}
|
||||
|
||||
static int
|
||||
window_buffer_cmp_time(const void *a0, const void *b0)
|
||||
{
|
||||
const struct window_buffer_itemdata *const *a = a0;
|
||||
const struct window_buffer_itemdata *const *b = b0;
|
||||
|
||||
if ((*a)->order > (*b)->order)
|
||||
return (-1);
|
||||
if ((*a)->order < (*b)->order)
|
||||
return (1);
|
||||
return (strcmp((*a)->name, (*b)->name));
|
||||
}
|
||||
|
||||
static int
|
||||
window_buffer_cmp_size(const void *a0, const void *b0)
|
||||
{
|
||||
const struct window_buffer_itemdata *const *a = a0;
|
||||
const struct window_buffer_itemdata *const *b = b0;
|
||||
|
||||
if ((*a)->size > (*b)->size)
|
||||
return (-1);
|
||||
if ((*a)->size < (*b)->size)
|
||||
return (1);
|
||||
return (strcmp((*a)->name, (*b)->name));
|
||||
}
|
||||
|
||||
static void
|
||||
window_buffer_build(void *modedata, u_int sort_type, __unused uint64_t *tag)
|
||||
{
|
||||
struct window_buffer_modedata *data = modedata;
|
||||
struct window_buffer_itemdata *item;
|
||||
u_int i;
|
||||
struct paste_buffer *pb;
|
||||
char *tim;
|
||||
char *text;
|
||||
|
||||
for (i = 0; i < data->item_size; i++)
|
||||
window_buffer_free_item(data->item_list[i]);
|
||||
free(data->item_list);
|
||||
data->item_list = NULL;
|
||||
data->item_size = 0;
|
||||
|
||||
pb = NULL;
|
||||
while ((pb = paste_walk(pb)) != NULL) {
|
||||
item = window_buffer_add_item(data);
|
||||
item->name = xstrdup(paste_buffer_name(pb));
|
||||
item->created = paste_buffer_created(pb);
|
||||
paste_buffer_data(pb, &item->size);
|
||||
item->order = paste_buffer_order(pb);
|
||||
}
|
||||
|
||||
switch (sort_type) {
|
||||
case WINDOW_BUFFER_BY_NAME:
|
||||
qsort(data->item_list, data->item_size, sizeof *data->item_list,
|
||||
window_buffer_cmp_name);
|
||||
break;
|
||||
case WINDOW_BUFFER_BY_TIME:
|
||||
qsort(data->item_list, data->item_size, sizeof *data->item_list,
|
||||
window_buffer_cmp_time);
|
||||
break;
|
||||
case WINDOW_BUFFER_BY_SIZE:
|
||||
qsort(data->item_list, data->item_size, sizeof *data->item_list,
|
||||
window_buffer_cmp_size);
|
||||
break;
|
||||
}
|
||||
|
||||
for (i = 0; i < data->item_size; i++) {
|
||||
item = data->item_list[i];
|
||||
|
||||
tim = ctime(&item->created);
|
||||
*strchr(tim, '\n') = '\0';
|
||||
|
||||
xasprintf(&text, "%zu bytes (%s)", item->size, tim);
|
||||
mode_tree_add(data->data, NULL, item, item->order, item->name,
|
||||
text, -1);
|
||||
free(text);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static struct screen *
|
||||
window_buffer_draw(__unused void *modedata, void *itemdata, u_int sx, u_int sy)
|
||||
{
|
||||
struct window_buffer_itemdata *item = itemdata;
|
||||
struct paste_buffer *pb;
|
||||
static struct screen s;
|
||||
struct screen_write_ctx ctx;
|
||||
char line[1024];
|
||||
const char *pdata, *end, *cp;
|
||||
size_t psize, at;
|
||||
u_int i;
|
||||
|
||||
pb = paste_get_name(item->name);
|
||||
if (pb == NULL)
|
||||
return (NULL);
|
||||
|
||||
screen_init(&s, sx, sy, 0);
|
||||
|
||||
screen_write_start(&ctx, NULL, &s);
|
||||
screen_write_clearscreen(&ctx, 8);
|
||||
|
||||
pdata = end = paste_buffer_data (pb, &psize);
|
||||
for (i = 0; i < sy; i++) {
|
||||
at = 0;
|
||||
while (end != pdata + psize && *end != '\n') {
|
||||
if ((sizeof line) - at > 5) {
|
||||
cp = vis(line + at, *end, VIS_TAB|VIS_OCTAL, 0);
|
||||
at = cp - line;
|
||||
}
|
||||
end++;
|
||||
}
|
||||
if (at > sx)
|
||||
at = sx;
|
||||
line[at] = '\0';
|
||||
|
||||
if (*line != '\0') {
|
||||
screen_write_cursormove(&ctx, 0, i);
|
||||
screen_write_puts(&ctx, &grid_default_cell, "%s", line);
|
||||
}
|
||||
|
||||
if (end == pdata + psize)
|
||||
break;
|
||||
end++;
|
||||
}
|
||||
|
||||
screen_write_stop(&ctx);
|
||||
return (&s);
|
||||
}
|
||||
|
||||
static struct screen *
|
||||
window_buffer_init(struct window_pane *wp, __unused struct cmd_find_state *fs,
|
||||
struct args *args)
|
||||
{
|
||||
struct window_buffer_modedata *data;
|
||||
struct screen *s;
|
||||
|
||||
wp->modedata = data = xcalloc(1, sizeof *data);
|
||||
|
||||
if (args == NULL || args->argc == 0)
|
||||
data->command = xstrdup(WINDOW_BUFFER_DEFAULT_COMMAND);
|
||||
else
|
||||
data->command = xstrdup(args->argv[0]);
|
||||
|
||||
data->data = mode_tree_start(wp, window_buffer_build,
|
||||
window_buffer_draw, data, window_buffer_sort_list,
|
||||
nitems(window_buffer_sort_list), &s);
|
||||
|
||||
mode_tree_build(data->data);
|
||||
mode_tree_draw(data->data);
|
||||
|
||||
return (s);
|
||||
}
|
||||
|
||||
static void
|
||||
window_buffer_free(struct window_pane *wp)
|
||||
{
|
||||
struct window_buffer_modedata *data = wp->modedata;
|
||||
u_int i;
|
||||
|
||||
if (data == NULL)
|
||||
return;
|
||||
|
||||
mode_tree_free(data->data);
|
||||
|
||||
for (i = 0; i < data->item_size; i++)
|
||||
window_buffer_free_item(data->item_list[i]);
|
||||
free(data->item_list);
|
||||
|
||||
free(data->command);
|
||||
free(data);
|
||||
}
|
||||
|
||||
static void
|
||||
window_buffer_resize(struct window_pane *wp, u_int sx, u_int sy)
|
||||
{
|
||||
struct window_buffer_modedata *data = wp->modedata;
|
||||
|
||||
mode_tree_resize(data->data, sx, sy);
|
||||
}
|
||||
|
||||
static void
|
||||
window_buffer_do_delete(void* modedata, void *itemdata, __unused key_code key)
|
||||
{
|
||||
struct window_buffer_modedata *data = modedata;
|
||||
struct window_buffer_itemdata *item = itemdata;
|
||||
struct paste_buffer *pb;
|
||||
|
||||
if (item == mode_tree_get_current(data->data))
|
||||
mode_tree_down(data->data, 0);
|
||||
if ((pb = paste_get_name(item->name)) != NULL)
|
||||
paste_free(pb);
|
||||
}
|
||||
|
||||
static void
|
||||
window_buffer_key(struct window_pane *wp, struct client *c,
|
||||
__unused struct session *s, key_code key, struct mouse_event *m)
|
||||
{
|
||||
struct window_buffer_modedata *data = wp->modedata;
|
||||
struct window_buffer_itemdata *item;
|
||||
char *command, *name;
|
||||
int finished;
|
||||
|
||||
/*
|
||||
* t = toggle tag
|
||||
* T = tag none
|
||||
* C-t = tag all
|
||||
* q = exit
|
||||
* O = change sort order
|
||||
*
|
||||
* d = delete buffer
|
||||
* D = delete tagged buffers
|
||||
* Enter = paste buffer
|
||||
*/
|
||||
|
||||
finished = mode_tree_key(data->data, &key, m);
|
||||
switch (key) {
|
||||
case 'd':
|
||||
item = mode_tree_get_current(data->data);
|
||||
window_buffer_do_delete(data, item, key);
|
||||
mode_tree_build(data->data);
|
||||
break;
|
||||
case 'D':
|
||||
mode_tree_each_tagged(data->data, window_buffer_do_delete, key,
|
||||
0);
|
||||
mode_tree_build(data->data);
|
||||
break;
|
||||
case '\r':
|
||||
item = mode_tree_get_current(data->data);
|
||||
command = xstrdup(data->command);
|
||||
name = xstrdup(item->name);
|
||||
window_pane_reset_mode(wp);
|
||||
mode_tree_run_command(c, NULL, command, name);
|
||||
free(name);
|
||||
free(command);
|
||||
return;
|
||||
}
|
||||
if (finished || paste_get_top(NULL) == NULL)
|
||||
window_pane_reset_mode(wp);
|
||||
else {
|
||||
mode_tree_draw(data->data);
|
||||
wp->flags |= PANE_REDRAW;
|
||||
}
|
||||
}
|
1078
window-choose.c
1078
window-choose.c
File diff suppressed because it is too large
Load Diff
335
window-client.c
Normal file
335
window-client.c
Normal file
@ -0,0 +1,335 @@
|
||||
/* $OpenBSD$ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2017 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
|
||||
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "tmux.h"
|
||||
|
||||
static struct screen *window_client_init(struct window_pane *,
|
||||
struct cmd_find_state *, struct args *);
|
||||
static void window_client_free(struct window_pane *);
|
||||
static void window_client_resize(struct window_pane *, u_int,
|
||||
u_int);
|
||||
static void window_client_key(struct window_pane *,
|
||||
struct client *, struct session *, key_code,
|
||||
struct mouse_event *);
|
||||
|
||||
#define WINDOW_CLIENT_DEFAULT_COMMAND "detach-client -t '%%'"
|
||||
|
||||
const struct window_mode window_client_mode = {
|
||||
.name = "client-mode",
|
||||
|
||||
.init = window_client_init,
|
||||
.free = window_client_free,
|
||||
.resize = window_client_resize,
|
||||
.key = window_client_key,
|
||||
};
|
||||
|
||||
enum window_client_sort_type {
|
||||
WINDOW_CLIENT_BY_NAME,
|
||||
WINDOW_CLIENT_BY_CREATION_TIME,
|
||||
WINDOW_CLIENT_BY_ACTIVITY_TIME,
|
||||
};
|
||||
static const char *window_client_sort_list[] = {
|
||||
"name",
|
||||
"creation time",
|
||||
"activity time"
|
||||
};
|
||||
|
||||
struct window_client_itemdata {
|
||||
struct client *c;
|
||||
};
|
||||
|
||||
struct window_client_modedata {
|
||||
struct mode_tree_data *data;
|
||||
char *command;
|
||||
|
||||
struct window_client_itemdata **item_list;
|
||||
u_int item_size;
|
||||
};
|
||||
|
||||
static struct window_client_itemdata *
|
||||
window_client_add_item(struct window_client_modedata *data)
|
||||
{
|
||||
struct window_client_itemdata *item;
|
||||
|
||||
data->item_list = xreallocarray(data->item_list, data->item_size + 1,
|
||||
sizeof *data->item_list);
|
||||
item = data->item_list[data->item_size++] = xcalloc(1, sizeof *item);
|
||||
return (item);
|
||||
}
|
||||
|
||||
static void
|
||||
window_client_free_item(struct window_client_itemdata *item)
|
||||
{
|
||||
server_client_unref(item->c);
|
||||
free(item);
|
||||
}
|
||||
|
||||
static int
|
||||
window_client_cmp_name(const void *a0, const void *b0)
|
||||
{
|
||||
const struct window_client_itemdata *const *a = a0;
|
||||
const struct window_client_itemdata *const *b = b0;
|
||||
|
||||
return (strcmp((*a)->c->name, (*b)->c->name));
|
||||
}
|
||||
|
||||
static int
|
||||
window_client_cmp_creation_time(const void *a0, const void *b0)
|
||||
{
|
||||
const struct window_client_itemdata *const *a = a0;
|
||||
const struct window_client_itemdata *const *b = b0;
|
||||
|
||||
if (timercmp(&(*a)->c->creation_time, &(*b)->c->creation_time, >))
|
||||
return (-1);
|
||||
if (timercmp(&(*a)->c->creation_time, &(*b)->c->creation_time, <))
|
||||
return (1);
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
window_client_cmp_activity_time(const void *a0, const void *b0)
|
||||
{
|
||||
const struct window_client_itemdata *const *a = a0;
|
||||
const struct window_client_itemdata *const *b = b0;
|
||||
|
||||
if (timercmp(&(*a)->c->activity_time, &(*b)->c->activity_time, >))
|
||||
return (-1);
|
||||
if (timercmp(&(*a)->c->activity_time, &(*b)->c->activity_time, <))
|
||||
return (1);
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void
|
||||
window_client_build(void *modedata, u_int sort_type, __unused uint64_t *tag)
|
||||
{
|
||||
struct window_client_modedata *data = modedata;
|
||||
struct window_client_itemdata *item;
|
||||
u_int i;
|
||||
struct client *c;
|
||||
char *tim;
|
||||
char *text;
|
||||
|
||||
for (i = 0; i < data->item_size; i++)
|
||||
window_client_free_item(data->item_list[i]);
|
||||
free(data->item_list);
|
||||
data->item_list = NULL;
|
||||
data->item_size = 0;
|
||||
|
||||
TAILQ_FOREACH(c, &clients, entry) {
|
||||
if (c->session == NULL || (c->flags & (CLIENT_DETACHING)))
|
||||
continue;
|
||||
|
||||
item = window_client_add_item(data);
|
||||
item->c = c;
|
||||
|
||||
c->references++;
|
||||
}
|
||||
|
||||
switch (sort_type) {
|
||||
case WINDOW_CLIENT_BY_NAME:
|
||||
qsort(data->item_list, data->item_size, sizeof *data->item_list,
|
||||
window_client_cmp_name);
|
||||
break;
|
||||
case WINDOW_CLIENT_BY_CREATION_TIME:
|
||||
qsort(data->item_list, data->item_size, sizeof *data->item_list,
|
||||
window_client_cmp_creation_time);
|
||||
break;
|
||||
case WINDOW_CLIENT_BY_ACTIVITY_TIME:
|
||||
qsort(data->item_list, data->item_size, sizeof *data->item_list,
|
||||
window_client_cmp_activity_time);
|
||||
break;
|
||||
}
|
||||
|
||||
for (i = 0; i < data->item_size; i++) {
|
||||
item = data->item_list[i];
|
||||
c = item->c;
|
||||
|
||||
tim = ctime(&c->activity_time.tv_sec);
|
||||
*strchr(tim, '\n') = '\0';
|
||||
|
||||
xasprintf(&text, "session %s (%s)", c->session->name, tim);
|
||||
mode_tree_add(data->data, NULL, item, (uint64_t)c, c->name,
|
||||
text, -1);
|
||||
free(text);
|
||||
}
|
||||
}
|
||||
|
||||
static struct screen *
|
||||
window_client_draw(__unused void *modedata, void *itemdata, u_int sx, u_int sy)
|
||||
{
|
||||
struct window_client_itemdata *item = itemdata;
|
||||
struct client *c = item->c;
|
||||
struct window_pane *wp;
|
||||
static struct screen s;
|
||||
struct screen_write_ctx ctx;
|
||||
|
||||
if (c->session == NULL || (c->flags & (CLIENT_DEAD|CLIENT_DETACHING)))
|
||||
return (NULL);
|
||||
wp = c->session->curw->window->active;
|
||||
|
||||
screen_init(&s, sx, sy, 0);
|
||||
|
||||
screen_write_start(&ctx, NULL, &s);
|
||||
screen_write_clearscreen(&ctx, 8);
|
||||
|
||||
screen_write_preview(&ctx, &wp->base, sx, sy - 3);
|
||||
|
||||
screen_write_cursormove(&ctx, 0, sy - 2);
|
||||
screen_write_line(&ctx, sx, 0, 0);
|
||||
|
||||
screen_write_cursormove(&ctx, 0, sy - 1);
|
||||
if (c->old_status != NULL)
|
||||
screen_write_copy(&ctx, c->old_status, 0, 0, sx, 1, NULL, NULL);
|
||||
else
|
||||
screen_write_copy(&ctx, &c->status, 0, 0, sx, 1, NULL, NULL);
|
||||
|
||||
screen_write_stop(&ctx);
|
||||
return (&s);
|
||||
}
|
||||
|
||||
static struct screen *
|
||||
window_client_init(struct window_pane *wp, __unused struct cmd_find_state *fs,
|
||||
struct args *args)
|
||||
{
|
||||
struct window_client_modedata *data;
|
||||
struct screen *s;
|
||||
|
||||
wp->modedata = data = xcalloc(1, sizeof *data);
|
||||
|
||||
if (args == NULL || args->argc == 0)
|
||||
data->command = xstrdup(WINDOW_CLIENT_DEFAULT_COMMAND);
|
||||
else
|
||||
data->command = xstrdup(args->argv[0]);
|
||||
|
||||
data->data = mode_tree_start(wp, window_client_build,
|
||||
window_client_draw, data, window_client_sort_list,
|
||||
nitems(window_client_sort_list), &s);
|
||||
|
||||
mode_tree_build(data->data);
|
||||
mode_tree_draw(data->data);
|
||||
|
||||
return (s);
|
||||
}
|
||||
|
||||
static void
|
||||
window_client_free(struct window_pane *wp)
|
||||
{
|
||||
struct window_client_modedata *data = wp->modedata;
|
||||
u_int i;
|
||||
|
||||
if (data == NULL)
|
||||
return;
|
||||
|
||||
mode_tree_free(data->data);
|
||||
|
||||
for (i = 0; i < data->item_size; i++)
|
||||
window_client_free_item(data->item_list[i]);
|
||||
free(data->item_list);
|
||||
|
||||
free(data->command);
|
||||
free(data);
|
||||
}
|
||||
|
||||
static void
|
||||
window_client_resize(struct window_pane *wp, u_int sx, u_int sy)
|
||||
{
|
||||
struct window_client_modedata *data = wp->modedata;
|
||||
|
||||
mode_tree_resize(data->data, sx, sy);
|
||||
}
|
||||
|
||||
static void
|
||||
window_client_do_detach(void* modedata, void *itemdata, key_code key)
|
||||
{
|
||||
struct window_client_modedata *data = modedata;
|
||||
struct window_client_itemdata *item = itemdata;
|
||||
|
||||
if (item == mode_tree_get_current(data->data))
|
||||
mode_tree_down(data->data, 0);
|
||||
if (key == 'd' || key == 'D')
|
||||
server_client_detach(item->c, MSG_DETACH);
|
||||
else if (key == 'x' || key == 'X')
|
||||
server_client_detach(item->c, MSG_DETACHKILL);
|
||||
else if (key == 'z' || key == 'Z')
|
||||
server_client_suspend(item->c);
|
||||
}
|
||||
|
||||
static void
|
||||
window_client_key(struct window_pane *wp, struct client *c,
|
||||
__unused struct session *s, key_code key, struct mouse_event *m)
|
||||
{
|
||||
struct window_client_modedata *data = wp->modedata;
|
||||
struct window_client_itemdata *item;
|
||||
char *command, *name;
|
||||
int finished;
|
||||
|
||||
/*
|
||||
* t = toggle tag
|
||||
* T = tag none
|
||||
* C-t = tag all
|
||||
* q = exit
|
||||
* O = change sort order
|
||||
*
|
||||
* d = detach client
|
||||
* D = detach tagged clients
|
||||
* x = detach and kill client
|
||||
* X = detach and kill tagged clients
|
||||
* z = suspend client
|
||||
* Z = suspend tagged clients
|
||||
* Enter = detach client
|
||||
*/
|
||||
|
||||
finished = mode_tree_key(data->data, &key, m);
|
||||
switch (key) {
|
||||
case 'd':
|
||||
case 'x':
|
||||
case 'z':
|
||||
item = mode_tree_get_current(data->data);
|
||||
window_client_do_detach(data, item, key);
|
||||
mode_tree_build(data->data);
|
||||
break;
|
||||
case 'D':
|
||||
case 'X':
|
||||
case 'Z':
|
||||
mode_tree_each_tagged(data->data, window_client_do_detach, key,
|
||||
0);
|
||||
mode_tree_build(data->data);
|
||||
break;
|
||||
case '\r':
|
||||
item = mode_tree_get_current(data->data);
|
||||
command = xstrdup(data->command);
|
||||
name = xstrdup(item->c->ttyname);
|
||||
window_pane_reset_mode(wp);
|
||||
mode_tree_run_command(c, NULL, command, name);
|
||||
free(name);
|
||||
free(command);
|
||||
return;
|
||||
}
|
||||
if (finished || server_client_how_many() == 0)
|
||||
window_pane_reset_mode(wp);
|
||||
else {
|
||||
mode_tree_draw(data->data);
|
||||
wp->flags |= PANE_REDRAW;
|
||||
}
|
||||
}
|
@ -24,7 +24,8 @@
|
||||
|
||||
#include "tmux.h"
|
||||
|
||||
static struct screen *window_clock_init(struct window_pane *);
|
||||
static struct screen *window_clock_init(struct window_pane *,
|
||||
struct cmd_find_state *, struct args *);
|
||||
static void window_clock_free(struct window_pane *);
|
||||
static void window_clock_resize(struct window_pane *, u_int, u_int);
|
||||
static void window_clock_key(struct window_pane *, struct client *,
|
||||
@ -145,7 +146,8 @@ window_clock_timer_callback(__unused int fd, __unused short events, void *arg)
|
||||
}
|
||||
|
||||
static struct screen *
|
||||
window_clock_init(struct window_pane *wp)
|
||||
window_clock_init(struct window_pane *wp, __unused struct cmd_find_state *fs,
|
||||
__unused struct args *args)
|
||||
{
|
||||
struct window_clock_mode_data *data;
|
||||
struct screen *s;
|
||||
|
@ -27,7 +27,8 @@
|
||||
static const char *window_copy_key_table(struct window_pane *);
|
||||
static void window_copy_command(struct window_pane *, struct client *,
|
||||
struct session *, struct args *, struct mouse_event *);
|
||||
static struct screen *window_copy_init(struct window_pane *);
|
||||
static struct screen *window_copy_init(struct window_pane *,
|
||||
struct cmd_find_state *, struct args *);
|
||||
static void window_copy_free(struct window_pane *);
|
||||
static int window_copy_pagedown(struct window_pane *, int);
|
||||
static void window_copy_next_paragraph(struct window_pane *);
|
||||
@ -187,7 +188,8 @@ struct window_copy_mode_data {
|
||||
};
|
||||
|
||||
static struct screen *
|
||||
window_copy_init(struct window_pane *wp)
|
||||
window_copy_init(struct window_pane *wp, __unused struct cmd_find_state *fs,
|
||||
__unused struct args *args)
|
||||
{
|
||||
struct window_copy_mode_data *data;
|
||||
struct screen *s;
|
||||
|
713
window-tree.c
Normal file
713
window-tree.c
Normal file
@ -0,0 +1,713 @@
|
||||
/* $OpenBSD$ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2017 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
|
||||
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "tmux.h"
|
||||
|
||||
static struct screen *window_tree_init(struct window_pane *,
|
||||
struct cmd_find_state *, struct args *);
|
||||
static void window_tree_free(struct window_pane *);
|
||||
static void window_tree_resize(struct window_pane *, u_int, u_int);
|
||||
static void window_tree_key(struct window_pane *,
|
||||
struct client *, struct session *, key_code,
|
||||
struct mouse_event *);
|
||||
|
||||
#define WINDOW_TREE_DEFAULT_COMMAND "switch-client -t '%%'"
|
||||
|
||||
const struct window_mode window_tree_mode = {
|
||||
.name = "tree-mode",
|
||||
|
||||
.init = window_tree_init,
|
||||
.free = window_tree_free,
|
||||
.resize = window_tree_resize,
|
||||
.key = window_tree_key,
|
||||
};
|
||||
|
||||
enum window_tree_sort_type {
|
||||
WINDOW_TREE_BY_INDEX,
|
||||
WINDOW_TREE_BY_NAME,
|
||||
WINDOW_TREE_BY_TIME,
|
||||
};
|
||||
static const char *window_tree_sort_list[] = {
|
||||
"index",
|
||||
"name",
|
||||
"time"
|
||||
};
|
||||
|
||||
enum window_tree_type {
|
||||
WINDOW_TREE_NONE,
|
||||
WINDOW_TREE_SESSION,
|
||||
WINDOW_TREE_WINDOW,
|
||||
WINDOW_TREE_PANE,
|
||||
};
|
||||
|
||||
struct window_tree_itemdata {
|
||||
enum window_tree_type type;
|
||||
int session;
|
||||
int winlink;
|
||||
int pane;
|
||||
};
|
||||
|
||||
struct window_tree_modedata {
|
||||
struct window_pane *wp;
|
||||
int dead;
|
||||
int references;
|
||||
|
||||
struct mode_tree_data *data;
|
||||
char *command;
|
||||
|
||||
struct window_tree_itemdata **item_list;
|
||||
u_int item_size;
|
||||
|
||||
struct client *client;
|
||||
const char *entered;
|
||||
|
||||
char *filter;
|
||||
|
||||
struct cmd_find_state fs;
|
||||
enum window_tree_type type;
|
||||
};
|
||||
|
||||
static void
|
||||
window_tree_pull_item(struct window_tree_itemdata *item, struct session **sp,
|
||||
struct winlink **wlp, struct window_pane **wp)
|
||||
{
|
||||
*wp = NULL;
|
||||
*wlp = NULL;
|
||||
*sp = session_find_by_id(item->session);
|
||||
if (*sp == NULL)
|
||||
return;
|
||||
if (item->type == WINDOW_TREE_SESSION) {
|
||||
*wlp = (*sp)->curw;
|
||||
*wp = (*wlp)->window->active;
|
||||
return;
|
||||
}
|
||||
|
||||
*wlp = winlink_find_by_index(&(*sp)->windows, item->winlink);
|
||||
if (*wlp == NULL) {
|
||||
*sp = NULL;
|
||||
return;
|
||||
}
|
||||
if (item->type == WINDOW_TREE_WINDOW) {
|
||||
*wp = (*wlp)->window->active;
|
||||
return;
|
||||
}
|
||||
|
||||
*wp = window_pane_find_by_id(item->pane);
|
||||
if (!window_has_pane((*wlp)->window, *wp))
|
||||
*wp = NULL;
|
||||
if (*wp == NULL) {
|
||||
*sp = NULL;
|
||||
*wlp = NULL;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static struct window_tree_itemdata *
|
||||
window_tree_add_item(struct window_tree_modedata *data)
|
||||
{
|
||||
struct window_tree_itemdata *item;
|
||||
|
||||
data->item_list = xreallocarray(data->item_list, data->item_size + 1,
|
||||
sizeof *data->item_list);
|
||||
item = data->item_list[data->item_size++] = xcalloc(1, sizeof *item);
|
||||
return (item);
|
||||
}
|
||||
|
||||
static void
|
||||
window_tree_free_item(struct window_tree_itemdata *item)
|
||||
{
|
||||
free(item);
|
||||
}
|
||||
|
||||
static int
|
||||
window_tree_cmp_session_name(const void *a0, const void *b0)
|
||||
{
|
||||
const struct session *const *a = a0;
|
||||
const struct session *const *b = b0;
|
||||
|
||||
return (strcmp((*a)->name, (*b)->name));
|
||||
}
|
||||
|
||||
static int
|
||||
window_tree_cmp_session_time(const void *a0, const void *b0)
|
||||
{
|
||||
const struct session *const *a = a0;
|
||||
const struct session *const *b = b0;
|
||||
|
||||
if (timercmp(&(*a)->activity_time, &(*b)->activity_time, >))
|
||||
return (-1);
|
||||
if (timercmp(&(*a)->activity_time, &(*b)->activity_time, <))
|
||||
return (1);
|
||||
return (strcmp((*a)->name, (*b)->name));
|
||||
}
|
||||
|
||||
static int
|
||||
window_tree_cmp_window_name(const void *a0, const void *b0)
|
||||
{
|
||||
const struct winlink *const *a = a0;
|
||||
const struct winlink *const *b = b0;
|
||||
|
||||
return (strcmp((*a)->window->name, (*b)->window->name));
|
||||
}
|
||||
|
||||
static int
|
||||
window_tree_cmp_window_time(const void *a0, const void *b0)
|
||||
{
|
||||
const struct winlink *const *a = a0;
|
||||
const struct winlink *const *b = b0;
|
||||
|
||||
if (timercmp(&(*a)->window->activity_time,
|
||||
&(*b)->window->activity_time, >))
|
||||
return (-1);
|
||||
if (timercmp(&(*a)->window->activity_time,
|
||||
&(*b)->window->activity_time, <))
|
||||
return (1);
|
||||
return (strcmp((*a)->window->name, (*b)->window->name));
|
||||
}
|
||||
|
||||
static int
|
||||
window_tree_cmp_pane_time(const void *a0, const void *b0)
|
||||
{
|
||||
const struct window_pane *const *a = a0;
|
||||
const struct window_pane *const *b = b0;
|
||||
|
||||
if ((*a)->active_point < (*b)->active_point)
|
||||
return (-1);
|
||||
if ((*a)->active_point > (*b)->active_point)
|
||||
return (1);
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void
|
||||
window_tree_build_pane(struct session *s, struct winlink *wl,
|
||||
struct window_pane *wp, void *modedata, struct mode_tree_item *parent)
|
||||
{
|
||||
struct window_tree_modedata *data = modedata;
|
||||
struct window_tree_itemdata *item;
|
||||
char *name, *text;
|
||||
u_int idx;
|
||||
|
||||
window_pane_index(wp, &idx);
|
||||
|
||||
item = window_tree_add_item(data);
|
||||
item->type = WINDOW_TREE_PANE;
|
||||
item->session = s->id;
|
||||
item->winlink = wl->idx;
|
||||
item->pane = wp->id;
|
||||
|
||||
text = format_single(NULL,
|
||||
"#{pane_current_command} \"#{pane_title}\"",
|
||||
NULL, s, wl, wp);
|
||||
xasprintf(&name, "%u", idx);
|
||||
|
||||
mode_tree_add(data->data, parent, item, (uint64_t)wp, name, text, -1);
|
||||
free(text);
|
||||
free(name);
|
||||
}
|
||||
|
||||
static int
|
||||
window_tree_build_window(struct session *s, struct winlink *wl, void* modedata,
|
||||
u_int sort_type, struct mode_tree_item *parent, int no_filter)
|
||||
{
|
||||
struct window_tree_modedata *data = modedata;
|
||||
struct window_tree_itemdata *item;
|
||||
struct mode_tree_item *mti;
|
||||
char *name, *text, *cp;
|
||||
struct window_pane *wp, **l;
|
||||
u_int n, i;
|
||||
int expanded;
|
||||
|
||||
item = window_tree_add_item(data);
|
||||
item->type = WINDOW_TREE_WINDOW;
|
||||
item->session = s->id;
|
||||
item->winlink = wl->idx;
|
||||
item->pane = -1;
|
||||
|
||||
text = format_single(NULL,
|
||||
"#{window_name}#{window_flags} (#{window_panes} panes)",
|
||||
NULL, s, wl, NULL);
|
||||
xasprintf(&name, "%u", wl->idx);
|
||||
|
||||
if (data->type == WINDOW_TREE_SESSION ||
|
||||
data->type == WINDOW_TREE_WINDOW)
|
||||
expanded = 0;
|
||||
else
|
||||
expanded = 1;
|
||||
mti = mode_tree_add(data->data, parent, item, (uint64_t)wl, name, text,
|
||||
expanded);
|
||||
free(text);
|
||||
free(name);
|
||||
|
||||
l = NULL;
|
||||
n = 0;
|
||||
TAILQ_FOREACH(wp, &wl->window->panes, entry) {
|
||||
if (!no_filter && data->filter != NULL) {
|
||||
cp = format_single(NULL, data->filter, NULL, s, wl, wp);
|
||||
if (!format_true(cp)) {
|
||||
free(cp);
|
||||
continue;
|
||||
}
|
||||
free(cp);
|
||||
}
|
||||
l = xreallocarray(l, n + 1, sizeof *l);
|
||||
l[n++] = wp;
|
||||
}
|
||||
if (n == 0) {
|
||||
window_tree_free_item(item);
|
||||
data->item_size--;
|
||||
mode_tree_remove(data->data, mti);
|
||||
return (0);
|
||||
}
|
||||
|
||||
switch (sort_type) {
|
||||
case WINDOW_TREE_BY_INDEX:
|
||||
break;
|
||||
case WINDOW_TREE_BY_NAME:
|
||||
/* Panes don't have names, so leave in number order. */
|
||||
break;
|
||||
case WINDOW_TREE_BY_TIME:
|
||||
qsort(l, n, sizeof *l, window_tree_cmp_pane_time);
|
||||
break;
|
||||
}
|
||||
|
||||
for (i = 0; i < n; i++)
|
||||
window_tree_build_pane(s, wl, l[i], modedata, mti);
|
||||
free(l);
|
||||
return (1);
|
||||
}
|
||||
|
||||
static void
|
||||
window_tree_build_session(struct session *s, void* modedata,
|
||||
u_int sort_type, int no_filter)
|
||||
{
|
||||
struct window_tree_modedata *data = modedata;
|
||||
struct window_tree_itemdata *item;
|
||||
struct mode_tree_item *mti;
|
||||
char *text;
|
||||
struct winlink *wl, **l;
|
||||
u_int n, i, empty;
|
||||
int expanded;
|
||||
|
||||
item = window_tree_add_item(data);
|
||||
item->type = WINDOW_TREE_SESSION;
|
||||
item->session = s->id;
|
||||
item->winlink = -1;
|
||||
item->pane = -1;
|
||||
|
||||
text = format_single(NULL,
|
||||
"#{session_windows} windows"
|
||||
"#{?session_grouped, (group ,}"
|
||||
"#{session_group}#{?session_grouped,),}"
|
||||
"#{?session_attached, (attached),}",
|
||||
NULL, s, NULL, NULL);
|
||||
|
||||
if (data->type == WINDOW_TREE_SESSION)
|
||||
expanded = 0;
|
||||
else
|
||||
expanded = 1;
|
||||
mti = mode_tree_add(data->data, NULL, item, (uint64_t)s, s->name, text,
|
||||
expanded);
|
||||
free(text);
|
||||
|
||||
l = NULL;
|
||||
n = 0;
|
||||
RB_FOREACH(wl, winlinks, &s->windows) {
|
||||
l = xreallocarray(l, n + 1, sizeof *l);
|
||||
l[n++] = wl;
|
||||
}
|
||||
switch (sort_type) {
|
||||
case WINDOW_TREE_BY_INDEX:
|
||||
break;
|
||||
case WINDOW_TREE_BY_NAME:
|
||||
qsort(l, n, sizeof *l, window_tree_cmp_window_name);
|
||||
break;
|
||||
case WINDOW_TREE_BY_TIME:
|
||||
qsort(l, n, sizeof *l, window_tree_cmp_window_time);
|
||||
break;
|
||||
}
|
||||
|
||||
empty = 0;
|
||||
for (i = 0; i < n; i++) {
|
||||
if (!window_tree_build_window(s, l[i], modedata, sort_type, mti,
|
||||
no_filter))
|
||||
empty++;
|
||||
}
|
||||
if (empty == n) {
|
||||
window_tree_free_item(item);
|
||||
data->item_size--;
|
||||
mode_tree_remove(data->data, mti);
|
||||
}
|
||||
free(l);
|
||||
}
|
||||
|
||||
static void
|
||||
window_tree_build(void *modedata, u_int sort_type, uint64_t *tag)
|
||||
{
|
||||
struct window_tree_modedata *data = modedata;
|
||||
struct session *s, **l;
|
||||
u_int n, i;
|
||||
int no_filter = 0;
|
||||
|
||||
restart:
|
||||
for (i = 0; i < data->item_size; i++)
|
||||
window_tree_free_item(data->item_list[i]);
|
||||
free(data->item_list);
|
||||
data->item_list = NULL;
|
||||
data->item_size = 0;
|
||||
|
||||
l = NULL;
|
||||
n = 0;
|
||||
RB_FOREACH(s, sessions, &sessions) {
|
||||
l = xreallocarray(l, n + 1, sizeof *l);
|
||||
l[n++] = s;
|
||||
}
|
||||
switch (sort_type) {
|
||||
case WINDOW_TREE_BY_INDEX:
|
||||
break;
|
||||
case WINDOW_TREE_BY_NAME:
|
||||
qsort(l, n, sizeof *l, window_tree_cmp_session_name);
|
||||
break;
|
||||
case WINDOW_TREE_BY_TIME:
|
||||
qsort(l, n, sizeof *l, window_tree_cmp_session_time);
|
||||
break;
|
||||
}
|
||||
|
||||
for (i = 0; i < n; i++)
|
||||
window_tree_build_session(l[i], modedata, sort_type, no_filter);
|
||||
free(l);
|
||||
|
||||
if (!no_filter && data->item_size == 0) {
|
||||
no_filter = 1;
|
||||
goto restart;
|
||||
}
|
||||
|
||||
switch (data->type) {
|
||||
case WINDOW_TREE_NONE:
|
||||
break;
|
||||
case WINDOW_TREE_SESSION:
|
||||
*tag = (uint64_t)data->fs.s;
|
||||
break;
|
||||
case WINDOW_TREE_WINDOW:
|
||||
*tag = (uint64_t)data->fs.wl;
|
||||
break;
|
||||
case WINDOW_TREE_PANE:
|
||||
*tag = (uint64_t)data->fs.wp;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static struct screen *
|
||||
window_tree_draw(__unused void *modedata, void *itemdata, u_int sx, u_int sy)
|
||||
{
|
||||
struct window_tree_itemdata *item = itemdata;
|
||||
struct session *sp;
|
||||
struct winlink *wlp;
|
||||
struct window_pane *wp;
|
||||
static struct screen s;
|
||||
struct screen_write_ctx ctx;
|
||||
|
||||
window_tree_pull_item(item, &sp, &wlp, &wp);
|
||||
if (wp == NULL)
|
||||
return (NULL);
|
||||
|
||||
screen_init(&s, sx, sy, 0);
|
||||
|
||||
screen_write_start(&ctx, NULL, &s);
|
||||
|
||||
screen_write_preview(&ctx, &wp->base, sx, sy);
|
||||
|
||||
screen_write_stop(&ctx);
|
||||
return (&s);
|
||||
}
|
||||
|
||||
static struct screen *
|
||||
window_tree_init(struct window_pane *wp, struct cmd_find_state *fs,
|
||||
struct args *args)
|
||||
{
|
||||
struct window_tree_modedata *data;
|
||||
struct screen *s;
|
||||
|
||||
wp->modedata = data = xcalloc(1, sizeof *data);
|
||||
|
||||
if (args_has(args, 's'))
|
||||
data->type = WINDOW_TREE_SESSION;
|
||||
else if (args_has(args, 'w'))
|
||||
data->type = WINDOW_TREE_WINDOW;
|
||||
else
|
||||
data->type = WINDOW_TREE_PANE;
|
||||
memcpy(&data->fs, fs, sizeof data->fs);
|
||||
|
||||
data->wp = wp;
|
||||
data->references = 1;
|
||||
|
||||
if (args_has(args, 'f'))
|
||||
data->filter = xstrdup(args_get(args, 'f'));
|
||||
else
|
||||
data->filter = NULL;
|
||||
|
||||
if (args == NULL || args->argc == 0)
|
||||
data->command = xstrdup(WINDOW_TREE_DEFAULT_COMMAND);
|
||||
else
|
||||
data->command = xstrdup(args->argv[0]);
|
||||
|
||||
data->data = mode_tree_start(wp, window_tree_build,
|
||||
window_tree_draw, data, window_tree_sort_list,
|
||||
nitems(window_tree_sort_list), &s);
|
||||
|
||||
mode_tree_build(data->data);
|
||||
mode_tree_draw(data->data);
|
||||
|
||||
data->type = WINDOW_TREE_NONE;
|
||||
|
||||
return (s);
|
||||
}
|
||||
|
||||
static void
|
||||
window_tree_destroy(struct window_tree_modedata *data)
|
||||
{
|
||||
u_int i;
|
||||
|
||||
if (--data->references != 0)
|
||||
return;
|
||||
|
||||
mode_tree_free(data->data);
|
||||
|
||||
for (i = 0; i < data->item_size; i++)
|
||||
window_tree_free_item(data->item_list[i]);
|
||||
free(data->item_list);
|
||||
|
||||
free(data->filter);
|
||||
|
||||
free(data->command);
|
||||
free(data);
|
||||
}
|
||||
|
||||
static void
|
||||
window_tree_free(struct window_pane *wp)
|
||||
{
|
||||
struct window_tree_modedata *data = wp->modedata;
|
||||
|
||||
if (data == NULL)
|
||||
return;
|
||||
|
||||
data->dead = 1;
|
||||
window_tree_destroy(data);
|
||||
}
|
||||
|
||||
static void
|
||||
window_tree_resize(struct window_pane *wp, u_int sx, u_int sy)
|
||||
{
|
||||
struct window_tree_modedata *data = wp->modedata;
|
||||
|
||||
mode_tree_resize(data->data, sx, sy);
|
||||
}
|
||||
|
||||
static char *
|
||||
window_tree_get_target(struct window_tree_itemdata *item,
|
||||
struct cmd_find_state *fs)
|
||||
{
|
||||
struct session *s;
|
||||
struct winlink *wl;
|
||||
struct window_pane *wp;
|
||||
char *target;
|
||||
|
||||
window_tree_pull_item(item, &s, &wl, &wp);
|
||||
|
||||
target = NULL;
|
||||
switch (item->type) {
|
||||
case WINDOW_TREE_NONE:
|
||||
break;
|
||||
case WINDOW_TREE_SESSION:
|
||||
if (s == NULL)
|
||||
break;
|
||||
xasprintf(&target, "=%s:", s->name);
|
||||
break;
|
||||
case WINDOW_TREE_WINDOW:
|
||||
if (s == NULL || wl == NULL)
|
||||
break;
|
||||
xasprintf(&target, "=%s:%u.", s->name, wl->idx);
|
||||
break;
|
||||
case WINDOW_TREE_PANE:
|
||||
if (s == NULL || wl == NULL || wp == NULL)
|
||||
break;
|
||||
xasprintf(&target, "=%s:%u.%%%u", s->name, wl->idx, wp->id);
|
||||
break;
|
||||
}
|
||||
if (target == NULL)
|
||||
cmd_find_clear_state(fs, 0);
|
||||
else
|
||||
cmd_find_from_winlink_pane(fs, wl, wp);
|
||||
return (target);
|
||||
}
|
||||
|
||||
static void
|
||||
window_tree_command_each(void* modedata, void* itemdata, __unused key_code key)
|
||||
{
|
||||
struct window_tree_modedata *data = modedata;
|
||||
struct window_tree_itemdata *item = itemdata;
|
||||
char *name;
|
||||
struct cmd_find_state fs;
|
||||
|
||||
name = window_tree_get_target(item, &fs);
|
||||
if (name != NULL)
|
||||
mode_tree_run_command(data->client, &fs, data->entered, name);
|
||||
free(name);
|
||||
}
|
||||
|
||||
static enum cmd_retval
|
||||
window_tree_command_done(__unused struct cmdq_item *item, void *modedata)
|
||||
{
|
||||
struct window_tree_modedata *data = modedata;
|
||||
|
||||
if (!data->dead) {
|
||||
mode_tree_build(data->data);
|
||||
mode_tree_draw(data->data);
|
||||
data->wp->flags |= PANE_REDRAW;
|
||||
}
|
||||
window_tree_destroy(data);
|
||||
return (CMD_RETURN_NORMAL);
|
||||
}
|
||||
|
||||
static int
|
||||
window_tree_command_callback(struct client *c, void *modedata, const char *s,
|
||||
__unused int done)
|
||||
{
|
||||
struct window_tree_modedata *data = modedata;
|
||||
|
||||
if (data->dead)
|
||||
return (0);
|
||||
|
||||
data->client = c;
|
||||
data->entered = s;
|
||||
|
||||
mode_tree_each_tagged(data->data, window_tree_command_each, KEYC_NONE,
|
||||
1);
|
||||
|
||||
data->client = NULL;
|
||||
data->entered = NULL;
|
||||
|
||||
data->references++;
|
||||
cmdq_append(c, cmdq_get_callback(window_tree_command_done, data));
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void
|
||||
window_tree_command_free(void *modedata)
|
||||
{
|
||||
struct window_tree_modedata *data = modedata;
|
||||
|
||||
window_tree_destroy(data);
|
||||
}
|
||||
|
||||
static int
|
||||
window_tree_filter_callback(__unused struct client *c, void *modedata,
|
||||
const char *s, __unused int done)
|
||||
{
|
||||
struct window_tree_modedata *data = modedata;
|
||||
|
||||
if (data->dead)
|
||||
return (0);
|
||||
|
||||
if (data->filter != NULL)
|
||||
free(data->filter);
|
||||
if (s == NULL || *s == '\0')
|
||||
data->filter = NULL;
|
||||
else
|
||||
data->filter = xstrdup(s);
|
||||
|
||||
mode_tree_build(data->data);
|
||||
mode_tree_draw(data->data);
|
||||
data->wp->flags |= PANE_REDRAW;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void
|
||||
window_tree_filter_free(void *modedata)
|
||||
{
|
||||
struct window_tree_modedata *data = modedata;
|
||||
|
||||
window_tree_destroy(data);
|
||||
}
|
||||
|
||||
static void
|
||||
window_tree_key(struct window_pane *wp, struct client *c,
|
||||
__unused struct session *s, key_code key, struct mouse_event *m)
|
||||
{
|
||||
struct window_tree_modedata *data = wp->modedata;
|
||||
struct window_tree_itemdata *item;
|
||||
char *command, *name, *prompt;
|
||||
struct cmd_find_state fs;
|
||||
int finished;
|
||||
u_int tagged;
|
||||
|
||||
/*
|
||||
* t = toggle tag
|
||||
* T = tag none
|
||||
* C-t = tag all
|
||||
* q = exit
|
||||
* O = change sort order
|
||||
*
|
||||
* Enter = select item
|
||||
* : = enter command
|
||||
* f = enter filter
|
||||
*/
|
||||
|
||||
finished = mode_tree_key(data->data, &key, m);
|
||||
switch (key) {
|
||||
case 'f':
|
||||
data->references++;
|
||||
status_prompt_set(c, "(filter) ", data->filter,
|
||||
window_tree_filter_callback, window_tree_filter_free, data,
|
||||
PROMPT_NOFORMAT);
|
||||
break;
|
||||
case ':':
|
||||
tagged = mode_tree_count_tagged(data->data);
|
||||
if (tagged != 0)
|
||||
xasprintf(&prompt, "(%u tagged) ", tagged);
|
||||
else
|
||||
xasprintf(&prompt, "(current) ");
|
||||
data->references++;
|
||||
status_prompt_set(c, prompt, "", window_tree_command_callback,
|
||||
window_tree_command_free, data, PROMPT_NOFORMAT);
|
||||
free(prompt);
|
||||
break;
|
||||
case '\r':
|
||||
item = mode_tree_get_current(data->data);
|
||||
command = xstrdup(data->command);
|
||||
name = window_tree_get_target(item, &fs);
|
||||
window_pane_reset_mode(wp);
|
||||
if (name != NULL)
|
||||
mode_tree_run_command(c, &fs, command, name);
|
||||
free(name);
|
||||
free(command);
|
||||
return;
|
||||
}
|
||||
if (finished)
|
||||
window_pane_reset_mode(wp);
|
||||
else {
|
||||
mode_tree_draw(data->data);
|
||||
wp->flags |= PANE_REDRAW;
|
||||
}
|
||||
}
|
35
window.c
35
window.c
@ -800,8 +800,8 @@ window_pane_create(struct window *w, u_int sx, u_int sy, u_int hlimit)
|
||||
wp->xoff = 0;
|
||||
wp->yoff = 0;
|
||||
|
||||
wp->sx = sx;
|
||||
wp->sy = sy;
|
||||
wp->sx = wp->osx = sx;
|
||||
wp->sy = wp->osx = sy;
|
||||
|
||||
wp->pipe_fd = -1;
|
||||
wp->pipe_off = 0;
|
||||
@ -1186,7 +1186,8 @@ window_pane_mode_timer(__unused int fd, __unused short events, void *arg)
|
||||
}
|
||||
|
||||
int
|
||||
window_pane_set_mode(struct window_pane *wp, const struct window_mode *mode)
|
||||
window_pane_set_mode(struct window_pane *wp, const struct window_mode *mode,
|
||||
struct cmd_find_state *fs, struct args *args)
|
||||
{
|
||||
struct screen *s;
|
||||
struct timeval tv = { .tv_sec = 10 };
|
||||
@ -1199,7 +1200,7 @@ window_pane_set_mode(struct window_pane *wp, const struct window_mode *mode)
|
||||
evtimer_set(&wp->modetimer, window_pane_mode_timer, wp);
|
||||
evtimer_add(&wp->modetimer, &tv);
|
||||
|
||||
if ((s = wp->mode->init(wp)) != NULL)
|
||||
if ((s = wp->mode->init(wp, fs, args)) != NULL)
|
||||
wp->screen = s;
|
||||
wp->flags |= (PANE_REDRAW|PANE_CHANGED);
|
||||
|
||||
@ -1306,32 +1307,6 @@ window_pane_search(struct window_pane *wp, const char *searchstr)
|
||||
return (i + 1);
|
||||
}
|
||||
|
||||
char *
|
||||
window_pane_search_old(struct window_pane *wp, const char *searchstr,
|
||||
u_int *lineno)
|
||||
{
|
||||
struct screen *s = &wp->base;
|
||||
char *newsearchstr, *line, *msg;
|
||||
u_int i;
|
||||
|
||||
msg = NULL;
|
||||
xasprintf(&newsearchstr, "*%s*", searchstr);
|
||||
|
||||
for (i = 0; i < screen_size_y(s); i++) {
|
||||
line = grid_view_string_cells(s->grid, 0, i, screen_size_x(s));
|
||||
if (fnmatch(newsearchstr, line, 0) == 0) {
|
||||
msg = line;
|
||||
if (lineno != NULL)
|
||||
*lineno = i;
|
||||
break;
|
||||
}
|
||||
free(line);
|
||||
}
|
||||
|
||||
free(newsearchstr);
|
||||
return (msg);
|
||||
}
|
||||
|
||||
/* Get MRU pane from a list. */
|
||||
static struct window_pane *
|
||||
window_pane_choose_best(struct window_pane **list, u_int size)
|
||||
|
Loading…
Reference in New Issue
Block a user