mirror of
https://github.com/tmux/tmux.git
synced 2025-04-10 11:08:49 +00:00
Merge branch 'master' into 3.2-rc
This commit is contained in:
commit
c2048c5c65
alerts.ccfg.ccmd-choose-tree.ccmd-display-message.ccmd-list-keys.ccmd-queue.ccmd-run-shell.ccontrol-notify.cformat.cgrid-reader.cinput-keys.ckey-string.clog.cmode-tree.cnotify.cscreen.cserver-client.cstatus.ctmux.1tmux.htty-keys.ctty.cwindow-buffer.cwindow-client.cwindow-copy.cwindow-customize.cwindow-tree.c
9
alerts.c
9
alerts.c
@ -314,10 +314,11 @@ alerts_set_message(struct winlink *wl, const char *type, const char *option)
|
||||
tty_putcode(&c->tty, TTYC_BEL);
|
||||
if (visual == VISUAL_OFF)
|
||||
continue;
|
||||
if (c->session->curw == wl)
|
||||
status_message_set(c, -1, 1, "%s in current window", type);
|
||||
else {
|
||||
status_message_set(c, -1, 1, "%s in window %d", type,
|
||||
if (c->session->curw == wl) {
|
||||
status_message_set(c, -1, 1, 0, "%s in current window",
|
||||
type);
|
||||
} else {
|
||||
status_message_set(c, -1, 1, 0, "%s in window %d", type,
|
||||
wl->idx);
|
||||
}
|
||||
}
|
||||
|
20
cfg.c
20
cfg.c
@ -102,6 +102,7 @@ load_cfg(const char *path, struct client *c, struct cmdq_item *item, int flags,
|
||||
struct cmd_parse_input pi;
|
||||
struct cmd_parse_result *pr;
|
||||
struct cmdq_item *new_item0;
|
||||
struct cmdq_state *state;
|
||||
|
||||
if (new_item != NULL)
|
||||
*new_item = NULL;
|
||||
@ -135,12 +136,19 @@ load_cfg(const char *path, struct client *c, struct cmdq_item *item, int flags,
|
||||
return (0);
|
||||
}
|
||||
|
||||
new_item0 = cmdq_get_command(pr->cmdlist, NULL);
|
||||
if (item != NULL)
|
||||
state = cmdq_copy_state(cmdq_get_state(item));
|
||||
else
|
||||
state = cmdq_new_state(NULL, NULL, 0);
|
||||
cmdq_add_format(state, "current_file", "%s", pi.file);
|
||||
|
||||
new_item0 = cmdq_get_command(pr->cmdlist, state);
|
||||
if (item != NULL)
|
||||
new_item0 = cmdq_insert_after(item, new_item0);
|
||||
else
|
||||
new_item0 = cmdq_append(NULL, new_item0);
|
||||
cmd_list_free(pr->cmdlist);
|
||||
cmdq_free_state(state);
|
||||
|
||||
if (new_item != NULL)
|
||||
*new_item = new_item0;
|
||||
@ -155,6 +163,7 @@ load_cfg_from_buffer(const void *buf, size_t len, const char *path,
|
||||
struct cmd_parse_input pi;
|
||||
struct cmd_parse_result *pr;
|
||||
struct cmdq_item *new_item0;
|
||||
struct cmdq_state *state;
|
||||
|
||||
if (new_item != NULL)
|
||||
*new_item = NULL;
|
||||
@ -181,12 +190,19 @@ load_cfg_from_buffer(const void *buf, size_t len, const char *path,
|
||||
return (0);
|
||||
}
|
||||
|
||||
new_item0 = cmdq_get_command(pr->cmdlist, NULL);
|
||||
if (item != NULL)
|
||||
state = cmdq_copy_state(cmdq_get_state(item));
|
||||
else
|
||||
state = cmdq_new_state(NULL, NULL, 0);
|
||||
cmdq_add_format(state, "current_file", "%s", pi.file);
|
||||
|
||||
new_item0 = cmdq_get_command(pr->cmdlist, state);
|
||||
if (item != NULL)
|
||||
new_item0 = cmdq_insert_after(item, new_item0);
|
||||
else
|
||||
new_item0 = cmdq_append(NULL, new_item0);
|
||||
cmd_list_free(pr->cmdlist);
|
||||
cmdq_free_state(state);
|
||||
|
||||
if (new_item != NULL)
|
||||
*new_item = new_item0;
|
||||
|
@ -30,9 +30,9 @@ const struct cmd_entry cmd_choose_tree_entry = {
|
||||
.name = "choose-tree",
|
||||
.alias = NULL,
|
||||
|
||||
.args = { "F:Gf:NO:rst:wZ", 0, 1 },
|
||||
.usage = "[-GNrswZ] [-F format] [-f filter] [-O sort-order] "
|
||||
CMD_TARGET_PANE_USAGE " [template]",
|
||||
.args = { "F:f:GK:NO:rst:wZ", 0, 1 },
|
||||
.usage = "[-GNrswZ] [-F format] [-f filter] [-K key-format] "
|
||||
"[-O sort-order] " CMD_TARGET_PANE_USAGE " [template]",
|
||||
|
||||
.target = { 't', CMD_FIND_PANE, 0 },
|
||||
|
||||
@ -44,9 +44,9 @@ const struct cmd_entry cmd_choose_client_entry = {
|
||||
.name = "choose-client",
|
||||
.alias = NULL,
|
||||
|
||||
.args = { "F:f:NO:rt:Z", 0, 1 },
|
||||
.usage = "[-NrZ] [-F format] [-f filter] [-O sort-order] "
|
||||
CMD_TARGET_PANE_USAGE " [template]",
|
||||
.args = { "F:f:K:NO:rt:Z", 0, 1 },
|
||||
.usage = "[-NrZ] [-F format] [-f filter] [-K key-format] "
|
||||
"[-O sort-order] " CMD_TARGET_PANE_USAGE " [template]",
|
||||
|
||||
.target = { 't', CMD_FIND_PANE, 0 },
|
||||
|
||||
@ -58,9 +58,9 @@ const struct cmd_entry cmd_choose_buffer_entry = {
|
||||
.name = "choose-buffer",
|
||||
.alias = NULL,
|
||||
|
||||
.args = { "F:f:NO:rt:Z", 0, 1 },
|
||||
.usage = "[-NrZ] [-F format] [-f filter] [-O sort-order] "
|
||||
CMD_TARGET_PANE_USAGE " [template]",
|
||||
.args = { "F:f:K:NO:rt:Z", 0, 1 },
|
||||
.usage = "[-NrZ] [-F format] [-f filter] [-K key-format] "
|
||||
"[-O sort-order] " CMD_TARGET_PANE_USAGE " [template]",
|
||||
|
||||
.target = { 't', CMD_FIND_PANE, 0 },
|
||||
|
||||
|
@ -39,11 +39,11 @@ const struct cmd_entry cmd_display_message_entry = {
|
||||
.name = "display-message",
|
||||
.alias = "display",
|
||||
|
||||
.args = { "acd:Ipt:F:v", 0, 1 },
|
||||
.usage = "[-aIpv] [-c target-client] [-d delay] [-F format] "
|
||||
.args = { "acd:INpt:F:v", 0, 1 },
|
||||
.usage = "[-aINpv] [-c target-client] [-d delay] [-F format] "
|
||||
CMD_TARGET_PANE_USAGE " [message]",
|
||||
|
||||
.target = { 't', CMD_FIND_PANE, 0 },
|
||||
.target = { 't', CMD_FIND_PANE, CMD_FIND_CANFAIL },
|
||||
|
||||
.flags = CMD_AFTERHOOK|CMD_CLIENT_CFLAG|CMD_CLIENT_CANFAIL,
|
||||
.exec = cmd_display_message_exec
|
||||
@ -73,6 +73,8 @@ cmd_display_message_exec(struct cmd *self, struct cmdq_item *item)
|
||||
int flags;
|
||||
|
||||
if (args_has(args, 'I')) {
|
||||
if (wp == NULL)
|
||||
return (CMD_RETURN_NORMAL);
|
||||
if (window_pane_start_input(wp, item, &cause) != 0) {
|
||||
cmdq_error(item, "%s", cause);
|
||||
free(cause);
|
||||
@ -109,8 +111,10 @@ cmd_display_message_exec(struct cmd *self, struct cmdq_item *item)
|
||||
*/
|
||||
if (tc != NULL && tc->session == s)
|
||||
c = tc;
|
||||
else
|
||||
else if (s != NULL)
|
||||
c = cmd_find_best_client(s);
|
||||
else
|
||||
c = NULL;
|
||||
if (args_has(args, 'v'))
|
||||
flags = FORMAT_VERBOSE;
|
||||
else
|
||||
@ -124,10 +128,14 @@ cmd_display_message_exec(struct cmd *self, struct cmdq_item *item)
|
||||
}
|
||||
|
||||
msg = format_expand_time(ft, template);
|
||||
if (args_has(args, 'p'))
|
||||
if (cmdq_get_client(item) == NULL)
|
||||
cmdq_error(item, "%s", msg);
|
||||
else if (args_has(args, 'p'))
|
||||
cmdq_print(item, "%s", msg);
|
||||
else if (tc != NULL)
|
||||
status_message_set(tc, delay, 0, "%s", msg);
|
||||
else if (tc != NULL) {
|
||||
status_message_set(tc, delay, 0, args_has(args, 'N'), "%s",
|
||||
msg);
|
||||
}
|
||||
free(msg);
|
||||
|
||||
format_free(ft);
|
||||
|
@ -113,9 +113,10 @@ cmd_list_keys_print_notes(struct cmdq_item *item, struct args *args,
|
||||
else
|
||||
note = xstrdup(bd->note);
|
||||
tmp = utf8_padcstr(key, keywidth + 1);
|
||||
if (args_has(args, '1') && tc != NULL)
|
||||
status_message_set(tc, -1, 1, "%s%s%s", prefix, tmp, note);
|
||||
else
|
||||
if (args_has(args, '1') && tc != NULL) {
|
||||
status_message_set(tc, -1, 1, 0, "%s%s%s", prefix, tmp,
|
||||
note);
|
||||
} else
|
||||
cmdq_print(item, "%s%s%s", prefix, tmp, note);
|
||||
free(tmp);
|
||||
free(note);
|
||||
|
@ -276,7 +276,7 @@ cmdq_merge_formats(struct cmdq_item *item, struct format_tree *ft)
|
||||
const struct cmd_entry *entry;
|
||||
|
||||
if (item->cmd != NULL) {
|
||||
entry = cmd_get_entry (item->cmd);
|
||||
entry = cmd_get_entry(item->cmd);
|
||||
format_add(ft, "command", "%s", entry->name);
|
||||
}
|
||||
if (item->state->formats != NULL)
|
||||
@ -862,7 +862,7 @@ cmdq_error(struct cmdq_item *item, const char *fmt, ...)
|
||||
c->retval = 1;
|
||||
} else {
|
||||
*msg = toupper((u_char) *msg);
|
||||
status_message_set(c, -1, 1, "%s", msg);
|
||||
status_message_set(c, -1, 1, 0, "%s", msg);
|
||||
}
|
||||
|
||||
free(msg);
|
||||
|
@ -20,6 +20,7 @@
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
#include <ctype.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
@ -190,8 +191,12 @@ cmd_run_shell_timer(__unused int fd, __unused short events, void* arg)
|
||||
&error);
|
||||
}
|
||||
if (status == CMD_PARSE_ERROR) {
|
||||
cmdq_error(cdata->item, "%s", error);
|
||||
free(error);
|
||||
if (cdata->item == NULL) {
|
||||
*error = toupper((u_char)*error);
|
||||
status_message_set(c, -1, 1, 0, "%s", error);
|
||||
} else
|
||||
cmdq_error(cdata->item, "%s", error);
|
||||
free(error);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -171,6 +171,17 @@ control_notify_client_session_changed(struct client *cc)
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
control_notify_client_detached(struct client *cc)
|
||||
{
|
||||
struct client *c;
|
||||
|
||||
TAILQ_FOREACH(c, &clients, entry) {
|
||||
if (CONTROL_SHOULD_NOTIFY_CLIENT(c))
|
||||
control_write(c, "%%client-detached %s", cc->name);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
control_notify_session_renamed(struct session *s)
|
||||
{
|
||||
|
34
format.c
34
format.c
@ -100,6 +100,7 @@ format_job_cmp(struct format_job *fj1, struct format_job *fj2)
|
||||
#define FORMAT_QUOTE_STYLE 0x2000
|
||||
#define FORMAT_WINDOW_NAME 0x4000
|
||||
#define FORMAT_SESSION_NAME 0x8000
|
||||
#define FORMAT_CHARACTER 0x10000
|
||||
|
||||
/* Limit on recursion. */
|
||||
#define FORMAT_LOOP_LIMIT 10
|
||||
@ -3522,7 +3523,7 @@ format_build_modifiers(struct format_expand_state *es, const char **s,
|
||||
|
||||
/*
|
||||
* Modifiers are a ; separated list of the forms:
|
||||
* l,m,C,b,d,n,t,w,q,E,T,S,W,P,<,>
|
||||
* l,m,C,a,b,d,n,t,w,q,E,T,S,W,P,<,>
|
||||
* =a
|
||||
* =/a
|
||||
* =/a/
|
||||
@ -3539,7 +3540,7 @@ format_build_modifiers(struct format_expand_state *es, const char **s,
|
||||
cp++;
|
||||
|
||||
/* Check single character modifiers with no arguments. */
|
||||
if (strchr("lbdnwETSWP<>", cp[0]) != NULL &&
|
||||
if (strchr("labdnwETSWP<>", cp[0]) != NULL &&
|
||||
format_is_end(cp[1])) {
|
||||
format_add_modifier(&list, count, cp, 1, NULL, 0);
|
||||
cp++;
|
||||
@ -3956,7 +3957,7 @@ format_replace_expression(struct format_modifier *mexp,
|
||||
mright = (long long)mright;
|
||||
}
|
||||
format_log(es, "expression left side is: %.*f", prec, mleft);
|
||||
format_log(es, "expression right side is: %.*f", prec, mright);
|
||||
format_log(es, "expression right side is: %.*f", prec, mright);
|
||||
|
||||
switch (operator) {
|
||||
case ADD:
|
||||
@ -4016,10 +4017,10 @@ format_replace(struct format_expand_state *es, const char *key, size_t keylen,
|
||||
{
|
||||
struct format_tree *ft = es->ft;
|
||||
struct window_pane *wp = ft->wp;
|
||||
const char *errptr, *copy, *cp, *marker = NULL;
|
||||
const char *errstr, *copy, *cp, *marker = NULL;
|
||||
const char *time_format = NULL;
|
||||
char *copy0, *condition, *found, *new;
|
||||
char *value, *left, *right;
|
||||
char *value, *left, *right, c;
|
||||
size_t valuelen;
|
||||
int modifiers = 0, limit = 0, width = 0;
|
||||
int j;
|
||||
@ -4063,8 +4064,8 @@ format_replace(struct format_expand_state *es, const char *key, size_t keylen,
|
||||
if (fm->argc < 1)
|
||||
break;
|
||||
limit = strtonum(fm->argv[0], INT_MIN, INT_MAX,
|
||||
&errptr);
|
||||
if (errptr != NULL)
|
||||
&errstr);
|
||||
if (errstr != NULL)
|
||||
limit = 0;
|
||||
if (fm->argc >= 2 && fm->argv[1] != NULL)
|
||||
marker = fm->argv[1];
|
||||
@ -4073,8 +4074,8 @@ format_replace(struct format_expand_state *es, const char *key, size_t keylen,
|
||||
if (fm->argc < 1)
|
||||
break;
|
||||
width = strtonum(fm->argv[0], INT_MIN, INT_MAX,
|
||||
&errptr);
|
||||
if (errptr != NULL)
|
||||
&errstr);
|
||||
if (errstr != NULL)
|
||||
width = 0;
|
||||
break;
|
||||
case 'w':
|
||||
@ -4088,6 +4089,9 @@ format_replace(struct format_expand_state *es, const char *key, size_t keylen,
|
||||
case 'l':
|
||||
modifiers |= FORMAT_LITERAL;
|
||||
break;
|
||||
case 'a':
|
||||
modifiers |= FORMAT_CHARACTER;
|
||||
break;
|
||||
case 'b':
|
||||
modifiers |= FORMAT_BASENAME;
|
||||
break;
|
||||
@ -4154,6 +4158,18 @@ format_replace(struct format_expand_state *es, const char *key, size_t keylen,
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Is this a character? */
|
||||
if (modifiers & FORMAT_CHARACTER) {
|
||||
new = format_expand1(es, copy);
|
||||
c = strtonum(new, 32, 126, &errstr);
|
||||
if (errstr != NULL)
|
||||
value = xstrdup("");
|
||||
else
|
||||
xasprintf(&value, "%c", c);
|
||||
free (new);
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Is this a loop, comparison or condition? */
|
||||
if (modifiers & FORMAT_SESSIONS) {
|
||||
value = format_loop_sessions(es, copy);
|
||||
|
@ -71,7 +71,7 @@ grid_reader_cursor_right(struct grid_reader *gr, int wrap, int all)
|
||||
|
||||
/* Move cursor back one position. */
|
||||
void
|
||||
grid_reader_cursor_left(struct grid_reader *gr)
|
||||
grid_reader_cursor_left(struct grid_reader *gr, int wrap)
|
||||
{
|
||||
struct grid_cell gc;
|
||||
|
||||
@ -81,7 +81,9 @@ grid_reader_cursor_left(struct grid_reader *gr)
|
||||
break;
|
||||
gr->cx--;
|
||||
}
|
||||
if (gr->cx == 0 && gr->cy > 0) {
|
||||
if (gr->cx == 0 && gr->cy > 0 &&
|
||||
(wrap ||
|
||||
grid_get_line(gr->gd, gr->cy - 1)->flags & GRID_LINE_WRAPPED)) {
|
||||
grid_reader_cursor_up(gr);
|
||||
grid_reader_cursor_end_of_line(gr, 0, 0);
|
||||
} else if (gr->cx > 0)
|
||||
@ -363,3 +365,25 @@ grid_reader_cursor_jump_back(struct grid_reader *gr, const struct utf8_data *jc)
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Jump back to the first non-blank character of the line. */
|
||||
void
|
||||
grid_reader_cursor_back_to_indentation(struct grid_reader *gr)
|
||||
{
|
||||
struct grid_cell gc;
|
||||
u_int px, py, xx, yy;
|
||||
|
||||
yy = gr->gd->hsize + gr->gd->sy - 1;
|
||||
grid_reader_cursor_start_of_line(gr, 1);
|
||||
|
||||
for (py = gr->cy; py <= yy; py++) {
|
||||
xx = grid_line_length(gr->gd, py);
|
||||
for (px = 0; px < xx; px++) {
|
||||
grid_get_cell(gr->gd, px, py, &gc);
|
||||
if (gc.data.size != 1 || *gc.data.data != ' ')
|
||||
break;
|
||||
}
|
||||
if (~grid_get_line(gr->gd, py)->flags & GRID_LINE_WRAPPED)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
26
input-keys.c
26
input-keys.c
@ -428,6 +428,14 @@ input_key_pane(struct window_pane *wp, key_code key, struct mouse_event *m)
|
||||
return (input_key(wp->screen, wp->event, key));
|
||||
}
|
||||
|
||||
static void
|
||||
input_key_write(const char *from, struct bufferevent *bev, const char *data,
|
||||
size_t size)
|
||||
{
|
||||
log_debug("%s: %.*s", from, (int)size, data);
|
||||
bufferevent_write(bev, data, size);
|
||||
}
|
||||
|
||||
/* Translate a key code into an output key sequence. */
|
||||
int
|
||||
input_key(struct screen *s, struct bufferevent *bev, key_code key)
|
||||
@ -444,7 +452,7 @@ input_key(struct screen *s, struct bufferevent *bev, key_code key)
|
||||
/* Literal keys go as themselves (can't be more than eight bits). */
|
||||
if (key & KEYC_LITERAL) {
|
||||
ud.data[0] = (u_char)key;
|
||||
bufferevent_write(bev, &ud.data[0], 1);
|
||||
input_key_write(__func__, bev, &ud.data[0], 1);
|
||||
return (0);
|
||||
}
|
||||
|
||||
@ -463,16 +471,16 @@ input_key(struct screen *s, struct bufferevent *bev, key_code key)
|
||||
justkey = (key & ~(KEYC_META|KEYC_IMPLIED_META));
|
||||
if (justkey <= 0x7f) {
|
||||
if (key & KEYC_META)
|
||||
bufferevent_write(bev, "\033", 1);
|
||||
input_key_write(__func__, bev, "\033", 1);
|
||||
ud.data[0] = justkey;
|
||||
bufferevent_write(bev, &ud.data[0], 1);
|
||||
input_key_write(__func__, bev, &ud.data[0], 1);
|
||||
return (0);
|
||||
}
|
||||
if (justkey > 0x7f && justkey < KEYC_BASE) {
|
||||
if (key & KEYC_META)
|
||||
bufferevent_write(bev, "\033", 1);
|
||||
input_key_write(__func__, bev, "\033", 1);
|
||||
utf8_to_data(justkey, &ud);
|
||||
bufferevent_write(bev, ud.data, ud.size);
|
||||
input_key_write(__func__, bev, ud.data, ud.size);
|
||||
return (0);
|
||||
}
|
||||
|
||||
@ -494,8 +502,8 @@ input_key(struct screen *s, struct bufferevent *bev, key_code key)
|
||||
if (ike != NULL) {
|
||||
log_debug("found key 0x%llx: \"%s\"", key, ike->data);
|
||||
if ((key & KEYC_META) && (~key & KEYC_IMPLIED_META))
|
||||
bufferevent_write(bev, "\033", 1);
|
||||
bufferevent_write(bev, ike->data, strlen(ike->data));
|
||||
input_key_write(__func__, bev, "\033", 1);
|
||||
input_key_write(__func__, bev, ike->data, strlen(ike->data));
|
||||
return (0);
|
||||
}
|
||||
|
||||
@ -560,7 +568,7 @@ input_key(struct screen *s, struct bufferevent *bev, key_code key)
|
||||
goto missing;
|
||||
}
|
||||
xsnprintf(tmp, sizeof tmp, "\033[%llu;%cu", outkey, modifier);
|
||||
bufferevent_write(bev, tmp, strlen(tmp));
|
||||
input_key_write(__func__, bev, tmp, strlen(tmp));
|
||||
return (0);
|
||||
|
||||
missing:
|
||||
@ -656,5 +664,5 @@ input_key_mouse(struct window_pane *wp, struct mouse_event *m)
|
||||
if (!input_key_get_mouse(s, m, x, y, &buf, &len))
|
||||
return;
|
||||
log_debug("writing mouse %.*s to %%%u", (int)len, buf, wp->id);
|
||||
bufferevent_write(wp->event, buf, len);
|
||||
input_key_write(__func__, wp->event, buf, len);
|
||||
}
|
||||
|
17
key-string.c
17
key-string.c
@ -45,9 +45,9 @@ static const struct {
|
||||
{ "F11", KEYC_F11|KEYC_IMPLIED_META },
|
||||
{ "F12", KEYC_F12|KEYC_IMPLIED_META },
|
||||
{ "IC", KEYC_IC|KEYC_IMPLIED_META },
|
||||
{ "Insert", KEYC_IC|KEYC_IMPLIED_META },
|
||||
{ "Insert", KEYC_IC|KEYC_IMPLIED_META },
|
||||
{ "DC", KEYC_DC|KEYC_IMPLIED_META },
|
||||
{ "Delete", KEYC_DC|KEYC_IMPLIED_META },
|
||||
{ "Delete", KEYC_DC|KEYC_IMPLIED_META },
|
||||
{ "Home", KEYC_HOME|KEYC_IMPLIED_META },
|
||||
{ "End", KEYC_END|KEYC_IMPLIED_META },
|
||||
{ "NPage", KEYC_NPAGE|KEYC_IMPLIED_META },
|
||||
@ -70,7 +70,7 @@ static const struct {
|
||||
{ "Right", KEYC_RIGHT|KEYC_CURSOR|KEYC_IMPLIED_META },
|
||||
|
||||
/* Numeric keypad. */
|
||||
{ "KP/", KEYC_KP_SLASH|KEYC_KEYPAD },
|
||||
{ "KP/", KEYC_KP_SLASH|KEYC_KEYPAD },
|
||||
{ "KP*", KEYC_KP_STAR|KEYC_KEYPAD },
|
||||
{ "KP-", KEYC_KP_MINUS|KEYC_KEYPAD },
|
||||
{ "KP7", KEYC_KP_SEVEN|KEYC_KEYPAD },
|
||||
@ -164,7 +164,7 @@ key_string_get_modifiers(const char **string)
|
||||
key_code
|
||||
key_string_lookup_string(const char *string)
|
||||
{
|
||||
static const char *other = "!#()+,-.0123456789:;<=>'\r\t";
|
||||
static const char *other = "!#()+,-.0123456789:;<=>'\r\t\177";
|
||||
key_code key, modifiers;
|
||||
u_int u, i;
|
||||
struct utf8_data ud, *udp;
|
||||
@ -181,8 +181,8 @@ key_string_lookup_string(const char *string)
|
||||
|
||||
/* Is this a hexadecimal value? */
|
||||
if (string[0] == '0' && string[1] == 'x') {
|
||||
if (sscanf(string + 2, "%x", &u) != 1)
|
||||
return (KEYC_UNKNOWN);
|
||||
if (sscanf(string + 2, "%x", &u) != 1)
|
||||
return (KEYC_UNKNOWN);
|
||||
mlen = wctomb(m, u);
|
||||
if (mlen <= 0 || mlen > MB_LEN_MAX)
|
||||
return (KEYC_UNKNOWN);
|
||||
@ -238,11 +238,12 @@ key_string_lookup_string(const char *string)
|
||||
}
|
||||
|
||||
/* Convert the standard control keys. */
|
||||
if (key < KEYC_BASE && (modifiers & KEYC_CTRL) && !strchr(other, key)) {
|
||||
if (key < KEYC_BASE && (modifiers & KEYC_CTRL) &&
|
||||
strchr(other, key) == NULL) {
|
||||
if (key >= 97 && key <= 122)
|
||||
key -= 96;
|
||||
else if (key >= 64 && key <= 95)
|
||||
key -= 64;
|
||||
key -= 64;
|
||||
else if (key == 32)
|
||||
key = 0;
|
||||
else if (key == 63)
|
||||
|
13
log.c
13
log.c
@ -110,15 +110,16 @@ log_vwrite(const char *msg, va_list ap)
|
||||
return;
|
||||
|
||||
if (vasprintf(&fmt, msg, ap) == -1)
|
||||
exit(1);
|
||||
if (stravis(&out, fmt, VIS_OCTAL|VIS_CSTYLE|VIS_TAB|VIS_NL) == -1)
|
||||
exit(1);
|
||||
return;
|
||||
if (stravis(&out, fmt, VIS_OCTAL|VIS_CSTYLE|VIS_TAB|VIS_NL) == -1) {
|
||||
free(fmt);
|
||||
return;
|
||||
}
|
||||
|
||||
gettimeofday(&tv, NULL);
|
||||
if (fprintf(log_file, "%lld.%06d %s\n", (long long)tv.tv_sec,
|
||||
(int)tv.tv_usec, out) == -1)
|
||||
exit(1);
|
||||
fflush(log_file);
|
||||
(int)tv.tv_usec, out) != -1)
|
||||
fflush(log_file);
|
||||
|
||||
free(out);
|
||||
free(fmt);
|
||||
|
70
mode-tree.c
70
mode-tree.c
@ -46,6 +46,7 @@ struct mode_tree_data {
|
||||
mode_tree_search_cb searchcb;
|
||||
mode_tree_menu_cb menucb;
|
||||
mode_tree_height_cb heightcb;
|
||||
mode_tree_key_cb keycb;
|
||||
|
||||
struct mode_tree_list children;
|
||||
struct mode_tree_list saved;
|
||||
@ -74,6 +75,10 @@ struct mode_tree_item {
|
||||
void *itemdata;
|
||||
u_int line;
|
||||
|
||||
key_code key;
|
||||
const char *keystr;
|
||||
size_t keylen;
|
||||
|
||||
uint64_t tag;
|
||||
const char *name;
|
||||
const char *text;
|
||||
@ -135,6 +140,7 @@ mode_tree_free_item(struct mode_tree_item *mti)
|
||||
|
||||
free((void *)mti->name);
|
||||
free((void *)mti->text);
|
||||
free((void *)mti->keystr);
|
||||
|
||||
free(mti);
|
||||
}
|
||||
@ -193,6 +199,26 @@ mode_tree_build_lines(struct mode_tree_data *mtd,
|
||||
flat = 0;
|
||||
if (mti->expanded)
|
||||
mode_tree_build_lines(mtd, &mti->children, depth + 1);
|
||||
|
||||
if (mtd->keycb != NULL) {
|
||||
mti->key = mtd->keycb(mtd->modedata, mti->itemdata,
|
||||
mti->line);
|
||||
if (mti->key == KEYC_UNKNOWN)
|
||||
mti->key = KEYC_NONE;
|
||||
} else if (mti->line < 10)
|
||||
mti->key = '0' + mti->line;
|
||||
else if (mti->line < 36)
|
||||
mti->key = KEYC_META|('a' + mti->line - 10);
|
||||
else
|
||||
mti->key = KEYC_NONE;
|
||||
if (mti->key != KEYC_NONE) {
|
||||
mti->keystr = xstrdup(key_string_lookup_key(mti->key,
|
||||
0));
|
||||
mti->keylen = strlen(mti->keystr);
|
||||
} else {
|
||||
mti->keystr = NULL;
|
||||
mti->keylen = 0;
|
||||
}
|
||||
}
|
||||
TAILQ_FOREACH(mti, mtl, entry) {
|
||||
for (i = 0; i < mtd->line_size; i++) {
|
||||
@ -363,7 +389,7 @@ struct mode_tree_data *
|
||||
mode_tree_start(struct window_pane *wp, struct args *args,
|
||||
mode_tree_build_cb buildcb, mode_tree_draw_cb drawcb,
|
||||
mode_tree_search_cb searchcb, mode_tree_menu_cb menucb,
|
||||
mode_tree_height_cb heightcb, void *modedata,
|
||||
mode_tree_height_cb heightcb, mode_tree_key_cb keycb, void *modedata,
|
||||
const struct menu_item *menu, const char **sort_list, u_int sort_size,
|
||||
struct screen **s)
|
||||
{
|
||||
@ -402,6 +428,7 @@ mode_tree_start(struct window_pane *wp, struct args *args,
|
||||
mtd->searchcb = searchcb;
|
||||
mtd->menucb = menucb;
|
||||
mtd->heightcb = heightcb;
|
||||
mtd->keycb = keycb;
|
||||
|
||||
TAILQ_INIT(&mtd->children);
|
||||
|
||||
@ -596,10 +623,10 @@ mode_tree_draw(struct mode_tree_data *mtd)
|
||||
struct screen_write_ctx ctx;
|
||||
struct grid_cell gc0, gc;
|
||||
u_int w, h, i, j, sy, box_x, box_y, width;
|
||||
char *text, *start, key[7];
|
||||
char *text, *start, *key;
|
||||
const char *tag, *symbol;
|
||||
size_t size, n;
|
||||
int keylen;
|
||||
int keylen, pad;
|
||||
|
||||
if (mtd->line_size == 0)
|
||||
return;
|
||||
@ -614,28 +641,30 @@ mode_tree_draw(struct mode_tree_data *mtd)
|
||||
screen_write_start(&ctx, s);
|
||||
screen_write_clearscreen(&ctx, 8);
|
||||
|
||||
if (mtd->line_size > 10)
|
||||
keylen = 6;
|
||||
else
|
||||
keylen = 4;
|
||||
keylen = 0;
|
||||
for (i = 0; i < mtd->line_size; i++) {
|
||||
mti = mtd->line_list[i].item;
|
||||
if (mti->key == KEYC_NONE)
|
||||
continue;
|
||||
if ((int)mti->keylen + 3 > keylen)
|
||||
keylen = mti->keylen + 3;
|
||||
}
|
||||
|
||||
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, 0);
|
||||
|
||||
if (i < 10)
|
||||
snprintf(key, sizeof key, "(%c) ", '0' + i);
|
||||
else if (i < 36)
|
||||
snprintf(key, sizeof key, "(M-%c)", 'a' + (i - 10));
|
||||
pad = keylen - 2 - mti->keylen;
|
||||
if (mti->key != KEYC_NONE)
|
||||
xasprintf(&key, "(%s)%*s", mti->keystr, pad, "");
|
||||
else
|
||||
*key = '\0';
|
||||
key = xstrdup("");
|
||||
|
||||
if (line->flat)
|
||||
symbol = "";
|
||||
@ -698,6 +727,7 @@ mode_tree_draw(struct mode_tree_data *mtd)
|
||||
}
|
||||
}
|
||||
free(text);
|
||||
free(key);
|
||||
|
||||
if (mti->tagged) {
|
||||
gc.attr ^= GRID_ATTR_BRIGHT;
|
||||
@ -951,7 +981,6 @@ mode_tree_key(struct mode_tree_data *mtd, struct client *c, key_code *key,
|
||||
struct mode_tree_item *current, *parent, *mti;
|
||||
u_int i, x, y;
|
||||
int choice;
|
||||
key_code tmp;
|
||||
|
||||
if (KEYC_IS_MOUSE(*key) && m != NULL) {
|
||||
if (cmd_mouse_at(mtd->wp, m, &x, &y, 0) != 0) {
|
||||
@ -993,12 +1022,11 @@ mode_tree_key(struct mode_tree_data *mtd, struct client *c, key_code *key,
|
||||
current = line->item;
|
||||
|
||||
choice = -1;
|
||||
if (*key >= '0' && *key <= '9')
|
||||
choice = (*key) - '0';
|
||||
else if (((*key) & KEYC_MASK_MODIFIERS) == KEYC_META) {
|
||||
tmp = (*key) & KEYC_MASK_KEY;
|
||||
if (tmp >= 'a' && tmp <= 'z')
|
||||
choice = 10 + (tmp - 'a');
|
||||
for (i = 0; i < mtd->line_size; i++) {
|
||||
if (*key == mtd->line_list[i].item->key) {
|
||||
choice = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (choice != -1) {
|
||||
if ((u_int)choice > mtd->line_size - 1) {
|
||||
@ -1176,7 +1204,7 @@ mode_tree_run_command(struct client *c, struct cmd_find_state *fs,
|
||||
if (status == CMD_PARSE_ERROR) {
|
||||
if (c != NULL) {
|
||||
*error = toupper((u_char)*error);
|
||||
status_message_set(c, -1, 1, "%s", error);
|
||||
status_message_set(c, -1, 1, 0, "%s", error);
|
||||
}
|
||||
free(error);
|
||||
}
|
||||
|
2
notify.c
2
notify.c
@ -125,6 +125,8 @@ notify_callback(struct cmdq_item *item, void *data)
|
||||
control_notify_window_renamed(ne->window);
|
||||
if (strcmp(ne->name, "client-session-changed") == 0)
|
||||
control_notify_client_session_changed(ne->client);
|
||||
if (strcmp(ne->name, "client-detached") == 0)
|
||||
control_notify_client_detached(ne->client);
|
||||
if (strcmp(ne->name, "session-renamed") == 0)
|
||||
control_notify_session_renamed(ne->session);
|
||||
if (strcmp(ne->name, "session-created") == 0)
|
||||
|
4
screen.c
4
screen.c
@ -153,8 +153,10 @@ screen_reset_tabs(struct screen *s)
|
||||
void
|
||||
screen_set_cursor_style(struct screen *s, u_int style)
|
||||
{
|
||||
if (style <= 6)
|
||||
if (style <= 6) {
|
||||
s->cstyle = style;
|
||||
s->mode &= ~MODE_BLINKING;
|
||||
}
|
||||
}
|
||||
|
||||
/* Set screen cursor colour. */
|
||||
|
@ -296,6 +296,9 @@ server_client_lost(struct client *c)
|
||||
TAILQ_REMOVE(&clients, c, entry);
|
||||
log_debug("lost client %p", c);
|
||||
|
||||
if (c->flags & CLIENT_ATTACHED)
|
||||
notify_client("client-detached", c);
|
||||
|
||||
if (c->flags & CLIENT_CONTROL)
|
||||
control_stop(c);
|
||||
if (c->flags & CLIENT_TERMINAL)
|
||||
@ -1305,7 +1308,11 @@ server_client_handle_key(struct client *c, struct key_event *event)
|
||||
* immediately rather than queued.
|
||||
*/
|
||||
if (~c->flags & CLIENT_READONLY) {
|
||||
status_message_clear(c);
|
||||
if (c->message_string != NULL) {
|
||||
if (c->message_ignore_keys)
|
||||
return (0);
|
||||
status_message_clear(c);
|
||||
}
|
||||
if (c->overlay_key != NULL) {
|
||||
switch (c->overlay_key(c, event)) {
|
||||
case 0:
|
||||
@ -1766,9 +1773,6 @@ server_client_check_exit(struct client *c)
|
||||
if (EVBUFFER_LENGTH(cf->buffer) != 0)
|
||||
return;
|
||||
}
|
||||
|
||||
if (c->flags & CLIENT_ATTACHED)
|
||||
notify_client("client-detached", c);
|
||||
c->flags |= CLIENT_EXITED;
|
||||
|
||||
switch (c->exit_type) {
|
||||
|
7
status.c
7
status.c
@ -424,7 +424,7 @@ status_redraw(struct client *c)
|
||||
/* Set a status line message. */
|
||||
void
|
||||
status_message_set(struct client *c, int delay, int ignore_styles,
|
||||
const char *fmt, ...)
|
||||
int ignore_keys, const char *fmt, ...)
|
||||
{
|
||||
struct timeval tv;
|
||||
va_list ap;
|
||||
@ -433,7 +433,6 @@ status_message_set(struct client *c, int delay, int ignore_styles,
|
||||
status_push_screen(c);
|
||||
|
||||
va_start(ap, fmt);
|
||||
c->message_ignore_styles = ignore_styles;
|
||||
xvasprintf(&c->message_string, fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
@ -456,6 +455,10 @@ status_message_set(struct client *c, int delay, int ignore_styles,
|
||||
evtimer_add(&c->message_timer, &tv);
|
||||
}
|
||||
|
||||
if (delay != 0)
|
||||
c->message_ignore_keys = ignore_keys;
|
||||
c->message_ignore_styles = ignore_styles;
|
||||
|
||||
c->tty.flags |= (TTY_NOCURSOR|TTY_FREEZE);
|
||||
c->flags |= CLIENT_REDRAWSTATUS;
|
||||
}
|
||||
|
45
tmux.1
45
tmux.1
@ -1985,12 +1985,17 @@ The default is to capture only the visible contents of the pane.
|
||||
.Op Fl NrZ
|
||||
.Op Fl F Ar format
|
||||
.Op Fl f Ar filter
|
||||
.Op Fl K Ar key-format
|
||||
.Op Fl O Ar sort-order
|
||||
.Op Fl t Ar target-pane
|
||||
.Op Ar template
|
||||
.Xc
|
||||
Put a pane into client mode, allowing a client to be selected interactively from
|
||||
a list.
|
||||
Each client is shown on one line.
|
||||
A shortcut key is shown on the left in brackets allowing for immediate choice,
|
||||
or the list may be navigated and an item chosen or otherwise manipulated using
|
||||
the keys below.
|
||||
.Fl Z
|
||||
zooms the pane.
|
||||
The following keys may be used in client mode:
|
||||
@ -2040,7 +2045,9 @@ specifies an initial filter: the filter is a format - if it evaluates to zero,
|
||||
the item in the list is not shown, otherwise it is shown.
|
||||
If a filter would lead to an empty list, it is ignored.
|
||||
.Fl F
|
||||
specifies the format for each item in the list.
|
||||
specifies the format for each item in the list and
|
||||
.Fl K
|
||||
a format for each shortcut key; both are evaluated once for each line.
|
||||
.Fl N
|
||||
starts without the preview.
|
||||
This command works only if at least one client is attached.
|
||||
@ -2049,12 +2056,17 @@ This command works only if at least one client is attached.
|
||||
.Op Fl GNrswZ
|
||||
.Op Fl F Ar format
|
||||
.Op Fl f Ar filter
|
||||
.Op Fl K Ar key-format
|
||||
.Op Fl O Ar sort-order
|
||||
.Op Fl t Ar target-pane
|
||||
.Op Ar template
|
||||
.Xc
|
||||
Put a pane into tree mode, where a session, window or pane may be chosen
|
||||
interactively from a list.
|
||||
interactively from a tree.
|
||||
Each session, window or pane is shown on one line.
|
||||
A shortcut key is shown on the left in brackets allowing for immediate choice,
|
||||
or the tree may be navigated and an item chosen or otherwise manipulated using
|
||||
the keys below.
|
||||
.Fl s
|
||||
starts with sessions collapsed and
|
||||
.Fl w
|
||||
@ -2113,7 +2125,9 @@ specifies an initial filter: the filter is a format - if it evaluates to zero,
|
||||
the item in the list is not shown, otherwise it is shown.
|
||||
If a filter would lead to an empty list, it is ignored.
|
||||
.Fl F
|
||||
specifies the format for each item in the tree.
|
||||
specifies the format for each item in the tree and
|
||||
.Fl K
|
||||
a format for each shortcut key; both are evaluated once for each line.
|
||||
.Fl N
|
||||
starts without the preview.
|
||||
.Fl G
|
||||
@ -3149,8 +3163,8 @@ The appearance and behaviour of
|
||||
may be modified by changing the value of various options.
|
||||
There are four types of option:
|
||||
.Em server options ,
|
||||
.Em session options
|
||||
.Em window options
|
||||
.Em session options ,
|
||||
.Em window options ,
|
||||
and
|
||||
.Em pane options .
|
||||
.Pp
|
||||
@ -4663,6 +4677,11 @@ For example,
|
||||
multiplies 5.5 by 3 for a result with four decimal places and
|
||||
.Ql #{e|%%:7,3}
|
||||
returns the modulus of 7 and 3.
|
||||
.Ql a
|
||||
replaces a numeric argument by its ASCII equivalent, so
|
||||
.Ql #{a:98}
|
||||
results in
|
||||
.Ql b .
|
||||
.Pp
|
||||
A limit may be placed on the length of the resultant string by prefixing it
|
||||
by an
|
||||
@ -4859,6 +4878,7 @@ The following variables are available, where appropriate:
|
||||
.It Li "copy_cursor_word" Ta "" Ta "Word under cursor in copy mode"
|
||||
.It Li "copy_cursor_x" Ta "" Ta "Cursor X position in copy mode"
|
||||
.It Li "copy_cursor_y" Ta "" Ta "Cursor Y position in copy mode"
|
||||
.It Li "current_file" Ta "" Ta "Current configuration file"
|
||||
.It Li "cursor_character" Ta "" Ta "Character at cursor in pane"
|
||||
.It Li "cursor_flag" Ta "" Ta "Pane cursor flag"
|
||||
.It Li "cursor_x" Ta "" Ta "Cursor X position in pane"
|
||||
@ -5545,7 +5565,7 @@ The following keys are also available:
|
||||
.It Li "q" Ta "Exit menu"
|
||||
.El
|
||||
.It Xo Ic display-message
|
||||
.Op Fl aIpv
|
||||
.Op Fl aINpv
|
||||
.Op Fl c Ar target-client
|
||||
.Op Fl d Ar delay
|
||||
.Op Fl t Ar target-pane
|
||||
@ -5565,6 +5585,8 @@ If
|
||||
is not given, the
|
||||
.Ic message-time
|
||||
option is used; a delay of zero waits for a key press.
|
||||
.Ql N
|
||||
ignores key presses and closes only after the delay expires.
|
||||
The format of
|
||||
.Ar message
|
||||
is described in the
|
||||
@ -5680,12 +5702,17 @@ The buffer commands are as follows:
|
||||
.Op Fl NZr
|
||||
.Op Fl F Ar format
|
||||
.Op Fl f Ar filter
|
||||
.Op Fl K Ar key-format
|
||||
.Op Fl O Ar sort-order
|
||||
.Op Fl t Ar target-pane
|
||||
.Op Ar template
|
||||
.Xc
|
||||
Put a pane into buffer mode, where a buffer may be chosen interactively from
|
||||
a list.
|
||||
Each buffer is shown on one line.
|
||||
A shortcut key is shown on the left in brackets allowing for immediate choice,
|
||||
or the list may be navigated and an item chosen or otherwise manipulated using
|
||||
the keys below.
|
||||
.Fl Z
|
||||
zooms the pane.
|
||||
The following keys may be used in buffer mode:
|
||||
@ -5733,7 +5760,9 @@ specifies an initial filter: the filter is a format - if it evaluates to zero,
|
||||
the item in the list is not shown, otherwise it is shown.
|
||||
If a filter would lead to an empty list, it is ignored.
|
||||
.Fl F
|
||||
specifies the format for each item in the list.
|
||||
specifies the format for each item in the list and
|
||||
.Fl K
|
||||
a format for each shortcut key; both are evaluated once for each line.
|
||||
.Fl N
|
||||
starts without the preview.
|
||||
This command works only if at least one client is attached.
|
||||
@ -6107,6 +6136,8 @@ A notification will never occur inside an output block.
|
||||
.Pp
|
||||
The following notifications are defined:
|
||||
.Bl -tag -width Ds
|
||||
.It Ic %client-detached Ar client
|
||||
The client has detached.
|
||||
.It Ic %client-session-changed Ar client session-id name
|
||||
The client is now attached to the session with ID
|
||||
.Ar session-id ,
|
||||
|
10
tmux.h
10
tmux.h
@ -1688,6 +1688,7 @@ struct client {
|
||||
|
||||
uint64_t redraw_panes;
|
||||
|
||||
int message_ignore_keys;
|
||||
int message_ignore_styles;
|
||||
char *message_string;
|
||||
struct event message_timer;
|
||||
@ -2491,7 +2492,7 @@ struct style_range *status_get_range(struct client *, u_int, u_int);
|
||||
void status_init(struct client *);
|
||||
void status_free(struct client *);
|
||||
int status_redraw(struct client *);
|
||||
void status_message_set(struct client *, int, int, const char *, ...);
|
||||
void status_message_set(struct client *, int, int, int, const char *, ...);
|
||||
void status_message_clear(struct client *);
|
||||
int status_message_redraw(struct client *);
|
||||
void status_prompt_set(struct client *, struct cmd_find_state *,
|
||||
@ -2584,7 +2585,7 @@ void grid_reader_get_cursor(struct grid_reader *, u_int *, u_int *);
|
||||
u_int grid_reader_line_length(struct grid_reader *);
|
||||
int grid_reader_in_set(struct grid_reader *, const char *);
|
||||
void grid_reader_cursor_right(struct grid_reader *, int, int);
|
||||
void grid_reader_cursor_left(struct grid_reader *);
|
||||
void grid_reader_cursor_left(struct grid_reader *, int);
|
||||
void grid_reader_cursor_down(struct grid_reader *);
|
||||
void grid_reader_cursor_up(struct grid_reader *);
|
||||
void grid_reader_cursor_start_of_line(struct grid_reader *, int);
|
||||
@ -2597,6 +2598,7 @@ int grid_reader_cursor_jump(struct grid_reader *,
|
||||
const struct utf8_data *);
|
||||
int grid_reader_cursor_jump_back(struct grid_reader *,
|
||||
const struct utf8_data *);
|
||||
void grid_reader_cursor_back_to_indentation(struct grid_reader *);
|
||||
|
||||
/* grid-view.c */
|
||||
void grid_view_get_cell(struct grid *, u_int, u_int, struct grid_cell *);
|
||||
@ -2855,6 +2857,7 @@ typedef void (*mode_tree_draw_cb)(void *, void *, struct screen_write_ctx *,
|
||||
typedef int (*mode_tree_search_cb)(void *, void *, const char *);
|
||||
typedef void (*mode_tree_menu_cb)(void *, struct client *, key_code);
|
||||
typedef u_int (*mode_tree_height_cb)(void *, u_int);
|
||||
typedef key_code (*mode_tree_key_cb)(void *, void *, u_int);
|
||||
typedef void (*mode_tree_each_cb)(void *, void *, struct client *, key_code);
|
||||
u_int mode_tree_count_tagged(struct mode_tree_data *);
|
||||
void *mode_tree_get_current(struct mode_tree_data *);
|
||||
@ -2869,7 +2872,7 @@ 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 *, struct args *,
|
||||
mode_tree_build_cb, mode_tree_draw_cb, mode_tree_search_cb,
|
||||
mode_tree_menu_cb, mode_tree_height_cb, void *,
|
||||
mode_tree_menu_cb, mode_tree_height_cb, mode_tree_key_cb, void *,
|
||||
const struct menu_item *, const char **, u_int, struct screen **);
|
||||
void mode_tree_zoom(struct mode_tree_data *, struct args *);
|
||||
void mode_tree_build(struct mode_tree_data *);
|
||||
@ -2946,6 +2949,7 @@ void control_notify_window_unlinked(struct session *, struct window *);
|
||||
void control_notify_window_linked(struct session *, struct window *);
|
||||
void control_notify_window_renamed(struct window *);
|
||||
void control_notify_client_session_changed(struct client *);
|
||||
void control_notify_client_detached(struct client *);
|
||||
void control_notify_session_renamed(struct session *);
|
||||
void control_notify_session_created(struct session *);
|
||||
void control_notify_session_closed(struct session *);
|
||||
|
61
tty-keys.c
61
tty-keys.c
@ -61,7 +61,7 @@ static int tty_keys_extended_device_attributes(struct tty *, const char *,
|
||||
/* Default raw keys. */
|
||||
struct tty_default_key_raw {
|
||||
const char *string;
|
||||
key_code key;
|
||||
key_code key;
|
||||
};
|
||||
static const struct tty_default_key_raw tty_default_raw_keys[] = {
|
||||
/* Application escape. */
|
||||
@ -262,7 +262,7 @@ static const key_code tty_default_xterm_modifiers[] = {
|
||||
*/
|
||||
struct tty_default_key_code {
|
||||
enum tty_code_code code;
|
||||
key_code key;
|
||||
key_code key;
|
||||
};
|
||||
static const struct tty_default_key_code tty_default_code_keys[] = {
|
||||
/* Function keys. */
|
||||
@ -420,7 +420,7 @@ tty_keys_add(struct tty *tty, const char *s, key_code key)
|
||||
{
|
||||
struct tty_key *tk;
|
||||
size_t size;
|
||||
const char *keystr;
|
||||
const char *keystr;
|
||||
|
||||
keystr = key_string_lookup_key(key, 1);
|
||||
if ((tk = tty_keys_find(tty, s, strlen(s), &size)) == NULL) {
|
||||
@ -477,7 +477,7 @@ tty_keys_build(struct tty *tty)
|
||||
const struct tty_default_key_raw *tdkr;
|
||||
const struct tty_default_key_xterm *tdkx;
|
||||
const struct tty_default_key_code *tdkc;
|
||||
u_int i, j;
|
||||
u_int i, j;
|
||||
const char *s;
|
||||
struct options_entry *o;
|
||||
struct options_array_item *a;
|
||||
@ -869,6 +869,9 @@ tty_keys_extended_key(struct tty *tty, const char *buf, size_t len,
|
||||
size_t end;
|
||||
u_int number, modifiers;
|
||||
char tmp[64];
|
||||
cc_t bspace;
|
||||
key_code nkey;
|
||||
key_code onlykey;
|
||||
|
||||
*size = 0;
|
||||
|
||||
@ -911,38 +914,68 @@ tty_keys_extended_key(struct tty *tty, const char *buf, size_t len,
|
||||
}
|
||||
*size = end + 1;
|
||||
|
||||
/* Store the key and modifiers. */
|
||||
*key = number;
|
||||
/* Store the key. */
|
||||
bspace = tty->tio.c_cc[VERASE];
|
||||
if (bspace != _POSIX_VDISABLE && number == bspace)
|
||||
nkey = KEYC_BSPACE;
|
||||
else
|
||||
nkey = number;
|
||||
|
||||
/* Update the modifiers. */
|
||||
switch (modifiers) {
|
||||
case 2:
|
||||
(*key) |= KEYC_SHIFT;
|
||||
nkey |= KEYC_SHIFT;
|
||||
break;
|
||||
case 3:
|
||||
(*key) |= (KEYC_META|KEYC_IMPLIED_META);
|
||||
nkey |= (KEYC_META|KEYC_IMPLIED_META);
|
||||
break;
|
||||
case 4:
|
||||
(*key) |= (KEYC_SHIFT|KEYC_META|KEYC_IMPLIED_META);
|
||||
nkey |= (KEYC_SHIFT|KEYC_META|KEYC_IMPLIED_META);
|
||||
break;
|
||||
case 5:
|
||||
(*key) |= KEYC_CTRL;
|
||||
nkey |= KEYC_CTRL;
|
||||
break;
|
||||
case 6:
|
||||
(*key) |= (KEYC_SHIFT|KEYC_CTRL);
|
||||
nkey |= (KEYC_SHIFT|KEYC_CTRL);
|
||||
break;
|
||||
case 7:
|
||||
(*key) |= (KEYC_META|KEYC_CTRL);
|
||||
nkey |= (KEYC_META|KEYC_CTRL);
|
||||
break;
|
||||
case 8:
|
||||
(*key) |= (KEYC_SHIFT|KEYC_META|KEYC_IMPLIED_META|KEYC_CTRL);
|
||||
nkey |= (KEYC_SHIFT|KEYC_META|KEYC_IMPLIED_META|KEYC_CTRL);
|
||||
break;
|
||||
default:
|
||||
*key = KEYC_NONE;
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* Don't allow both KEYC_CTRL and as an implied modifier. Also convert
|
||||
* C-X into C-x and so on.
|
||||
*/
|
||||
if (nkey & KEYC_CTRL){
|
||||
onlykey = (nkey & KEYC_MASK_KEY);
|
||||
if (onlykey < 32)
|
||||
onlykey = (nkey & ~KEYC_CTRL);
|
||||
else {
|
||||
if (onlykey >= 97 && onlykey <= 122)
|
||||
onlykey -= 96;
|
||||
else if (onlykey >= 64 && onlykey <= 95)
|
||||
onlykey -= 64;
|
||||
else if (onlykey == 32)
|
||||
onlykey = 0;
|
||||
else if (onlykey == 63)
|
||||
onlykey = 127;
|
||||
onlykey |= ((nkey & KEYC_MASK_MODIFIERS) & ~KEYC_CTRL);
|
||||
}
|
||||
nkey = onlykey;
|
||||
}
|
||||
|
||||
if (log_get_level() != 0) {
|
||||
log_debug("%s: extended key %.*s is %llx (%s)", c->name,
|
||||
(int)*size, buf, *key, key_string_lookup_key(*key, 1));
|
||||
(int)*size, buf, nkey, key_string_lookup_key(nkey, 1));
|
||||
}
|
||||
*key = nkey;
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
38
tty.c
38
tty.c
@ -670,19 +670,10 @@ tty_update_mode(struct tty *tty, int mode, struct screen *s)
|
||||
if (changed != 0)
|
||||
log_debug("%s: update mode %x to %x", c->name, tty->mode, mode);
|
||||
|
||||
if (changed & MODE_BLINKING) {
|
||||
if (tty_term_has(tty->term, TTYC_CVVIS))
|
||||
tty_putcode(tty, TTYC_CVVIS);
|
||||
else
|
||||
tty_putcode(tty, TTYC_CNORM);
|
||||
changed |= MODE_CURSOR;
|
||||
}
|
||||
if (changed & MODE_CURSOR) {
|
||||
if (mode & MODE_CURSOR)
|
||||
tty_putcode(tty, TTYC_CNORM);
|
||||
else
|
||||
tty_putcode(tty, TTYC_CIVIS);
|
||||
}
|
||||
/*
|
||||
* The cursor blinking flag can be reset by setting the cursor style, so
|
||||
* set the style first.
|
||||
*/
|
||||
if (s != NULL && tty->cstyle != s->cstyle) {
|
||||
if (tty_term_has(tty->term, TTYC_SS)) {
|
||||
if (s->cstyle == 0 && tty_term_has(tty->term, TTYC_SE))
|
||||
@ -691,7 +682,28 @@ tty_update_mode(struct tty *tty, int mode, struct screen *s)
|
||||
tty_putcode1(tty, TTYC_SS, s->cstyle);
|
||||
}
|
||||
tty->cstyle = s->cstyle;
|
||||
changed |= (MODE_CURSOR|MODE_BLINKING);
|
||||
}
|
||||
|
||||
/*
|
||||
* Cursor invisible (RM ?25) overrides cursor blinking (SM ?12 or RM
|
||||
* 34), and we need to be careful not send cnorm after cvvis since it
|
||||
* can undo it.
|
||||
*/
|
||||
if (changed & (MODE_CURSOR|MODE_BLINKING)) {
|
||||
log_debug("%s: cursor %s, %sblinking", __func__,
|
||||
(mode & MODE_CURSOR) ? "on" : "off",
|
||||
(mode & MODE_BLINKING) ? "" : "not ");
|
||||
if (~mode & MODE_CURSOR)
|
||||
tty_putcode(tty, TTYC_CIVIS);
|
||||
else if (mode & MODE_BLINKING) {
|
||||
tty_putcode(tty, TTYC_CNORM);
|
||||
if (tty_term_has(tty->term, TTYC_CVVIS))
|
||||
tty_putcode(tty, TTYC_CVVIS);
|
||||
} else
|
||||
tty_putcode(tty, TTYC_CNORM);
|
||||
}
|
||||
|
||||
if ((changed & ALL_MOUSE_MODES) &&
|
||||
tty_term_has(tty->term, TTYC_KMOUS)) {
|
||||
/*
|
||||
|
@ -41,6 +41,17 @@ static void window_buffer_key(struct window_mode_entry *,
|
||||
#define WINDOW_BUFFER_DEFAULT_FORMAT \
|
||||
"#{t/p:buffer_created}: #{buffer_sample}"
|
||||
|
||||
#define WINDOW_BUFFER_DEFAULT_KEY_FORMAT \
|
||||
"#{?#{e|<:#{line},10}," \
|
||||
"#{line}" \
|
||||
"," \
|
||||
"#{?#{e|<:#{line},36}," \
|
||||
"M-#{a:#{e|+:97,#{e|-:#{line},10}}}" \
|
||||
"," \
|
||||
"" \
|
||||
"}" \
|
||||
"}"
|
||||
|
||||
static const struct menu_item window_buffer_menu_items[] = {
|
||||
{ "Paste", 'p', NULL },
|
||||
{ "Paste Tagged", 'P', NULL },
|
||||
@ -93,6 +104,7 @@ struct window_buffer_modedata {
|
||||
struct mode_tree_data *data;
|
||||
char *command;
|
||||
char *format;
|
||||
char *key_format;
|
||||
|
||||
struct window_buffer_itemdata **item_list;
|
||||
u_int item_size;
|
||||
@ -232,7 +244,8 @@ window_buffer_draw(__unused void *modedata, void *itemdata,
|
||||
while (end != pdata + psize && *end != '\n')
|
||||
end++;
|
||||
buf = xreallocarray(buf, 4, end - start + 1);
|
||||
utf8_strvis(buf, start, end - start, VIS_OCTAL|VIS_CSTYLE|VIS_TAB);
|
||||
utf8_strvis(buf, start, end - start,
|
||||
VIS_OCTAL|VIS_CSTYLE|VIS_TAB);
|
||||
if (*buf != '\0') {
|
||||
screen_write_cursormove(ctx, cx, cy + i, 0);
|
||||
screen_write_nputs(ctx, sx, &grid_default_cell, "%s",
|
||||
@ -275,6 +288,41 @@ window_buffer_menu(void *modedata, struct client *c, key_code key)
|
||||
window_buffer_key(wme, c, NULL, NULL, key, NULL);
|
||||
}
|
||||
|
||||
static key_code
|
||||
window_buffer_get_key(void *modedata, void *itemdata, u_int line)
|
||||
{
|
||||
struct window_buffer_modedata *data = modedata;
|
||||
struct window_buffer_itemdata *item = itemdata;
|
||||
struct format_tree *ft;
|
||||
struct session *s;
|
||||
struct winlink *wl;
|
||||
struct window_pane *wp;
|
||||
struct paste_buffer *pb;
|
||||
char *expanded;
|
||||
key_code key;
|
||||
|
||||
if (cmd_find_valid_state(&data->fs)) {
|
||||
s = data->fs.s;
|
||||
wl = data->fs.wl;
|
||||
wp = data->fs.wp;
|
||||
}
|
||||
pb = paste_get_name(item->name);
|
||||
if (pb == NULL)
|
||||
return KEYC_NONE;
|
||||
|
||||
ft = format_create(NULL, NULL, FORMAT_NONE, 0);
|
||||
format_defaults(ft, NULL, NULL, 0, NULL);
|
||||
format_defaults(ft, NULL, s, wl, wp);
|
||||
format_defaults_paste_buffer(ft, pb);
|
||||
format_add(ft, "line", "%u", line);
|
||||
|
||||
expanded = format_expand(ft, data->key_format);
|
||||
key = key_string_lookup_string(expanded);
|
||||
free(expanded);
|
||||
format_free(ft);
|
||||
return key;
|
||||
}
|
||||
|
||||
static struct screen *
|
||||
window_buffer_init(struct window_mode_entry *wme, struct cmd_find_state *fs,
|
||||
struct args *args)
|
||||
@ -291,6 +339,10 @@ window_buffer_init(struct window_mode_entry *wme, struct cmd_find_state *fs,
|
||||
data->format = xstrdup(WINDOW_BUFFER_DEFAULT_FORMAT);
|
||||
else
|
||||
data->format = xstrdup(args_get(args, 'F'));
|
||||
if (args == NULL || !args_has(args, 'K'))
|
||||
data->key_format = xstrdup(WINDOW_BUFFER_DEFAULT_KEY_FORMAT);
|
||||
else
|
||||
data->key_format = xstrdup(args_get(args, 'K'));
|
||||
if (args == NULL || args->argc == 0)
|
||||
data->command = xstrdup(WINDOW_BUFFER_DEFAULT_COMMAND);
|
||||
else
|
||||
@ -298,8 +350,8 @@ window_buffer_init(struct window_mode_entry *wme, struct cmd_find_state *fs,
|
||||
|
||||
data->data = mode_tree_start(wp, args, window_buffer_build,
|
||||
window_buffer_draw, window_buffer_search, window_buffer_menu, NULL,
|
||||
data, window_buffer_menu_items, window_buffer_sort_list,
|
||||
nitems(window_buffer_sort_list), &s);
|
||||
window_buffer_get_key, data, window_buffer_menu_items,
|
||||
window_buffer_sort_list, nitems(window_buffer_sort_list), &s);
|
||||
mode_tree_zoom(data->data, args);
|
||||
|
||||
mode_tree_build(data->data);
|
||||
@ -324,6 +376,7 @@ window_buffer_free(struct window_mode_entry *wme)
|
||||
free(data->item_list);
|
||||
|
||||
free(data->format);
|
||||
free(data->key_format);
|
||||
free(data->command);
|
||||
|
||||
free(data);
|
||||
|
@ -40,6 +40,17 @@ static void window_client_key(struct window_mode_entry *,
|
||||
#define WINDOW_CLIENT_DEFAULT_FORMAT \
|
||||
"#{t/p:client_activity}: session #{session_name}"
|
||||
|
||||
#define WINDOW_CLIENT_DEFAULT_KEY_FORMAT \
|
||||
"#{?#{e|<:#{line},10}," \
|
||||
"#{line}" \
|
||||
"," \
|
||||
"#{?#{e|<:#{line},36}," \
|
||||
"M-#{a:#{e|+:97,#{e|-:#{line},10}}}" \
|
||||
"," \
|
||||
"" \
|
||||
"}" \
|
||||
"}"
|
||||
|
||||
static const struct menu_item window_client_menu_items[] = {
|
||||
{ "Detach", 'd', NULL },
|
||||
{ "Detach Tagged", 'D', NULL },
|
||||
@ -87,6 +98,7 @@ struct window_client_modedata {
|
||||
|
||||
struct mode_tree_data *data;
|
||||
char *format;
|
||||
char *key_format;
|
||||
char *command;
|
||||
|
||||
struct window_client_itemdata **item_list;
|
||||
@ -252,6 +264,26 @@ window_client_menu(void *modedata, struct client *c, key_code key)
|
||||
window_client_key(wme, c, NULL, NULL, key, NULL);
|
||||
}
|
||||
|
||||
static key_code
|
||||
window_client_get_key(void *modedata, void *itemdata, u_int line)
|
||||
{
|
||||
struct window_client_modedata *data = modedata;
|
||||
struct window_client_itemdata *item = itemdata;
|
||||
struct format_tree *ft;
|
||||
char *expanded;
|
||||
key_code key;
|
||||
|
||||
ft = format_create(NULL, NULL, FORMAT_NONE, 0);
|
||||
format_defaults(ft, item->c, NULL, 0, NULL);
|
||||
format_add(ft, "line", "%u", line);
|
||||
|
||||
expanded = format_expand(ft, data->key_format);
|
||||
key = key_string_lookup_string(expanded);
|
||||
free(expanded);
|
||||
format_free(ft);
|
||||
return key;
|
||||
}
|
||||
|
||||
static struct screen *
|
||||
window_client_init(struct window_mode_entry *wme,
|
||||
__unused struct cmd_find_state *fs, struct args *args)
|
||||
@ -267,15 +299,19 @@ window_client_init(struct window_mode_entry *wme,
|
||||
data->format = xstrdup(WINDOW_CLIENT_DEFAULT_FORMAT);
|
||||
else
|
||||
data->format = xstrdup(args_get(args, 'F'));
|
||||
if (args == NULL || !args_has(args, 'K'))
|
||||
data->key_format = xstrdup(WINDOW_CLIENT_DEFAULT_KEY_FORMAT);
|
||||
else
|
||||
data->key_format = xstrdup(args_get(args, 'K'));
|
||||
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, args, window_client_build,
|
||||
window_client_draw, NULL, window_client_menu, NULL, data,
|
||||
window_client_menu_items, window_client_sort_list,
|
||||
nitems(window_client_sort_list), &s);
|
||||
window_client_draw, NULL, window_client_menu, NULL,
|
||||
window_client_get_key, data, window_client_menu_items,
|
||||
window_client_sort_list, nitems(window_client_sort_list), &s);
|
||||
mode_tree_zoom(data->data, args);
|
||||
|
||||
mode_tree_build(data->data);
|
||||
@ -300,6 +336,7 @@ window_client_free(struct window_mode_entry *wme)
|
||||
free(data->item_list);
|
||||
|
||||
free(data->format);
|
||||
free(data->key_format);
|
||||
free(data->command);
|
||||
|
||||
free(data);
|
||||
|
257
window-copy.c
257
window-copy.c
@ -64,6 +64,8 @@ static int window_copy_search_rl(struct grid *, struct grid *, u_int *,
|
||||
static int window_copy_last_regex(struct grid *, u_int, u_int, u_int,
|
||||
u_int, u_int *, u_int *, const char *, const regex_t *,
|
||||
int);
|
||||
static int window_copy_search_mark_at(struct window_copy_mode_data *,
|
||||
u_int, u_int, u_int *);
|
||||
static char *window_copy_stringify(struct grid *, u_int, u_int, u_int,
|
||||
char *, u_int *);
|
||||
static void window_copy_cstrtocellpos(struct grid *, u_int, u_int *,
|
||||
@ -71,16 +73,15 @@ static void window_copy_cstrtocellpos(struct grid *, u_int, u_int *,
|
||||
static int window_copy_search_marks(struct window_mode_entry *,
|
||||
struct screen *, int, int);
|
||||
static void window_copy_clear_marks(struct window_mode_entry *);
|
||||
static void window_copy_move_left(struct screen *, u_int *, u_int *, int);
|
||||
static int window_copy_is_lowercase(const char *);
|
||||
static void window_copy_search_back_overlap(struct grid *, regex_t *,
|
||||
u_int *, u_int *, u_int *, u_int);
|
||||
static int window_copy_search_jump(struct window_mode_entry *,
|
||||
struct grid *, struct grid *, u_int, u_int, u_int, int, int,
|
||||
int, int, u_int *);
|
||||
static int window_copy_search(struct window_mode_entry *, int, int, int);
|
||||
static int window_copy_search_up(struct window_mode_entry *, int, int);
|
||||
static int window_copy_search_down(struct window_mode_entry *, int, int);
|
||||
int, int);
|
||||
static int window_copy_search(struct window_mode_entry *, int, int);
|
||||
static int window_copy_search_up(struct window_mode_entry *, int);
|
||||
static int window_copy_search_down(struct window_mode_entry *, int);
|
||||
static void window_copy_goto_line(struct window_mode_entry *, const char *);
|
||||
static void window_copy_update_cursor(struct window_mode_entry *, u_int,
|
||||
u_int);
|
||||
@ -275,6 +276,7 @@ struct window_copy_mode_data {
|
||||
int showmark;
|
||||
|
||||
int searchtype;
|
||||
int searchdirection;
|
||||
int searchregex;
|
||||
char *searchstr;
|
||||
u_char *searchmark;
|
||||
@ -1718,10 +1720,10 @@ window_copy_cmd_search_again(struct window_copy_cmd_state *cs)
|
||||
|
||||
if (data->searchtype == WINDOW_COPY_SEARCHUP) {
|
||||
for (; np != 0; np--)
|
||||
window_copy_search_up(wme, data->searchregex, 1);
|
||||
window_copy_search_up(wme, data->searchregex);
|
||||
} else if (data->searchtype == WINDOW_COPY_SEARCHDOWN) {
|
||||
for (; np != 0; np--)
|
||||
window_copy_search_down(wme, data->searchregex, 1);
|
||||
window_copy_search_down(wme, data->searchregex);
|
||||
}
|
||||
return (WINDOW_COPY_CMD_NOTHING);
|
||||
}
|
||||
@ -1735,10 +1737,10 @@ window_copy_cmd_search_reverse(struct window_copy_cmd_state *cs)
|
||||
|
||||
if (data->searchtype == WINDOW_COPY_SEARCHUP) {
|
||||
for (; np != 0; np--)
|
||||
window_copy_search_down(wme, data->searchregex, 1);
|
||||
window_copy_search_down(wme, data->searchregex);
|
||||
} else if (data->searchtype == WINDOW_COPY_SEARCHDOWN) {
|
||||
for (; np != 0; np--)
|
||||
window_copy_search_up(wme, data->searchregex, 1);
|
||||
window_copy_search_up(wme, data->searchregex);
|
||||
}
|
||||
return (WINDOW_COPY_CMD_NOTHING);
|
||||
}
|
||||
@ -2042,7 +2044,7 @@ window_copy_cmd_search_backward(struct window_copy_cmd_state *cs)
|
||||
data->searchregex = 1;
|
||||
data->timeout = 0;
|
||||
for (; np != 0; np--)
|
||||
window_copy_search_up(wme, 1, 0);
|
||||
window_copy_search_up(wme, 1);
|
||||
}
|
||||
return (WINDOW_COPY_CMD_NOTHING);
|
||||
}
|
||||
@ -2062,7 +2064,7 @@ window_copy_cmd_search_backward_text(struct window_copy_cmd_state *cs)
|
||||
data->searchregex = 0;
|
||||
data->timeout = 0;
|
||||
for (; np != 0; np--)
|
||||
window_copy_search_up(wme, 0, 0);
|
||||
window_copy_search_up(wme, 0);
|
||||
}
|
||||
return (WINDOW_COPY_CMD_NOTHING);
|
||||
}
|
||||
@ -2082,7 +2084,7 @@ window_copy_cmd_search_forward(struct window_copy_cmd_state *cs)
|
||||
data->searchregex = 1;
|
||||
data->timeout = 0;
|
||||
for (; np != 0; np--)
|
||||
window_copy_search_down(wme, 1, 0);
|
||||
window_copy_search_down(wme, 1);
|
||||
}
|
||||
return (WINDOW_COPY_CMD_NOTHING);
|
||||
}
|
||||
@ -2102,7 +2104,7 @@ window_copy_cmd_search_forward_text(struct window_copy_cmd_state *cs)
|
||||
data->searchregex = 0;
|
||||
data->timeout = 0;
|
||||
for (; np != 0; np--)
|
||||
window_copy_search_down(wme, 0, 0);
|
||||
window_copy_search_down(wme, 0);
|
||||
}
|
||||
return (WINDOW_COPY_CMD_NOTHING);
|
||||
}
|
||||
@ -2143,7 +2145,7 @@ window_copy_cmd_search_backward_incremental(struct window_copy_cmd_state *cs)
|
||||
data->searchregex = 0;
|
||||
free(data->searchstr);
|
||||
data->searchstr = xstrdup(argument);
|
||||
if (!window_copy_search_up(wme, 0, 1)) {
|
||||
if (!window_copy_search_up(wme, 0)) {
|
||||
window_copy_clear_marks(wme);
|
||||
return (WINDOW_COPY_CMD_REDRAW);
|
||||
}
|
||||
@ -2153,7 +2155,7 @@ window_copy_cmd_search_backward_incremental(struct window_copy_cmd_state *cs)
|
||||
data->searchregex = 0;
|
||||
free(data->searchstr);
|
||||
data->searchstr = xstrdup(argument);
|
||||
if (!window_copy_search_down(wme, 0, 0)) {
|
||||
if (!window_copy_search_down(wme, 0)) {
|
||||
window_copy_clear_marks(wme);
|
||||
return (WINDOW_COPY_CMD_REDRAW);
|
||||
}
|
||||
@ -2198,7 +2200,7 @@ window_copy_cmd_search_forward_incremental(struct window_copy_cmd_state *cs)
|
||||
data->searchregex = 0;
|
||||
free(data->searchstr);
|
||||
data->searchstr = xstrdup(argument);
|
||||
if (!window_copy_search_down(wme, 0, 1)) {
|
||||
if (!window_copy_search_down(wme, 0)) {
|
||||
window_copy_clear_marks(wme);
|
||||
return (WINDOW_COPY_CMD_REDRAW);
|
||||
}
|
||||
@ -2208,7 +2210,7 @@ window_copy_cmd_search_forward_incremental(struct window_copy_cmd_state *cs)
|
||||
data->searchregex = 0;
|
||||
free(data->searchstr);
|
||||
data->searchstr = xstrdup(argument);
|
||||
if (!window_copy_search_up(wme, 0, 1)) {
|
||||
if (!window_copy_search_up(wme, 0)) {
|
||||
window_copy_clear_marks(wme);
|
||||
return (WINDOW_COPY_CMD_REDRAW);
|
||||
}
|
||||
@ -2917,6 +2919,23 @@ window_copy_move_left(struct screen *s, u_int *fx, u_int *fy, int wrapflag)
|
||||
*fx = *fx - 1;
|
||||
}
|
||||
|
||||
static void
|
||||
window_copy_move_right(struct screen *s, u_int *fx, u_int *fy, int wrapflag)
|
||||
{
|
||||
if (*fx == screen_size_x(s) - 1) { /* right */
|
||||
if (*fy == screen_hsize(s) + screen_size_y(s) - 1) { /* bottom */
|
||||
if (wrapflag) {
|
||||
*fx = 0;
|
||||
*fy = 0;
|
||||
}
|
||||
return;
|
||||
}
|
||||
*fx = 0;
|
||||
*fy = *fy + 1;
|
||||
} else
|
||||
*fx = *fx + 1;
|
||||
}
|
||||
|
||||
static int
|
||||
window_copy_is_lowercase(const char *ptr)
|
||||
{
|
||||
@ -2979,7 +2998,7 @@ window_copy_search_back_overlap(struct grid *gd, regex_t *preg, u_int *ppx,
|
||||
static int
|
||||
window_copy_search_jump(struct window_mode_entry *wme, struct grid *gd,
|
||||
struct grid *sgd, u_int fx, u_int fy, u_int endline, int cis, int wrap,
|
||||
int direction, int regex, u_int *foundlen)
|
||||
int direction, int regex)
|
||||
{
|
||||
u_int i, px, sx, ssize = 1;
|
||||
int found = 0, cflags = REG_EXTENDED;
|
||||
@ -3004,20 +3023,15 @@ window_copy_search_jump(struct window_mode_entry *wme, struct grid *gd,
|
||||
if (regex) {
|
||||
found = window_copy_search_lr_regex(gd,
|
||||
&px, &sx, i, fx, gd->sx, ®);
|
||||
if (found)
|
||||
*foundlen = sx;
|
||||
} else {
|
||||
found = window_copy_search_lr(gd, sgd,
|
||||
&px, i, fx, gd->sx, cis);
|
||||
if (found)
|
||||
*foundlen = sgd->sx;
|
||||
}
|
||||
if (found)
|
||||
break;
|
||||
fx = 0;
|
||||
}
|
||||
} else {
|
||||
*foundlen = 0;
|
||||
for (i = fy + 1; endline < i; i--) {
|
||||
if (regex) {
|
||||
found = window_copy_search_rl_regex(gd,
|
||||
@ -3048,18 +3062,40 @@ window_copy_search_jump(struct window_mode_entry *wme, struct grid *gd,
|
||||
return (window_copy_search_jump(wme, gd, sgd,
|
||||
direction ? 0 : gd->sx - 1,
|
||||
direction ? 0 : gd->hsize + gd->sy - 1, fy, cis, 0,
|
||||
direction, regex, foundlen));
|
||||
direction, regex));
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void
|
||||
window_copy_move_after_search_mark(struct window_copy_mode_data *data,
|
||||
u_int *fx, u_int *fy, int wrapflag)
|
||||
{
|
||||
struct screen *s = data->backing;
|
||||
u_int at, start;
|
||||
|
||||
if (window_copy_search_mark_at(data, *fx, *fy, &start) == 0 &&
|
||||
data->searchmark[start] != 0) {
|
||||
while (window_copy_search_mark_at(data, *fx, *fy, &at) == 0) {
|
||||
if (data->searchmark[at] != data->searchmark[start])
|
||||
break;
|
||||
/* Stop if not wrapping and at the end of the grid. */
|
||||
if (!wrapflag &&
|
||||
*fx == screen_size_x(s) - 1 &&
|
||||
*fy == screen_hsize(s) + screen_size_y(s) - 1)
|
||||
break;
|
||||
|
||||
window_copy_move_right(s, fx, fy, wrapflag);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Search in for text searchstr. If direction is 0 then search up, otherwise
|
||||
* down.
|
||||
*/
|
||||
static int
|
||||
window_copy_search(struct window_mode_entry *wme, int direction, int regex,
|
||||
int again)
|
||||
window_copy_search(struct window_mode_entry *wme, int direction, int regex)
|
||||
{
|
||||
struct window_pane *wp = wme->wp;
|
||||
struct window_copy_mode_data *data = wme->data;
|
||||
@ -3067,12 +3103,15 @@ window_copy_search(struct window_mode_entry *wme, int direction, int regex,
|
||||
struct screen_write_ctx ctx;
|
||||
struct grid *gd = s->grid;
|
||||
const char *str = data->searchstr;
|
||||
u_int fx, fy, endline, i, foundlen;
|
||||
int wrapflag, cis, found, visible_only;
|
||||
u_int at, endline, fx, fy, start;
|
||||
int cis, found, keys, visible_only;
|
||||
int wrapflag;
|
||||
|
||||
if (regex && str[strcspn(str, "^$*+()?[].\\")] == '\0')
|
||||
regex = 0;
|
||||
|
||||
data->searchdirection = direction;
|
||||
|
||||
if (data->timeout)
|
||||
return (0);
|
||||
|
||||
@ -3097,27 +3136,94 @@ window_copy_search(struct window_mode_entry *wme, int direction, int regex,
|
||||
wrapflag = options_get_number(wp->window->options, "wrap-search");
|
||||
cis = window_copy_is_lowercase(str);
|
||||
|
||||
if (direction)
|
||||
keys = options_get_number(wp->window->options, "mode-keys");
|
||||
|
||||
if (direction) {
|
||||
/*
|
||||
* Behave according to mode-keys. If it is emacs, search forward
|
||||
* leaves the cursor after the match. If it is vi, the cursor
|
||||
* remains at the beginning of the match, regardless of
|
||||
* direction, which means that we need to start the next search
|
||||
* after the term the cursor is currently on when searching
|
||||
* forward.
|
||||
*/
|
||||
if (keys == MODEKEY_VI) {
|
||||
if (data->searchmark != NULL)
|
||||
window_copy_move_after_search_mark(data, &fx,
|
||||
&fy, wrapflag);
|
||||
else {
|
||||
/*
|
||||
* When there are no search marks, start the
|
||||
* search after the current cursor position.
|
||||
*/
|
||||
window_copy_move_right(s, &fx, &fy, wrapflag);
|
||||
}
|
||||
}
|
||||
endline = gd->hsize + gd->sy - 1;
|
||||
}
|
||||
else {
|
||||
if (again)
|
||||
window_copy_move_left(s, &fx, &fy, wrapflag);
|
||||
window_copy_move_left(s, &fx, &fy, wrapflag);
|
||||
endline = 0;
|
||||
}
|
||||
|
||||
found = window_copy_search_jump(wme, gd, ss.grid, fx, fy, endline, cis,
|
||||
wrapflag, direction, regex, &foundlen);
|
||||
wrapflag, direction, regex);
|
||||
if (found) {
|
||||
window_copy_search_marks(wme, &ss, regex, visible_only);
|
||||
if (foundlen != 0) {
|
||||
/* Adjust for wrapped lines eating one right. */
|
||||
i = data->cx + foundlen;
|
||||
while (i > gd->sx - 1) {
|
||||
i -= gd->sx;
|
||||
window_copy_cursor_right(wme, 1);
|
||||
fx = data->cx;
|
||||
fy = screen_hsize(data->backing) - data->oy + data->cy;
|
||||
|
||||
/*
|
||||
* When searching forward, if the cursor is not at the beginning
|
||||
* of the mark, search again.
|
||||
*/
|
||||
if (direction &&
|
||||
window_copy_search_mark_at(data, fx, fy, &at) == 0 &&
|
||||
at > 0 &&
|
||||
data->searchmark[at] == data->searchmark[at - 1]) {
|
||||
window_copy_move_after_search_mark(data, &fx, &fy,
|
||||
wrapflag);
|
||||
window_copy_search_jump(wme, gd, ss.grid, fx,
|
||||
fy, endline, cis, wrapflag, direction,
|
||||
regex);
|
||||
fx = data->cx;
|
||||
fy = screen_hsize(data->backing) - data->oy + data->cy;
|
||||
}
|
||||
|
||||
if (direction) {
|
||||
/*
|
||||
* When in Emacs mode, position the cursor just after
|
||||
* the mark.
|
||||
*/
|
||||
if (keys == MODEKEY_EMACS) {
|
||||
window_copy_move_after_search_mark(data, &fx,
|
||||
&fy, wrapflag);
|
||||
data->cx = fx;
|
||||
data->cy = fy - screen_hsize(data->backing) +
|
||||
data-> oy;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/*
|
||||
* When searching backward, position the cursor at the
|
||||
* beginning of the mark.
|
||||
*/
|
||||
if (window_copy_search_mark_at(data, fx, fy,
|
||||
&start) == 0) {
|
||||
while (window_copy_search_mark_at(data, fx, fy,
|
||||
&at) == 0 &&
|
||||
data->searchmark[at] ==
|
||||
data->searchmark[start]) {
|
||||
data->cx = fx;
|
||||
data->cy = fy -
|
||||
screen_hsize(data->backing) +
|
||||
data-> oy;
|
||||
if (at == 0)
|
||||
break;
|
||||
|
||||
window_copy_move_left(s, &fx, &fy, 0);
|
||||
}
|
||||
}
|
||||
for (i = 0; i < foundlen; i++)
|
||||
window_copy_cursor_right(wme, 1);
|
||||
}
|
||||
}
|
||||
window_copy_redraw_screen(wme);
|
||||
@ -3302,15 +3408,15 @@ window_copy_clear_marks(struct window_mode_entry *wme)
|
||||
}
|
||||
|
||||
static int
|
||||
window_copy_search_up(struct window_mode_entry *wme, int regex, int again)
|
||||
window_copy_search_up(struct window_mode_entry *wme, int regex)
|
||||
{
|
||||
return (window_copy_search(wme, 0, regex, again));
|
||||
return (window_copy_search(wme, 0, regex));
|
||||
}
|
||||
|
||||
static int
|
||||
window_copy_search_down(struct window_mode_entry *wme, int regex, int again)
|
||||
window_copy_search_down(struct window_mode_entry *wme, int regex)
|
||||
{
|
||||
return (window_copy_search(wme, 1, regex, again));
|
||||
return (window_copy_search(wme, 1, regex));
|
||||
}
|
||||
|
||||
static void
|
||||
@ -3396,9 +3502,11 @@ window_copy_update_style(struct window_mode_entry *wme, u_int fx, u_int fy,
|
||||
struct grid_cell *gc, const struct grid_cell *mgc,
|
||||
const struct grid_cell *cgc, const struct grid_cell *mkgc)
|
||||
{
|
||||
struct window_pane *wp = wme->wp;
|
||||
struct window_copy_mode_data *data = wme->data;
|
||||
u_int mark, start, end, cy, cursor, current;
|
||||
int inv = 0, found = 0;
|
||||
int keys;
|
||||
|
||||
if (data->showmark && fy == data->my) {
|
||||
gc->attr = mkgc->attr;
|
||||
@ -3425,13 +3533,16 @@ window_copy_update_style(struct window_mode_entry *wme, u_int fx, u_int fy,
|
||||
|
||||
cy = screen_hsize(data->backing) - data->oy + data->cy;
|
||||
if (window_copy_search_mark_at(data, data->cx, cy, &cursor) == 0) {
|
||||
if (data->searchmark[cursor] == mark)
|
||||
found = 1;
|
||||
else if (cursor != 0) {
|
||||
cursor--;
|
||||
if (data->searchmark[cursor] == mark)
|
||||
keys = options_get_number(wp->window->options, "mode-keys");
|
||||
if (cursor != 0 &&
|
||||
keys == MODEKEY_EMACS &&
|
||||
data->searchdirection) {
|
||||
if (data->searchmark[cursor - 1] == mark) {
|
||||
cursor--;
|
||||
found = 1;
|
||||
}
|
||||
}
|
||||
} else if (data->searchmark[cursor] == mark)
|
||||
found = 1;
|
||||
if (found) {
|
||||
window_copy_match_start_end(data, cursor, &start, &end);
|
||||
if (current >= start && current <= end) {
|
||||
@ -4180,23 +4291,19 @@ static void
|
||||
window_copy_cursor_back_to_indentation(struct window_mode_entry *wme)
|
||||
{
|
||||
struct window_copy_mode_data *data = wme->data;
|
||||
u_int px, py, xx;
|
||||
struct grid_cell gc;
|
||||
struct screen *back_s = data->backing;
|
||||
struct grid_reader gr;
|
||||
u_int px, py, oldy, hsize;
|
||||
|
||||
px = 0;
|
||||
py = screen_hsize(data->backing) + data->cy - data->oy;
|
||||
xx = window_copy_find_length(wme, py);
|
||||
px = data->cx;
|
||||
hsize = screen_hsize(back_s);
|
||||
py = hsize + data->cy - data->oy;
|
||||
oldy = data->cy;
|
||||
|
||||
while (px < xx) {
|
||||
grid_get_cell(data->backing->grid, px, py, &gc);
|
||||
if (gc.data.size != 1 || *gc.data.data != ' ')
|
||||
break;
|
||||
px++;
|
||||
}
|
||||
|
||||
window_copy_update_cursor(wme, px, data->cy);
|
||||
if (window_copy_update_selection(wme, 1, 0))
|
||||
window_copy_redraw_lines(wme, data->cy, 1);
|
||||
grid_reader_start(&gr, back_s->grid, px, py);
|
||||
grid_reader_cursor_back_to_indentation(&gr);
|
||||
grid_reader_get_cursor(&gr, &px, &py);
|
||||
window_copy_acquire_cursor_up(wme, hsize, data->oy, oldy, px, py);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -4287,7 +4394,7 @@ window_copy_cursor_left(struct window_mode_entry *wme)
|
||||
oldy = data->cy;
|
||||
|
||||
grid_reader_start(&gr, back_s->grid, px, py);
|
||||
grid_reader_cursor_left(&gr);
|
||||
grid_reader_cursor_left(&gr, 1);
|
||||
grid_reader_get_cursor(&gr, &px, &py);
|
||||
window_copy_acquire_cursor_up(wme, hsize, data->oy, oldy, px, py);
|
||||
}
|
||||
@ -4472,10 +4579,8 @@ window_copy_cursor_jump_back(struct window_mode_entry *wme)
|
||||
py = hsize + data->cy - data->oy;
|
||||
oldy = data->cy;
|
||||
|
||||
if (px > 0)
|
||||
px--;
|
||||
|
||||
grid_reader_start(&gr, back_s->grid, px, py);
|
||||
grid_reader_cursor_left(&gr, 0);
|
||||
if (grid_reader_cursor_jump_back(&gr, data->jumpchar)) {
|
||||
grid_reader_get_cursor(&gr, &px, &py);
|
||||
window_copy_acquire_cursor_up(wme, hsize, data->oy, oldy, px,
|
||||
@ -4498,7 +4603,7 @@ window_copy_cursor_jump_to(struct window_mode_entry *wme)
|
||||
|
||||
grid_reader_start(&gr, back_s->grid, px, py);
|
||||
if (grid_reader_cursor_jump(&gr, data->jumpchar)) {
|
||||
grid_reader_cursor_left(&gr);
|
||||
grid_reader_cursor_left(&gr, 1);
|
||||
grid_reader_get_cursor(&gr, &px, &py);
|
||||
window_copy_acquire_cursor_down(wme, hsize,
|
||||
screen_size_y(back_s), data->oy, oldy, px, py, 0);
|
||||
@ -4518,13 +4623,9 @@ window_copy_cursor_jump_to_back(struct window_mode_entry *wme)
|
||||
py = hsize + data->cy - data->oy;
|
||||
oldy = data->cy;
|
||||
|
||||
if (px > 0)
|
||||
px--;
|
||||
|
||||
if (px > 0)
|
||||
px--;
|
||||
|
||||
grid_reader_start(&gr, back_s->grid, px, py);
|
||||
grid_reader_cursor_left(&gr, 0);
|
||||
grid_reader_cursor_left(&gr, 0);
|
||||
if (grid_reader_cursor_jump_back(&gr, data->jumpchar)) {
|
||||
grid_reader_cursor_right(&gr, 1, 0);
|
||||
grid_reader_get_cursor(&gr, &px, &py);
|
||||
@ -4577,7 +4678,7 @@ window_copy_cursor_next_word_end_pos(struct window_mode_entry *wme,
|
||||
grid_reader_cursor_right(&gr, 0, 0);
|
||||
grid_reader_cursor_next_word_end(&gr, separators);
|
||||
if (keys == MODEKEY_VI)
|
||||
grid_reader_cursor_left(&gr);
|
||||
grid_reader_cursor_left(&gr, 1);
|
||||
grid_reader_get_cursor(&gr, &px, &py);
|
||||
*ppx = px;
|
||||
*ppy = py;
|
||||
@ -4607,7 +4708,7 @@ window_copy_cursor_next_word_end(struct window_mode_entry *wme,
|
||||
grid_reader_cursor_right(&gr, 0, 0);
|
||||
grid_reader_cursor_next_word_end(&gr, separators);
|
||||
if (keys == MODEKEY_VI)
|
||||
grid_reader_cursor_left(&gr);
|
||||
grid_reader_cursor_left(&gr, 1);
|
||||
grid_reader_get_cursor(&gr, &px, &py);
|
||||
window_copy_acquire_cursor_down(wme, hsize, screen_size_y(back_s),
|
||||
data->oy, oldy, px, py, no_reset);
|
||||
|
@ -890,8 +890,8 @@ window_customize_init(struct window_mode_entry *wme, struct cmd_find_state *fs,
|
||||
|
||||
data->data = mode_tree_start(wp, args, window_customize_build,
|
||||
window_customize_draw, NULL, window_customize_menu,
|
||||
window_customize_height, data, window_customize_menu_items, NULL, 0,
|
||||
&s);
|
||||
window_customize_height, NULL, data, window_customize_menu_items,
|
||||
NULL, 0, &s);
|
||||
mode_tree_zoom(data->data, args);
|
||||
|
||||
mode_tree_build(data->data);
|
||||
@ -999,7 +999,7 @@ window_customize_set_option_callback(struct client *c, void *itemdata,
|
||||
|
||||
fail:
|
||||
*cause = toupper((u_char)*cause);
|
||||
status_message_set(c, -1, 1, "%s", cause);
|
||||
status_message_set(c, -1, 1, 0, "%s", cause);
|
||||
free(cause);
|
||||
return (0);
|
||||
}
|
||||
@ -1205,7 +1205,7 @@ window_customize_set_command_callback(struct client *c, void *itemdata,
|
||||
|
||||
fail:
|
||||
*error = toupper((u_char)*error);
|
||||
status_message_set(c, -1, 1, "%s", error);
|
||||
status_message_set(c, -1, 1, 0, "%s", error);
|
||||
free(error);
|
||||
return (0);
|
||||
}
|
||||
|
@ -56,6 +56,17 @@ static void window_tree_key(struct window_mode_entry *,
|
||||
"}" \
|
||||
"}"
|
||||
|
||||
#define WINDOW_TREE_DEFAULT_KEY_FORMAT \
|
||||
"#{?#{e|<:#{line},10}," \
|
||||
"#{line}" \
|
||||
"," \
|
||||
"#{?#{e|<:#{line},36}," \
|
||||
"M-#{a:#{e|+:97,#{e|-:#{line},10}}}" \
|
||||
"," \
|
||||
"" \
|
||||
"}" \
|
||||
"}"
|
||||
|
||||
static const struct menu_item window_tree_menu_items[] = {
|
||||
{ "Select", '\r', NULL },
|
||||
{ "Expand", KEYC_RIGHT, NULL },
|
||||
@ -117,6 +128,7 @@ struct window_tree_modedata {
|
||||
|
||||
struct mode_tree_data *data;
|
||||
char *format;
|
||||
char *key_format;
|
||||
char *command;
|
||||
int squash_groups;
|
||||
|
||||
@ -856,6 +868,35 @@ window_tree_menu(void *modedata, struct client *c, key_code key)
|
||||
window_tree_key(wme, c, NULL, NULL, key, NULL);
|
||||
}
|
||||
|
||||
static key_code
|
||||
window_tree_get_key(void *modedata, void *itemdata, u_int line)
|
||||
{
|
||||
struct window_tree_modedata *data = modedata;
|
||||
struct window_tree_itemdata *item = itemdata;
|
||||
struct format_tree *ft;
|
||||
struct session *s;
|
||||
struct winlink *wl;
|
||||
struct window_pane *wp;
|
||||
char *expanded;
|
||||
key_code key;
|
||||
|
||||
ft = format_create(NULL, NULL, FORMAT_NONE, 0);
|
||||
window_tree_pull_item(item, &s, &wl, &wp);
|
||||
if (item->type == WINDOW_TREE_SESSION)
|
||||
format_defaults(ft, NULL, s, NULL, NULL);
|
||||
else if (item->type == WINDOW_TREE_WINDOW)
|
||||
format_defaults(ft, NULL, s, wl, NULL);
|
||||
else
|
||||
format_defaults(ft, NULL, s, wl, wp);
|
||||
format_add(ft, "line", "%u", line);
|
||||
|
||||
expanded = format_expand(ft, data->key_format);
|
||||
key = key_string_lookup_string(expanded);
|
||||
free(expanded);
|
||||
format_free(ft);
|
||||
return key;
|
||||
}
|
||||
|
||||
static struct screen *
|
||||
window_tree_init(struct window_mode_entry *wme, struct cmd_find_state *fs,
|
||||
struct args *args)
|
||||
@ -880,6 +921,10 @@ window_tree_init(struct window_mode_entry *wme, struct cmd_find_state *fs,
|
||||
data->format = xstrdup(WINDOW_TREE_DEFAULT_FORMAT);
|
||||
else
|
||||
data->format = xstrdup(args_get(args, 'F'));
|
||||
if (args == NULL || !args_has(args, 'K'))
|
||||
data->key_format = xstrdup(WINDOW_TREE_DEFAULT_KEY_FORMAT);
|
||||
else
|
||||
data->key_format = xstrdup(args_get(args, 'K'));
|
||||
if (args == NULL || args->argc == 0)
|
||||
data->command = xstrdup(WINDOW_TREE_DEFAULT_COMMAND);
|
||||
else
|
||||
@ -887,9 +932,9 @@ window_tree_init(struct window_mode_entry *wme, struct cmd_find_state *fs,
|
||||
data->squash_groups = !args_has(args, 'G');
|
||||
|
||||
data->data = mode_tree_start(wp, args, window_tree_build,
|
||||
window_tree_draw, window_tree_search, window_tree_menu, NULL, data,
|
||||
window_tree_menu_items, window_tree_sort_list,
|
||||
nitems(window_tree_sort_list), &s);
|
||||
window_tree_draw, window_tree_search, window_tree_menu, NULL,
|
||||
window_tree_get_key, data, window_tree_menu_items,
|
||||
window_tree_sort_list, nitems(window_tree_sort_list), &s);
|
||||
mode_tree_zoom(data->data, args);
|
||||
|
||||
mode_tree_build(data->data);
|
||||
@ -913,6 +958,7 @@ window_tree_destroy(struct window_tree_modedata *data)
|
||||
free(data->item_list);
|
||||
|
||||
free(data->format);
|
||||
free(data->key_format);
|
||||
free(data->command);
|
||||
|
||||
free(data);
|
||||
|
Loading…
Reference in New Issue
Block a user