mirror of
https://github.com/tmux/tmux.git
synced 2024-12-24 18:38:48 +00:00
Merge branch 'obsd-master'
This commit is contained in:
commit
21e00e4635
203
arguments.c
203
arguments.c
@ -37,6 +37,10 @@ struct args_entry {
|
|||||||
u_char flag;
|
u_char flag;
|
||||||
struct args_values values;
|
struct args_values values;
|
||||||
u_int count;
|
u_int count;
|
||||||
|
|
||||||
|
int flags;
|
||||||
|
#define ARGS_ENTRY_OPTIONAL_VALUE 0x1
|
||||||
|
|
||||||
RB_ENTRY(args_entry) entry;
|
RB_ENTRY(args_entry) entry;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -122,6 +126,101 @@ args_create(void)
|
|||||||
return (args);
|
return (args);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Parse a single flag. */
|
||||||
|
static int
|
||||||
|
args_parse_flag_argument(struct args_value *values, u_int count, char **cause,
|
||||||
|
struct args *args, u_int *i, const char *string, int flag,
|
||||||
|
int optional_argument)
|
||||||
|
{
|
||||||
|
struct args_value *argument, *new;
|
||||||
|
const char *s;
|
||||||
|
|
||||||
|
new = xcalloc(1, sizeof *new);
|
||||||
|
if (*string != '\0') {
|
||||||
|
new->type = ARGS_STRING;
|
||||||
|
new->string = xstrdup(string);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*i == count)
|
||||||
|
argument = NULL;
|
||||||
|
else {
|
||||||
|
argument = &values[*i];
|
||||||
|
if (argument->type != ARGS_STRING) {
|
||||||
|
xasprintf(cause, "-%c argument must be a string", flag);
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
if (argument->string[0] == '-')
|
||||||
|
argument = NULL;
|
||||||
|
}
|
||||||
|
if (argument == NULL) {
|
||||||
|
if (optional_argument) {
|
||||||
|
log_debug("%s: -%c (optional)", __func__, flag);
|
||||||
|
args_set(args, flag, NULL, ARGS_ENTRY_OPTIONAL_VALUE);
|
||||||
|
return (0); /* either - or end */
|
||||||
|
}
|
||||||
|
xasprintf(cause, "-%c expects an argument", flag);
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
args_copy_value(new, argument);
|
||||||
|
(*i)++;
|
||||||
|
|
||||||
|
out:
|
||||||
|
s = args_value_as_string(new);
|
||||||
|
log_debug("%s: -%c = %s", __func__, flag, s);
|
||||||
|
args_set(args, flag, new, 0);
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Parse flags argument. */
|
||||||
|
static int
|
||||||
|
args_parse_flags(const struct args_parse *parse, struct args_value *values,
|
||||||
|
u_int count, char **cause, struct args *args, int *i)
|
||||||
|
{
|
||||||
|
struct args_value *value;
|
||||||
|
u_char flag;
|
||||||
|
const char *found, *string;
|
||||||
|
int optional_argument;
|
||||||
|
|
||||||
|
value = &values[*i];
|
||||||
|
if (value->type != ARGS_STRING)
|
||||||
|
return (1);
|
||||||
|
|
||||||
|
string = value->string;
|
||||||
|
log_debug("%s: next %s", __func__, string);
|
||||||
|
if (*string++ != '-' || *string == '\0')
|
||||||
|
return (1);
|
||||||
|
(*i)++;
|
||||||
|
if (string[0] == '-' && string[1] == '\0')
|
||||||
|
return (1);
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
flag = *string++;
|
||||||
|
if (flag == '\0')
|
||||||
|
return (0);
|
||||||
|
if (flag == '?')
|
||||||
|
return (-1);
|
||||||
|
if (!isalnum(flag)) {
|
||||||
|
xasprintf(cause, "invalid flag -%c", flag);
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
found = strchr(parse->template, flag);
|
||||||
|
if (found == NULL) {
|
||||||
|
xasprintf(cause, "unknown flag -%c", flag);
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
if (*++found != ':') {
|
||||||
|
log_debug("%s: -%c", __func__, flag);
|
||||||
|
args_set(args, flag, NULL, 0);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
optional_argument = (*found == ':');
|
||||||
|
return (args_parse_flag_argument(values, count, cause, args, i,
|
||||||
|
string, flag, optional_argument));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Parse arguments into a new argument set. */
|
/* Parse arguments into a new argument set. */
|
||||||
struct args *
|
struct args *
|
||||||
args_parse(const struct args_parse *parse, struct args_value *values,
|
args_parse(const struct args_parse *parse, struct args_value *values,
|
||||||
@ -131,86 +230,21 @@ args_parse(const struct args_parse *parse, struct args_value *values,
|
|||||||
u_int i;
|
u_int i;
|
||||||
enum args_parse_type type;
|
enum args_parse_type type;
|
||||||
struct args_value *value, *new;
|
struct args_value *value, *new;
|
||||||
u_char flag;
|
const char *s;
|
||||||
const char *found, *string, *s;
|
int stop;
|
||||||
int optional_argument;
|
|
||||||
|
|
||||||
if (count == 0)
|
if (count == 0)
|
||||||
return (args_create());
|
return (args_create());
|
||||||
|
|
||||||
args = args_create();
|
args = args_create();
|
||||||
for (i = 1; i < count; /* nothing */) {
|
for (i = 1; i < count; /* nothing */) {
|
||||||
value = &values[i];
|
stop = args_parse_flags(parse, values, count, cause, args, &i);
|
||||||
if (value->type != ARGS_STRING)
|
if (stop == -1) {
|
||||||
break;
|
args_free(args);
|
||||||
|
return (NULL);
|
||||||
string = value->string;
|
|
||||||
if (*string++ != '-' || *string == '\0')
|
|
||||||
break;
|
|
||||||
i++;
|
|
||||||
if (string[0] == '-' && string[1] == '\0')
|
|
||||||
break;
|
|
||||||
|
|
||||||
for (;;) {
|
|
||||||
flag = *string++;
|
|
||||||
if (flag == '\0')
|
|
||||||
break;
|
|
||||||
if (flag == '?') {
|
|
||||||
args_free(args);
|
|
||||||
return (NULL);
|
|
||||||
}
|
|
||||||
if (!isalnum(flag)) {
|
|
||||||
xasprintf(cause, "invalid flag -%c", flag);
|
|
||||||
args_free(args);
|
|
||||||
return (NULL);
|
|
||||||
}
|
|
||||||
found = strchr(parse->template, flag);
|
|
||||||
if (found == NULL) {
|
|
||||||
xasprintf(cause, "unknown flag -%c", flag);
|
|
||||||
args_free(args);
|
|
||||||
return (NULL);
|
|
||||||
}
|
|
||||||
if (*++found != ':') {
|
|
||||||
log_debug("%s: -%c", __func__, flag);
|
|
||||||
args_set(args, flag, NULL);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (*found == ':') {
|
|
||||||
optional_argument = 1;
|
|
||||||
found++;
|
|
||||||
}
|
|
||||||
new = xcalloc(1, sizeof *new);
|
|
||||||
if (*string != '\0') {
|
|
||||||
new->type = ARGS_STRING;
|
|
||||||
new->string = xstrdup(string);
|
|
||||||
} else {
|
|
||||||
if (i == count) {
|
|
||||||
if (optional_argument) {
|
|
||||||
log_debug("%s: -%c", __func__,
|
|
||||||
flag);
|
|
||||||
args_set(args, flag, NULL);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
xasprintf(cause,
|
|
||||||
"-%c expects an argument",
|
|
||||||
flag);
|
|
||||||
args_free(args);
|
|
||||||
return (NULL);
|
|
||||||
}
|
|
||||||
if (values[i].type != ARGS_STRING) {
|
|
||||||
xasprintf(cause,
|
|
||||||
"-%c argument must be a string",
|
|
||||||
flag);
|
|
||||||
args_free(args);
|
|
||||||
return (NULL);
|
|
||||||
}
|
|
||||||
args_copy_value(new, &values[i++]);
|
|
||||||
}
|
|
||||||
s = args_value_as_string(new);
|
|
||||||
log_debug("%s: -%c = %s", __func__, flag, s);
|
|
||||||
args_set(args, flag, new);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
if (stop == 1)
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
log_debug("%s: flags end at %u of %u", __func__, i, count);
|
log_debug("%s: flags end at %u of %u", __func__, i, count);
|
||||||
if (i != count) {
|
if (i != count) {
|
||||||
@ -323,13 +357,13 @@ args_copy(struct args *args, int argc, char **argv)
|
|||||||
RB_FOREACH(entry, args_tree, &args->tree) {
|
RB_FOREACH(entry, args_tree, &args->tree) {
|
||||||
if (TAILQ_EMPTY(&entry->values)) {
|
if (TAILQ_EMPTY(&entry->values)) {
|
||||||
for (i = 0; i < entry->count; i++)
|
for (i = 0; i < entry->count; i++)
|
||||||
args_set(new_args, entry->flag, NULL);
|
args_set(new_args, entry->flag, NULL, 0);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
TAILQ_FOREACH(value, &entry->values, entry) {
|
TAILQ_FOREACH(value, &entry->values, entry) {
|
||||||
new_value = xcalloc(1, sizeof *new_value);
|
new_value = xcalloc(1, sizeof *new_value);
|
||||||
args_copy_copy_value(new_value, value, argc, argv);
|
args_copy_copy_value(new_value, value, argc, argv);
|
||||||
args_set(new_args, entry->flag, new_value);
|
args_set(new_args, entry->flag, new_value, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (args->count == 0)
|
if (args->count == 0)
|
||||||
@ -487,6 +521,7 @@ args_print(struct args *args)
|
|||||||
char *buf;
|
char *buf;
|
||||||
u_int i, j;
|
u_int i, j;
|
||||||
struct args_entry *entry;
|
struct args_entry *entry;
|
||||||
|
struct args_entry *last = NULL;
|
||||||
struct args_value *value;
|
struct args_value *value;
|
||||||
|
|
||||||
len = 1;
|
len = 1;
|
||||||
@ -494,6 +529,8 @@ args_print(struct args *args)
|
|||||||
|
|
||||||
/* Process the flags first. */
|
/* Process the flags first. */
|
||||||
RB_FOREACH(entry, args_tree, &args->tree) {
|
RB_FOREACH(entry, args_tree, &args->tree) {
|
||||||
|
if (entry->flags & ARGS_ENTRY_OPTIONAL_VALUE)
|
||||||
|
continue;
|
||||||
if (!TAILQ_EMPTY(&entry->values))
|
if (!TAILQ_EMPTY(&entry->values))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@ -505,6 +542,16 @@ args_print(struct args *args)
|
|||||||
|
|
||||||
/* Then the flags with arguments. */
|
/* Then the flags with arguments. */
|
||||||
RB_FOREACH(entry, args_tree, &args->tree) {
|
RB_FOREACH(entry, args_tree, &args->tree) {
|
||||||
|
if (entry->flags & ARGS_ENTRY_OPTIONAL_VALUE) {
|
||||||
|
if (*buf != '\0')
|
||||||
|
args_print_add(&buf, &len, " -%c", entry->flag);
|
||||||
|
else
|
||||||
|
args_print_add(&buf, &len, "-%c", entry->flag);
|
||||||
|
last = entry;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (TAILQ_EMPTY(&entry->values))
|
||||||
|
continue;
|
||||||
TAILQ_FOREACH(value, &entry->values, entry) {
|
TAILQ_FOREACH(value, &entry->values, entry) {
|
||||||
if (*buf != '\0')
|
if (*buf != '\0')
|
||||||
args_print_add(&buf, &len, " -%c", entry->flag);
|
args_print_add(&buf, &len, " -%c", entry->flag);
|
||||||
@ -512,7 +559,10 @@ args_print(struct args *args)
|
|||||||
args_print_add(&buf, &len, "-%c", entry->flag);
|
args_print_add(&buf, &len, "-%c", entry->flag);
|
||||||
args_print_add_value(&buf, &len, value);
|
args_print_add_value(&buf, &len, value);
|
||||||
}
|
}
|
||||||
|
last = entry;
|
||||||
}
|
}
|
||||||
|
if (last && (last->flags & ARGS_ENTRY_OPTIONAL_VALUE))
|
||||||
|
args_print_add(&buf, &len, " --");
|
||||||
|
|
||||||
/* And finally the argument vector. */
|
/* And finally the argument vector. */
|
||||||
for (i = 0; i < args->count; i++)
|
for (i = 0; i < args->count; i++)
|
||||||
@ -582,7 +632,7 @@ args_has(struct args *args, u_char flag)
|
|||||||
|
|
||||||
/* Set argument value in the arguments tree. */
|
/* Set argument value in the arguments tree. */
|
||||||
void
|
void
|
||||||
args_set(struct args *args, u_char flag, struct args_value *value)
|
args_set(struct args *args, u_char flag, struct args_value *value, int flags)
|
||||||
{
|
{
|
||||||
struct args_entry *entry;
|
struct args_entry *entry;
|
||||||
|
|
||||||
@ -591,6 +641,7 @@ args_set(struct args *args, u_char flag, struct args_value *value)
|
|||||||
entry = xcalloc(1, sizeof *entry);
|
entry = xcalloc(1, sizeof *entry);
|
||||||
entry->flag = flag;
|
entry->flag = flag;
|
||||||
entry->count = 1;
|
entry->count = 1;
|
||||||
|
entry->flags = flags;
|
||||||
TAILQ_INIT(&entry->values);
|
TAILQ_INIT(&entry->values);
|
||||||
RB_INSERT(args_tree, &args->tree, entry);
|
RB_INSERT(args_tree, &args->tree, entry);
|
||||||
} else
|
} else
|
||||||
|
3
client.c
3
client.c
@ -700,6 +700,9 @@ client_dispatch_wait(struct imsg *imsg)
|
|||||||
!(client_flags & CLIENT_CONTROL), client_file_check_cb,
|
!(client_flags & CLIENT_CONTROL), client_file_check_cb,
|
||||||
NULL);
|
NULL);
|
||||||
break;
|
break;
|
||||||
|
case MSG_READ_CANCEL:
|
||||||
|
file_read_cancel(&client_files, imsg);
|
||||||
|
break;
|
||||||
case MSG_WRITE_OPEN:
|
case MSG_WRITE_OPEN:
|
||||||
file_write_open(&client_files, client_peer, imsg, 1,
|
file_write_open(&client_files, client_peer, imsg, 1,
|
||||||
!(client_flags & CLIENT_CONTROL), client_file_check_cb,
|
!(client_flags & CLIENT_CONTROL), client_file_check_cb,
|
||||||
|
@ -103,8 +103,8 @@ cmd_find_window_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
|
|
||||||
new_args = args_create();
|
new_args = args_create();
|
||||||
if (args_has(args, 'Z'))
|
if (args_has(args, 'Z'))
|
||||||
args_set(new_args, 'Z', NULL);
|
args_set(new_args, 'Z', NULL, 0);
|
||||||
args_set(new_args, 'f', filter);
|
args_set(new_args, 'f', filter, 0);
|
||||||
|
|
||||||
window_pane_set_mode(wp, NULL, &window_tree_mode, target, new_args);
|
window_pane_set_mode(wp, NULL, &window_tree_mode, target, new_args);
|
||||||
args_free(new_args);
|
args_free(new_args);
|
||||||
|
@ -833,7 +833,8 @@ cmdq_print_data(struct cmdq_item *item, int parse, struct evbuffer *evb)
|
|||||||
char *sanitized, *msg, *line;
|
char *sanitized, *msg, *line;
|
||||||
|
|
||||||
if (!parse) {
|
if (!parse) {
|
||||||
utf8_stravisx(&msg, data, size, VIS_OCTAL|VIS_CSTYLE|VIS_TAB);
|
utf8_stravisx(&msg, data, size,
|
||||||
|
VIS_OCTAL|VIS_CSTYLE|VIS_NOSLASH);
|
||||||
log_debug("%s: %s", __func__, msg);
|
log_debug("%s: %s", __func__, msg);
|
||||||
} else {
|
} else {
|
||||||
msg = EVBUFFER_DATA(evb);
|
msg = EVBUFFER_DATA(evb);
|
||||||
|
@ -33,13 +33,13 @@ const struct cmd_entry cmd_send_keys_entry = {
|
|||||||
.name = "send-keys",
|
.name = "send-keys",
|
||||||
.alias = "send",
|
.alias = "send",
|
||||||
|
|
||||||
.args = { "FHlMN:Rt:X", 0, -1, NULL },
|
.args = { "c:FHKlMN:Rt:X", 0, -1, NULL },
|
||||||
.usage = "[-FHlMRX] [-N repeat-count] " CMD_TARGET_PANE_USAGE
|
.usage = "[-FHKlMRX] [-c target-client] [-N repeat-count] "
|
||||||
" key ...",
|
CMD_TARGET_PANE_USAGE " key ...",
|
||||||
|
|
||||||
.target = { 't', CMD_FIND_PANE, 0 },
|
.target = { 't', CMD_FIND_PANE, 0 },
|
||||||
|
|
||||||
.flags = CMD_AFTERHOOK,
|
.flags = CMD_AFTERHOOK|CMD_CLIENT_CFLAG|CMD_CLIENT_CANFAIL,
|
||||||
.exec = cmd_send_keys_exec
|
.exec = cmd_send_keys_exec
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -58,7 +58,7 @@ const struct cmd_entry cmd_send_prefix_entry = {
|
|||||||
|
|
||||||
static struct cmdq_item *
|
static struct cmdq_item *
|
||||||
cmd_send_keys_inject_key(struct cmdq_item *item, struct cmdq_item *after,
|
cmd_send_keys_inject_key(struct cmdq_item *item, struct cmdq_item *after,
|
||||||
key_code key)
|
struct args *args, key_code key)
|
||||||
{
|
{
|
||||||
struct cmd_find_state *target = cmdq_get_target(item);
|
struct cmd_find_state *target = cmdq_get_target(item);
|
||||||
struct client *tc = cmdq_get_target_client(item);
|
struct client *tc = cmdq_get_target_client(item);
|
||||||
@ -66,8 +66,20 @@ cmd_send_keys_inject_key(struct cmdq_item *item, struct cmdq_item *after,
|
|||||||
struct winlink *wl = target->wl;
|
struct winlink *wl = target->wl;
|
||||||
struct window_pane *wp = target->wp;
|
struct window_pane *wp = target->wp;
|
||||||
struct window_mode_entry *wme;
|
struct window_mode_entry *wme;
|
||||||
struct key_table *table;
|
struct key_table *table = NULL;
|
||||||
struct key_binding *bd;
|
struct key_binding *bd;
|
||||||
|
struct key_event *event;
|
||||||
|
|
||||||
|
if (args_has(args, 'K')) {
|
||||||
|
if (tc == NULL)
|
||||||
|
return (item);
|
||||||
|
event = xmalloc(sizeof *event);
|
||||||
|
event->key = key;
|
||||||
|
memset(&event->m, 0, sizeof event->m);
|
||||||
|
if (server_client_handle_key(tc, event) == 0)
|
||||||
|
free(event);
|
||||||
|
return (item);
|
||||||
|
}
|
||||||
|
|
||||||
wme = TAILQ_FIRST(&wp->modes);
|
wme = TAILQ_FIRST(&wp->modes);
|
||||||
if (wme == NULL || wme->mode->key_table == NULL) {
|
if (wme == NULL || wme->mode->key_table == NULL) {
|
||||||
@ -102,14 +114,16 @@ cmd_send_keys_inject_string(struct cmdq_item *item, struct cmdq_item *after,
|
|||||||
n = strtol(s, &endptr, 16);
|
n = strtol(s, &endptr, 16);
|
||||||
if (*s =='\0' || n < 0 || n > 0xff || *endptr != '\0')
|
if (*s =='\0' || n < 0 || n > 0xff || *endptr != '\0')
|
||||||
return (item);
|
return (item);
|
||||||
return (cmd_send_keys_inject_key(item, after, KEYC_LITERAL|n));
|
return (cmd_send_keys_inject_key(item, after, args,
|
||||||
|
KEYC_LITERAL|n));
|
||||||
}
|
}
|
||||||
|
|
||||||
literal = args_has(args, 'l');
|
literal = args_has(args, 'l');
|
||||||
if (!literal) {
|
if (!literal) {
|
||||||
key = key_string_lookup_string(s);
|
key = key_string_lookup_string(s);
|
||||||
if (key != KEYC_NONE && key != KEYC_UNKNOWN) {
|
if (key != KEYC_NONE && key != KEYC_UNKNOWN) {
|
||||||
after = cmd_send_keys_inject_key(item, after, key);
|
after = cmd_send_keys_inject_key(item, after, args,
|
||||||
|
key);
|
||||||
if (after != NULL)
|
if (after != NULL)
|
||||||
return (after);
|
return (after);
|
||||||
}
|
}
|
||||||
@ -125,7 +139,8 @@ cmd_send_keys_inject_string(struct cmdq_item *item, struct cmdq_item *after,
|
|||||||
continue;
|
continue;
|
||||||
key = uc;
|
key = uc;
|
||||||
}
|
}
|
||||||
after = cmd_send_keys_inject_key(item, after, key);
|
after = cmd_send_keys_inject_key(item, after, args,
|
||||||
|
key);
|
||||||
}
|
}
|
||||||
free(ud);
|
free(ud);
|
||||||
}
|
}
|
||||||
@ -193,7 +208,7 @@ cmd_send_keys_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
key = options_get_number(s->options, "prefix2");
|
key = options_get_number(s->options, "prefix2");
|
||||||
else
|
else
|
||||||
key = options_get_number(s->options, "prefix");
|
key = options_get_number(s->options, "prefix");
|
||||||
cmd_send_keys_inject_key(item, item, key);
|
cmd_send_keys_inject_key(item, item, args, key);
|
||||||
return (CMD_RETURN_NORMAL);
|
return (CMD_RETURN_NORMAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -207,7 +222,7 @@ cmd_send_keys_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
if (args_has(args, 'N') || args_has(args, 'R'))
|
if (args_has(args, 'N') || args_has(args, 'R'))
|
||||||
return (CMD_RETURN_NORMAL);
|
return (CMD_RETURN_NORMAL);
|
||||||
for (; np != 0; np--)
|
for (; np != 0; np--)
|
||||||
cmd_send_keys_inject_key(item, NULL, event->key);
|
cmd_send_keys_inject_key(item, NULL, args, event->key);
|
||||||
return (CMD_RETURN_NORMAL);
|
return (CMD_RETURN_NORMAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
42
colour.c
42
colour.c
@ -960,6 +960,47 @@ colour_byname(const char *name)
|
|||||||
return (-1);
|
return (-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Parse colour from an X11 string. */
|
||||||
|
int
|
||||||
|
colour_parseX11(const char *p)
|
||||||
|
{
|
||||||
|
double c, m, y, k = 0;
|
||||||
|
u_int r, g, b;
|
||||||
|
size_t len = strlen(p);
|
||||||
|
int colour = -1;
|
||||||
|
char *copy;
|
||||||
|
|
||||||
|
if ((len == 12 && sscanf(p, "rgb:%02x/%02x/%02x", &r, &g, &b) == 3) ||
|
||||||
|
(len == 7 && sscanf(p, "#%02x%02x%02x", &r, &g, &b) == 3) ||
|
||||||
|
sscanf(p, "%d,%d,%d", &r, &g, &b) == 3)
|
||||||
|
colour = colour_join_rgb(r, g, b);
|
||||||
|
else if ((len == 18 &&
|
||||||
|
sscanf(p, "rgb:%04x/%04x/%04x", &r, &g, &b) == 3) ||
|
||||||
|
(len == 13 && sscanf(p, "#%04x%04x%04x", &r, &g, &b) == 3))
|
||||||
|
colour = colour_join_rgb(r >> 8, g >> 8, b >> 8);
|
||||||
|
else if ((sscanf(p, "cmyk:%lf/%lf/%lf/%lf", &c, &m, &y, &k) == 4 ||
|
||||||
|
sscanf(p, "cmy:%lf/%lf/%lf", &c, &m, &y) == 3) &&
|
||||||
|
c >= 0 && c <= 1 && m >= 0 && m <= 1 &&
|
||||||
|
y >= 0 && y <= 1 && k >= 0 && k <= 1) {
|
||||||
|
colour = colour_join_rgb(
|
||||||
|
(1 - c) * (1 - k) * 255,
|
||||||
|
(1 - m) * (1 - k) * 255,
|
||||||
|
(1 - y) * (1 - k) * 255);
|
||||||
|
} else {
|
||||||
|
while (len != 0 && *p == ' ') {
|
||||||
|
p++;
|
||||||
|
len--;
|
||||||
|
}
|
||||||
|
while (len != 0 && p[len - 1] == ' ')
|
||||||
|
len--;
|
||||||
|
copy = xstrndup(p, len);
|
||||||
|
colour = colour_byname(copy);
|
||||||
|
free(copy);
|
||||||
|
}
|
||||||
|
log_debug("%s: %s = %s", __func__, p, colour_tostring(colour));
|
||||||
|
return (colour);
|
||||||
|
}
|
||||||
|
|
||||||
/* Initialize palette. */
|
/* Initialize palette. */
|
||||||
void
|
void
|
||||||
colour_palette_init(struct colour_palette *p)
|
colour_palette_init(struct colour_palette *p)
|
||||||
@ -1069,5 +1110,4 @@ colour_palette_from_option(struct colour_palette *p, struct options *oo)
|
|||||||
}
|
}
|
||||||
a = options_array_next(a);
|
a = options_array_next(a);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
44
file.c
44
file.c
@ -149,7 +149,8 @@ file_fire_done_cb(__unused int fd, __unused short events, void *arg)
|
|||||||
struct client_file *cf = arg;
|
struct client_file *cf = arg;
|
||||||
struct client *c = cf->c;
|
struct client *c = cf->c;
|
||||||
|
|
||||||
if (cf->cb != NULL && (c == NULL || (~c->flags & CLIENT_DEAD)))
|
if (cf->cb != NULL &&
|
||||||
|
(cf->closed || c == NULL || (~c->flags & CLIENT_DEAD)))
|
||||||
cf->cb(c, cf->path, cf->error, 1, cf->buffer, cf->data);
|
cf->cb(c, cf->path, cf->error, 1, cf->buffer, cf->data);
|
||||||
file_free(cf);
|
file_free(cf);
|
||||||
}
|
}
|
||||||
@ -352,7 +353,7 @@ done:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Read a file. */
|
/* Read a file. */
|
||||||
void
|
struct client_file *
|
||||||
file_read(struct client *c, const char *path, client_file_cb cb, void *cbdata)
|
file_read(struct client *c, const char *path, client_file_cb cb, void *cbdata)
|
||||||
{
|
{
|
||||||
struct client_file *cf;
|
struct client_file *cf;
|
||||||
@ -420,10 +421,27 @@ skip:
|
|||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
free(msg);
|
free(msg);
|
||||||
return;
|
return cf;
|
||||||
|
|
||||||
done:
|
done:
|
||||||
file_fire_done(cf);
|
file_fire_done(cf);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Cancel a file read. */
|
||||||
|
void
|
||||||
|
file_cancel(struct client_file *cf)
|
||||||
|
{
|
||||||
|
struct msg_read_cancel msg;
|
||||||
|
|
||||||
|
log_debug("read cancel file %d", cf->stream);
|
||||||
|
|
||||||
|
if (cf->closed)
|
||||||
|
return;
|
||||||
|
cf->closed = 1;
|
||||||
|
|
||||||
|
msg.stream = cf->stream;
|
||||||
|
proc_send(cf->peer, MSG_READ_CANCEL, -1, &msg, sizeof msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Push event, fired if there is more writing to be done. */
|
/* Push event, fired if there is more writing to be done. */
|
||||||
@ -757,6 +775,24 @@ reply:
|
|||||||
proc_send(peer, MSG_READ_DONE, -1, &reply, sizeof reply);
|
proc_send(peer, MSG_READ_DONE, -1, &reply, sizeof reply);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Handle a read cancel message (client). */
|
||||||
|
void
|
||||||
|
file_read_cancel(struct client_files *files, struct imsg *imsg)
|
||||||
|
{
|
||||||
|
struct msg_read_cancel *msg = imsg->data;
|
||||||
|
size_t msglen = imsg->hdr.len - IMSG_HEADER_SIZE;
|
||||||
|
struct client_file find, *cf;
|
||||||
|
|
||||||
|
if (msglen != sizeof *msg)
|
||||||
|
fatalx("bad MSG_READ_CANCEL size");
|
||||||
|
find.stream = msg->stream;
|
||||||
|
if ((cf = RB_FIND(client_files, files, &find)) == NULL)
|
||||||
|
fatalx("unknown stream number");
|
||||||
|
log_debug("cancel file %d", cf->stream);
|
||||||
|
|
||||||
|
file_read_error_callback(NULL, 0, cf);
|
||||||
|
}
|
||||||
|
|
||||||
/* Handle a write ready message (server). */
|
/* Handle a write ready message (server). */
|
||||||
void
|
void
|
||||||
file_write_ready(struct client_files *files, struct imsg *imsg)
|
file_write_ready(struct client_files *files, struct imsg *imsg)
|
||||||
@ -794,7 +830,7 @@ file_read_data(struct client_files *files, struct imsg *imsg)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
log_debug("file %d read %zu bytes", cf->stream, bsize);
|
log_debug("file %d read %zu bytes", cf->stream, bsize);
|
||||||
if (cf->error == 0) {
|
if (cf->error == 0 && !cf->closed) {
|
||||||
if (evbuffer_add(cf->buffer, bdata, bsize) != 0) {
|
if (evbuffer_add(cf->buffer, bdata, bsize) != 0) {
|
||||||
cf->error = ENOMEM;
|
cf->error = ENOMEM;
|
||||||
file_fire_done(cf);
|
file_fire_done(cf);
|
||||||
|
115
input.c
115
input.c
@ -1086,6 +1086,7 @@ input_reply(struct input_ctx *ictx, const char *fmt, ...)
|
|||||||
xvasprintf(&reply, fmt, ap);
|
xvasprintf(&reply, fmt, ap);
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
|
|
||||||
|
log_debug("%s: %s", __func__, reply);
|
||||||
bufferevent_write(bev, reply, strlen(reply));
|
bufferevent_write(bev, reply, strlen(reply));
|
||||||
free(reply);
|
free(reply);
|
||||||
}
|
}
|
||||||
@ -2456,47 +2457,6 @@ input_top_bit_set(struct input_ctx *ictx)
|
|||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Parse colour from OSC. */
|
|
||||||
static int
|
|
||||||
input_osc_parse_colour(const char *p)
|
|
||||||
{
|
|
||||||
double c, m, y, k = 0;
|
|
||||||
u_int r, g, b;
|
|
||||||
size_t len = strlen(p);
|
|
||||||
int colour = -1;
|
|
||||||
char *copy;
|
|
||||||
|
|
||||||
if ((len == 12 && sscanf(p, "rgb:%02x/%02x/%02x", &r, &g, &b) == 3) ||
|
|
||||||
(len == 7 && sscanf(p, "#%02x%02x%02x", &r, &g, &b) == 3) ||
|
|
||||||
sscanf(p, "%d,%d,%d", &r, &g, &b) == 3)
|
|
||||||
colour = colour_join_rgb(r, g, b);
|
|
||||||
else if ((len == 18 &&
|
|
||||||
sscanf(p, "rgb:%04x/%04x/%04x", &r, &g, &b) == 3) ||
|
|
||||||
(len == 13 && sscanf(p, "#%04x%04x%04x", &r, &g, &b) == 3))
|
|
||||||
colour = colour_join_rgb(r >> 8, g >> 8, b >> 8);
|
|
||||||
else if ((sscanf(p, "cmyk:%lf/%lf/%lf/%lf", &c, &m, &y, &k) == 4 ||
|
|
||||||
sscanf(p, "cmy:%lf/%lf/%lf", &c, &m, &y) == 3) &&
|
|
||||||
c >= 0 && c <= 1 && m >= 0 && m <= 1 &&
|
|
||||||
y >= 0 && y <= 1 && k >= 0 && k <= 1) {
|
|
||||||
colour = colour_join_rgb(
|
|
||||||
(1 - c) * (1 - k) * 255,
|
|
||||||
(1 - m) * (1 - k) * 255,
|
|
||||||
(1 - y) * (1 - k) * 255);
|
|
||||||
} else {
|
|
||||||
while (len != 0 && *p == ' ') {
|
|
||||||
p++;
|
|
||||||
len--;
|
|
||||||
}
|
|
||||||
while (len != 0 && p[len - 1] == ' ')
|
|
||||||
len--;
|
|
||||||
copy = xstrndup(p, len);
|
|
||||||
colour = colour_byname(copy);
|
|
||||||
free(copy);
|
|
||||||
}
|
|
||||||
log_debug("%s: %s = %s", __func__, p, colour_tostring(colour));
|
|
||||||
return (colour);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Reply to a colour request. */
|
/* Reply to a colour request. */
|
||||||
static void
|
static void
|
||||||
input_osc_colour_reply(struct input_ctx *ictx, u_int n, int c)
|
input_osc_colour_reply(struct input_ctx *ictx, u_int n, int c)
|
||||||
@ -2545,7 +2505,7 @@ input_osc_4(struct input_ctx *ictx, const char *p)
|
|||||||
input_osc_colour_reply(ictx, 4, c);
|
input_osc_colour_reply(ictx, 4, c);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if ((c = input_osc_parse_colour(s)) == -1) {
|
if ((c = colour_parseX11(s)) == -1) {
|
||||||
s = next;
|
s = next;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -2601,6 +2561,47 @@ bad:
|
|||||||
free(id);
|
free(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Get a client with a foreground for the pane. There isn't much to choose
|
||||||
|
* between them so just use the first.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
input_get_fg_client(struct window_pane *wp)
|
||||||
|
{
|
||||||
|
struct window *w = wp->window;
|
||||||
|
struct client *loop;
|
||||||
|
|
||||||
|
TAILQ_FOREACH(loop, &clients, entry) {
|
||||||
|
if (loop->flags & CLIENT_UNATTACHEDFLAGS)
|
||||||
|
continue;
|
||||||
|
if (loop->session == NULL || !session_has(loop->session, w))
|
||||||
|
continue;
|
||||||
|
if (loop->tty.fg == -1)
|
||||||
|
continue;
|
||||||
|
return (loop->tty.fg);
|
||||||
|
}
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get a client with a background for the pane. */
|
||||||
|
static int
|
||||||
|
input_get_bg_client(struct window_pane *wp)
|
||||||
|
{
|
||||||
|
struct window *w = wp->window;
|
||||||
|
struct client *loop;
|
||||||
|
|
||||||
|
TAILQ_FOREACH(loop, &clients, entry) {
|
||||||
|
if (loop->flags & CLIENT_UNATTACHEDFLAGS)
|
||||||
|
continue;
|
||||||
|
if (loop->session == NULL || !session_has(loop->session, w))
|
||||||
|
continue;
|
||||||
|
if (loop->tty.bg == -1)
|
||||||
|
continue;
|
||||||
|
return (loop->tty.bg);
|
||||||
|
}
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
|
||||||
/* Handle the OSC 10 sequence for setting and querying foreground colour. */
|
/* Handle the OSC 10 sequence for setting and querying foreground colour. */
|
||||||
static void
|
static void
|
||||||
input_osc_10(struct input_ctx *ictx, const char *p)
|
input_osc_10(struct input_ctx *ictx, const char *p)
|
||||||
@ -2610,14 +2611,18 @@ input_osc_10(struct input_ctx *ictx, const char *p)
|
|||||||
int c;
|
int c;
|
||||||
|
|
||||||
if (strcmp(p, "?") == 0) {
|
if (strcmp(p, "?") == 0) {
|
||||||
if (wp != NULL) {
|
if (wp == NULL)
|
||||||
tty_default_colours(&defaults, wp);
|
return;
|
||||||
input_osc_colour_reply(ictx, 10, defaults.fg);
|
tty_default_colours(&defaults, wp);
|
||||||
}
|
if (COLOUR_DEFAULT(defaults.fg))
|
||||||
|
c = input_get_fg_client(wp);
|
||||||
|
else
|
||||||
|
c = defaults.fg;
|
||||||
|
input_osc_colour_reply(ictx, 10, c);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((c = input_osc_parse_colour(p)) == -1) {
|
if ((c = colour_parseX11(p)) == -1) {
|
||||||
log_debug("bad OSC 10: %s", p);
|
log_debug("bad OSC 10: %s", p);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -2654,14 +2659,18 @@ input_osc_11(struct input_ctx *ictx, const char *p)
|
|||||||
int c;
|
int c;
|
||||||
|
|
||||||
if (strcmp(p, "?") == 0) {
|
if (strcmp(p, "?") == 0) {
|
||||||
if (wp != NULL) {
|
if (wp == NULL)
|
||||||
tty_default_colours(&defaults, wp);
|
return;
|
||||||
input_osc_colour_reply(ictx, 11, defaults.bg);
|
tty_default_colours(&defaults, wp);
|
||||||
}
|
if (COLOUR_DEFAULT(defaults.bg))
|
||||||
|
c = input_get_bg_client(wp);
|
||||||
|
else
|
||||||
|
c = defaults.bg;
|
||||||
|
input_osc_colour_reply(ictx, 11, c);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((c = input_osc_parse_colour(p)) == -1) {
|
if ((c = colour_parseX11(p)) == -1) {
|
||||||
log_debug("bad OSC 11: %s", p);
|
log_debug("bad OSC 11: %s", p);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -2706,7 +2715,7 @@ input_osc_12(struct input_ctx *ictx, const char *p)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((c = input_osc_parse_colour(p)) == -1) {
|
if ((c = colour_parseX11(p)) == -1) {
|
||||||
log_debug("bad OSC 12: %s", p);
|
log_debug("bad OSC 12: %s", p);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1820,7 +1820,7 @@ screen_write_cell(struct screen_write_ctx *ctx, const struct grid_cell *gc)
|
|||||||
struct grid_cell tmp_gc, now_gc;
|
struct grid_cell tmp_gc, now_gc;
|
||||||
struct tty_ctx ttyctx;
|
struct tty_ctx ttyctx;
|
||||||
u_int sx = screen_size_x(s), sy = screen_size_y(s);
|
u_int sx = screen_size_x(s), sy = screen_size_y(s);
|
||||||
u_int width = gc->data.width, xx, last, cx, cy;
|
u_int width = gc->data.width, xx, last, cy;
|
||||||
int selected, skip = 1;
|
int selected, skip = 1;
|
||||||
|
|
||||||
/* Ignore padding cells. */
|
/* Ignore padding cells. */
|
||||||
@ -1853,12 +1853,12 @@ screen_write_cell(struct screen_write_ctx *ctx, const struct grid_cell *gc)
|
|||||||
ctx->flags &= ~SCREEN_WRITE_ZWJ;
|
ctx->flags &= ~SCREEN_WRITE_ZWJ;
|
||||||
screen_write_collect_flush(ctx, 0, __func__);
|
screen_write_collect_flush(ctx, 0, __func__);
|
||||||
if ((gc = screen_write_combine(ctx, ud, &xx)) != NULL) {
|
if ((gc = screen_write_combine(ctx, ud, &xx)) != NULL) {
|
||||||
cx = s->cx; cy = s->cy;
|
cy = s->cy;
|
||||||
screen_write_set_cursor(ctx, xx, s->cy);
|
screen_write_set_cursor(ctx, xx, s->cy);
|
||||||
screen_write_initctx(ctx, &ttyctx, 0);
|
screen_write_initctx(ctx, &ttyctx, 0);
|
||||||
ttyctx.cell = gc;
|
ttyctx.cell = gc;
|
||||||
tty_write(tty_cmd_cell, &ttyctx);
|
tty_write(tty_cmd_cell, &ttyctx);
|
||||||
s->cx = cx; s->cy = cy;
|
s->cx = xx + 1 + gc->data.width; s->cy = cy;
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -2016,6 +2016,14 @@ screen_write_combine(struct screen_write_ctx *ctx, const struct utf8_data *ud,
|
|||||||
memcpy(gc.data.data + gc.data.size, ud->data, ud->size);
|
memcpy(gc.data.data + gc.data.size, ud->data, ud->size);
|
||||||
gc.data.size += ud->size;
|
gc.data.size += ud->size;
|
||||||
|
|
||||||
|
/* If this is U+FE0F VARIATION SELECTOR-16, force the width to 2. */
|
||||||
|
if (gc.data.width == 1 &&
|
||||||
|
ud->size == 3 &&
|
||||||
|
memcmp(ud->data, "\357\270\217", 3) == 0) {
|
||||||
|
grid_view_set_padding(gd, (*xx) + 1, s->cy);
|
||||||
|
gc.data.width = 2;
|
||||||
|
}
|
||||||
|
|
||||||
/* Set the new cell. */
|
/* Set the new cell. */
|
||||||
grid_view_set_cell(gd, *xx, s->cy, &gc);
|
grid_view_set_cell(gd, *xx, s->cy, &gc);
|
||||||
|
|
||||||
|
@ -66,7 +66,8 @@ enum msgtype {
|
|||||||
MSG_WRITE_OPEN,
|
MSG_WRITE_OPEN,
|
||||||
MSG_WRITE,
|
MSG_WRITE,
|
||||||
MSG_WRITE_READY,
|
MSG_WRITE_READY,
|
||||||
MSG_WRITE_CLOSE
|
MSG_WRITE_CLOSE,
|
||||||
|
MSG_READ_CANCEL
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -92,6 +93,10 @@ struct msg_read_done {
|
|||||||
int error;
|
int error;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct msg_read_cancel {
|
||||||
|
int stream;
|
||||||
|
};
|
||||||
|
|
||||||
struct msg_write_open {
|
struct msg_write_open {
|
||||||
int stream;
|
int stream;
|
||||||
int fd;
|
int fd;
|
||||||
|
23
tmux.1
23
tmux.1
@ -964,7 +964,7 @@ Will run
|
|||||||
directly without invoking the shell.
|
directly without invoking the shell.
|
||||||
.Pp
|
.Pp
|
||||||
.Ar command
|
.Ar command
|
||||||
.Op Ar arguments
|
.Op Ar argument ...
|
||||||
refers to a
|
refers to a
|
||||||
.Nm
|
.Nm
|
||||||
command, either passed with the command and arguments separately, for example:
|
command, either passed with the command and arguments separately, for example:
|
||||||
@ -1541,8 +1541,7 @@ show debugging information about jobs and terminals.
|
|||||||
.Tg source
|
.Tg source
|
||||||
.It Xo Ic source-file
|
.It Xo Ic source-file
|
||||||
.Op Fl Fnqv
|
.Op Fl Fnqv
|
||||||
.Ar path
|
.Ar path ...
|
||||||
.Ar ...
|
|
||||||
.Xc
|
.Xc
|
||||||
.D1 Pq alias: Ic source
|
.D1 Pq alias: Ic source
|
||||||
Execute commands from one or more files specified by
|
Execute commands from one or more files specified by
|
||||||
@ -3123,7 +3122,7 @@ Commands related to key bindings are as follows:
|
|||||||
.Op Fl nr
|
.Op Fl nr
|
||||||
.Op Fl N Ar note
|
.Op Fl N Ar note
|
||||||
.Op Fl T Ar key-table
|
.Op Fl T Ar key-table
|
||||||
.Ar key command Op Ar arguments
|
.Ar key command Op Ar argument ...
|
||||||
.Xc
|
.Xc
|
||||||
.D1 Pq alias: Ic bind
|
.D1 Pq alias: Ic bind
|
||||||
Bind key
|
Bind key
|
||||||
@ -3215,13 +3214,14 @@ lists only the first matching key.
|
|||||||
lists the command for keys that do not have a note rather than skipping them.
|
lists the command for keys that do not have a note rather than skipping them.
|
||||||
.Tg send
|
.Tg send
|
||||||
.It Xo Ic send-keys
|
.It Xo Ic send-keys
|
||||||
.Op Fl FHlMRX
|
.Op Fl FHKlMRX
|
||||||
|
.Op Fl c Ar target-client
|
||||||
.Op Fl N Ar repeat-count
|
.Op Fl N Ar repeat-count
|
||||||
.Op Fl t Ar target-pane
|
.Op Fl t Ar target-pane
|
||||||
.Ar key Ar ...
|
.Ar key ...
|
||||||
.Xc
|
.Xc
|
||||||
.D1 Pq alias: Ic send
|
.D1 Pq alias: Ic send
|
||||||
Send a key or keys to a window.
|
Send a key or keys to a window or client.
|
||||||
Each argument
|
Each argument
|
||||||
.Ar key
|
.Ar key
|
||||||
is the name of the key (such as
|
is the name of the key (such as
|
||||||
@ -3230,6 +3230,12 @@ or
|
|||||||
.Ql NPage )
|
.Ql NPage )
|
||||||
to send; if the string is not recognised as a key, it is sent as a series of
|
to send; if the string is not recognised as a key, it is sent as a series of
|
||||||
characters.
|
characters.
|
||||||
|
If
|
||||||
|
.Fl K
|
||||||
|
is given, keys are sent to
|
||||||
|
.Ar target-client ,
|
||||||
|
so they are looked up in the client's key table, rather than to
|
||||||
|
.Ar target-pane .
|
||||||
All arguments are sent sequentially from first to last.
|
All arguments are sent sequentially from first to last.
|
||||||
If no keys are given and the command is bound to a key, then that key is used.
|
If no keys are given and the command is bound to a key, then that key is used.
|
||||||
.Pp
|
.Pp
|
||||||
@ -5817,8 +5823,7 @@ until it is dismissed.
|
|||||||
.Op Fl y Ar position
|
.Op Fl y Ar position
|
||||||
.Ar name
|
.Ar name
|
||||||
.Ar key
|
.Ar key
|
||||||
.Ar command
|
.Ar command Op Ar argument ...
|
||||||
.Ar ...
|
|
||||||
.Xc
|
.Xc
|
||||||
.D1 Pq alias: Ic menu
|
.D1 Pq alias: Ic menu
|
||||||
Display a menu on
|
Display a menu on
|
||||||
|
16
tmux.h
16
tmux.h
@ -1381,6 +1381,8 @@ struct tty {
|
|||||||
u_int osy;
|
u_int osy;
|
||||||
|
|
||||||
int mode;
|
int mode;
|
||||||
|
int fg;
|
||||||
|
int bg;
|
||||||
|
|
||||||
u_int rlower;
|
u_int rlower;
|
||||||
u_int rupper;
|
u_int rupper;
|
||||||
@ -1411,7 +1413,11 @@ struct tty {
|
|||||||
#define TTY_HAVEDA 0x100 /* Primary DA. */
|
#define TTY_HAVEDA 0x100 /* Primary DA. */
|
||||||
#define TTY_HAVEXDA 0x200
|
#define TTY_HAVEXDA 0x200
|
||||||
#define TTY_SYNCING 0x400
|
#define TTY_SYNCING 0x400
|
||||||
#define TTY_HAVEDA2 0x800 /* Seconday DA. */
|
#define TTY_HAVEDA2 0x800 /* Secondary DA. */
|
||||||
|
#define TTY_HAVEFG 0x1000
|
||||||
|
#define TTY_HAVEBG 0x2000
|
||||||
|
#define TTY_ALL_REQUEST_FLAGS \
|
||||||
|
(TTY_HAVEDA|TTY_HAVEDA2|TTY_HAVEXDA|TTY_HAVEFG|TTY_HAVEBG)
|
||||||
int flags;
|
int flags;
|
||||||
|
|
||||||
struct tty_term *term;
|
struct tty_term *term;
|
||||||
@ -2388,7 +2394,7 @@ void tty_keys_free(struct tty *);
|
|||||||
int tty_keys_next(struct tty *);
|
int tty_keys_next(struct tty *);
|
||||||
|
|
||||||
/* arguments.c */
|
/* arguments.c */
|
||||||
void args_set(struct args *, u_char, struct args_value *);
|
void args_set(struct args *, u_char, struct args_value *, int);
|
||||||
struct args *args_create(void);
|
struct args *args_create(void);
|
||||||
struct args *args_parse(const struct args_parse *, struct args_value *,
|
struct args *args_parse(const struct args_parse *, struct args_value *,
|
||||||
u_int, char **);
|
u_int, char **);
|
||||||
@ -2606,7 +2612,9 @@ void file_print_buffer(struct client *, void *, size_t);
|
|||||||
void printflike(2, 3) file_error(struct client *, const char *, ...);
|
void printflike(2, 3) file_error(struct client *, const char *, ...);
|
||||||
void file_write(struct client *, const char *, int, const void *, size_t,
|
void file_write(struct client *, const char *, int, const void *, size_t,
|
||||||
client_file_cb, void *);
|
client_file_cb, void *);
|
||||||
void file_read(struct client *, const char *, client_file_cb, void *);
|
struct client_file *file_read(struct client *, const char *, client_file_cb,
|
||||||
|
void *);
|
||||||
|
void file_cancel(struct client_file *);
|
||||||
void file_push(struct client_file *);
|
void file_push(struct client_file *);
|
||||||
int file_write_left(struct client_files *);
|
int file_write_left(struct client_files *);
|
||||||
void file_write_open(struct client_files *, struct tmuxpeer *,
|
void file_write_open(struct client_files *, struct tmuxpeer *,
|
||||||
@ -2618,6 +2626,7 @@ void file_read_open(struct client_files *, struct tmuxpeer *, struct imsg *,
|
|||||||
void file_write_ready(struct client_files *, struct imsg *);
|
void file_write_ready(struct client_files *, struct imsg *);
|
||||||
void file_read_data(struct client_files *, struct imsg *);
|
void file_read_data(struct client_files *, struct imsg *);
|
||||||
void file_read_done(struct client_files *, struct imsg *);
|
void file_read_done(struct client_files *, struct imsg *);
|
||||||
|
void file_read_cancel(struct client_files *, struct imsg *);
|
||||||
|
|
||||||
/* server.c */
|
/* server.c */
|
||||||
extern struct tmuxproc *server_proc;
|
extern struct tmuxproc *server_proc;
|
||||||
@ -2761,6 +2770,7 @@ int colour_fromstring(const char *s);
|
|||||||
int colour_256toRGB(int);
|
int colour_256toRGB(int);
|
||||||
int colour_256to16(int);
|
int colour_256to16(int);
|
||||||
int colour_byname(const char *);
|
int colour_byname(const char *);
|
||||||
|
int colour_parseX11(const char *);
|
||||||
void colour_palette_init(struct colour_palette *);
|
void colour_palette_init(struct colour_palette *);
|
||||||
void colour_palette_clear(struct colour_palette *);
|
void colour_palette_clear(struct colour_palette *);
|
||||||
void colour_palette_free(struct colour_palette *);
|
void colour_palette_free(struct colour_palette *);
|
||||||
|
83
tty-keys.c
83
tty-keys.c
@ -59,6 +59,7 @@ static int tty_keys_device_attributes2(struct tty *, const char *, size_t,
|
|||||||
size_t *);
|
size_t *);
|
||||||
static int tty_keys_extended_device_attributes(struct tty *, const char *,
|
static int tty_keys_extended_device_attributes(struct tty *, const char *,
|
||||||
size_t, size_t *);
|
size_t, size_t *);
|
||||||
|
static int tty_keys_colours(struct tty *, const char *, size_t, size_t *);
|
||||||
|
|
||||||
/* A key tree entry. */
|
/* A key tree entry. */
|
||||||
struct tty_key {
|
struct tty_key {
|
||||||
@ -719,6 +720,17 @@ tty_keys_next(struct tty *tty)
|
|||||||
goto partial_key;
|
goto partial_key;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Is this a colours response? */
|
||||||
|
switch (tty_keys_colours(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? */
|
/* Is this a mouse key press? */
|
||||||
switch (tty_keys_mouse(tty, buf, len, &size, &m)) {
|
switch (tty_keys_mouse(tty, buf, len, &size, &m)) {
|
||||||
case 0: /* yes */
|
case 0: /* yes */
|
||||||
@ -1278,7 +1290,7 @@ tty_keys_device_attributes(struct tty *tty, const char *buf, size_t len,
|
|||||||
if (len == 3)
|
if (len == 3)
|
||||||
return (1);
|
return (1);
|
||||||
|
|
||||||
/* Copy the rest up to a 'c'. */
|
/* Copy the rest up to a c. */
|
||||||
for (i = 0; i < (sizeof tmp); i++) {
|
for (i = 0; i < (sizeof tmp); i++) {
|
||||||
if (3 + i == len)
|
if (3 + i == len)
|
||||||
return (1);
|
return (1);
|
||||||
@ -1352,7 +1364,7 @@ tty_keys_device_attributes2(struct tty *tty, const char *buf, size_t len,
|
|||||||
if (len == 3)
|
if (len == 3)
|
||||||
return (1);
|
return (1);
|
||||||
|
|
||||||
/* Copy the rest up to a 'c'. */
|
/* Copy the rest up to a c. */
|
||||||
for (i = 0; i < (sizeof tmp); i++) {
|
for (i = 0; i < (sizeof tmp); i++) {
|
||||||
if (3 + i == len)
|
if (3 + i == len)
|
||||||
return (1);
|
return (1);
|
||||||
@ -1433,7 +1445,7 @@ tty_keys_extended_device_attributes(struct tty *tty, const char *buf,
|
|||||||
if (len == 4)
|
if (len == 4)
|
||||||
return (1);
|
return (1);
|
||||||
|
|
||||||
/* Copy the rest up to a '\033\\'. */
|
/* Copy the rest up to \033\. */
|
||||||
for (i = 0; i < (sizeof tmp) - 1; i++) {
|
for (i = 0; i < (sizeof tmp) - 1; i++) {
|
||||||
if (4 + i == len)
|
if (4 + i == len)
|
||||||
return (1);
|
return (1);
|
||||||
@ -1465,3 +1477,68 @@ tty_keys_extended_device_attributes(struct tty *tty, const char *buf,
|
|||||||
|
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Handle foreground or background input. Returns 0 for success, -1 for
|
||||||
|
* failure, 1 for partial.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
tty_keys_colours(struct tty *tty, const char *buf, size_t len, size_t *size)
|
||||||
|
{
|
||||||
|
struct client *c = tty->client;
|
||||||
|
u_int i;
|
||||||
|
char tmp[128];
|
||||||
|
int n;
|
||||||
|
|
||||||
|
*size = 0;
|
||||||
|
if ((tty->flags & TTY_HAVEFG) && (tty->flags & TTY_HAVEBG))
|
||||||
|
return (-1);
|
||||||
|
|
||||||
|
/* First four bytes are always \033]1 and 0 or 1 and ;. */
|
||||||
|
if (buf[0] != '\033')
|
||||||
|
return (-1);
|
||||||
|
if (len == 1)
|
||||||
|
return (1);
|
||||||
|
if (buf[1] != ']')
|
||||||
|
return (-1);
|
||||||
|
if (len == 2)
|
||||||
|
return (1);
|
||||||
|
if (buf[2] != '1')
|
||||||
|
return (-1);
|
||||||
|
if (len == 3)
|
||||||
|
return (1);
|
||||||
|
if (buf[3] != '0' && buf[3] != '1')
|
||||||
|
return (-1);
|
||||||
|
if (len == 4)
|
||||||
|
return (1);
|
||||||
|
if (buf[4] != ';')
|
||||||
|
return (-1);
|
||||||
|
if (len == 5)
|
||||||
|
return (1);
|
||||||
|
|
||||||
|
/* Copy the rest up to \033\. */
|
||||||
|
for (i = 0; i < (sizeof tmp) - 1; i++) {
|
||||||
|
if (5 + i == len)
|
||||||
|
return (1);
|
||||||
|
if (buf[5 + i - 1] == '\033' && buf[5 + i] == '\\')
|
||||||
|
break;
|
||||||
|
tmp[i] = buf[5 + i];
|
||||||
|
}
|
||||||
|
if (i == (sizeof tmp) - 1)
|
||||||
|
return (-1);
|
||||||
|
tmp[i - 1] = '\0';
|
||||||
|
*size = 6 + i;
|
||||||
|
|
||||||
|
n = colour_parseX11(tmp);
|
||||||
|
if (n != -1 && buf[3] == '0') {
|
||||||
|
log_debug("%s: foreground is %s", c->name, colour_tostring(n));
|
||||||
|
tty->fg = n;
|
||||||
|
tty->flags |= TTY_HAVEFG;
|
||||||
|
} else if (n != -1) {
|
||||||
|
log_debug("%s: background is %s", c->name, colour_tostring(n));
|
||||||
|
tty->bg = n;
|
||||||
|
tty->flags |= TTY_HAVEBG;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
10
tty.c
10
tty.c
@ -108,6 +108,7 @@ tty_init(struct tty *tty, struct client *c)
|
|||||||
|
|
||||||
tty->cstyle = SCREEN_CURSOR_DEFAULT;
|
tty->cstyle = SCREEN_CURSOR_DEFAULT;
|
||||||
tty->ccolour = -1;
|
tty->ccolour = -1;
|
||||||
|
tty->fg = tty->bg = -1;
|
||||||
|
|
||||||
if (tcgetattr(c->fd, &tty->tio) != 0)
|
if (tcgetattr(c->fd, &tty->tio) != 0)
|
||||||
return (-1);
|
return (-1);
|
||||||
@ -286,7 +287,6 @@ tty_open(struct tty *tty, char **cause)
|
|||||||
evtimer_set(&tty->timer, tty_timer_callback, tty);
|
evtimer_set(&tty->timer, tty_timer_callback, tty);
|
||||||
|
|
||||||
tty_start_tty(tty);
|
tty_start_tty(tty);
|
||||||
|
|
||||||
tty_keys_build(tty);
|
tty_keys_build(tty);
|
||||||
|
|
||||||
return (0);
|
return (0);
|
||||||
@ -301,7 +301,7 @@ tty_start_timer_callback(__unused int fd, __unused short events, void *data)
|
|||||||
log_debug("%s: start timer fired", c->name);
|
log_debug("%s: start timer fired", c->name);
|
||||||
if ((tty->flags & (TTY_HAVEDA|TTY_HAVEDA2|TTY_HAVEXDA)) == 0)
|
if ((tty->flags & (TTY_HAVEDA|TTY_HAVEDA2|TTY_HAVEXDA)) == 0)
|
||||||
tty_update_features(tty);
|
tty_update_features(tty);
|
||||||
tty->flags |= (TTY_HAVEDA|TTY_HAVEDA2|TTY_HAVEXDA);
|
tty->flags |= TTY_ALL_REQUEST_FLAGS;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -369,8 +369,12 @@ tty_send_requests(struct tty *tty)
|
|||||||
tty_puts(tty, "\033[>c");
|
tty_puts(tty, "\033[>c");
|
||||||
if (~tty->flags & TTY_HAVEXDA)
|
if (~tty->flags & TTY_HAVEXDA)
|
||||||
tty_puts(tty, "\033[>q");
|
tty_puts(tty, "\033[>q");
|
||||||
|
if (~tty->flags & TTY_HAVEFG)
|
||||||
|
tty_puts(tty, "\033]10;?\033\\");
|
||||||
|
if (~tty->flags & TTY_HAVEBG)
|
||||||
|
tty_puts(tty, "\033]11;?\033\\");
|
||||||
} else
|
} else
|
||||||
tty->flags |= (TTY_HAVEDA|TTY_HAVEDA2|TTY_HAVEXDA);
|
tty->flags |= TTY_ALL_REQUEST_FLAGS;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
4
utf8.c
4
utf8.c
@ -233,10 +233,10 @@ utf8_width(struct utf8_data *ud, int *width)
|
|||||||
*width = utf8proc_wcwidth(wc);
|
*width = utf8proc_wcwidth(wc);
|
||||||
#else
|
#else
|
||||||
*width = wcwidth(wc);
|
*width = wcwidth(wc);
|
||||||
#endif
|
log_debug("UTF-8 %.*s %#x, wcwidth() %d", (int)ud->size, ud->data,
|
||||||
|
(u_int)wc, *width);
|
||||||
if (*width >= 0 && *width <= 0xff)
|
if (*width >= 0 && *width <= 0xff)
|
||||||
return (UTF8_DONE);
|
return (UTF8_DONE);
|
||||||
log_debug("UTF-8 %.*s, wcwidth() %d", (int)ud->size, ud->data, *width);
|
|
||||||
return (UTF8_ERROR);
|
return (UTF8_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
16
window.c
16
window.c
@ -64,6 +64,7 @@ static u_int next_active_point;
|
|||||||
struct window_pane_input_data {
|
struct window_pane_input_data {
|
||||||
struct cmdq_item *item;
|
struct cmdq_item *item;
|
||||||
u_int wp;
|
u_int wp;
|
||||||
|
struct client_file *file;
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct window_pane *window_pane_create(struct window *, u_int, u_int,
|
static struct window_pane *window_pane_create(struct window *, u_int, u_int,
|
||||||
@ -1543,18 +1544,16 @@ window_pane_input_callback(struct client *c, __unused const char *path,
|
|||||||
size_t len = EVBUFFER_LENGTH(buffer);
|
size_t len = EVBUFFER_LENGTH(buffer);
|
||||||
|
|
||||||
wp = window_pane_find_by_id(cdata->wp);
|
wp = window_pane_find_by_id(cdata->wp);
|
||||||
if (wp == NULL || closed || error != 0 || (c->flags & CLIENT_DEAD)) {
|
if (cdata->file != NULL && (wp == NULL || c->flags & CLIENT_DEAD)) {
|
||||||
if (wp == NULL)
|
if (wp == NULL)
|
||||||
c->flags |= CLIENT_EXIT;
|
c->flags |= CLIENT_EXIT;
|
||||||
|
file_cancel(cdata->file);
|
||||||
evbuffer_drain(buffer, len);
|
} else if (cdata->file == NULL || closed || error != 0) {
|
||||||
cmdq_continue(cdata->item);
|
cmdq_continue(cdata->item);
|
||||||
|
|
||||||
server_client_unref(c);
|
server_client_unref(c);
|
||||||
free(cdata);
|
free(cdata);
|
||||||
return;
|
} else
|
||||||
}
|
input_parse_buffer(wp, buf, len);
|
||||||
input_parse_buffer(wp, buf, len);
|
|
||||||
evbuffer_drain(buffer, len);
|
evbuffer_drain(buffer, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1577,9 +1576,8 @@ window_pane_start_input(struct window_pane *wp, struct cmdq_item *item,
|
|||||||
cdata = xmalloc(sizeof *cdata);
|
cdata = xmalloc(sizeof *cdata);
|
||||||
cdata->item = item;
|
cdata->item = item;
|
||||||
cdata->wp = wp->id;
|
cdata->wp = wp->id;
|
||||||
|
cdata->file = file_read(c, "-", window_pane_input_callback, cdata);
|
||||||
c->references++;
|
c->references++;
|
||||||
file_read(c, "-", window_pane_input_callback, cdata);
|
|
||||||
|
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user