mirror of
https://github.com/tmux/tmux.git
synced 2025-01-09 17:48:48 +00:00
Merge branch 'sixel-passthrough' into sixel
This commit is contained in:
commit
3a741aacd1
27
CHANGES
27
CHANGES
@ -1,5 +1,32 @@
|
||||
CHANGES FROM 3.0 to X.X
|
||||
|
||||
* Add support for adding a note to a key binding (with bind-key -N) and use
|
||||
this to add descriptions to the default key bindings. A new -N flag to
|
||||
list-keys shows key bindings with notes. Change the default ? binding to use
|
||||
this to show a readable summary of keys. Also extend command-prompt to return
|
||||
the name of the key pressed and add a default binding (/) to show the note
|
||||
for the next key pressed.
|
||||
|
||||
* Add support for the iTerm2 DSR 1337 sequence to get the terminal version.
|
||||
|
||||
* Treat plausible but invalid keys (like C-BSpace) as literal like any other
|
||||
unrecognised string passed to send-keys
|
||||
|
||||
* Detect iTerm2 and enable use of DECSLRM (much faster with horizontally split
|
||||
windows).
|
||||
|
||||
* Add -Z to default switch-client command in tree mode.
|
||||
|
||||
* Add ~ to quoted characters for %%%.
|
||||
|
||||
* Document client exit messages in the manual page.
|
||||
|
||||
* Do not let read-only clients limit the size, unless all clients are
|
||||
read-only.
|
||||
|
||||
* Add a number of new formats to inspect what sessions and clients a window is
|
||||
present or active in.
|
||||
|
||||
* Change file reading and writing to go through the client if necessary. This
|
||||
fixes commands like "tmux loadb /dev/fd/X". Also modify source-file to
|
||||
support "-" for standard input, like load-buffer and save-buffer.
|
||||
|
@ -11,8 +11,9 @@ EXTRA_DIST = \
|
||||
dist_EXTRA_tmux_SOURCES = compat/*.[ch]
|
||||
|
||||
# Preprocessor flags.
|
||||
AM_CPPFLAGS += @XOPEN_DEFINES@
|
||||
AM_CPPFLAGS += -DTMUX_CONF="\"$(sysconfdir)/tmux.conf:~/.tmux.conf:~/.config/tmux/tmux.conf\""
|
||||
AM_CPPFLAGS += @XOPEN_DEFINES@ \
|
||||
-DTMUX_VERSION="\"@VERSION@\"" \
|
||||
-DTMUX_CONF="\"$(sysconfdir)/tmux.conf:~/.tmux.conf:~/.config/tmux/tmux.conf\""
|
||||
|
||||
# Additional object files.
|
||||
LDADD = $(LIBOBJS)
|
||||
|
6
client.c
6
client.c
@ -865,6 +865,12 @@ client_dispatch_wait(struct imsg *imsg)
|
||||
case MSG_WRITE_CLOSE:
|
||||
client_write_close(data, datalen);
|
||||
break;
|
||||
case MSG_OLDSTDERR:
|
||||
case MSG_OLDSTDIN:
|
||||
case MSG_OLDSTDOUT:
|
||||
fprintf(stderr, "server version is too old for client\n");
|
||||
proc_exit(client_proc);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -33,8 +33,8 @@ const struct cmd_entry cmd_bind_key_entry = {
|
||||
.name = "bind-key",
|
||||
.alias = "bind",
|
||||
|
||||
.args = { "cnrT:", 2, -1 },
|
||||
.usage = "[-cnr] [-T key-table] key "
|
||||
.args = { "cnrN:T:", 2, -1 },
|
||||
.usage = "[-cnr] [-T key-table] [-N note] key "
|
||||
"command [arguments]",
|
||||
|
||||
.flags = CMD_AFTERHOOK,
|
||||
@ -46,10 +46,10 @@ cmd_bind_key_exec(struct cmd *self, struct cmdq_item *item)
|
||||
{
|
||||
struct args *args = self->args;
|
||||
key_code key;
|
||||
const char *tablename;
|
||||
const char *tablename, *note;
|
||||
struct cmd_parse_result *pr;
|
||||
char **argv = args->argv;
|
||||
int argc = args->argc;
|
||||
int argc = args->argc, repeat;
|
||||
|
||||
key = key_string_lookup_string(argv[0]);
|
||||
if (key == KEYC_NONE || key == KEYC_UNKNOWN) {
|
||||
@ -63,6 +63,7 @@ cmd_bind_key_exec(struct cmd *self, struct cmdq_item *item)
|
||||
tablename = "root";
|
||||
else
|
||||
tablename = "prefix";
|
||||
repeat = args_has(args, 'r');
|
||||
|
||||
if (argc == 2)
|
||||
pr = cmd_parse_from_string(argv[1], NULL);
|
||||
@ -79,6 +80,7 @@ cmd_bind_key_exec(struct cmd *self, struct cmdq_item *item)
|
||||
case CMD_PARSE_SUCCESS:
|
||||
break;
|
||||
}
|
||||
key_bindings_add(tablename, key, args_has(args, 'r'), pr->cmdlist);
|
||||
note = args_get(args, 'N');
|
||||
key_bindings_add(tablename, key, note, repeat, pr->cmdlist);
|
||||
return (CMD_RETURN_NORMAL);
|
||||
}
|
||||
|
@ -40,8 +40,8 @@ const struct cmd_entry cmd_command_prompt_entry = {
|
||||
.name = "command-prompt",
|
||||
.alias = NULL,
|
||||
|
||||
.args = { "1iI:Np:t:", 0, 1 },
|
||||
.usage = "[-1Ni] [-I inputs] [-p prompts] " CMD_TARGET_CLIENT_USAGE " "
|
||||
.args = { "1kiI:Np:t:", 0, 1 },
|
||||
.usage = "[-1kiN] [-I inputs] [-p prompts] " CMD_TARGET_CLIENT_USAGE " "
|
||||
"[template]",
|
||||
|
||||
.flags = 0,
|
||||
@ -122,6 +122,8 @@ cmd_command_prompt_exec(struct cmd *self, struct cmdq_item *item)
|
||||
cdata->flags |= PROMPT_NUMERIC;
|
||||
else if (args_has(args, 'i'))
|
||||
cdata->flags |= PROMPT_INCREMENTAL;
|
||||
else if (args_has(args, 'k'))
|
||||
cdata->flags |= PROMPT_KEY;
|
||||
status_prompt_set(c, prompt, input, cmd_command_prompt_callback,
|
||||
cmd_command_prompt_free, cdata, cdata->flags);
|
||||
free(prompt);
|
||||
|
148
cmd-list-keys.c
148
cmd-list-keys.c
@ -36,8 +36,8 @@ const struct cmd_entry cmd_list_keys_entry = {
|
||||
.name = "list-keys",
|
||||
.alias = "lsk",
|
||||
|
||||
.args = { "T:", 0, 0 },
|
||||
.usage = "[-T key-table]",
|
||||
.args = { "1NP:T:", 0, 1 },
|
||||
.usage = "[-1N] [-P prefix-string] [-T key-table] [key]",
|
||||
|
||||
.flags = CMD_STARTSERVER|CMD_AFTERHOOK,
|
||||
.exec = cmd_list_keys_exec
|
||||
@ -54,6 +54,88 @@ const struct cmd_entry cmd_list_commands_entry = {
|
||||
.exec = cmd_list_keys_exec
|
||||
};
|
||||
|
||||
static u_int
|
||||
cmd_list_keys_get_width(const char *tablename, key_code only)
|
||||
{
|
||||
struct key_table *table;
|
||||
struct key_binding *bd;
|
||||
u_int width, keywidth = 0;
|
||||
|
||||
table = key_bindings_get_table(tablename, 0);
|
||||
if (table == NULL)
|
||||
return (0);
|
||||
bd = key_bindings_first(table);
|
||||
while (bd != NULL) {
|
||||
if ((only != KEYC_UNKNOWN && bd->key != only) ||
|
||||
KEYC_IS_MOUSE(bd->key) ||
|
||||
bd->note == NULL) {
|
||||
bd = key_bindings_next(table, bd);
|
||||
continue;
|
||||
}
|
||||
width = utf8_cstrwidth(key_string_lookup_key(bd->key));
|
||||
if (width > keywidth)
|
||||
keywidth = width;
|
||||
|
||||
bd = key_bindings_next(table, bd);
|
||||
}
|
||||
return (keywidth);
|
||||
}
|
||||
|
||||
static int
|
||||
cmd_list_keys_print_notes(struct cmdq_item *item, struct args *args,
|
||||
const char *tablename, u_int keywidth, key_code only, const char *prefix)
|
||||
{
|
||||
struct client *c = cmd_find_client(item, NULL, 1);
|
||||
struct key_table *table;
|
||||
struct key_binding *bd;
|
||||
const char *key;
|
||||
char *tmp;
|
||||
int found = 0;
|
||||
|
||||
table = key_bindings_get_table(tablename, 0);
|
||||
if (table == NULL)
|
||||
return (0);
|
||||
bd = key_bindings_first(table);
|
||||
while (bd != NULL) {
|
||||
if ((only != KEYC_UNKNOWN && bd->key != only) ||
|
||||
KEYC_IS_MOUSE(bd->key) ||
|
||||
bd->note == NULL) {
|
||||
bd = key_bindings_next(table, bd);
|
||||
continue;
|
||||
}
|
||||
found = 1;
|
||||
key = key_string_lookup_key(bd->key);
|
||||
|
||||
tmp = utf8_padcstr(key, keywidth + 1);
|
||||
if (args_has(args, '1') && c != NULL)
|
||||
status_message_set(c, "%s%s%s", prefix, tmp, bd->note);
|
||||
else
|
||||
cmdq_print(item, "%s%s%s", prefix, tmp, bd->note);
|
||||
free(tmp);
|
||||
|
||||
if (args_has(args, '1'))
|
||||
break;
|
||||
bd = key_bindings_next(table, bd);
|
||||
}
|
||||
return (found);
|
||||
}
|
||||
|
||||
static char *
|
||||
cmd_list_keys_get_prefix(struct args *args, key_code *prefix)
|
||||
{
|
||||
char *s;
|
||||
|
||||
*prefix = options_get_number(global_s_options, "prefix");
|
||||
if (!args_has(args, 'P')) {
|
||||
if (*prefix != KEYC_NONE)
|
||||
xasprintf(&s, "%s ", key_string_lookup_key(*prefix));
|
||||
else
|
||||
s = xstrdup("");
|
||||
} else
|
||||
s = xstrdup(args_get(args, 'P'));
|
||||
return (s);
|
||||
}
|
||||
|
||||
static enum cmd_retval
|
||||
cmd_list_keys_exec(struct cmd *self, struct cmdq_item *item)
|
||||
{
|
||||
@ -61,19 +143,63 @@ cmd_list_keys_exec(struct cmd *self, struct cmdq_item *item)
|
||||
struct key_table *table;
|
||||
struct key_binding *bd;
|
||||
const char *tablename, *r;
|
||||
char *key, *cp, *tmp;
|
||||
int repeat, width, tablewidth, keywidth;
|
||||
char *key, *cp, *tmp, *start, *empty;
|
||||
key_code prefix, only = KEYC_UNKNOWN;
|
||||
int repeat, width, tablewidth, keywidth, found = 0;
|
||||
size_t tmpsize, tmpused, cplen;
|
||||
|
||||
if (self->entry == &cmd_list_commands_entry)
|
||||
return (cmd_list_keys_commands(self, item));
|
||||
|
||||
if (args->argc != 0) {
|
||||
only = key_string_lookup_string(args->argv[0]);
|
||||
if (only == KEYC_UNKNOWN) {
|
||||
cmdq_error(item, "invalid key: %s", args->argv[0]);
|
||||
return (CMD_RETURN_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
tablename = args_get(args, 'T');
|
||||
if (tablename != NULL && key_bindings_get_table(tablename, 0) == NULL) {
|
||||
cmdq_error(item, "table %s doesn't exist", tablename);
|
||||
return (CMD_RETURN_ERROR);
|
||||
}
|
||||
|
||||
if (args_has(args, 'N')) {
|
||||
if (tablename == NULL) {
|
||||
start = cmd_list_keys_get_prefix(args, &prefix);
|
||||
keywidth = cmd_list_keys_get_width("root", only);
|
||||
if (prefix != KEYC_NONE) {
|
||||
width = cmd_list_keys_get_width("prefix", only);
|
||||
if (width == 0)
|
||||
prefix = KEYC_NONE;
|
||||
else if (width > keywidth)
|
||||
keywidth = width;
|
||||
}
|
||||
empty = utf8_padcstr("", utf8_cstrwidth(start));
|
||||
|
||||
found = cmd_list_keys_print_notes(item, args, "root",
|
||||
keywidth, only, empty);
|
||||
if (prefix != KEYC_NONE) {
|
||||
if (cmd_list_keys_print_notes(item, args,
|
||||
"prefix", keywidth, only, start))
|
||||
found = 1;
|
||||
}
|
||||
free(empty);
|
||||
} else {
|
||||
if (args_has(args, 'P'))
|
||||
start = xstrdup(args_get(args, 'P'));
|
||||
else
|
||||
start = xstrdup("");
|
||||
keywidth = cmd_list_keys_get_width(tablename, only);
|
||||
found = cmd_list_keys_print_notes(item, args, tablename,
|
||||
keywidth, only, start);
|
||||
|
||||
}
|
||||
free(start);
|
||||
goto out;
|
||||
}
|
||||
|
||||
repeat = 0;
|
||||
tablewidth = keywidth = 0;
|
||||
table = key_bindings_first_table ();
|
||||
@ -84,6 +210,10 @@ cmd_list_keys_exec(struct cmd *self, struct cmdq_item *item)
|
||||
}
|
||||
bd = key_bindings_first(table);
|
||||
while (bd != NULL) {
|
||||
if (only != KEYC_UNKNOWN && bd->key != only) {
|
||||
bd = key_bindings_next(table, bd);
|
||||
continue;
|
||||
}
|
||||
key = args_escape(key_string_lookup_key(bd->key));
|
||||
|
||||
if (bd->flags & KEY_BINDING_REPEAT)
|
||||
@ -113,6 +243,11 @@ cmd_list_keys_exec(struct cmd *self, struct cmdq_item *item)
|
||||
}
|
||||
bd = key_bindings_first(table);
|
||||
while (bd != NULL) {
|
||||
if (only != KEYC_UNKNOWN && bd->key != only) {
|
||||
bd = key_bindings_next(table, bd);
|
||||
continue;
|
||||
}
|
||||
found = 1;
|
||||
key = args_escape(key_string_lookup_key(bd->key));
|
||||
|
||||
if (!repeat)
|
||||
@ -162,6 +297,11 @@ cmd_list_keys_exec(struct cmd *self, struct cmdq_item *item)
|
||||
|
||||
free(tmp);
|
||||
|
||||
out:
|
||||
if (only != KEYC_UNKNOWN && !found) {
|
||||
cmdq_error(item, "unknown key: %s", args->argv[0]);
|
||||
return (CMD_RETURN_ERROR);
|
||||
}
|
||||
return (CMD_RETURN_NORMAL);
|
||||
}
|
||||
|
||||
|
36
cmd-parse.y
36
cmd-parse.y
@ -133,7 +133,12 @@ statements : statement '\n'
|
||||
free($2);
|
||||
}
|
||||
|
||||
statement : condition
|
||||
statement : /* empty */
|
||||
{
|
||||
$$ = xmalloc (sizeof *$$);
|
||||
TAILQ_INIT($$);
|
||||
}
|
||||
| condition
|
||||
{
|
||||
struct cmd_parse_state *ps = &parse_state;
|
||||
|
||||
@ -144,11 +149,6 @@ statement : condition
|
||||
cmd_parse_free_commands($1);
|
||||
}
|
||||
}
|
||||
| assignment
|
||||
{
|
||||
$$ = xmalloc (sizeof *$$);
|
||||
TAILQ_INIT($$);
|
||||
}
|
||||
| commands
|
||||
{
|
||||
struct cmd_parse_state *ps = &parse_state;
|
||||
@ -194,8 +194,10 @@ expanded : format
|
||||
free($1);
|
||||
}
|
||||
|
||||
assignment : /* empty */
|
||||
| EQUALS
|
||||
optional_assignment : /* empty */
|
||||
| assignment
|
||||
|
||||
assignment : EQUALS
|
||||
{
|
||||
struct cmd_parse_state *ps = &parse_state;
|
||||
int flags = ps->input->flags;
|
||||
@ -339,7 +341,8 @@ commands : command
|
||||
struct cmd_parse_state *ps = &parse_state;
|
||||
|
||||
$$ = cmd_parse_new_commands();
|
||||
if (ps->scope == NULL || ps->scope->flag)
|
||||
if ($1->name != NULL &&
|
||||
(ps->scope == NULL || ps->scope->flag))
|
||||
TAILQ_INSERT_TAIL($$, $1, entry);
|
||||
else
|
||||
cmd_parse_free_command($1);
|
||||
@ -358,7 +361,8 @@ commands : command
|
||||
{
|
||||
struct cmd_parse_state *ps = &parse_state;
|
||||
|
||||
if (ps->scope == NULL || ps->scope->flag) {
|
||||
if ($3->name != NULL &&
|
||||
(ps->scope == NULL || ps->scope->flag)) {
|
||||
$$ = $1;
|
||||
TAILQ_INSERT_TAIL($$, $3, entry);
|
||||
} else {
|
||||
@ -372,7 +376,15 @@ commands : command
|
||||
$$ = $1;
|
||||
}
|
||||
|
||||
command : assignment TOKEN
|
||||
command : assignment
|
||||
{
|
||||
struct cmd_parse_state *ps = &parse_state;
|
||||
|
||||
$$ = xcalloc(1, sizeof *$$);
|
||||
$$->name = NULL;
|
||||
$$->line = ps->input->line;
|
||||
}
|
||||
| optional_assignment TOKEN
|
||||
{
|
||||
struct cmd_parse_state *ps = &parse_state;
|
||||
|
||||
@ -381,7 +393,7 @@ command : assignment TOKEN
|
||||
$$->line = ps->input->line;
|
||||
|
||||
}
|
||||
| assignment TOKEN arguments
|
||||
| optional_assignment TOKEN arguments
|
||||
{
|
||||
struct cmd_parse_state *ps = &parse_state;
|
||||
|
||||
|
@ -60,6 +60,9 @@ static struct cmdq_item *
|
||||
cmd_send_keys_inject_key(struct client *c, struct cmd_find_state *fs,
|
||||
struct cmdq_item *item, key_code key)
|
||||
{
|
||||
struct session *s = fs->s;
|
||||
struct winlink *wl = fs->wl;
|
||||
struct window_pane *wp = fs->wp;
|
||||
struct window_mode_entry *wme;
|
||||
struct key_table *table;
|
||||
struct key_binding *bd;
|
||||
@ -68,7 +71,8 @@ cmd_send_keys_inject_key(struct client *c, struct cmd_find_state *fs,
|
||||
if (wme == NULL || wme->mode->key_table == NULL) {
|
||||
if (options_get_number(fs->wp->window->options, "xterm-keys"))
|
||||
key |= KEYC_XTERM;
|
||||
window_pane_key(fs->wp, item->client, fs->s, fs->wl, key, NULL);
|
||||
if (window_pane_key(wp, item->client, s, wl, key, NULL) != 0)
|
||||
return (NULL);
|
||||
return (item);
|
||||
}
|
||||
table = key_bindings_get_table(wme->mode->key_table(wme), 1);
|
||||
@ -87,6 +91,7 @@ cmd_send_keys_inject_string(struct client *c, struct cmd_find_state *fs,
|
||||
struct cmdq_item *item, struct args *args, int i)
|
||||
{
|
||||
const char *s = args->argv[i];
|
||||
struct cmdq_item *new_item;
|
||||
struct utf8_data *ud, *uc;
|
||||
wchar_t wc;
|
||||
key_code key;
|
||||
@ -104,8 +109,11 @@ cmd_send_keys_inject_string(struct client *c, struct cmd_find_state *fs,
|
||||
literal = args_has(args, 'l');
|
||||
if (!literal) {
|
||||
key = key_string_lookup_string(s);
|
||||
if (key != KEYC_NONE && key != KEYC_UNKNOWN)
|
||||
return (cmd_send_keys_inject_key(c, fs, item, key));
|
||||
if (key != KEYC_NONE && key != KEYC_UNKNOWN) {
|
||||
new_item = cmd_send_keys_inject_key(c, fs, item, key);
|
||||
if (new_item != NULL)
|
||||
return (new_item);
|
||||
}
|
||||
literal = 1;
|
||||
}
|
||||
if (literal) {
|
||||
|
4
compat.h
4
compat.h
@ -171,8 +171,12 @@ void warnx(const char *, ...);
|
||||
#endif
|
||||
|
||||
#ifndef FNM_CASEFOLD
|
||||
#ifdef FNM_IGNORECASE
|
||||
#define FNM_CASEFOLD FNM_IGNORECASE
|
||||
#else
|
||||
#define FNM_CASEFOLD 0
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef INFTIM
|
||||
#define INFTIM -1
|
||||
|
5
format.c
5
format.c
@ -1121,7 +1121,7 @@ format_create(struct client *c, struct cmdq_item *item, int tag, int flags)
|
||||
ft->flags = flags;
|
||||
ft->time = time(NULL);
|
||||
|
||||
format_add(ft, "version", "%s", VERSION);
|
||||
format_add(ft, "version", "%s", getversion());
|
||||
format_add_cb(ft, "host", format_cb_host);
|
||||
format_add_cb(ft, "host_short", format_cb_host_short);
|
||||
format_add_cb(ft, "pid", format_cb_pid);
|
||||
@ -2362,7 +2362,6 @@ format_defaults_client(struct format_tree *ft, struct client *c)
|
||||
struct session *s;
|
||||
const char *name;
|
||||
struct tty *tty = &c->tty;
|
||||
const char *types[] = TTY_TYPES;
|
||||
|
||||
if (ft->s == NULL)
|
||||
ft->s = c->session;
|
||||
@ -2380,8 +2379,6 @@ format_defaults_client(struct format_tree *ft, struct client *c)
|
||||
|
||||
if (tty->term_name != NULL)
|
||||
format_add(ft, "client_termname", "%s", tty->term_name);
|
||||
if (tty->term_name != NULL)
|
||||
format_add(ft, "client_termtype", "%s", types[tty->term_type]);
|
||||
|
||||
format_add_tv(ft, "client_created", &c->creation_time);
|
||||
format_add_tv(ft, "client_activity", &c->activity_time);
|
||||
|
17
input-keys.c
17
input-keys.c
@ -149,7 +149,7 @@ input_split2(u_int c, u_char *dst)
|
||||
}
|
||||
|
||||
/* Translate a key code into an output key sequence. */
|
||||
void
|
||||
int
|
||||
input_key(struct window_pane *wp, key_code key, struct mouse_event *m)
|
||||
{
|
||||
const struct input_key_ent *ike;
|
||||
@ -166,14 +166,14 @@ input_key(struct window_pane *wp, key_code key, struct mouse_event *m)
|
||||
if (KEYC_IS_MOUSE(key)) {
|
||||
if (m != NULL && m->wp != -1 && (u_int)m->wp == wp->id)
|
||||
input_key_mouse(wp, m);
|
||||
return;
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* Literal keys go as themselves (can't be more than eight bits). */
|
||||
if (key & KEYC_LITERAL) {
|
||||
ud.data[0] = (u_char)key;
|
||||
bufferevent_write(wp->event, &ud.data[0], 1);
|
||||
return;
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* Is this backspace? */
|
||||
@ -194,15 +194,15 @@ input_key(struct window_pane *wp, key_code key, struct mouse_event *m)
|
||||
bufferevent_write(wp->event, "\033", 1);
|
||||
ud.data[0] = justkey;
|
||||
bufferevent_write(wp->event, &ud.data[0], 1);
|
||||
return;
|
||||
return (0);
|
||||
}
|
||||
if (justkey > 0x7f && justkey < KEYC_BASE) {
|
||||
if (utf8_split(justkey, &ud) != UTF8_DONE)
|
||||
return;
|
||||
return (-1);
|
||||
if (key & KEYC_ESCAPE)
|
||||
bufferevent_write(wp->event, "\033", 1);
|
||||
bufferevent_write(wp->event, ud.data, ud.size);
|
||||
return;
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -213,7 +213,7 @@ input_key(struct window_pane *wp, key_code key, struct mouse_event *m)
|
||||
if ((out = xterm_keys_lookup(key)) != NULL) {
|
||||
bufferevent_write(wp->event, out, strlen(out));
|
||||
free(out);
|
||||
return;
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
key &= ~KEYC_XTERM;
|
||||
@ -236,7 +236,7 @@ input_key(struct window_pane *wp, key_code key, struct mouse_event *m)
|
||||
}
|
||||
if (i == nitems(input_keys)) {
|
||||
log_debug("key 0x%llx missing", key);
|
||||
return;
|
||||
return (-1);
|
||||
}
|
||||
dlen = strlen(ike->data);
|
||||
log_debug("found key 0x%llx: \"%s\"", key, ike->data);
|
||||
@ -245,6 +245,7 @@ input_key(struct window_pane *wp, key_code key, struct mouse_event *m)
|
||||
if (key & KEYC_ESCAPE)
|
||||
bufferevent_write(wp->event, "\033", 1);
|
||||
bufferevent_write(wp->event, ike->data, dlen);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* Translate mouse and output. */
|
||||
|
12
input.c
12
input.c
@ -20,6 +20,7 @@
|
||||
|
||||
#include <netinet/in.h>
|
||||
|
||||
#include <ctype.h>
|
||||
#include <resolv.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
@ -772,6 +773,7 @@ input_save_state(struct input_ctx *ictx)
|
||||
ictx->old_mode = s->mode;
|
||||
}
|
||||
|
||||
/* Restore screen state. */
|
||||
static void
|
||||
input_restore_state(struct input_ctx *ictx)
|
||||
{
|
||||
@ -1301,6 +1303,7 @@ input_csi_dispatch(struct input_ctx *ictx)
|
||||
struct input_table_entry *entry;
|
||||
int i, n, m;
|
||||
u_int cx, bg = ictx->cell.cell.bg;
|
||||
char *copy, *cp;
|
||||
|
||||
if (ictx->flags & INPUT_DISCARD)
|
||||
return (0);
|
||||
@ -1432,6 +1435,13 @@ input_csi_dispatch(struct input_ctx *ictx)
|
||||
case 6:
|
||||
input_reply(ictx, "\033[%u;%uR", s->cy + 1, s->cx + 1);
|
||||
break;
|
||||
case 1337: /* Terminal version, from iTerm2. */
|
||||
copy = xstrdup(getversion());
|
||||
for (cp = copy; *cp != '\0'; cp++)
|
||||
*cp = toupper((u_char)*cp);
|
||||
input_reply(ictx, "\033[TMUX %sn", copy);
|
||||
free(copy);
|
||||
break;
|
||||
default:
|
||||
log_debug("%s: unknown '%c'", __func__, ictx->ch);
|
||||
break;
|
||||
@ -2151,8 +2161,6 @@ static int
|
||||
input_dcs_dispatch(struct input_ctx *ictx)
|
||||
{
|
||||
struct screen_write_ctx *sctx = &ictx->ctx;
|
||||
struct window_pane *wp = ictx->wp;
|
||||
struct window *w = wp->window;
|
||||
u_char *buf = ictx->input_buf;
|
||||
size_t len = ictx->input_len;
|
||||
const char prefix[] = "tmux;";
|
||||
|
168
key-bindings.c
168
key-bindings.c
@ -90,6 +90,7 @@ key_bindings_free(struct key_table *table, struct key_binding *bd)
|
||||
{
|
||||
RB_REMOVE(key_bindings, &table->key_bindings, bd);
|
||||
cmd_list_free(bd->cmdlist);
|
||||
free((void *)bd->note);
|
||||
free(bd);
|
||||
}
|
||||
|
||||
@ -163,7 +164,7 @@ key_bindings_next(__unused struct key_table *table, struct key_binding *bd)
|
||||
}
|
||||
|
||||
void
|
||||
key_bindings_add(const char *name, key_code key, int repeat,
|
||||
key_bindings_add(const char *name, key_code key, const char *note, int repeat,
|
||||
struct cmd_list *cmdlist)
|
||||
{
|
||||
struct key_table *table;
|
||||
@ -177,6 +178,8 @@ key_bindings_add(const char *name, key_code key, int repeat,
|
||||
|
||||
bd = xcalloc(1, sizeof *bd);
|
||||
bd->key = key;
|
||||
if (note != NULL)
|
||||
bd->note = xstrdup(note);
|
||||
RB_INSERT(key_bindings, &table->key_bindings, bd);
|
||||
|
||||
if (repeat)
|
||||
@ -226,87 +229,88 @@ void
|
||||
key_bindings_init(void)
|
||||
{
|
||||
static const char *defaults[] = {
|
||||
"bind C-b send-prefix",
|
||||
"bind C-o rotate-window",
|
||||
"bind C-z suspend-client",
|
||||
"bind Space next-layout",
|
||||
"bind ! break-pane",
|
||||
"bind '\"' split-window",
|
||||
"bind '#' list-buffers",
|
||||
"bind '$' command-prompt -I'#S' \"rename-session -- '%%'\"",
|
||||
"bind % split-window -h",
|
||||
"bind & confirm-before -p\"kill-window #W? (y/n)\" kill-window",
|
||||
"bind \"'\" command-prompt -pindex \"select-window -t ':%%'\"",
|
||||
"bind ( switch-client -p",
|
||||
"bind ) switch-client -n",
|
||||
"bind , command-prompt -I'#W' \"rename-window -- '%%'\"",
|
||||
"bind - delete-buffer",
|
||||
"bind . command-prompt \"move-window -t '%%'\"",
|
||||
"bind 0 select-window -t:=0",
|
||||
"bind 1 select-window -t:=1",
|
||||
"bind 2 select-window -t:=2",
|
||||
"bind 3 select-window -t:=3",
|
||||
"bind 4 select-window -t:=4",
|
||||
"bind 5 select-window -t:=5",
|
||||
"bind 6 select-window -t:=6",
|
||||
"bind 7 select-window -t:=7",
|
||||
"bind 8 select-window -t:=8",
|
||||
"bind 9 select-window -t:=9",
|
||||
"bind : command-prompt",
|
||||
"bind \\; last-pane",
|
||||
"bind = choose-buffer -Z",
|
||||
"bind ? list-keys",
|
||||
"bind D choose-client -Z",
|
||||
"bind E select-layout -E",
|
||||
"bind L switch-client -l",
|
||||
"bind M select-pane -M",
|
||||
"bind [ copy-mode",
|
||||
"bind ] paste-buffer",
|
||||
"bind c new-window",
|
||||
"bind d detach-client",
|
||||
"bind f command-prompt \"find-window -Z -- '%%'\"",
|
||||
"bind i display-message",
|
||||
"bind l last-window",
|
||||
"bind m select-pane -m",
|
||||
"bind n next-window",
|
||||
"bind o select-pane -t:.+",
|
||||
"bind p previous-window",
|
||||
"bind q display-panes",
|
||||
"bind r refresh-client",
|
||||
"bind s choose-tree -Zs",
|
||||
"bind t clock-mode",
|
||||
"bind w choose-tree -Zw",
|
||||
"bind x confirm-before -p\"kill-pane #P? (y/n)\" kill-pane",
|
||||
"bind z resize-pane -Z",
|
||||
"bind '{' swap-pane -U",
|
||||
"bind '}' swap-pane -D",
|
||||
"bind '~' show-messages",
|
||||
"bind PPage copy-mode -u",
|
||||
"bind -r Up select-pane -U",
|
||||
"bind -r Down select-pane -D",
|
||||
"bind -r Left select-pane -L",
|
||||
"bind -r Right select-pane -R",
|
||||
"bind M-1 select-layout even-horizontal",
|
||||
"bind M-2 select-layout even-vertical",
|
||||
"bind M-3 select-layout main-horizontal",
|
||||
"bind M-4 select-layout main-vertical",
|
||||
"bind M-5 select-layout tiled",
|
||||
"bind M-n next-window -a",
|
||||
"bind M-o rotate-window -D",
|
||||
"bind M-p previous-window -a",
|
||||
"bind -r S-Up refresh-client -U 10",
|
||||
"bind -r S-Down refresh-client -D 10",
|
||||
"bind -r S-Left refresh-client -L 10",
|
||||
"bind -r S-Right refresh-client -R 10",
|
||||
"bind -r DC refresh-client -c",
|
||||
"bind -r M-Up resize-pane -U 5",
|
||||
"bind -r M-Down resize-pane -D 5",
|
||||
"bind -r M-Left resize-pane -L 5",
|
||||
"bind -r M-Right resize-pane -R 5",
|
||||
"bind -r C-Up resize-pane -U",
|
||||
"bind -r C-Down resize-pane -D",
|
||||
"bind -r C-Left resize-pane -L",
|
||||
"bind -r C-Right resize-pane -R",
|
||||
"bind -N 'Send the prefix key' C-b send-prefix",
|
||||
"bind -N 'Rotate through the panes' C-o rotate-window",
|
||||
"bind -N 'Suspend the current client' C-z suspend-client",
|
||||
"bind -N 'Select next layout' Space next-layout",
|
||||
"bind -N 'Break pane to a new window' ! break-pane",
|
||||
"bind -N 'Split window vertically' '\"' split-window",
|
||||
"bind -N 'List all paste buffers' '#' list-buffers",
|
||||
"bind -N 'Rename current session' '$' command-prompt -I'#S' \"rename-session -- '%%'\"",
|
||||
"bind -N 'Split window horizontally' % split-window -h",
|
||||
"bind -N 'Kill current window' & confirm-before -p\"kill-window #W? (y/n)\" kill-window",
|
||||
"bind -N 'Prompt for window index to select' \"'\" command-prompt -pindex \"select-window -t ':%%'\"",
|
||||
"bind -N 'Switch to previous client' ( switch-client -p",
|
||||
"bind -N 'Switch to next client' ) switch-client -n",
|
||||
"bind -N 'Rename current window' , command-prompt -I'#W' \"rename-window -- '%%'\"",
|
||||
"bind -N 'Delete the most recent paste buffer' - delete-buffer",
|
||||
"bind -N 'Move the current window' . command-prompt \"move-window -t '%%'\"",
|
||||
"bind -N 'Describe key binding' '/' command-prompt -kpkey 'list-keys -1N \"%%%\"'",
|
||||
"bind -N 'Select window 0' 0 select-window -t:=0",
|
||||
"bind -N 'Select window 1' 1 select-window -t:=1",
|
||||
"bind -N 'Select window 2' 2 select-window -t:=2",
|
||||
"bind -N 'Select window 3' 3 select-window -t:=3",
|
||||
"bind -N 'Select window 4' 4 select-window -t:=4",
|
||||
"bind -N 'Select window 5' 5 select-window -t:=5",
|
||||
"bind -N 'Select window 6' 6 select-window -t:=6",
|
||||
"bind -N 'Select window 7' 7 select-window -t:=7",
|
||||
"bind -N 'Select window 8' 8 select-window -t:=8",
|
||||
"bind -N 'Select window 9' 9 select-window -t:=9",
|
||||
"bind -N 'Prompt for a command' : command-prompt",
|
||||
"bind -N 'Move to the previously active pane' \\; last-pane",
|
||||
"bind -N 'Choose a paste buffer from a list' = choose-buffer -Z",
|
||||
"bind -N 'List key bindings' ? list-keys -N",
|
||||
"bind -N 'Choose a client from a list' D choose-client -Z",
|
||||
"bind -N 'Spread panes out evenly' E select-layout -E",
|
||||
"bind -N 'Switch to the last client' L switch-client -l",
|
||||
"bind -N 'Clear the marked pane' M select-pane -M",
|
||||
"bind -N 'Enter copy mode' [ copy-mode",
|
||||
"bind -N 'Paste the most recent paste buffer' ] paste-buffer",
|
||||
"bind -N 'Create a new window' c new-window",
|
||||
"bind -N 'Detach the current client' d detach-client",
|
||||
"bind -N 'Search for a pane' f command-prompt \"find-window -Z -- '%%'\"",
|
||||
"bind -N 'Display window information' i display-message",
|
||||
"bind -N 'Select the previously current window' l last-window",
|
||||
"bind -N 'Toggle the marked pane' m select-pane -m",
|
||||
"bind -N 'Select the next window' n next-window",
|
||||
"bind -N 'Select the next pane' o select-pane -t:.+",
|
||||
"bind -N 'Select the previous pane' p previous-window",
|
||||
"bind -N 'Display pane numbers' q display-panes",
|
||||
"bind -N 'Redraw the current client' r refresh-client",
|
||||
"bind -N 'Choose a session from a list' s choose-tree -Zs",
|
||||
"bind -N 'Show a clock' t clock-mode",
|
||||
"bind -N 'Choose a window from a list' w choose-tree -Zw",
|
||||
"bind -N 'Kill the active pane' x confirm-before -p\"kill-pane #P? (y/n)\" kill-pane",
|
||||
"bind -N 'Zoom the active pane' z resize-pane -Z",
|
||||
"bind -N 'Swap the active pane with the pane above' '{' swap-pane -U",
|
||||
"bind -N 'Swap the active pane with the pane below' '}' swap-pane -D",
|
||||
"bind -N 'Show messages' '~' show-messages",
|
||||
"bind -N 'Enter copy mode and scroll up' PPage copy-mode -u",
|
||||
"bind -N 'Select the pane above the active pane' -r Up select-pane -U",
|
||||
"bind -N 'Select the pane below the active pane' -r Down select-pane -D",
|
||||
"bind -N 'Select the pane to the left of the active pane' -r Left select-pane -L",
|
||||
"bind -N 'Select the pane to the right of the active pane' -r Right select-pane -R",
|
||||
"bind -N 'Set the even-horizontal layout' M-1 select-layout even-horizontal",
|
||||
"bind -N 'Set the even-vertical layout' M-2 select-layout even-vertical",
|
||||
"bind -N 'Set the main-horizontal layout' M-3 select-layout main-horizontal",
|
||||
"bind -N 'Set the main-vertical layout' M-4 select-layout main-vertical",
|
||||
"bind -N 'Select the tiled layout' M-5 select-layout tiled",
|
||||
"bind -N 'Select the next window with an alert' M-n next-window -a",
|
||||
"bind -N 'Rotate through the panes in reverse' M-o rotate-window -D",
|
||||
"bind -N 'Select the previous window with an alert' M-p previous-window -a",
|
||||
"bind -N 'Move the visible part of the window up' -r S-Up refresh-client -U 10",
|
||||
"bind -N 'Move the visible part of the window down' -r S-Down refresh-client -D 10",
|
||||
"bind -N 'Move the visible part of the window left' -r S-Left refresh-client -L 10",
|
||||
"bind -N 'Move the visible part of the window right' -r S-Right refresh-client -R 10",
|
||||
"bind -N 'Reset so the visible part of the window follows the cursor' -r DC refresh-client -c",
|
||||
"bind -N 'Resize the pane up by 5' -r M-Up resize-pane -U 5",
|
||||
"bind -N 'Resize the pane down by 5' -r M-Down resize-pane -D 5",
|
||||
"bind -N 'Resize the pane left by 5' -r M-Left resize-pane -L 5",
|
||||
"bind -N 'Resize the pane right by 5' -r M-Right resize-pane -R 5",
|
||||
"bind -N 'Resize the pane up' -r C-Up resize-pane -U",
|
||||
"bind -N 'Resize the pane down' -r C-Down resize-pane -D",
|
||||
"bind -N 'Resize the pane left' -r C-Left resize-pane -L",
|
||||
"bind -N 'Resize the pane right' -r C-Right resize-pane -R",
|
||||
|
||||
"bind -n MouseDown1Pane select-pane -t=\\; send-keys -M",
|
||||
"bind -n MouseDrag1Border resize-pane -M",
|
||||
|
2
proc.c
2
proc.c
@ -181,7 +181,7 @@ proc_start(const char *name)
|
||||
memset(&u, 0, sizeof u);
|
||||
|
||||
log_debug("%s started (%ld): version %s, socket %s, protocol %d", name,
|
||||
(long)getpid(), VERSION, socket_path, PROTOCOL_VERSION);
|
||||
(long)getpid(), getversion(), socket_path, PROTOCOL_VERSION);
|
||||
log_debug("on %s %s %s; libevent %s (%s)", u.sysname, u.release,
|
||||
u.version, event_get_version(), event_get_method());
|
||||
|
||||
|
21
resize.c
21
resize.c
@ -66,10 +66,26 @@ resize_window(struct window *w, u_int sx, u_int sy, int xpixel, int ypixel)
|
||||
static int
|
||||
ignore_client_size(struct client *c)
|
||||
{
|
||||
struct client *loop;
|
||||
|
||||
if (c->session == NULL)
|
||||
return (1);
|
||||
if (c->flags & CLIENT_NOSIZEFLAGS)
|
||||
return (1);
|
||||
if (c->flags & CLIENT_READONLY) {
|
||||
/*
|
||||
* Ignore readonly clients if there are any attached clients
|
||||
* that aren't readonly.
|
||||
*/
|
||||
TAILQ_FOREACH (loop, &clients, entry) {
|
||||
if (loop->session == NULL)
|
||||
continue;
|
||||
if (loop->flags & CLIENT_NOSIZEFLAGS)
|
||||
continue;
|
||||
if (~loop->flags & CLIENT_READONLY)
|
||||
return (1);
|
||||
}
|
||||
}
|
||||
if ((c->flags & CLIENT_CONTROL) && (~c->flags & CLIENT_SIZECHANGED))
|
||||
return (1);
|
||||
return (0);
|
||||
@ -363,14 +379,15 @@ recalculate_sizes(void)
|
||||
* client.
|
||||
*/
|
||||
TAILQ_FOREACH(c, &clients, entry) {
|
||||
s = c->session;
|
||||
if (s != NULL && !(c->flags & CLIENT_UNATTACHEDFLAGS))
|
||||
s->attached++;
|
||||
if (ignore_client_size(c))
|
||||
continue;
|
||||
s = c->session;
|
||||
if (c->tty.sy <= s->statuslines || (c->flags & CLIENT_CONTROL))
|
||||
c->flags |= CLIENT_STATUSOFF;
|
||||
else
|
||||
c->flags &= ~CLIENT_STATUSOFF;
|
||||
s->attached++;
|
||||
}
|
||||
|
||||
/* Walk each window and adjust the size. */
|
||||
|
@ -1032,7 +1032,7 @@ server_client_key_callback(struct cmdq_item *item, void *data)
|
||||
key_code key0;
|
||||
|
||||
/* Check the client is good to accept input. */
|
||||
if (s == NULL || (c->flags & (CLIENT_DEAD|CLIENT_SUSPENDED)) != 0)
|
||||
if (s == NULL || (c->flags & CLIENT_UNATTACHEDFLAGS))
|
||||
goto out;
|
||||
wl = s->curw;
|
||||
|
||||
@ -1219,7 +1219,7 @@ server_client_handle_key(struct client *c, struct key_event *event)
|
||||
struct cmdq_item *item;
|
||||
|
||||
/* Check the client is good to accept input. */
|
||||
if (s == NULL || (c->flags & (CLIENT_DEAD|CLIENT_SUSPENDED)) != 0)
|
||||
if (s == NULL || (c->flags & CLIENT_UNATTACHEDFLAGS))
|
||||
return (0);
|
||||
|
||||
/*
|
||||
|
35
spawn.c
35
spawn.c
@ -223,6 +223,17 @@ spawn_pane(struct spawn_context *sc, char **cause)
|
||||
|
||||
spawn_log(__func__, sc);
|
||||
|
||||
/*
|
||||
* Work out the current working directory. If respawning, use
|
||||
* the pane's stored one unless specified.
|
||||
*/
|
||||
if (sc->cwd != NULL)
|
||||
cwd = format_single(item, sc->cwd, c, s, NULL, NULL);
|
||||
else if (~sc->flags & SPAWN_RESPAWN)
|
||||
cwd = xstrdup(server_client_get_cwd(c, s));
|
||||
else
|
||||
cwd = NULL;
|
||||
|
||||
/*
|
||||
* If we are respawning then get rid of the old process. Otherwise
|
||||
* either create a new cell or assign to the one we are given.
|
||||
@ -233,6 +244,7 @@ spawn_pane(struct spawn_context *sc, char **cause)
|
||||
window_pane_index(sc->wp0, &idx);
|
||||
xasprintf(cause, "pane %s:%d.%u still active",
|
||||
s->name, sc->wl->idx, idx);
|
||||
free(cwd);
|
||||
return (NULL);
|
||||
}
|
||||
if (sc->wp0->fd != -1) {
|
||||
@ -253,8 +265,8 @@ spawn_pane(struct spawn_context *sc, char **cause)
|
||||
}
|
||||
|
||||
/*
|
||||
* Now we have a pane with nothing running in it ready for the new
|
||||
* process. Work out the command and arguments.
|
||||
* Now we have a pane with nothing running in it ready for the new process.
|
||||
* Work out the command and arguments and store the working directory.
|
||||
*/
|
||||
if (sc->argc == 0 && (~sc->flags & SPAWN_RESPAWN)) {
|
||||
cmd = options_get_string(s->options, "default-command");
|
||||
@ -269,6 +281,10 @@ spawn_pane(struct spawn_context *sc, char **cause)
|
||||
argc = sc->argc;
|
||||
argv = sc->argv;
|
||||
}
|
||||
if (cwd != NULL) {
|
||||
free(new_wp->cwd);
|
||||
new_wp->cwd = cwd;
|
||||
}
|
||||
|
||||
/*
|
||||
* Replace the stored arguments if there are new ones. If not, the
|
||||
@ -280,21 +296,6 @@ spawn_pane(struct spawn_context *sc, char **cause)
|
||||
new_wp->argv = cmd_copy_argv(argc, argv);
|
||||
}
|
||||
|
||||
/*
|
||||
* Work out the current working directory. If respawning, use
|
||||
* the pane's stored one unless specified.
|
||||
*/
|
||||
if (sc->cwd != NULL)
|
||||
cwd = format_single(item, sc->cwd, c, s, NULL, NULL);
|
||||
else if (~sc->flags & SPAWN_RESPAWN)
|
||||
cwd = xstrdup(server_client_get_cwd(c, s));
|
||||
else
|
||||
cwd = NULL;
|
||||
if (cwd != NULL) {
|
||||
free(new_wp->cwd);
|
||||
new_wp->cwd = cwd;
|
||||
}
|
||||
|
||||
/* Create an environment for this pane. */
|
||||
child = environ_for_session(s, 0);
|
||||
if (sc->environ != NULL)
|
||||
|
8
status.c
8
status.c
@ -915,11 +915,17 @@ status_prompt_key(struct client *c, key_code key)
|
||||
{
|
||||
struct options *oo = c->session->options;
|
||||
char *s, *cp, word[64], prefix = '=';
|
||||
const char *histstr, *ws = NULL;
|
||||
const char *histstr, *ws = NULL, *keystring;
|
||||
size_t size, n, off, idx, used;
|
||||
struct utf8_data tmp, *first, *last, *ud;
|
||||
int keys;
|
||||
|
||||
if (c->prompt_flags & PROMPT_KEY) {
|
||||
keystring = key_string_lookup_key(key);
|
||||
c->prompt_inputcb(c, c->prompt_data, keystring, 1);
|
||||
status_prompt_clear(c);
|
||||
return (0);
|
||||
}
|
||||
size = utf8_strlen(c->prompt_buffer);
|
||||
|
||||
if (c->prompt_flags & PROMPT_NUMERIC) {
|
||||
|
68
tmux.1
68
tmux.1
@ -214,7 +214,6 @@ was given) and off.
|
||||
Report the
|
||||
.Nm
|
||||
version.
|
||||
.Pp
|
||||
.It Ar command Op Ar flags
|
||||
This specifies one of a set of commands used to control
|
||||
.Nm ,
|
||||
@ -1292,6 +1291,17 @@ shows the parsed commands and line numbers if possible.
|
||||
Start the
|
||||
.Nm
|
||||
server, if not already running, without creating any sessions.
|
||||
.Pp
|
||||
Note that as by default the
|
||||
.Nm
|
||||
server will exit with no sessions, this is only useful if a session is created in
|
||||
.Pa ~/.tmux.conf ,
|
||||
.Ic exit-empty
|
||||
is turned off, or another command is run as part of the same command sequence.
|
||||
For example:
|
||||
.Bd -literal -offset indent
|
||||
$ tmux start \\; show -g
|
||||
.Ed
|
||||
.It Xo Ic suspend-client
|
||||
.Op Fl t Ar target-client
|
||||
.Xc
|
||||
@ -1340,7 +1350,8 @@ is used,
|
||||
option will not be applied.
|
||||
.Pp
|
||||
.Fl T
|
||||
sets the client's key table; the next key from the client will be interpreted from
|
||||
sets the client's key table; the next key from the client will be interpreted
|
||||
from
|
||||
.Ar key-table .
|
||||
This may be used to configure multiple prefix keys, or to bind commands to
|
||||
sequences of keys.
|
||||
@ -2538,10 +2549,11 @@ This is similar to
|
||||
except the source and destination windows are swapped.
|
||||
It is an error if no window exists at
|
||||
.Ar src-window .
|
||||
If
|
||||
.Fl d
|
||||
is given, the new window does not become the current window.
|
||||
.Pp
|
||||
Like
|
||||
.Ic swap-pane ,
|
||||
if
|
||||
If
|
||||
.Fl s
|
||||
is omitted and a marked pane is present (see
|
||||
.Ic select-pane
|
||||
@ -2617,6 +2629,7 @@ Commands related to key bindings are as follows:
|
||||
.Bl -tag -width Ds
|
||||
.It Xo Ic bind-key
|
||||
.Op Fl nr
|
||||
.Op Fl N Ar note
|
||||
.Op Fl T Ar key-table
|
||||
.Ar key Ar command Op Ar arguments
|
||||
.Xc
|
||||
@ -2664,22 +2677,46 @@ The
|
||||
flag indicates this key may repeat, see the
|
||||
.Ic repeat-time
|
||||
option.
|
||||
.Fl N
|
||||
attaches a note to the key (shown with
|
||||
.Ic list-keys
|
||||
.Fl N ) .
|
||||
.Pp
|
||||
To view the default bindings and possible commands, see the
|
||||
.Ic list-keys
|
||||
command.
|
||||
.It Xo Ic list-keys
|
||||
.Op Fl T Ar key-table
|
||||
.Op Fl 1N
|
||||
.Op Fl P Ar prefix-string Fl T Ar key-table
|
||||
.Op key
|
||||
.Xc
|
||||
.D1 (alias: Ic lsk )
|
||||
List all key bindings.
|
||||
Without
|
||||
.Fl T
|
||||
all key tables are printed.
|
||||
By default this shows all keys or any bindings for
|
||||
.Ar key
|
||||
in the syntax of the
|
||||
.Ic bind-key
|
||||
command.
|
||||
.Fl N
|
||||
instead show keys and attached notes, i
|
||||
.Ar key-table
|
||||
if given or in the
|
||||
.Em root
|
||||
and
|
||||
.Em prefix
|
||||
key tables by default.
|
||||
.Fl P
|
||||
specifies a prefix to print before each key.
|
||||
With
|
||||
.Fl 1
|
||||
only the first matching key and note is shown.
|
||||
.Pp
|
||||
Without
|
||||
.Fl N ,
|
||||
.Fl T
|
||||
only
|
||||
.Ar key-table .
|
||||
prints only keys in
|
||||
.Ar key-table ,
|
||||
otherwise all key tables are printed.
|
||||
.It Xo Ic send-keys
|
||||
.Op Fl FHlMRX
|
||||
.Op Fl N Ar repeat-count
|
||||
@ -4232,7 +4269,6 @@ The following variables are available, where appropriate:
|
||||
.It Li "client_readonly" Ta "" Ta "1 if client is readonly"
|
||||
.It Li "client_session" Ta "" Ta "Name of the client's session"
|
||||
.It Li "client_termname" Ta "" Ta "Terminal name of client"
|
||||
.It Li "client_termtype" Ta "" Ta "Terminal type of client"
|
||||
.It Li "client_tty" Ta "" Ta "Pseudo terminal of client"
|
||||
.It Li "client_utf8" Ta "" Ta "1 if client supports UTF-8"
|
||||
.It Li "client_width" Ta "" Ta "Width of client"
|
||||
@ -4700,7 +4736,7 @@ session option.
|
||||
Commands related to the status line are as follows:
|
||||
.Bl -tag -width Ds
|
||||
.It Xo Ic command-prompt
|
||||
.Op Fl 1Ni
|
||||
.Op Fl 1ikN
|
||||
.Op Fl I Ar inputs
|
||||
.Op Fl p Ar prompts
|
||||
.Op Fl t Ar target-client
|
||||
@ -4750,6 +4786,10 @@ but any quotation marks are escaped.
|
||||
.Fl 1
|
||||
makes the prompt only accept one key press, in this case the resulting input
|
||||
is a single character.
|
||||
.Fl k
|
||||
is like
|
||||
.Fl 1
|
||||
but the key press is translated to a key name.
|
||||
.Fl N
|
||||
makes the prompt only accept numeric key presses.
|
||||
.Fl i
|
||||
@ -4913,7 +4953,7 @@ When the
|
||||
option is reached, the oldest automatically named buffer is deleted.
|
||||
Explicitly named buffers are not subject to
|
||||
.Ic buffer-limit
|
||||
and may be deleted with
|
||||
and may be deleted with the
|
||||
.Ic delete-buffer
|
||||
command.
|
||||
.Pp
|
||||
|
15
tmux.c
15
tmux.c
@ -18,6 +18,7 @@
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/utsname.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <event.h>
|
||||
@ -209,6 +210,12 @@ find_home(void)
|
||||
return (home);
|
||||
}
|
||||
|
||||
const char *
|
||||
getversion(void)
|
||||
{
|
||||
return TMUX_VERSION;
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
@ -235,7 +242,7 @@ main(int argc, char **argv)
|
||||
flags = 0;
|
||||
|
||||
label = path = NULL;
|
||||
while ((opt = getopt(argc, argv, "2c:Cdf:lL:qS:uUVv")) != -1) {
|
||||
while ((opt = getopt(argc, argv, "2c:Cdf:lL:qS:uUvV")) != -1) {
|
||||
switch (opt) {
|
||||
case '2':
|
||||
flags |= CLIENT_256COLOURS;
|
||||
@ -249,12 +256,12 @@ main(int argc, char **argv)
|
||||
else
|
||||
flags |= CLIENT_CONTROL;
|
||||
break;
|
||||
case 'V':
|
||||
printf("%s %s\n", getprogname(), VERSION);
|
||||
exit(0);
|
||||
case 'f':
|
||||
set_cfg_file(optarg);
|
||||
break;
|
||||
case 'V':
|
||||
printf("%s %s\n", getprogname(), getversion());
|
||||
exit(0);
|
||||
case 'l':
|
||||
flags |= CLIENT_LOGIN;
|
||||
break;
|
||||
|
51
tmux.h
51
tmux.h
@ -1187,8 +1187,11 @@ struct tty_term {
|
||||
struct tty_code *codes;
|
||||
|
||||
#define TERM_256COLOURS 0x1
|
||||
#define TERM_EARLYWRAP 0x2
|
||||
#define TERM_SIXEL 0x4
|
||||
#define TERM_NOXENL 0x2
|
||||
#define TERM_DECSLRM 0x4
|
||||
#define TERM_DECFRA 0x8
|
||||
#define TERM_RGBCOLOURS 0x10
|
||||
#define TERM_SIXEL 0x20
|
||||
int flags;
|
||||
|
||||
LIST_ENTRY(tty_term) entry;
|
||||
@ -1197,6 +1200,7 @@ LIST_HEAD(tty_terms, tty_term);
|
||||
|
||||
struct tty {
|
||||
struct client *client;
|
||||
struct event start_timer;
|
||||
|
||||
u_int sx;
|
||||
u_int sy;
|
||||
@ -1245,22 +1249,14 @@ struct tty {
|
||||
#define TTY_OPENED 0x20
|
||||
#define TTY_FOCUS 0x40
|
||||
#define TTY_BLOCK 0x80
|
||||
#define TTY_NOBLOCK 0x100
|
||||
#define TTY_HAVEDA 0x100
|
||||
#define TTY_HAVEDSR 0x200
|
||||
#define TTY_NOBLOCK 0x400
|
||||
int flags;
|
||||
|
||||
struct tty_term *term;
|
||||
char *term_name;
|
||||
int term_flags;
|
||||
enum {
|
||||
TTY_VT100,
|
||||
TTY_VT101,
|
||||
TTY_VT102,
|
||||
TTY_VT220,
|
||||
TTY_VT320,
|
||||
TTY_VT420,
|
||||
TTY_VT520,
|
||||
TTY_UNKNOWN
|
||||
} term_type;
|
||||
|
||||
u_int mouse_last_x;
|
||||
u_int mouse_last_y;
|
||||
@ -1274,15 +1270,6 @@ struct tty {
|
||||
struct event key_timer;
|
||||
struct tty_key *key_tree;
|
||||
};
|
||||
#define TTY_TYPES \
|
||||
{ "VT100", \
|
||||
"VT101", \
|
||||
"VT102", \
|
||||
"VT220", \
|
||||
"VT320", \
|
||||
"VT420", \
|
||||
"VT520", \
|
||||
"Unknown" }
|
||||
|
||||
/* TTY command context. */
|
||||
struct tty_ctx {
|
||||
@ -1293,6 +1280,7 @@ struct tty_ctx {
|
||||
|
||||
u_int num;
|
||||
void *ptr;
|
||||
int more;
|
||||
|
||||
/*
|
||||
* Cursor and region position before the screen was updated - this is
|
||||
@ -1617,11 +1605,14 @@ struct client {
|
||||
CLIENT_REDRAWSTATUSALWAYS| \
|
||||
CLIENT_REDRAWBORDERS| \
|
||||
CLIENT_REDRAWOVERLAY)
|
||||
#define CLIENT_UNATTACHEDFLAGS \
|
||||
(CLIENT_DEAD| \
|
||||
CLIENT_SUSPENDED| \
|
||||
CLIENT_DETACHING)
|
||||
#define CLIENT_NOSIZEFLAGS \
|
||||
(CLIENT_DEAD| \
|
||||
CLIENT_SUSPENDED| \
|
||||
CLIENT_DETACHING| \
|
||||
CLIENT_READONLY)
|
||||
CLIENT_DETACHING)
|
||||
int flags;
|
||||
struct key_table *keytable;
|
||||
|
||||
@ -1644,6 +1635,7 @@ struct client {
|
||||
#define PROMPT_NUMERIC 0x2
|
||||
#define PROMPT_INCREMENTAL 0x4
|
||||
#define PROMPT_NOFORMAT 0x8
|
||||
#define PROMPT_KEY 0x10
|
||||
int prompt_flags;
|
||||
|
||||
struct session *session;
|
||||
@ -1671,6 +1663,7 @@ TAILQ_HEAD(clients, client);
|
||||
struct key_binding {
|
||||
key_code key;
|
||||
struct cmd_list *cmdlist;
|
||||
const char *note;
|
||||
|
||||
int flags;
|
||||
#define KEY_BINDING_REPEAT 0x1
|
||||
@ -1798,6 +1791,7 @@ int areshell(const char *);
|
||||
void setblocking(int, int);
|
||||
const char *find_cwd(void);
|
||||
const char *find_home(void);
|
||||
const char *getversion(void);
|
||||
|
||||
/* proc.c */
|
||||
struct imsg;
|
||||
@ -2014,7 +2008,7 @@ void tty_draw_images(struct tty *, struct window_pane *, struct screen *);
|
||||
int tty_open(struct tty *, char **);
|
||||
void tty_close(struct tty *);
|
||||
void tty_free(struct tty *);
|
||||
void tty_set_type(struct tty *, int, int);
|
||||
void tty_set_flags(struct tty *, int);
|
||||
void tty_write(void (*)(struct tty *, const struct tty_ctx *),
|
||||
struct tty_ctx *);
|
||||
void tty_cmd_alignmenttest(struct tty *, const struct tty_ctx *);
|
||||
@ -2184,7 +2178,8 @@ void key_bindings_unref_table(struct key_table *);
|
||||
struct key_binding *key_bindings_get(struct key_table *, key_code);
|
||||
struct key_binding *key_bindings_first(struct key_table *);
|
||||
struct key_binding *key_bindings_next(struct key_table *, struct key_binding *);
|
||||
void key_bindings_add(const char *, key_code, int, struct cmd_list *);
|
||||
void key_bindings_add(const char *, key_code, const char *, int,
|
||||
struct cmd_list *);
|
||||
void key_bindings_remove(const char *, key_code);
|
||||
void key_bindings_remove_table(const char *);
|
||||
void key_bindings_init(void);
|
||||
@ -2315,7 +2310,7 @@ void input_parse(struct window_pane *);
|
||||
void input_parse_buffer(struct window_pane *, u_char *, size_t);
|
||||
|
||||
/* input-key.c */
|
||||
void input_key(struct window_pane *, key_code, struct mouse_event *);
|
||||
int input_key(struct window_pane *, key_code, struct mouse_event *);
|
||||
|
||||
/* xterm-keys.c */
|
||||
char *xterm_keys_lookup(key_code);
|
||||
@ -2540,7 +2535,7 @@ int window_pane_set_mode(struct window_pane *,
|
||||
struct args *);
|
||||
void window_pane_reset_mode(struct window_pane *);
|
||||
void window_pane_reset_mode_all(struct window_pane *);
|
||||
void window_pane_key(struct window_pane *, struct client *,
|
||||
int window_pane_key(struct window_pane *, struct client *,
|
||||
struct session *, struct winlink *, key_code,
|
||||
struct mouse_event *);
|
||||
int window_pane_visible(struct window_pane *);
|
||||
|
108
tty-keys.c
108
tty-keys.c
@ -52,6 +52,8 @@ static int tty_keys_clipboard(struct tty *, const char *, size_t,
|
||||
size_t *);
|
||||
static int tty_keys_device_attributes(struct tty *, const char *, size_t,
|
||||
size_t *);
|
||||
static int tty_keys_device_status_report(struct tty *, const char *,
|
||||
size_t, size_t *);
|
||||
|
||||
/* Default raw keys. */
|
||||
struct tty_default_key_raw {
|
||||
@ -607,6 +609,17 @@ tty_keys_next(struct tty *tty)
|
||||
goto partial_key;
|
||||
}
|
||||
|
||||
/* Is this a device status report response? */
|
||||
switch (tty_keys_device_status_report(tty, buf, len, &size)) {
|
||||
case 0: /* yes */
|
||||
key = KEYC_UNKNOWN;
|
||||
goto complete_key;
|
||||
case -1: /* no, or not valid */
|
||||
break;
|
||||
case 1: /* partial */
|
||||
goto partial_key;
|
||||
}
|
||||
|
||||
/* Is this a mouse key press? */
|
||||
switch (tty_keys_mouse(tty, buf, len, &size, &m)) {
|
||||
case 0: /* yes */
|
||||
@ -1004,10 +1017,11 @@ tty_keys_device_attributes(struct tty *tty, const char *buf, size_t len,
|
||||
struct client *c = tty->client;
|
||||
u_int i, n = 0;
|
||||
char tmp[64], *endptr, p[32] = { 0 }, *cp, *next;
|
||||
static const char *types[] = TTY_TYPES;
|
||||
int type, flags = 0;
|
||||
int flags = 0;
|
||||
|
||||
*size = 0;
|
||||
if (tty->flags & TTY_HAVEDA)
|
||||
return (-1);
|
||||
|
||||
/* First three bytes are always \033[?. */
|
||||
if (buf[0] != '\033')
|
||||
@ -1038,44 +1052,80 @@ tty_keys_device_attributes(struct tty *tty, const char *buf, size_t len,
|
||||
cp = tmp;
|
||||
while ((next = strsep(&cp, ";")) != NULL) {
|
||||
p[n] = strtoul(next, &endptr, 10);
|
||||
if (*endptr != '\0' && *endptr != ';')
|
||||
if (*endptr != '\0')
|
||||
p[n] = 0;
|
||||
n++;
|
||||
}
|
||||
|
||||
/* Store terminal type. */
|
||||
type = TTY_UNKNOWN;
|
||||
/* Set terminal flags. */
|
||||
switch (p[0]) {
|
||||
case 1:
|
||||
if (p[1] == 2)
|
||||
type = TTY_VT100;
|
||||
else if (p[1] == 0)
|
||||
type = TTY_VT101;
|
||||
break;
|
||||
case 6:
|
||||
type = TTY_VT102;
|
||||
break;
|
||||
case 62:
|
||||
type = TTY_VT220;
|
||||
break;
|
||||
case 63:
|
||||
type = TTY_VT320;
|
||||
break;
|
||||
case 64:
|
||||
type = TTY_VT420;
|
||||
break;
|
||||
case 65:
|
||||
type = TTY_VT520;
|
||||
case 64: /* VT420 */
|
||||
flags |= (TERM_DECFRA|TERM_DECSLRM);
|
||||
break;
|
||||
}
|
||||
for (i = 2; i < n; i++) {
|
||||
for (i = 1; i < n; i++) {
|
||||
log_debug("%s: DA feature: %d", c->name, p[i]);
|
||||
if (p[i] == 4)
|
||||
flags |= TERM_SIXEL;
|
||||
}
|
||||
tty_set_type(tty, type, flags);
|
||||
|
||||
log_debug("%s: received DA %.*s (%s)", c->name, (int)*size, buf,
|
||||
types[type]);
|
||||
tty_set_flags(tty, flags);
|
||||
tty->flags |= TTY_HAVEDA;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Handle device status report input. Returns 0 for success, -1 for failure, 1
|
||||
* for partial.
|
||||
*/
|
||||
static int
|
||||
tty_keys_device_status_report(struct tty *tty, const char *buf, size_t len,
|
||||
size_t *size)
|
||||
{
|
||||
struct client *c = tty->client;
|
||||
u_int i;
|
||||
char tmp[64];
|
||||
int flags = 0;
|
||||
|
||||
*size = 0;
|
||||
if (tty->flags & TTY_HAVEDSR)
|
||||
return (-1);
|
||||
|
||||
/* First three bytes are always \033[. */
|
||||
if (buf[0] != '\033')
|
||||
return (-1);
|
||||
if (len == 1)
|
||||
return (1);
|
||||
if (buf[1] != '[')
|
||||
return (-1);
|
||||
if (len == 2)
|
||||
return (1);
|
||||
if (buf[2] != 'I' && buf[2] != 'T')
|
||||
return (-1);
|
||||
if (len == 3)
|
||||
return (1);
|
||||
|
||||
/* Copy the rest up to a 'n'. */
|
||||
for (i = 0; i < (sizeof tmp) - 1 && buf[2 + i] != 'n'; i++) {
|
||||
if (2 + i == len)
|
||||
return (1);
|
||||
tmp[i] = buf[2 + i];
|
||||
}
|
||||
if (i == (sizeof tmp) - 1)
|
||||
return (-1);
|
||||
tmp[i] = '\0';
|
||||
*size = 3 + i;
|
||||
|
||||
/* Set terminal flags. */
|
||||
if (strncmp(tmp, "ITERM2 ", 7) == 0)
|
||||
flags |= (TERM_DECSLRM|TERM_256COLOURS|TERM_RGBCOLOURS);
|
||||
if (strncmp(tmp, "TMUX ", 5) == 0)
|
||||
flags |= (TERM_256COLOURS|TERM_RGBCOLOURS);
|
||||
log_debug("%s: received DSR %.*s", c->name, (int)*size, buf);
|
||||
|
||||
tty_set_flags(tty, flags);
|
||||
tty->flags |= TTY_HAVEDSR;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
30
tty-term.c
30
tty-term.c
@ -529,11 +529,16 @@ tty_term_find(char *name, int fd, char **cause)
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* Figure out if we have 256 colours (or more). */
|
||||
if (tty_term_number(term, TTYC_COLORS) >= 256 ||
|
||||
tty_term_has(term, TTYC_RGB))
|
||||
/* Set flag if terminal has 256 colours. */
|
||||
if (tty_term_number(term, TTYC_COLORS) >= 256)
|
||||
term->flags |= TERM_256COLOURS;
|
||||
|
||||
/* Set flag if terminal has RGB colours. */
|
||||
if ((tty_term_flag(term, TTYC_TC) || tty_term_has(term, TTYC_RGB)) ||
|
||||
(tty_term_has(term, TTYC_SETRGBF) &&
|
||||
tty_term_has(term, TTYC_SETRGBB)))
|
||||
term->flags |= TERM_RGBCOLOURS;
|
||||
|
||||
/*
|
||||
* Terminals without xenl (eat newline glitch) wrap at at $COLUMNS - 1
|
||||
* rather than $COLUMNS (the cursor can never be beyond $COLUMNS - 1).
|
||||
@ -545,7 +550,7 @@ tty_term_find(char *name, int fd, char **cause)
|
||||
* do the best possible.
|
||||
*/
|
||||
if (!tty_term_flag(term, TTYC_XENL))
|
||||
term->flags |= TERM_EARLYWRAP;
|
||||
term->flags |= TERM_NOXENL;
|
||||
|
||||
/* Generate ACS table. If none is present, use nearest ASCII. */
|
||||
memset(term->acs, 0, sizeof term->acs);
|
||||
@ -568,22 +573,7 @@ tty_term_find(char *name, int fd, char **cause)
|
||||
code->type = TTYCODE_STRING;
|
||||
}
|
||||
|
||||
/*
|
||||
* On terminals with RGB colour (Tc or RGB), fill in setrgbf and
|
||||
* setrgbb if they are missing.
|
||||
*/
|
||||
if ((tty_term_flag(term, TTYC_TC) || tty_term_flag(term, TTYC_RGB)) &&
|
||||
!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;
|
||||
}
|
||||
|
||||
/* Log it. */
|
||||
/* Log the capabilities. */
|
||||
for (i = 0; i < tty_term_ncodes(); i++)
|
||||
log_debug("%s%s", name, tty_term_describe(term, i));
|
||||
|
||||
|
67
tty.c
67
tty.c
@ -74,7 +74,7 @@ static void tty_default_attributes(struct tty *, struct window_pane *,
|
||||
u_int);
|
||||
|
||||
#define tty_use_margin(tty) \
|
||||
((tty)->term_type == TTY_VT420)
|
||||
((tty->term->flags|tty->term_flags) & TERM_DECSLRM)
|
||||
|
||||
#define tty_pane_full_width(tty, ctx) \
|
||||
((ctx)->xoff == 0 && screen_size_x((ctx)->wp->screen) >= (tty)->sx)
|
||||
@ -115,9 +115,7 @@ tty_init(struct tty *tty, struct client *c, int fd, char *term)
|
||||
tty->ccolour = xstrdup("");
|
||||
|
||||
tty->flags = 0;
|
||||
|
||||
tty->term_flags = 0;
|
||||
tty->term_type = TTY_UNKNOWN;
|
||||
|
||||
return (0);
|
||||
}
|
||||
@ -292,11 +290,22 @@ tty_open(struct tty *tty, char **cause)
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void
|
||||
tty_start_timer_callback(__unused int fd, __unused short events, void *data)
|
||||
{
|
||||
struct tty *tty = data;
|
||||
struct client *c = tty->client;
|
||||
|
||||
log_debug("%s: start timer fired", c->name);
|
||||
tty->flags |= (TTY_HAVEDA|TTY_HAVEDSR);
|
||||
}
|
||||
|
||||
void
|
||||
tty_start_tty(struct tty *tty)
|
||||
{
|
||||
struct client *c = tty->client;
|
||||
struct termios tio;
|
||||
struct timeval tv = { .tv_sec = 1 };
|
||||
|
||||
if (tty->fd != -1 && tcgetattr(tty->fd, &tty->tio) == 0) {
|
||||
setblocking(tty->fd, 0);
|
||||
@ -334,8 +343,15 @@ tty_start_tty(struct tty *tty)
|
||||
tty->flags |= TTY_FOCUS;
|
||||
tty_puts(tty, "\033[?1004h");
|
||||
}
|
||||
if (~tty->flags & TTY_HAVEDA)
|
||||
tty_puts(tty, "\033[c");
|
||||
}
|
||||
if (~tty->flags & TTY_HAVEDSR)
|
||||
tty_puts(tty, "\033[1337n");
|
||||
} else
|
||||
tty->flags |= (TTY_HAVEDA|TTY_HAVEDSR);
|
||||
|
||||
evtimer_set(&tty->start_timer, tty_start_timer_callback, tty);
|
||||
evtimer_add(&tty->start_timer, &tv);
|
||||
|
||||
tty->flags |= TTY_STARTED;
|
||||
tty_invalidate(tty);
|
||||
@ -357,6 +373,8 @@ tty_stop_tty(struct tty *tty)
|
||||
return;
|
||||
tty->flags &= ~TTY_STARTED;
|
||||
|
||||
evtimer_del(&tty->start_timer);
|
||||
|
||||
event_del(&tty->timer);
|
||||
tty->flags &= ~TTY_BLOCK;
|
||||
|
||||
@ -443,9 +461,8 @@ tty_free(struct tty *tty)
|
||||
}
|
||||
|
||||
void
|
||||
tty_set_type(struct tty *tty, int type, int flags)
|
||||
tty_set_flags(struct tty *tty, int flags)
|
||||
{
|
||||
tty->term_type = type;
|
||||
tty->term_flags |= flags;
|
||||
|
||||
if (tty_use_margin(tty))
|
||||
@ -549,7 +566,7 @@ tty_putc(struct tty *tty, u_char ch)
|
||||
{
|
||||
const char *acs;
|
||||
|
||||
if ((tty->term->flags & TERM_EARLYWRAP) &&
|
||||
if ((tty->term->flags & TERM_NOXENL) &&
|
||||
ch >= 0x20 && ch != 0x7f &&
|
||||
tty->cy == tty->sy - 1 &&
|
||||
tty->cx + 1 >= tty->sx)
|
||||
@ -575,7 +592,7 @@ tty_putc(struct tty *tty, u_char ch)
|
||||
* where we think it should be after a line wrap - this
|
||||
* means it works on sensible terminals as well.
|
||||
*/
|
||||
if (tty->term->flags & TERM_EARLYWRAP)
|
||||
if (tty->term->flags & TERM_NOXENL)
|
||||
tty_putcode2(tty, TTYC_CUP, tty->cy, tty->cx);
|
||||
} else
|
||||
tty->cx++;
|
||||
@ -585,7 +602,7 @@ tty_putc(struct tty *tty, u_char ch)
|
||||
void
|
||||
tty_putn(struct tty *tty, const void *buf, size_t len, u_int width)
|
||||
{
|
||||
if ((tty->term->flags & TERM_EARLYWRAP) &&
|
||||
if ((tty->term->flags & TERM_NOXENL) &&
|
||||
tty->cy == tty->sy - 1 &&
|
||||
tty->cx + len >= tty->sx)
|
||||
len = tty->sx - tty->cx - 1;
|
||||
@ -1135,7 +1152,8 @@ tty_clear_area(struct tty *tty, struct window_pane *wp, u_int py, u_int ny,
|
||||
* background colour isn't default (because it doesn't work
|
||||
* after SGR 0).
|
||||
*/
|
||||
if (tty->term_type == TTY_VT420 && !COLOUR_DEFAULT(bg)) {
|
||||
if (((tty->term->flags|tty->term_flags) & TERM_DECFRA) &&
|
||||
!COLOUR_DEFAULT(bg)) {
|
||||
xsnprintf(tmp, sizeof tmp, "\033[32;%u;%u;%u;%u$x",
|
||||
py + 1, px + 1, py + ny, px + nx);
|
||||
tty_puts(tty, tmp);
|
||||
@ -1862,7 +1880,7 @@ tty_cmd_cells(struct tty *tty, const struct tty_ctx *ctx)
|
||||
ctx->xoff + ctx->ocx + ctx->num > ctx->ox + ctx->sx)) {
|
||||
if (!ctx->wrapped ||
|
||||
!tty_pane_full_width(tty, ctx) ||
|
||||
(tty->term->flags & TERM_EARLYWRAP) ||
|
||||
(tty->term->flags & TERM_NOXENL) ||
|
||||
ctx->xoff + ctx->ocx != 0 ||
|
||||
ctx->yoff + ctx->ocy != tty->cy + 1 ||
|
||||
tty->cx < tty->sx ||
|
||||
@ -1957,7 +1975,7 @@ tty_cell(struct tty *tty, const struct grid_cell *gc, struct window_pane *wp)
|
||||
const struct grid_cell *gcp;
|
||||
|
||||
/* Skip last character if terminal is stupid. */
|
||||
if ((tty->term->flags & TERM_EARLYWRAP) &&
|
||||
if ((tty->term->flags & TERM_NOXENL) &&
|
||||
tty->cy == tty->sy - 1 &&
|
||||
tty->cx == tty->sx - 1)
|
||||
return;
|
||||
@ -2116,7 +2134,7 @@ tty_cursor_pane_unless_wrap(struct tty *tty, const struct tty_ctx *ctx,
|
||||
{
|
||||
if (!ctx->wrapped ||
|
||||
!tty_pane_full_width(tty, ctx) ||
|
||||
(tty->term->flags & TERM_EARLYWRAP) ||
|
||||
(tty->term->flags & TERM_NOXENL) ||
|
||||
ctx->xoff + cx != 0 ||
|
||||
ctx->yoff + cy != tty->cy + 1 ||
|
||||
tty->cx < tty->sx ||
|
||||
@ -2453,11 +2471,10 @@ tty_check_fg(struct tty *tty, struct window_pane *wp, struct grid_cell *gc)
|
||||
/* 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_has(tty->term, TTYC_SETRGBF)) {
|
||||
if ((tty->term->flags|tty->term_flags) & TERM_RGBCOLOURS)
|
||||
return;
|
||||
colour_split_rgb(gc->fg, &r, &g, &b);
|
||||
gc->fg = colour_find_rgb(r, g, b);
|
||||
} else
|
||||
return;
|
||||
}
|
||||
|
||||
/* How many colours does this terminal have? */
|
||||
@ -2503,11 +2520,10 @@ tty_check_bg(struct tty *tty, struct window_pane *wp, struct grid_cell *gc)
|
||||
/* 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_has(tty->term, TTYC_SETRGBB)) {
|
||||
if ((tty->term->flags|tty->term_flags) & TERM_RGBCOLOURS)
|
||||
return;
|
||||
colour_split_rgb(gc->bg, &r, &g, &b);
|
||||
gc->bg = colour_find_rgb(r, g, b);
|
||||
} else
|
||||
return;
|
||||
}
|
||||
|
||||
/* How many colours does this terminal have? */
|
||||
@ -2684,15 +2700,14 @@ tty_try_colour(struct tty *tty, int colour, const char *type)
|
||||
}
|
||||
|
||||
if (colour & COLOUR_FLAG_RGB) {
|
||||
colour_split_rgb(colour & 0xffffff, &r, &g, &b);
|
||||
if (*type == '3') {
|
||||
if (!tty_term_has(tty->term, TTYC_SETRGBF))
|
||||
return (-1);
|
||||
colour_split_rgb(colour & 0xffffff, &r, &g, &b);
|
||||
goto fallback_rgb;
|
||||
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);
|
||||
goto fallback_rgb;
|
||||
tty_putcode3(tty, TTYC_SETRGBB, r, g, b);
|
||||
}
|
||||
return (0);
|
||||
@ -2705,6 +2720,12 @@ fallback_256:
|
||||
log_debug("%s: 256 colour fallback: %s", tty->client->name, s);
|
||||
tty_puts(tty, s);
|
||||
return (0);
|
||||
|
||||
fallback_rgb:
|
||||
xsnprintf(s, sizeof s, "\033[%s;2;%d;%d;%dm", type, r, g, b);
|
||||
log_debug("%s: RGB colour fallback: %s", tty->client->name, s);
|
||||
tty_puts(tty, s);
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -210,7 +210,7 @@ window_client_draw(__unused void *modedata, void *itemdata,
|
||||
struct window_pane *wp;
|
||||
u_int cx = s->cx, cy = s->cy, lines, at;
|
||||
|
||||
if (c->session == NULL || (c->flags & (CLIENT_DEAD|CLIENT_DETACHING)))
|
||||
if (c->session == NULL || (c->flags & CLIENT_UNATTACHEDFLAGS))
|
||||
return;
|
||||
wp = c->session->curw->window->active;
|
||||
|
||||
|
14
window.c
14
window.c
@ -1239,7 +1239,7 @@ window_pane_reset_mode_all(struct window_pane *wp)
|
||||
window_pane_reset_mode(wp);
|
||||
}
|
||||
|
||||
void
|
||||
int
|
||||
window_pane_key(struct window_pane *wp, struct client *c, struct session *s,
|
||||
struct winlink *wl, key_code key, struct mouse_event *m)
|
||||
{
|
||||
@ -1247,23 +1247,24 @@ window_pane_key(struct window_pane *wp, struct client *c, struct session *s,
|
||||
struct window_pane *wp2;
|
||||
|
||||
if (KEYC_IS_MOUSE(key) && m == NULL)
|
||||
return;
|
||||
return (-1);
|
||||
|
||||
wme = TAILQ_FIRST(&wp->modes);
|
||||
if (wme != NULL) {
|
||||
wp->modelast = time(NULL);
|
||||
if (wme->mode->key != NULL)
|
||||
wme->mode->key(wme, c, s, wl, (key & ~KEYC_XTERM), m);
|
||||
return;
|
||||
return (0);
|
||||
}
|
||||
|
||||
if (wp->fd == -1 || wp->flags & PANE_INPUTOFF)
|
||||
return;
|
||||
return (0);
|
||||
|
||||
input_key(wp, key, m);
|
||||
if (input_key(wp, key, m) != 0)
|
||||
return (-1);
|
||||
|
||||
if (KEYC_IS_MOUSE(key))
|
||||
return;
|
||||
return (0);
|
||||
if (options_get_number(wp->window->options, "synchronize-panes")) {
|
||||
TAILQ_FOREACH(wp2, &wp->window->panes, entry) {
|
||||
if (wp2 != wp &&
|
||||
@ -1274,6 +1275,7 @@ window_pane_key(struct window_pane *wp, struct client *c, struct session *s,
|
||||
input_key(wp2, key, NULL);
|
||||
}
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
|
Loading…
Reference in New Issue
Block a user