mirror of
https://github.com/tmux/tmux.git
synced 2025-01-14 12:48:56 +00:00
Merge branch 'obsd-master'
This commit is contained in:
commit
c9fcb76651
590
cmd-set-option.c
590
cmd-set-option.c
@ -29,40 +29,14 @@
|
||||
|
||||
static enum cmd_retval cmd_set_option_exec(struct cmd *, struct cmdq_item *);
|
||||
|
||||
static enum cmd_retval cmd_set_option_user(struct cmd *, struct cmdq_item *,
|
||||
const char *, const char *);
|
||||
|
||||
static int cmd_set_option_unset(struct cmd *, struct cmdq_item *,
|
||||
const struct options_table_entry *, struct options *,
|
||||
const char *);
|
||||
static int cmd_set_option_set(struct cmd *, struct cmdq_item *,
|
||||
struct options *, struct option *, const char *);
|
||||
static int cmd_set_option_flag(struct cmdq_item *,
|
||||
const struct options_table_entry *, struct options *,
|
||||
const char *);
|
||||
static int cmd_set_option_choice(struct cmdq_item *,
|
||||
const struct options_table_entry *, struct options *,
|
||||
const char *);
|
||||
|
||||
static struct options_entry *cmd_set_option_string(struct cmd *,
|
||||
struct cmdq_item *, const struct options_table_entry *,
|
||||
struct options *, const char *);
|
||||
static struct options_entry *cmd_set_option_number(struct cmd *,
|
||||
struct cmdq_item *, const struct options_table_entry *,
|
||||
struct options *, const char *);
|
||||
static struct options_entry *cmd_set_option_key(struct cmd *,
|
||||
struct cmdq_item *, const struct options_table_entry *,
|
||||
struct options *, const char *);
|
||||
static struct options_entry *cmd_set_option_colour(struct cmd *,
|
||||
struct cmdq_item *, const struct options_table_entry *,
|
||||
struct options *, const char *);
|
||||
static struct options_entry *cmd_set_option_attributes(struct cmd *,
|
||||
struct cmdq_item *, const struct options_table_entry *,
|
||||
struct options *, const char *);
|
||||
static struct options_entry *cmd_set_option_flag(struct cmd *,
|
||||
struct cmdq_item *, const struct options_table_entry *,
|
||||
struct options *, const char *);
|
||||
static struct options_entry *cmd_set_option_choice(struct cmd *,
|
||||
struct cmdq_item *, const struct options_table_entry *,
|
||||
struct options *, const char *);
|
||||
static struct options_entry *cmd_set_option_style(struct cmd *,
|
||||
struct cmdq_item *, const struct options_table_entry *,
|
||||
struct options *, const char *);
|
||||
|
||||
const struct cmd_entry cmd_set_option_entry = {
|
||||
.name = "set-option",
|
||||
@ -93,99 +67,154 @@ const struct cmd_entry cmd_set_window_option_entry = {
|
||||
static enum cmd_retval
|
||||
cmd_set_option_exec(struct cmd *self, struct cmdq_item *item)
|
||||
{
|
||||
struct args *args = self->args;
|
||||
struct session *s = item->state.tflag.s;
|
||||
struct winlink *wl = item->state.tflag.wl;
|
||||
struct window *w;
|
||||
struct client *c;
|
||||
const struct options_table_entry *oe;
|
||||
struct options *oo;
|
||||
const char *optstr, *valstr, *target;
|
||||
struct args *args = self->args;
|
||||
struct cmd_find_state *fs = &item->state.tflag;
|
||||
struct session *s = fs->s;
|
||||
struct winlink *wl = fs->wl;
|
||||
struct window *w = wl->window;
|
||||
struct client *c;
|
||||
enum options_table_scope scope;
|
||||
struct options *oo;
|
||||
struct option *parent, *o;
|
||||
const char *name, *value, *target;
|
||||
int window, idx, already, error, ambiguous;
|
||||
char *cause;
|
||||
|
||||
/* Get the option name and value. */
|
||||
optstr = args->argv[0];
|
||||
if (*optstr == '\0') {
|
||||
cmdq_error(item, "invalid option");
|
||||
/* Parse option name and index. */
|
||||
name = options_match(args->argv[0], &idx, &ambiguous);
|
||||
if (name == NULL) {
|
||||
if (args_has(args, 'q'))
|
||||
return (CMD_RETURN_NORMAL);
|
||||
if (ambiguous)
|
||||
cmdq_error(item, "ambiguous option: %s", args->argv[0]);
|
||||
else
|
||||
cmdq_error(item, "invalid option: %s", args->argv[0]);
|
||||
return (CMD_RETURN_ERROR);
|
||||
}
|
||||
if (args->argc < 2)
|
||||
valstr = NULL;
|
||||
value = NULL;
|
||||
else
|
||||
valstr = args->argv[1];
|
||||
value = args->argv[1];
|
||||
|
||||
/* Is this a user option? */
|
||||
if (*optstr == '@')
|
||||
return (cmd_set_option_user(self, item, optstr, valstr));
|
||||
|
||||
/* Find the option entry. */
|
||||
oe = NULL;
|
||||
if (options_table_find(optstr, &oe) != 0) {
|
||||
if (!args_has(args, 'q')) {
|
||||
cmdq_error(item, "ambiguous option: %s", optstr);
|
||||
return (CMD_RETURN_ERROR);
|
||||
/*
|
||||
* Figure out the scope: for user options it comes from the arguments,
|
||||
* otherwise from the option name.
|
||||
*/
|
||||
if (*name == '@') {
|
||||
window = (self->entry == &cmd_set_window_option_entry);
|
||||
scope = options_scope_from_flags(args, window, fs, &oo, &cause);
|
||||
} else {
|
||||
if (options_get_only(global_options, name) != NULL)
|
||||
scope = OPTIONS_TABLE_SERVER;
|
||||
else if (options_get_only(global_s_options, name) != NULL)
|
||||
scope = OPTIONS_TABLE_SESSION;
|
||||
else if (options_get_only(global_w_options, name) != NULL)
|
||||
scope = OPTIONS_TABLE_WINDOW;
|
||||
else {
|
||||
scope = OPTIONS_TABLE_NONE;
|
||||
xasprintf(&cause, "unknown option: %s", args->argv[0]);
|
||||
}
|
||||
return (CMD_RETURN_NORMAL);
|
||||
}
|
||||
if (oe == NULL) {
|
||||
if (!args_has(args, 'q')) {
|
||||
cmdq_error(item, "unknown option: %s", optstr);
|
||||
return (CMD_RETURN_ERROR);
|
||||
}
|
||||
return (CMD_RETURN_NORMAL);
|
||||
if (scope == OPTIONS_TABLE_NONE) {
|
||||
if (args_has(args, 'q'))
|
||||
return (CMD_RETURN_NORMAL);
|
||||
cmdq_error(item, "%s", cause);
|
||||
free(cause);
|
||||
return (CMD_RETURN_ERROR);
|
||||
}
|
||||
|
||||
/* Work out the tree from the scope of the option. */
|
||||
if (oe->scope == OPTIONS_TABLE_SERVER)
|
||||
/* Which table should this option go into? */
|
||||
if (scope == OPTIONS_TABLE_SERVER)
|
||||
oo = global_options;
|
||||
else if (oe->scope == OPTIONS_TABLE_WINDOW) {
|
||||
if (args_has(self->args, 'g'))
|
||||
oo = global_w_options;
|
||||
else if (wl == NULL) {
|
||||
target = args_get(args, 't');
|
||||
if (target != NULL) {
|
||||
cmdq_error(item, "no such window: %s",
|
||||
target);
|
||||
} else
|
||||
cmdq_error(item, "no current window");
|
||||
return (CMD_RETURN_ERROR);
|
||||
} else
|
||||
oo = wl->window->options;
|
||||
} else if (oe->scope == OPTIONS_TABLE_SESSION) {
|
||||
else if (scope == OPTIONS_TABLE_SESSION) {
|
||||
if (args_has(self->args, 'g'))
|
||||
oo = global_s_options;
|
||||
else if (s == NULL) {
|
||||
target = args_get(args, 't');
|
||||
if (target != NULL) {
|
||||
cmdq_error(item, "no such session: %s",
|
||||
target);
|
||||
} else
|
||||
if (target != NULL)
|
||||
cmdq_error(item, "no such session: %s", target);
|
||||
else
|
||||
cmdq_error(item, "no current session");
|
||||
return (CMD_RETURN_ERROR);
|
||||
} else
|
||||
oo = s->options;
|
||||
} else if (scope == OPTIONS_TABLE_WINDOW) {
|
||||
if (args_has(self->args, 'g'))
|
||||
oo = global_w_options;
|
||||
else if (wl == NULL) {
|
||||
target = args_get(args, 't');
|
||||
if (target != NULL)
|
||||
cmdq_error(item, "no such window: %s", target);
|
||||
else
|
||||
cmdq_error(item, "no current window");
|
||||
return (CMD_RETURN_ERROR);
|
||||
} else
|
||||
oo = wl->window->options;
|
||||
}
|
||||
o = options_get_only(oo, name);
|
||||
parent = options_get(oo, name);
|
||||
|
||||
/* Check that array options and indexes match up. */
|
||||
if (idx != -1) {
|
||||
if (*name == '@' || options_array_size(parent, NULL) == -1) {
|
||||
cmdq_error(item, "not an array: %s", args->argv[0]);
|
||||
return (CMD_RETURN_ERROR);
|
||||
}
|
||||
} else {
|
||||
cmdq_error(item, "unknown table");
|
||||
return (CMD_RETURN_ERROR);
|
||||
if (*name != '@' && options_array_size(parent, NULL) != -1) {
|
||||
cmdq_error(item, "is an array: %s", args->argv[0]);
|
||||
return (CMD_RETURN_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
/* Unset or set the option. */
|
||||
/* With -o, check this option is not already set. */
|
||||
if (!args_has(args, 'u') && args_has(args, 'o')) {
|
||||
if (idx == -1)
|
||||
already = (o != NULL);
|
||||
else {
|
||||
if (o == NULL)
|
||||
already = 0;
|
||||
else
|
||||
already = (options_array_get(o, idx) != NULL);
|
||||
}
|
||||
if (already) {
|
||||
if (args_has(args, 'q'))
|
||||
return (CMD_RETURN_NORMAL);
|
||||
cmdq_error(item, "already set: %s", args->argv[0]);
|
||||
return (CMD_RETURN_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
/* Change the option. */
|
||||
if (args_has(args, 'u')) {
|
||||
if (cmd_set_option_unset(self, item, oe, oo, valstr) != 0)
|
||||
if (o == NULL)
|
||||
return (CMD_RETURN_NORMAL);
|
||||
if (idx == -1) {
|
||||
if (oo == global_options ||
|
||||
oo == global_s_options ||
|
||||
oo == global_w_options)
|
||||
options_default(oo, options_table_entry(o));
|
||||
else
|
||||
options_remove(o);
|
||||
} else
|
||||
options_array_set(o, idx, NULL);
|
||||
} else if (*name == '@')
|
||||
options_set_string(oo, name, args_has(args, 'a'), "%s", value);
|
||||
else if (idx == -1) {
|
||||
error = cmd_set_option_set(self, item, oo, parent, value);
|
||||
if (error != 0)
|
||||
return (CMD_RETURN_ERROR);
|
||||
} else {
|
||||
if (args_has(args, 'o') && options_find1(oo, optstr) != NULL) {
|
||||
if (!args_has(args, 'q')) {
|
||||
cmdq_error(item, "already set: %s", optstr);
|
||||
return (CMD_RETURN_ERROR);
|
||||
}
|
||||
return (CMD_RETURN_NORMAL);
|
||||
}
|
||||
if (cmd_set_option_set(self, item, oe, oo, valstr) != 0)
|
||||
if (o == NULL)
|
||||
o = options_empty(oo, options_table_entry(parent));
|
||||
if (options_array_set(o, idx, value) != 0) {
|
||||
cmdq_error(item, "invalid index: %s", args->argv[0]);
|
||||
return (CMD_RETURN_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
/* Update timers and so on for various options. */
|
||||
if (strcmp(oe->name, "automatic-rename") == 0) {
|
||||
if (strcmp(name, "automatic-rename") == 0) {
|
||||
RB_FOREACH(w, windows, &windows) {
|
||||
if (w->active == NULL)
|
||||
continue;
|
||||
@ -193,26 +222,29 @@ cmd_set_option_exec(struct cmd *self, struct cmdq_item *item)
|
||||
w->active->flags |= PANE_CHANGED;
|
||||
}
|
||||
}
|
||||
if (strcmp(oe->name, "key-table") == 0) {
|
||||
if (strcmp(name, "key-table") == 0) {
|
||||
TAILQ_FOREACH(c, &clients, entry)
|
||||
server_client_set_key_table(c, NULL);
|
||||
}
|
||||
if (strcmp(oe->name, "status") == 0 ||
|
||||
strcmp(oe->name, "status-interval") == 0)
|
||||
if (strcmp(name, "status") == 0 ||
|
||||
strcmp(name, "status-interval") == 0)
|
||||
status_timer_start_all();
|
||||
if (strcmp(oe->name, "monitor-silence") == 0)
|
||||
if (strcmp(name, "monitor-silence") == 0)
|
||||
alerts_reset_all();
|
||||
if (strcmp(oe->name, "window-style") == 0 ||
|
||||
strcmp(oe->name, "window-active-style") == 0) {
|
||||
if (strcmp(name, "window-style") == 0 ||
|
||||
strcmp(name, "window-active-style") == 0) {
|
||||
RB_FOREACH(w, windows, &windows)
|
||||
w->flags |= WINDOW_STYLECHANGED;
|
||||
}
|
||||
if (strcmp(oe->name, "pane-border-status") == 0) {
|
||||
if (strcmp(name, "pane-border-status") == 0) {
|
||||
RB_FOREACH(w, windows, &windows)
|
||||
layout_fix_panes(w, w->sx, w->sy);
|
||||
}
|
||||
|
||||
/* Update sizes and redraw. May not need it but meh. */
|
||||
/*
|
||||
* Update sizes and redraw. May not always be necessary but do it
|
||||
* anyway.
|
||||
*/
|
||||
recalculate_sizes();
|
||||
TAILQ_FOREACH(c, &clients, entry) {
|
||||
if (c->session != NULL)
|
||||
@ -222,250 +254,82 @@ cmd_set_option_exec(struct cmd *self, struct cmdq_item *item)
|
||||
return (CMD_RETURN_NORMAL);
|
||||
}
|
||||
|
||||
/* Set user option. */
|
||||
static enum cmd_retval
|
||||
cmd_set_option_user(struct cmd *self, struct cmdq_item *item,
|
||||
const char *optstr, const char *valstr)
|
||||
{
|
||||
struct args *args = self->args;
|
||||
struct session *s = item->state.tflag.s;
|
||||
struct winlink *wl = item->state.tflag.wl;
|
||||
struct options *oo;
|
||||
struct options_entry *o;
|
||||
const char *target;
|
||||
|
||||
if (args_has(args, 's'))
|
||||
oo = global_options;
|
||||
else if (args_has(self->args, 'w') ||
|
||||
self->entry == &cmd_set_window_option_entry) {
|
||||
if (args_has(self->args, 'g'))
|
||||
oo = global_w_options;
|
||||
else if (wl == NULL) {
|
||||
target = args_get(args, 't');
|
||||
if (target != NULL) {
|
||||
cmdq_error(item, "no such window: %s",
|
||||
target);
|
||||
} else
|
||||
cmdq_error(item, "no current window");
|
||||
return (CMD_RETURN_ERROR);
|
||||
} else
|
||||
oo = wl->window->options;
|
||||
} else {
|
||||
if (args_has(self->args, 'g'))
|
||||
oo = global_s_options;
|
||||
else if (s == NULL) {
|
||||
target = args_get(args, 't');
|
||||
if (target != NULL) {
|
||||
cmdq_error(item, "no such session: %s",
|
||||
target);
|
||||
} else
|
||||
cmdq_error(item, "no current session");
|
||||
return (CMD_RETURN_ERROR);
|
||||
} else
|
||||
oo = s->options;
|
||||
}
|
||||
|
||||
if (args_has(args, 'u')) {
|
||||
if (options_find1(oo, optstr) == NULL) {
|
||||
if (!args_has(args, 'q')) {
|
||||
cmdq_error(item, "unknown option: %s", optstr);
|
||||
return (CMD_RETURN_ERROR);
|
||||
}
|
||||
return (CMD_RETURN_NORMAL);
|
||||
}
|
||||
if (valstr != NULL) {
|
||||
cmdq_error(item, "value passed to unset option: %s",
|
||||
optstr);
|
||||
return (CMD_RETURN_ERROR);
|
||||
}
|
||||
options_remove(oo, optstr);
|
||||
} else {
|
||||
o = options_find1(oo, optstr);
|
||||
if (args_has(args, 'o') && o != NULL) {
|
||||
if (!args_has(args, 'q')) {
|
||||
cmdq_error(item, "already set: %s", optstr);
|
||||
return (CMD_RETURN_ERROR);
|
||||
}
|
||||
return (CMD_RETURN_NORMAL);
|
||||
}
|
||||
if (valstr == NULL) {
|
||||
cmdq_error(item, "empty value");
|
||||
return (CMD_RETURN_ERROR);
|
||||
}
|
||||
options_set_string(oo, optstr, args_has(args, 'a'), "%s",
|
||||
valstr);
|
||||
}
|
||||
return (CMD_RETURN_NORMAL);
|
||||
}
|
||||
|
||||
/* Unset an option. */
|
||||
static int
|
||||
cmd_set_option_unset(struct cmd *self, struct cmdq_item *item,
|
||||
const struct options_table_entry *oe, struct options *oo,
|
||||
const char *value)
|
||||
cmd_set_option_set(struct cmd *self, struct cmdq_item *item, struct options *oo,
|
||||
struct option *parent, const char *value)
|
||||
{
|
||||
struct args *args = self->args;
|
||||
const struct options_table_entry *oe;
|
||||
struct args *args = self->args;
|
||||
int append = args_has(args, 'a');
|
||||
struct option *o;
|
||||
long long number;
|
||||
const char *errstr;
|
||||
key_code key;
|
||||
|
||||
if (value != NULL) {
|
||||
cmdq_error(item, "value passed to unset option: %s", oe->name);
|
||||
oe = options_table_entry(parent);
|
||||
if (value == NULL &&
|
||||
oe->type != OPTIONS_TABLE_FLAG &&
|
||||
oe->type != OPTIONS_TABLE_CHOICE) {
|
||||
cmdq_error(item, "empty value");
|
||||
return (-1);
|
||||
}
|
||||
|
||||
if (args_has(args, 'g') || oo == global_options) {
|
||||
switch (oe->type) {
|
||||
case OPTIONS_TABLE_STRING:
|
||||
options_set_string(oo, oe->name, 0, "%s",
|
||||
oe->default_str);
|
||||
break;
|
||||
case OPTIONS_TABLE_STYLE:
|
||||
options_set_style(oo, oe->name, 0, oe->default_str);
|
||||
break;
|
||||
default:
|
||||
options_set_number(oo, oe->name, oe->default_num);
|
||||
break;
|
||||
}
|
||||
} else
|
||||
options_remove(oo, oe->name);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* Set an option. */
|
||||
static int
|
||||
cmd_set_option_set(struct cmd *self, struct cmdq_item *item,
|
||||
const struct options_table_entry *oe, struct options *oo,
|
||||
const char *value)
|
||||
{
|
||||
struct options_entry *o;
|
||||
|
||||
switch (oe->type) {
|
||||
case OPTIONS_TABLE_FLAG:
|
||||
case OPTIONS_TABLE_CHOICE:
|
||||
break;
|
||||
default:
|
||||
if (value == NULL) {
|
||||
cmdq_error(item, "empty value");
|
||||
return (-1);
|
||||
}
|
||||
}
|
||||
|
||||
o = NULL;
|
||||
switch (oe->type) {
|
||||
case OPTIONS_TABLE_STRING:
|
||||
o = cmd_set_option_string(self, item, oe, oo, value);
|
||||
break;
|
||||
options_set_string(oo, oe->name, append, "%s", value);
|
||||
return (0);
|
||||
case OPTIONS_TABLE_NUMBER:
|
||||
o = cmd_set_option_number(self, item, oe, oo, value);
|
||||
break;
|
||||
number = strtonum(value, oe->minimum, oe->maximum, &errstr);
|
||||
if (errstr != NULL) {
|
||||
cmdq_error(item, "value is %s: %s", errstr, value);
|
||||
return (-1);
|
||||
}
|
||||
options_set_number(oo, oe->name, number);
|
||||
return (0);
|
||||
case OPTIONS_TABLE_KEY:
|
||||
o = cmd_set_option_key(self, item, oe, oo, value);
|
||||
break;
|
||||
key = key_string_lookup_string(value);
|
||||
if (key == KEYC_UNKNOWN) {
|
||||
cmdq_error(item, "bad key: %s", value);
|
||||
return (-1);
|
||||
}
|
||||
options_set_number(oo, oe->name, key);
|
||||
return (0);
|
||||
case OPTIONS_TABLE_COLOUR:
|
||||
o = cmd_set_option_colour(self, item, oe, oo, value);
|
||||
if (o != NULL)
|
||||
style_update_new(oo, o->name, oe->style);
|
||||
break;
|
||||
if ((number = colour_fromstring(value)) == -1) {
|
||||
cmdq_error(item, "bad colour: %s", value);
|
||||
return (-1);
|
||||
}
|
||||
o = options_set_number(oo, oe->name, number);
|
||||
options_style_update_new(oo, o);
|
||||
return (0);
|
||||
case OPTIONS_TABLE_ATTRIBUTES:
|
||||
o = cmd_set_option_attributes(self, item, oe, oo, value);
|
||||
if (o != NULL)
|
||||
style_update_new(oo, o->name, oe->style);
|
||||
break;
|
||||
if ((number = attributes_fromstring(value)) == -1) {
|
||||
cmdq_error(item, "bad attributes: %s", value);
|
||||
return (-1);
|
||||
}
|
||||
o = options_set_number(oo, oe->name, number);
|
||||
options_style_update_new(oo, o);
|
||||
return (0);
|
||||
case OPTIONS_TABLE_FLAG:
|
||||
o = cmd_set_option_flag(self, item, oe, oo, value);
|
||||
break;
|
||||
return (cmd_set_option_flag(item, oe, oo, value));
|
||||
case OPTIONS_TABLE_CHOICE:
|
||||
o = cmd_set_option_choice(self, item, oe, oo, value);
|
||||
break;
|
||||
return (cmd_set_option_choice(item, oe, oo, value));
|
||||
case OPTIONS_TABLE_STYLE:
|
||||
o = cmd_set_option_style(self, item, oe, oo, value);
|
||||
o = options_set_style(oo, oe->name, append, value);
|
||||
if (o == NULL) {
|
||||
cmdq_error(item, "bad style: %s", value);
|
||||
return (-1);
|
||||
}
|
||||
options_style_update_old(oo, o);
|
||||
return (0);
|
||||
case OPTIONS_TABLE_ARRAY:
|
||||
break;
|
||||
}
|
||||
if (o == NULL)
|
||||
return (-1);
|
||||
return (0);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
/* Set a string option. */
|
||||
static struct options_entry *
|
||||
cmd_set_option_string(struct cmd *self, __unused struct cmdq_item *item,
|
||||
const struct options_table_entry *oe, struct options *oo,
|
||||
const char *value)
|
||||
{
|
||||
struct args *args = self->args;
|
||||
int append = args_has(args, 'a');
|
||||
|
||||
return (options_set_string(oo, oe->name, append, "%s", value));
|
||||
}
|
||||
|
||||
/* Set a number option. */
|
||||
static struct options_entry *
|
||||
cmd_set_option_number(__unused struct cmd *self, struct cmdq_item *item,
|
||||
const struct options_table_entry *oe, struct options *oo,
|
||||
const char *value)
|
||||
{
|
||||
long long ll;
|
||||
const char *errstr;
|
||||
|
||||
ll = strtonum(value, oe->minimum, oe->maximum, &errstr);
|
||||
if (errstr != NULL) {
|
||||
cmdq_error(item, "value is %s: %s", errstr, value);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
return (options_set_number(oo, oe->name, ll));
|
||||
}
|
||||
|
||||
/* Set a key option. */
|
||||
static struct options_entry *
|
||||
cmd_set_option_key(__unused struct cmd *self, struct cmdq_item *item,
|
||||
const struct options_table_entry *oe, struct options *oo,
|
||||
const char *value)
|
||||
{
|
||||
key_code key;
|
||||
|
||||
key = key_string_lookup_string(value);
|
||||
if (key == KEYC_UNKNOWN) {
|
||||
cmdq_error(item, "bad key: %s", value);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
return (options_set_number(oo, oe->name, key));
|
||||
}
|
||||
|
||||
/* Set a colour option. */
|
||||
static struct options_entry *
|
||||
cmd_set_option_colour(__unused struct cmd *self, struct cmdq_item *item,
|
||||
const struct options_table_entry *oe, struct options *oo,
|
||||
const char *value)
|
||||
{
|
||||
int colour;
|
||||
|
||||
if ((colour = colour_fromstring(value)) == -1) {
|
||||
cmdq_error(item, "bad colour: %s", value);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
return (options_set_number(oo, oe->name, colour));
|
||||
}
|
||||
|
||||
/* Set an attributes option. */
|
||||
static struct options_entry *
|
||||
cmd_set_option_attributes(__unused struct cmd *self, struct cmdq_item *item,
|
||||
const struct options_table_entry *oe, struct options *oo,
|
||||
const char *value)
|
||||
{
|
||||
int attr;
|
||||
|
||||
if ((attr = attributes_fromstring(value)) == -1) {
|
||||
cmdq_error(item, "bad attributes: %s", value);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
return (options_set_number(oo, oe->name, attr));
|
||||
}
|
||||
|
||||
/* Set a flag option. */
|
||||
static struct options_entry *
|
||||
cmd_set_option_flag(__unused struct cmd *self, struct cmdq_item *item,
|
||||
static int
|
||||
cmd_set_option_flag(struct cmdq_item *item,
|
||||
const struct options_table_entry *oe, struct options *oo,
|
||||
const char *value)
|
||||
{
|
||||
@ -473,31 +337,28 @@ cmd_set_option_flag(__unused struct cmd *self, struct cmdq_item *item,
|
||||
|
||||
if (value == NULL || *value == '\0')
|
||||
flag = !options_get_number(oo, oe->name);
|
||||
else if (strcmp(value, "1") == 0 ||
|
||||
strcasecmp(value, "on") == 0 ||
|
||||
strcasecmp(value, "yes") == 0)
|
||||
flag = 1;
|
||||
else if (strcmp(value, "0") == 0 ||
|
||||
strcasecmp(value, "off") == 0 ||
|
||||
strcasecmp(value, "no") == 0)
|
||||
flag = 0;
|
||||
else {
|
||||
if ((value[0] == '1' && value[1] == '\0') ||
|
||||
strcasecmp(value, "on") == 0 ||
|
||||
strcasecmp(value, "yes") == 0)
|
||||
flag = 1;
|
||||
else if ((value[0] == '0' && value[1] == '\0') ||
|
||||
strcasecmp(value, "off") == 0 ||
|
||||
strcasecmp(value, "no") == 0)
|
||||
flag = 0;
|
||||
else {
|
||||
cmdq_error(item, "bad value: %s", value);
|
||||
return (NULL);
|
||||
}
|
||||
cmdq_error(item, "bad value: %s", value);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
return (options_set_number(oo, oe->name, flag));
|
||||
options_set_number(oo, oe->name, flag);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* Set a choice option. */
|
||||
static struct options_entry *
|
||||
cmd_set_option_choice(__unused struct cmd *self, struct cmdq_item *item,
|
||||
static int
|
||||
cmd_set_option_choice(struct cmdq_item *item,
|
||||
const struct options_table_entry *oe, struct options *oo,
|
||||
const char *value)
|
||||
{
|
||||
const char **choicep;
|
||||
const char **cp;
|
||||
int n, choice = -1;
|
||||
|
||||
if (value == NULL) {
|
||||
@ -506,41 +367,16 @@ cmd_set_option_choice(__unused struct cmd *self, struct cmdq_item *item,
|
||||
choice = !choice;
|
||||
} else {
|
||||
n = 0;
|
||||
for (choicep = oe->choices; *choicep != NULL; choicep++) {
|
||||
for (cp = oe->choices; *cp != NULL; cp++) {
|
||||
if (strcmp(*cp, value) == 0)
|
||||
choice = n;
|
||||
n++;
|
||||
if (strncmp(*choicep, value, strlen(value)) != 0)
|
||||
continue;
|
||||
|
||||
if (choice != -1) {
|
||||
cmdq_error(item, "ambiguous value: %s", value);
|
||||
return (NULL);
|
||||
}
|
||||
choice = n - 1;
|
||||
}
|
||||
if (choice == -1) {
|
||||
cmdq_error(item, "unknown value: %s", value);
|
||||
return (NULL);
|
||||
return (-1);
|
||||
}
|
||||
}
|
||||
|
||||
return (options_set_number(oo, oe->name, choice));
|
||||
}
|
||||
|
||||
/* Set a style option. */
|
||||
static struct options_entry *
|
||||
cmd_set_option_style(struct cmd *self, struct cmdq_item *item,
|
||||
const struct options_table_entry *oe, struct options *oo,
|
||||
const char *value)
|
||||
{
|
||||
struct args *args = self->args;
|
||||
int append = args_has(args, 'a');
|
||||
struct options_entry *o;
|
||||
|
||||
if ((o = options_set_style(oo, oe->name, append, value)) == NULL) {
|
||||
cmdq_error(item, "bad style: %s", value);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
style_update_old(oo, oe->name, &o->style);
|
||||
return (o);
|
||||
options_set_number(oo, oe->name, choice);
|
||||
return (0);
|
||||
}
|
||||
|
@ -20,6 +20,7 @@
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <vis.h>
|
||||
|
||||
#include "tmux.h"
|
||||
|
||||
@ -30,9 +31,9 @@
|
||||
static enum cmd_retval cmd_show_options_exec(struct cmd *, struct cmdq_item *);
|
||||
|
||||
static enum cmd_retval cmd_show_options_one(struct cmd *, struct cmdq_item *,
|
||||
struct options *, int);
|
||||
struct options *);
|
||||
static enum cmd_retval cmd_show_options_all(struct cmd *, struct cmdq_item *,
|
||||
struct options *, enum options_table_scope);
|
||||
struct options *);
|
||||
|
||||
const struct cmd_entry cmd_show_options_entry = {
|
||||
.name = "show-options",
|
||||
@ -64,134 +65,106 @@ static enum cmd_retval
|
||||
cmd_show_options_exec(struct cmd *self, struct cmdq_item *item)
|
||||
{
|
||||
struct args *args = self->args;
|
||||
struct session *s = item->state.tflag.s;
|
||||
struct winlink *wl = item->state.tflag.wl;
|
||||
struct cmd_find_state *fs = &item->state.tflag;
|
||||
struct options *oo;
|
||||
enum options_table_scope scope;
|
||||
int quiet;
|
||||
const char *target;
|
||||
char *cause;
|
||||
int window;
|
||||
|
||||
if (args_has(self->args, 's')) {
|
||||
oo = global_options;
|
||||
scope = OPTIONS_TABLE_SERVER;
|
||||
} else if (args_has(self->args, 'w') ||
|
||||
self->entry == &cmd_show_window_options_entry) {
|
||||
scope = OPTIONS_TABLE_WINDOW;
|
||||
if (args_has(self->args, 'g'))
|
||||
oo = global_w_options;
|
||||
else if (wl == NULL) {
|
||||
target = args_get(args, 't');
|
||||
if (target != NULL) {
|
||||
cmdq_error(item, "no such window: %s", target);
|
||||
} else
|
||||
cmdq_error(item, "no current window");
|
||||
return (CMD_RETURN_ERROR);
|
||||
} else
|
||||
oo = wl->window->options;
|
||||
} else {
|
||||
scope = OPTIONS_TABLE_SESSION;
|
||||
if (args_has(self->args, 'g'))
|
||||
oo = global_s_options;
|
||||
else if (s == NULL) {
|
||||
target = args_get(args, 't');
|
||||
if (target != NULL) {
|
||||
cmdq_error(item, "no such session: %s", target);
|
||||
} else
|
||||
cmdq_error(item, "no current session");
|
||||
return (CMD_RETURN_ERROR);
|
||||
} else
|
||||
oo = s->options;
|
||||
window = (self->entry == &cmd_show_window_options_entry);
|
||||
scope = options_scope_from_flags(args, window, fs, &oo, &cause);
|
||||
if (scope == OPTIONS_TABLE_NONE) {
|
||||
cmdq_error(item, "%s", cause);
|
||||
free(cause);
|
||||
return (CMD_RETURN_ERROR);
|
||||
}
|
||||
|
||||
quiet = args_has(self->args, 'q');
|
||||
if (args->argc == 0)
|
||||
return (cmd_show_options_all(self, item, oo, scope));
|
||||
return (cmd_show_options_all(self, item, oo));
|
||||
else
|
||||
return (cmd_show_options_one(self, item, oo, quiet));
|
||||
return (cmd_show_options_one(self, item, oo));
|
||||
}
|
||||
|
||||
static void
|
||||
cmd_show_options_print(struct cmd *self, struct cmdq_item *item,
|
||||
struct option *o, int idx)
|
||||
{
|
||||
const char *name;
|
||||
const char *value;
|
||||
char *tmp, *escaped;
|
||||
|
||||
if (idx != -1) {
|
||||
xasprintf(&tmp, "%s[%d]", options_name(o), idx);
|
||||
name = tmp;
|
||||
} else {
|
||||
tmp = NULL;
|
||||
name = options_name(o);
|
||||
}
|
||||
|
||||
value = options_tostring(o, idx);
|
||||
if (args_has(self->args, 'v'))
|
||||
cmdq_print(item, "%s", value);
|
||||
else if (options_isstring(o)) {
|
||||
stravis(&escaped, value, VIS_OCTAL|VIS_TAB|VIS_NL|VIS_DQ);
|
||||
cmdq_print(item, "%s \"%s\"", name, escaped);
|
||||
free(escaped);
|
||||
} else
|
||||
cmdq_print(item, "%s %s", name, value);
|
||||
|
||||
free(tmp);
|
||||
}
|
||||
|
||||
static enum cmd_retval
|
||||
cmd_show_options_one(struct cmd *self, struct cmdq_item *item,
|
||||
struct options *oo, int quiet)
|
||||
struct options *oo)
|
||||
{
|
||||
struct args *args = self->args;
|
||||
const char *name = args->argv[0];
|
||||
const struct options_table_entry *oe;
|
||||
struct options_entry *o;
|
||||
const char *optval;
|
||||
struct args *args = self->args;
|
||||
struct option *o;
|
||||
int idx, ambiguous;
|
||||
const char *name = args->argv[0];
|
||||
|
||||
retry:
|
||||
if (*name == '@') {
|
||||
if ((o = options_find1(oo, name)) == NULL) {
|
||||
if (quiet)
|
||||
return (CMD_RETURN_NORMAL);
|
||||
cmdq_error(item, "unknown option: %s", name);
|
||||
o = options_match_get(oo, name, &idx, 1, &ambiguous);
|
||||
if (o == NULL) {
|
||||
if (args_has(args, 'q'))
|
||||
return (CMD_RETURN_NORMAL);
|
||||
if (ambiguous) {
|
||||
cmdq_error(item, "ambiguous option: %s", name);
|
||||
return (CMD_RETURN_ERROR);
|
||||
}
|
||||
if (args_has(self->args, 'v'))
|
||||
cmdq_print(item, "%s", o->str);
|
||||
else
|
||||
cmdq_print(item, "%s \"%s\"", o->name, o->str);
|
||||
return (CMD_RETURN_NORMAL);
|
||||
}
|
||||
|
||||
oe = NULL;
|
||||
if (options_table_find(name, &oe) != 0) {
|
||||
cmdq_error(item, "ambiguous option: %s", name);
|
||||
return (CMD_RETURN_ERROR);
|
||||
}
|
||||
if (oe == NULL) {
|
||||
if (quiet)
|
||||
if (options_match_get(oo, name, &idx, 0, &ambiguous) != NULL)
|
||||
return (CMD_RETURN_NORMAL);
|
||||
cmdq_error(item, "unknown option: %s", name);
|
||||
return (CMD_RETURN_ERROR);
|
||||
}
|
||||
if (oe->style != NULL) {
|
||||
name = oe->style;
|
||||
goto retry;
|
||||
}
|
||||
if ((o = options_find1(oo, oe->name)) == NULL)
|
||||
return (CMD_RETURN_NORMAL);
|
||||
optval = options_table_print_entry(oe, o, args_has(self->args, 'v'));
|
||||
if (args_has(self->args, 'v'))
|
||||
cmdq_print(item, "%s", optval);
|
||||
else
|
||||
cmdq_print(item, "%s %s", oe->name, optval);
|
||||
cmd_show_options_print(self, item, o, idx);
|
||||
return (CMD_RETURN_NORMAL);
|
||||
}
|
||||
|
||||
static enum cmd_retval
|
||||
cmd_show_options_all(struct cmd *self, struct cmdq_item *item,
|
||||
struct options *oo, enum options_table_scope scope)
|
||||
struct options *oo)
|
||||
{
|
||||
const struct options_table_entry *oe;
|
||||
struct options_entry *o;
|
||||
const char *optval;
|
||||
int vflag;
|
||||
struct option *o;
|
||||
const struct options_table_entry *oe;
|
||||
u_int size, idx;
|
||||
|
||||
o = options_first(oo);
|
||||
while (o != NULL) {
|
||||
if (*o->name == '@') {
|
||||
if (args_has(self->args, 'v'))
|
||||
cmdq_print(item, "%s", o->str);
|
||||
else
|
||||
cmdq_print(item, "%s \"%s\"", o->name, o->str);
|
||||
oe = options_table_entry(o);
|
||||
if (oe != NULL && oe->style != NULL) {
|
||||
o = options_next(o);
|
||||
continue;
|
||||
}
|
||||
if (options_array_size(o, &size) == -1)
|
||||
cmd_show_options_print(self, item, o, -1);
|
||||
else {
|
||||
for (idx = 0; idx < size; idx++) {
|
||||
if (options_array_get(o, idx) == NULL)
|
||||
continue;
|
||||
cmd_show_options_print(self, item, o, idx);
|
||||
}
|
||||
}
|
||||
o = options_next(o);
|
||||
}
|
||||
|
||||
vflag = args_has(self->args, 'v');
|
||||
for (oe = options_table; oe->name != NULL; oe++) {
|
||||
if (oe->style != NULL || oe->scope != scope)
|
||||
continue;
|
||||
if ((o = options_find1(oo, oe->name)) == NULL)
|
||||
continue;
|
||||
optval = options_table_print_entry(oe, o, vflag);
|
||||
if (vflag)
|
||||
cmdq_print(item, "%s", optval);
|
||||
else
|
||||
cmdq_print(item, "%s %s", oe->name, optval);
|
||||
}
|
||||
|
||||
return (CMD_RETURN_NORMAL);
|
||||
}
|
||||
|
30
format.c
30
format.c
@ -640,39 +640,29 @@ static char *
|
||||
format_find(struct format_tree *ft, const char *key, int modifiers)
|
||||
{
|
||||
struct format_entry *fe, fe_find;
|
||||
struct options_entry *o;
|
||||
struct environ_entry *envent;
|
||||
static char s[64];
|
||||
struct option *o;
|
||||
const char *found;
|
||||
int idx;
|
||||
char *copy, *saved;
|
||||
|
||||
found = NULL;
|
||||
|
||||
if (~modifiers & FORMAT_TIMESTRING) {
|
||||
o = options_find(global_options, key);
|
||||
o = options_parse_get(global_options, key, &idx, 0);
|
||||
if (o == NULL && ft->w != NULL)
|
||||
o = options_find(ft->w->options, key);
|
||||
o = options_parse_get(ft->w->options, key, &idx, 0);
|
||||
if (o == NULL)
|
||||
o = options_find(global_w_options, key);
|
||||
o = options_parse_get(global_w_options, key, &idx, 0);
|
||||
if (o == NULL && ft->s != NULL)
|
||||
o = options_find(ft->s->options, key);
|
||||
o = options_parse_get(ft->s->options, key, &idx, 0);
|
||||
if (o == NULL)
|
||||
o = options_find(global_s_options, key);
|
||||
o = options_parse_get(global_s_options, key, &idx, 0);
|
||||
if (o != NULL) {
|
||||
switch (o->type) {
|
||||
case OPTIONS_STRING:
|
||||
found = o->str;
|
||||
goto found;
|
||||
case OPTIONS_NUMBER:
|
||||
xsnprintf(s, sizeof s, "%lld", o->num);
|
||||
found = s;
|
||||
goto found;
|
||||
case OPTIONS_STYLE:
|
||||
found = style_tostring(&o->style);
|
||||
goto found;
|
||||
}
|
||||
found = options_tostring(o, idx);
|
||||
goto found;
|
||||
}
|
||||
}
|
||||
found = NULL;
|
||||
|
||||
fe_find.key = (char *) key;
|
||||
fe = RB_FIND(format_entry_tree, &ft->tree, &fe_find);
|
||||
|
105
options-table.c
105
options-table.c
@ -54,7 +54,7 @@ static const char *options_table_pane_status_list[] = {
|
||||
"off", "top", "bottom", NULL
|
||||
};
|
||||
|
||||
/* Server options. */
|
||||
/* Top-level options. */
|
||||
const struct options_table_entry options_table[] = {
|
||||
{ .name = "buffer-limit",
|
||||
.type = OPTIONS_TABLE_NUMBER,
|
||||
@ -104,12 +104,6 @@ const struct options_table_entry options_table[] = {
|
||||
.default_num = 100
|
||||
},
|
||||
|
||||
{ .name = "quiet",
|
||||
.type = OPTIONS_TABLE_FLAG,
|
||||
.scope = OPTIONS_TABLE_SERVER,
|
||||
.default_num = 0
|
||||
},
|
||||
|
||||
{ .name = "set-clipboard",
|
||||
.type = OPTIONS_TABLE_FLAG,
|
||||
.scope = OPTIONS_TABLE_SERVER,
|
||||
@ -900,100 +894,3 @@ const struct options_table_entry options_table[] = {
|
||||
|
||||
{ .name = NULL }
|
||||
};
|
||||
|
||||
/* Populate an options tree from a table. */
|
||||
void
|
||||
options_table_populate_tree(enum options_table_scope scope, struct options *oo)
|
||||
{
|
||||
const struct options_table_entry *oe;
|
||||
|
||||
for (oe = options_table; oe->name != NULL; oe++) {
|
||||
if (oe->scope == OPTIONS_TABLE_NONE)
|
||||
fatalx("no scope for %s", oe->name);
|
||||
if (oe->scope != scope)
|
||||
continue;
|
||||
switch (oe->type) {
|
||||
case OPTIONS_TABLE_STRING:
|
||||
options_set_string(oo, oe->name, 0, "%s",
|
||||
oe->default_str);
|
||||
break;
|
||||
case OPTIONS_TABLE_STYLE:
|
||||
options_set_style(oo, oe->name, 0, oe->default_str);
|
||||
break;
|
||||
default:
|
||||
options_set_number(oo, oe->name, oe->default_num);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Print an option using its type from the table. */
|
||||
const char *
|
||||
options_table_print_entry(const struct options_table_entry *oe,
|
||||
struct options_entry *o, int no_quotes)
|
||||
{
|
||||
static char out[BUFSIZ];
|
||||
const char *s;
|
||||
|
||||
*out = '\0';
|
||||
switch (oe->type) {
|
||||
case OPTIONS_TABLE_STRING:
|
||||
if (no_quotes)
|
||||
xsnprintf(out, sizeof out, "%s", o->str);
|
||||
else
|
||||
xsnprintf(out, sizeof out, "\"%s\"", o->str);
|
||||
break;
|
||||
case OPTIONS_TABLE_NUMBER:
|
||||
xsnprintf(out, sizeof out, "%lld", o->num);
|
||||
break;
|
||||
case OPTIONS_TABLE_KEY:
|
||||
s = key_string_lookup_key(o->num);
|
||||
xsnprintf(out, sizeof out, "%s", s);
|
||||
break;
|
||||
case OPTIONS_TABLE_COLOUR:
|
||||
s = colour_tostring(o->num);
|
||||
xsnprintf(out, sizeof out, "%s", s);
|
||||
break;
|
||||
case OPTIONS_TABLE_ATTRIBUTES:
|
||||
s = attributes_tostring(o->num);
|
||||
xsnprintf(out, sizeof out, "%s", s);
|
||||
break;
|
||||
case OPTIONS_TABLE_FLAG:
|
||||
if (o->num)
|
||||
strlcpy(out, "on", sizeof out);
|
||||
else
|
||||
strlcpy(out, "off", sizeof out);
|
||||
break;
|
||||
case OPTIONS_TABLE_CHOICE:
|
||||
s = oe->choices[o->num];
|
||||
xsnprintf(out, sizeof out, "%s", s);
|
||||
break;
|
||||
case OPTIONS_TABLE_STYLE:
|
||||
s = style_tostring(&o->style);
|
||||
xsnprintf(out, sizeof out, "%s", s);
|
||||
break;
|
||||
}
|
||||
return (out);
|
||||
}
|
||||
|
||||
/* Find an option. */
|
||||
int
|
||||
options_table_find(const char *optstr, const struct options_table_entry **oe)
|
||||
{
|
||||
const struct options_table_entry *oe_loop;
|
||||
|
||||
for (oe_loop = options_table; oe_loop->name != NULL; oe_loop++) {
|
||||
if (strncmp(oe_loop->name, optstr, strlen(optstr)) != 0)
|
||||
continue;
|
||||
|
||||
/* If already found, ambiguous. */
|
||||
if (*oe != NULL)
|
||||
return (-1);
|
||||
*oe = oe_loop;
|
||||
|
||||
/* Bail now if an exact match. */
|
||||
if (strcmp(oe_loop->name, optstr) == 0)
|
||||
break;
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
673
options.c
673
options.c
@ -18,6 +18,7 @@
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <ctype.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
@ -29,18 +30,72 @@
|
||||
* a red-black tree.
|
||||
*/
|
||||
|
||||
struct options {
|
||||
RB_HEAD(options_tree, options_entry) tree;
|
||||
struct options *parent;
|
||||
struct option {
|
||||
struct options *owner;
|
||||
|
||||
const char *name;
|
||||
const struct options_table_entry *tableentry;
|
||||
|
||||
union {
|
||||
char *string;
|
||||
long long number;
|
||||
struct grid_cell style;
|
||||
struct {
|
||||
const char **array;
|
||||
u_int arraysize;
|
||||
};
|
||||
};
|
||||
|
||||
RB_ENTRY(option) entry;
|
||||
};
|
||||
|
||||
static int options_cmp(struct options_entry *, struct options_entry *);
|
||||
RB_GENERATE_STATIC(options_tree, options_entry, entry, options_cmp);
|
||||
struct options {
|
||||
RB_HEAD(options_tree, option) tree;
|
||||
struct options *parent;
|
||||
};
|
||||
|
||||
static struct option *options_add(struct options *, const char *);
|
||||
|
||||
#define OPTIONS_ARRAY_LIMIT 1000
|
||||
|
||||
#define OPTIONS_IS_STRING(o) \
|
||||
((o)->tableentry == NULL || \
|
||||
(o)->tableentry->type == OPTIONS_TABLE_STRING)
|
||||
#define OPTIONS_IS_NUMBER(o) \
|
||||
((o)->tableentry != NULL && \
|
||||
((o)->tableentry->type == OPTIONS_TABLE_NUMBER || \
|
||||
(o)->tableentry->type == OPTIONS_TABLE_KEY || \
|
||||
(o)->tableentry->type == OPTIONS_TABLE_COLOUR || \
|
||||
(o)->tableentry->type == OPTIONS_TABLE_ATTRIBUTES || \
|
||||
(o)->tableentry->type == OPTIONS_TABLE_FLAG || \
|
||||
(o)->tableentry->type == OPTIONS_TABLE_CHOICE))
|
||||
#define OPTIONS_IS_STYLE(o) \
|
||||
((o)->tableentry != NULL && \
|
||||
(o)->tableentry->type == OPTIONS_TABLE_STYLE)
|
||||
#define OPTIONS_IS_ARRAY(o) \
|
||||
((o)->tableentry != NULL && \
|
||||
(o)->tableentry->type == OPTIONS_TABLE_ARRAY)
|
||||
|
||||
static int options_cmp(struct option *, struct option *);
|
||||
RB_GENERATE_STATIC(options_tree, option, entry, options_cmp);
|
||||
|
||||
static int
|
||||
options_cmp(struct options_entry *o1, struct options_entry *o2)
|
||||
options_cmp(struct option *lhs, struct option *rhs)
|
||||
{
|
||||
return (strcmp(o1->name, o2->name));
|
||||
return (strcmp(lhs->name, rhs->name));
|
||||
}
|
||||
|
||||
static const struct options_table_entry *
|
||||
options_parent_table_entry(struct options *oo, const char *s)
|
||||
{
|
||||
struct option *o;
|
||||
|
||||
if (oo->parent == NULL)
|
||||
fatalx("no parent options for %s", s);
|
||||
o = options_get_only(oo->parent, s);
|
||||
if (o == NULL)
|
||||
fatalx("%s not in parent options", s);
|
||||
return (o->tableentry);
|
||||
}
|
||||
|
||||
struct options *
|
||||
@ -54,181 +109,549 @@ options_create(struct options *parent)
|
||||
return (oo);
|
||||
}
|
||||
|
||||
static void
|
||||
options_free1(struct options *oo, struct options_entry *o)
|
||||
{
|
||||
RB_REMOVE(options_tree, &oo->tree, o);
|
||||
free((char *)o->name);
|
||||
if (o->type == OPTIONS_STRING)
|
||||
free(o->str);
|
||||
free(o);
|
||||
}
|
||||
|
||||
static struct options_entry *
|
||||
options_new(struct options *oo, const char *name)
|
||||
{
|
||||
struct options_entry *o;
|
||||
|
||||
if ((o = options_find1(oo, name)) == NULL) {
|
||||
o = xmalloc(sizeof *o);
|
||||
o->name = xstrdup(name);
|
||||
RB_INSERT(options_tree, &oo->tree, o);
|
||||
memcpy(&o->style, &grid_default_cell, sizeof o->style);
|
||||
} else if (o->type == OPTIONS_STRING)
|
||||
free(o->str);
|
||||
return (o);
|
||||
}
|
||||
|
||||
void
|
||||
options_free(struct options *oo)
|
||||
{
|
||||
struct options_entry *o, *o1;
|
||||
struct option *o, *tmp;
|
||||
|
||||
RB_FOREACH_SAFE (o, options_tree, &oo->tree, o1)
|
||||
options_free1(oo, o);
|
||||
RB_FOREACH_SAFE (o, options_tree, &oo->tree, tmp)
|
||||
options_remove(o);
|
||||
free(oo);
|
||||
}
|
||||
|
||||
struct options_entry *
|
||||
struct option *
|
||||
options_first(struct options *oo)
|
||||
{
|
||||
return (RB_MIN(options_tree, &oo->tree));
|
||||
}
|
||||
|
||||
struct options_entry *
|
||||
options_next(struct options_entry *o)
|
||||
struct option *
|
||||
options_next(struct option *o)
|
||||
{
|
||||
return (RB_NEXT(options_tree, &oo->tree, o));
|
||||
}
|
||||
|
||||
struct options_entry *
|
||||
options_find1(struct options *oo, const char *name)
|
||||
struct option *
|
||||
options_get_only(struct options *oo, const char *name)
|
||||
{
|
||||
struct options_entry p;
|
||||
struct option o;
|
||||
|
||||
p.name = (char *)name;
|
||||
return (RB_FIND(options_tree, &oo->tree, &p));
|
||||
o.name = name;
|
||||
return (RB_FIND(options_tree, &oo->tree, &o));
|
||||
}
|
||||
|
||||
struct options_entry *
|
||||
options_find(struct options *oo, const char *name)
|
||||
struct option *
|
||||
options_get(struct options *oo, const char *name)
|
||||
{
|
||||
struct options_entry *o, p;
|
||||
struct option *o;
|
||||
|
||||
p.name = (char *)name;
|
||||
o = RB_FIND(options_tree, &oo->tree, &p);
|
||||
o = options_get_only(oo, name);
|
||||
while (o == NULL) {
|
||||
oo = oo->parent;
|
||||
if (oo == NULL)
|
||||
break;
|
||||
o = RB_FIND(options_tree, &oo->tree, &p);
|
||||
o = options_get_only(oo, name);
|
||||
}
|
||||
return (o);
|
||||
}
|
||||
|
||||
struct option *
|
||||
options_empty(struct options *oo, const struct options_table_entry *oe)
|
||||
{
|
||||
struct option *o;
|
||||
|
||||
o = options_add(oo, oe->name);
|
||||
o->tableentry = oe;
|
||||
|
||||
return (o);
|
||||
}
|
||||
|
||||
struct option *
|
||||
options_default(struct options *oo, const struct options_table_entry *oe)
|
||||
{
|
||||
struct option *o;
|
||||
char *cp, *copy, *next;
|
||||
u_int idx = 0;
|
||||
|
||||
o = options_empty(oo, oe);
|
||||
|
||||
if (oe->type == OPTIONS_TABLE_ARRAY) {
|
||||
copy = cp = xstrdup(oe->default_str);
|
||||
while ((next = strsep(&cp, ",")) != NULL) {
|
||||
options_array_set(o, idx, next);
|
||||
idx++;
|
||||
}
|
||||
free(copy);
|
||||
return (o);
|
||||
}
|
||||
|
||||
if (oe->type == OPTIONS_TABLE_STRING)
|
||||
o->string = xstrdup(oe->default_str);
|
||||
else if (oe->type == OPTIONS_TABLE_STYLE) {
|
||||
memcpy(&o->style, &grid_default_cell, sizeof o->style);
|
||||
style_parse(&grid_default_cell, &o->style, oe->default_str);
|
||||
} else
|
||||
o->number = oe->default_num;
|
||||
return (o);
|
||||
}
|
||||
|
||||
static struct option *
|
||||
options_add(struct options *oo, const char *name)
|
||||
{
|
||||
struct option *o;
|
||||
|
||||
o = options_get_only(oo, name);
|
||||
if (o != NULL)
|
||||
options_remove(o);
|
||||
|
||||
o = xcalloc(1, sizeof *o);
|
||||
o->owner = oo;
|
||||
o->name = xstrdup(name);
|
||||
|
||||
RB_INSERT(options_tree, &oo->tree, o);
|
||||
return (o);
|
||||
}
|
||||
|
||||
void
|
||||
options_remove(struct options *oo, const char *name)
|
||||
options_remove(struct option *o)
|
||||
{
|
||||
struct options_entry *o;
|
||||
struct options *oo = o->owner;
|
||||
u_int i;
|
||||
|
||||
if ((o = options_find1(oo, name)) != NULL)
|
||||
options_free1(oo, o);
|
||||
}
|
||||
|
||||
struct options_entry *
|
||||
options_set_string(struct options *oo, const char *name, int append,
|
||||
const char *fmt, ...)
|
||||
{
|
||||
struct options_entry *o;
|
||||
va_list ap;
|
||||
char *s, *value;
|
||||
|
||||
va_start(ap, fmt);
|
||||
xvasprintf(&s, fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
o = options_find1(oo, name);
|
||||
if (o == NULL || !append)
|
||||
value = s;
|
||||
else {
|
||||
xasprintf(&value, "%s%s", s, o->str);
|
||||
free(s);
|
||||
if (OPTIONS_IS_STRING(o))
|
||||
free((void *)o->string);
|
||||
else if (OPTIONS_IS_ARRAY(o)) {
|
||||
for (i = 0; i < o->arraysize; i++)
|
||||
free((void *)o->array[i]);
|
||||
free(o->array);
|
||||
}
|
||||
|
||||
o = options_new(oo, name);
|
||||
o->type = OPTIONS_STRING;
|
||||
o->str = value;
|
||||
RB_REMOVE(options_tree, &oo->tree, o);
|
||||
free(o);
|
||||
}
|
||||
|
||||
const char *
|
||||
options_name(struct option *o)
|
||||
{
|
||||
return (o->name);
|
||||
}
|
||||
|
||||
const struct options_table_entry *
|
||||
options_table_entry(struct option *o)
|
||||
{
|
||||
return (o->tableentry);
|
||||
}
|
||||
|
||||
const char *
|
||||
options_array_get(struct option *o, u_int idx)
|
||||
{
|
||||
if (!OPTIONS_IS_ARRAY(o))
|
||||
return (NULL);
|
||||
if (idx >= o->arraysize)
|
||||
return (NULL);
|
||||
return (o->array[idx]);
|
||||
}
|
||||
|
||||
int
|
||||
options_array_set(struct option *o, u_int idx, const char *value)
|
||||
{
|
||||
u_int i;
|
||||
|
||||
if (!OPTIONS_IS_ARRAY(o))
|
||||
return (-1);
|
||||
|
||||
if (idx >= OPTIONS_ARRAY_LIMIT)
|
||||
return (-1);
|
||||
if (idx >= o->arraysize) {
|
||||
o->array = xreallocarray(o->array, idx + 1, sizeof *o->array);
|
||||
for (i = o->arraysize; i < idx + 1; i++)
|
||||
o->array[i] = NULL;
|
||||
o->arraysize = idx + 1;
|
||||
}
|
||||
if (o->array[idx] != NULL)
|
||||
free((void *)o->array[idx]);
|
||||
if (value != NULL)
|
||||
o->array[idx] = xstrdup(value);
|
||||
else
|
||||
o->array[idx] = NULL;
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
options_array_size(struct option *o, u_int *size)
|
||||
{
|
||||
if (!OPTIONS_IS_ARRAY(o))
|
||||
return (-1);
|
||||
if (size != NULL)
|
||||
*size = o->arraysize;
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
options_isstring(struct option *o)
|
||||
{
|
||||
if (o->tableentry == NULL)
|
||||
return (1);
|
||||
return (OPTIONS_IS_STRING(o) || OPTIONS_IS_ARRAY(o));
|
||||
}
|
||||
|
||||
const char *
|
||||
options_tostring(struct option *o, int idx)
|
||||
{
|
||||
static char s[1024];
|
||||
const char *tmp;
|
||||
|
||||
if (OPTIONS_IS_ARRAY(o)) {
|
||||
if (idx == -1)
|
||||
return (NULL);
|
||||
if ((u_int)idx >= o->arraysize || o->array[idx] == NULL)
|
||||
return ("");
|
||||
return (o->array[idx]);
|
||||
}
|
||||
if (OPTIONS_IS_STYLE(o))
|
||||
return (style_tostring(&o->style));
|
||||
if (OPTIONS_IS_NUMBER(o)) {
|
||||
tmp = NULL;
|
||||
switch (o->tableentry->type) {
|
||||
case OPTIONS_TABLE_NUMBER:
|
||||
xsnprintf(s, sizeof s, "%lld", o->number);
|
||||
break;
|
||||
case OPTIONS_TABLE_KEY:
|
||||
tmp = key_string_lookup_key(o->number);
|
||||
break;
|
||||
case OPTIONS_TABLE_COLOUR:
|
||||
tmp = colour_tostring(o->number);
|
||||
break;
|
||||
case OPTIONS_TABLE_ATTRIBUTES:
|
||||
tmp = attributes_tostring(o->number);
|
||||
break;
|
||||
case OPTIONS_TABLE_FLAG:
|
||||
tmp = (o->number ? "on" : "off");
|
||||
break;
|
||||
case OPTIONS_TABLE_CHOICE:
|
||||
tmp = o->tableentry->choices[o->number];
|
||||
break;
|
||||
case OPTIONS_TABLE_STRING:
|
||||
case OPTIONS_TABLE_STYLE:
|
||||
case OPTIONS_TABLE_ARRAY:
|
||||
break;
|
||||
}
|
||||
if (tmp != NULL)
|
||||
xsnprintf(s, sizeof s, "%s", tmp);
|
||||
return (s);
|
||||
}
|
||||
if (OPTIONS_IS_STRING(o))
|
||||
return (o->string);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
char *
|
||||
options_parse(const char *name, int *idx)
|
||||
{
|
||||
char *copy, *cp, *end;
|
||||
|
||||
if (*name == '\0')
|
||||
return (NULL);
|
||||
copy = xstrdup(name);
|
||||
if ((cp = strchr(copy, '[')) == NULL) {
|
||||
*idx = -1;
|
||||
return (copy);
|
||||
}
|
||||
end = strchr(cp + 1, ']');
|
||||
if (end == NULL || end[1] != '\0' || !isdigit((u_char)end[-1])) {
|
||||
free(copy);
|
||||
return (NULL);
|
||||
}
|
||||
if (sscanf(cp, "[%d]", idx) != 1 || *idx < 0) {
|
||||
free(copy);
|
||||
return (NULL);
|
||||
}
|
||||
*cp = '\0';
|
||||
return (copy);
|
||||
}
|
||||
|
||||
struct option *
|
||||
options_parse_get(struct options *oo, const char *s, int *idx, int only)
|
||||
{
|
||||
struct option *o;
|
||||
char *name;
|
||||
|
||||
name = options_parse(s, idx);
|
||||
if (name == NULL)
|
||||
return (NULL);
|
||||
if (only)
|
||||
o = options_get_only(oo, name);
|
||||
else
|
||||
o = options_get(oo, name);
|
||||
free(name);
|
||||
if (o != NULL) {
|
||||
if (OPTIONS_IS_ARRAY(o) && *idx == -1)
|
||||
return (NULL);
|
||||
if (!OPTIONS_IS_ARRAY(o) && *idx != -1)
|
||||
return (NULL);
|
||||
}
|
||||
return (o);
|
||||
}
|
||||
|
||||
char *
|
||||
options_match(const char *s, int *idx, int* ambiguous)
|
||||
{
|
||||
const struct options_table_entry *oe, *found;
|
||||
char *name;
|
||||
size_t namelen;
|
||||
|
||||
name = options_parse(s, idx);
|
||||
namelen = strlen(name);
|
||||
|
||||
found = NULL;
|
||||
for (oe = options_table; oe->name != NULL; oe++) {
|
||||
if (strcmp(oe->name, name) == 0) {
|
||||
found = oe;
|
||||
break;
|
||||
}
|
||||
if (strncmp(oe->name, name, namelen) == 0) {
|
||||
if (found != NULL) {
|
||||
*ambiguous = 1;
|
||||
free(name);
|
||||
return (NULL);
|
||||
}
|
||||
found = oe;
|
||||
}
|
||||
}
|
||||
free(name);
|
||||
if (found == NULL) {
|
||||
*ambiguous = 0;
|
||||
return (NULL);
|
||||
}
|
||||
return (xstrdup(found->name));
|
||||
}
|
||||
|
||||
struct option *
|
||||
options_match_get(struct options *oo, const char *s, int *idx, int only,
|
||||
int* ambiguous)
|
||||
{
|
||||
char *name;
|
||||
struct option *o;
|
||||
|
||||
name = options_match(s, idx, ambiguous);
|
||||
if (name == NULL)
|
||||
return (NULL);
|
||||
*ambiguous = 0;
|
||||
if (only)
|
||||
o = options_get_only(oo, name);
|
||||
else
|
||||
o = options_get(oo, name);
|
||||
free(name);
|
||||
if (o != NULL) {
|
||||
if (OPTIONS_IS_ARRAY(o) && *idx == -1)
|
||||
return (NULL);
|
||||
if (!OPTIONS_IS_ARRAY(o) && *idx != -1)
|
||||
return (NULL);
|
||||
}
|
||||
return (o);
|
||||
}
|
||||
|
||||
|
||||
const char *
|
||||
options_get_string(struct options *oo, const char *name)
|
||||
{
|
||||
struct options_entry *o;
|
||||
struct option *o;
|
||||
|
||||
if ((o = options_find(oo, name)) == NULL)
|
||||
o = options_get(oo, name);
|
||||
if (o == NULL)
|
||||
fatalx("missing option %s", name);
|
||||
if (o->type != OPTIONS_STRING)
|
||||
fatalx("option %s not a string", name);
|
||||
return (o->str);
|
||||
}
|
||||
|
||||
struct options_entry *
|
||||
options_set_number(struct options *oo, const char *name, long long value)
|
||||
{
|
||||
struct options_entry *o;
|
||||
|
||||
o = options_new(oo, name);
|
||||
o->type = OPTIONS_NUMBER;
|
||||
o->num = value;
|
||||
|
||||
return (o);
|
||||
if (!OPTIONS_IS_STRING(o))
|
||||
fatalx("option %s is not a string", name);
|
||||
return (o->string);
|
||||
}
|
||||
|
||||
long long
|
||||
options_get_number(struct options *oo, const char *name)
|
||||
{
|
||||
struct options_entry *o;
|
||||
struct option *o;
|
||||
|
||||
if ((o = options_find(oo, name)) == NULL)
|
||||
o = options_get(oo, name);
|
||||
if (o == NULL)
|
||||
fatalx("missing option %s", name);
|
||||
if (o->type != OPTIONS_NUMBER)
|
||||
fatalx("option %s not a number", name);
|
||||
return (o->num);
|
||||
}
|
||||
|
||||
struct options_entry *
|
||||
options_set_style(struct options *oo, const char *name, int append,
|
||||
const char *value)
|
||||
{
|
||||
struct options_entry *o;
|
||||
struct grid_cell tmpgc;
|
||||
|
||||
o = options_find1(oo, name);
|
||||
if (o == NULL || !append)
|
||||
memcpy(&tmpgc, &grid_default_cell, sizeof tmpgc);
|
||||
else
|
||||
memcpy(&tmpgc, &o->style, sizeof tmpgc);
|
||||
|
||||
if (style_parse(&grid_default_cell, &tmpgc, value) == -1)
|
||||
return (NULL);
|
||||
|
||||
o = options_new(oo, name);
|
||||
o->type = OPTIONS_STYLE;
|
||||
memcpy(&o->style, &tmpgc, sizeof o->style);
|
||||
|
||||
return (o);
|
||||
if (!OPTIONS_IS_NUMBER(o))
|
||||
fatalx("option %s is not a number", name);
|
||||
return (o->number);
|
||||
}
|
||||
|
||||
const struct grid_cell *
|
||||
options_get_style(struct options *oo, const char *name)
|
||||
{
|
||||
struct options_entry *o;
|
||||
struct option *o;
|
||||
|
||||
if ((o = options_find(oo, name)) == NULL)
|
||||
o = options_get(oo, name);
|
||||
if (o == NULL)
|
||||
fatalx("missing option %s", name);
|
||||
if (o->type != OPTIONS_STYLE)
|
||||
fatalx("option %s not a style", name);
|
||||
if (!OPTIONS_IS_STYLE(o))
|
||||
fatalx("option %s is not a style", name);
|
||||
return (&o->style);
|
||||
}
|
||||
|
||||
struct option *
|
||||
options_set_string(struct options *oo, const char *name, int append,
|
||||
const char *fmt, ...)
|
||||
{
|
||||
struct option *o;
|
||||
va_list ap;
|
||||
char *s, *value;
|
||||
|
||||
va_start(ap, fmt);
|
||||
xvasprintf(&s, fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
o = options_get_only(oo, name);
|
||||
if (o != NULL && append && OPTIONS_IS_STRING(o)) {
|
||||
xasprintf(&value, "%s%s", o->string, s);
|
||||
free(s);
|
||||
} else
|
||||
value = s;
|
||||
if (o == NULL && *name == '@')
|
||||
o = options_add(oo, name);
|
||||
else if (o == NULL) {
|
||||
o = options_default(oo, options_parent_table_entry(oo, name));
|
||||
if (o == NULL)
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
if (!OPTIONS_IS_STRING(o))
|
||||
fatalx("option %s is not a string", name);
|
||||
free(o->string);
|
||||
o->string = value;
|
||||
return (o);
|
||||
}
|
||||
|
||||
struct option *
|
||||
options_set_number(struct options *oo, const char *name, long long value)
|
||||
{
|
||||
struct option *o;
|
||||
|
||||
if (*name == '@')
|
||||
fatalx("user option %s must be a string", name);
|
||||
|
||||
o = options_get_only(oo, name);
|
||||
if (o == NULL) {
|
||||
o = options_default(oo, options_parent_table_entry(oo, name));
|
||||
if (o == NULL)
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
if (!OPTIONS_IS_NUMBER(o))
|
||||
fatalx("option %s is not a number", name);
|
||||
o->number = value;
|
||||
return (o);
|
||||
}
|
||||
|
||||
struct option *
|
||||
options_set_style(struct options *oo, const char *name, int append,
|
||||
const char *value)
|
||||
{
|
||||
struct option *o;
|
||||
struct grid_cell gc;
|
||||
|
||||
if (*name == '@')
|
||||
fatalx("user option %s must be a string", name);
|
||||
|
||||
o = options_get_only(oo, name);
|
||||
if (o != NULL && append && OPTIONS_IS_STYLE(o))
|
||||
memcpy(&gc, &o->style, sizeof gc);
|
||||
else
|
||||
memcpy(&gc, &grid_default_cell, sizeof gc);
|
||||
if (style_parse(&grid_default_cell, &gc, value) == -1)
|
||||
return (NULL);
|
||||
if (o == NULL) {
|
||||
o = options_default(oo, options_parent_table_entry(oo, name));
|
||||
if (o == NULL)
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
if (!OPTIONS_IS_STYLE(o))
|
||||
fatalx("option %s is not a style", name);
|
||||
memcpy(&o->style, &gc, sizeof o->style);
|
||||
return (o);
|
||||
}
|
||||
|
||||
enum options_table_scope
|
||||
options_scope_from_flags(struct args *args, int window,
|
||||
struct cmd_find_state *fs, struct options **oo, char **cause)
|
||||
{
|
||||
struct session *s = fs->s;
|
||||
struct winlink *wl = fs->wl;
|
||||
const char *target= args_get(args, 't');
|
||||
|
||||
if (args_has(args, 's')) {
|
||||
*oo = global_options;
|
||||
return (OPTIONS_TABLE_SERVER);
|
||||
}
|
||||
|
||||
if (window || args_has(args, 'w')) {
|
||||
if (args_has(args, 'g')) {
|
||||
*oo = global_w_options;
|
||||
return (OPTIONS_TABLE_WINDOW);
|
||||
}
|
||||
if (wl == NULL) {
|
||||
if (target != NULL)
|
||||
xasprintf(cause, "no such window: %s", target);
|
||||
else
|
||||
xasprintf(cause, "no current window");
|
||||
return (OPTIONS_TABLE_NONE);
|
||||
}
|
||||
*oo = wl->window->options;
|
||||
return (OPTIONS_TABLE_WINDOW);
|
||||
} else {
|
||||
if (args_has(args, 'g')) {
|
||||
*oo = global_s_options;
|
||||
return (OPTIONS_TABLE_SESSION);
|
||||
}
|
||||
if (s == NULL) {
|
||||
if (target != NULL)
|
||||
xasprintf(cause, "no such session: %s", target);
|
||||
else
|
||||
xasprintf(cause, "no current session");
|
||||
return (OPTIONS_TABLE_NONE);
|
||||
}
|
||||
*oo = s->options;
|
||||
return (OPTIONS_TABLE_SESSION);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
options_style_update_new(struct options *oo, struct option *o)
|
||||
{
|
||||
const char *newname = o->tableentry->style;
|
||||
struct option *new;
|
||||
|
||||
if (newname == NULL)
|
||||
return;
|
||||
new = options_get_only(oo, newname);
|
||||
if (new == NULL)
|
||||
new = options_set_style(oo, newname, 0, "default");
|
||||
|
||||
if (strstr(o->name, "-bg") != NULL)
|
||||
new->style.bg = o->number;
|
||||
else if (strstr(o->name, "-fg") != NULL)
|
||||
new->style.fg = o->number;
|
||||
else if (strstr(o->name, "-attr") != NULL)
|
||||
new->style.attr = o->number;
|
||||
}
|
||||
|
||||
void
|
||||
options_style_update_old(struct options *oo, struct option *o)
|
||||
{
|
||||
char newname[128];
|
||||
int size;
|
||||
|
||||
size = strrchr(o->name, '-') - o->name;
|
||||
|
||||
xsnprintf(newname, sizeof newname, "%.*s-bg", size, o->name);
|
||||
options_set_number(oo, newname, o->style.bg);
|
||||
|
||||
xsnprintf(newname, sizeof newname, "%.*s-fg", size, o->name);
|
||||
options_set_number(oo, newname, o->style.fg);
|
||||
|
||||
xsnprintf(newname, sizeof newname, "%.*s-attr", size, o->name);
|
||||
options_set_number(oo, newname, o->style.attr);
|
||||
}
|
||||
|
49
style.c
49
style.c
@ -129,55 +129,6 @@ style_tostring(struct grid_cell *gc)
|
||||
return (s);
|
||||
}
|
||||
|
||||
/* Synchronize new -style option with the old one. */
|
||||
void
|
||||
style_update_new(struct options *oo, const char *name, const char *newname)
|
||||
{
|
||||
int value;
|
||||
struct grid_cell *gc;
|
||||
struct options_entry *o;
|
||||
|
||||
/* It's a colour or attribute, but with no -style equivalent. */
|
||||
if (newname == NULL)
|
||||
return;
|
||||
|
||||
o = options_find1(oo, newname);
|
||||
if (o == NULL)
|
||||
o = options_set_style(oo, newname, 0, "default");
|
||||
gc = &o->style;
|
||||
|
||||
o = options_find1(oo, name);
|
||||
if (o == NULL)
|
||||
o = options_set_number(oo, name, 8);
|
||||
value = o->num;
|
||||
|
||||
if (strstr(name, "-bg") != NULL)
|
||||
gc->bg = value;
|
||||
else if (strstr(name, "-fg") != NULL)
|
||||
gc->fg = value;
|
||||
else if (strstr(name, "-attr") != NULL)
|
||||
gc->attr = value;
|
||||
}
|
||||
|
||||
/* Synchronize all the old options with the new -style one. */
|
||||
void
|
||||
style_update_old(struct options *oo, const char *name, struct grid_cell *gc)
|
||||
{
|
||||
char newname[128];
|
||||
int size;
|
||||
|
||||
size = strrchr(name, '-') - name;
|
||||
|
||||
xsnprintf(newname, sizeof newname, "%.*s-bg", size, name);
|
||||
options_set_number(oo, newname, gc->bg);
|
||||
|
||||
xsnprintf(newname, sizeof newname, "%.*s-fg", size, name);
|
||||
options_set_number(oo, newname, gc->fg);
|
||||
|
||||
xsnprintf(newname, sizeof newname, "%.*s-attr", size, name);
|
||||
options_set_number(oo, newname, gc->attr);
|
||||
}
|
||||
|
||||
/* Apply a style. */
|
||||
void
|
||||
style_apply(struct grid_cell *gc, struct options *oo, const char *name)
|
||||
|
30
tmux.c
30
tmux.c
@ -187,9 +187,11 @@ find_home(void)
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
char *path, *label, **var, tmp[PATH_MAX], *shellcmd = NULL;
|
||||
const char *s;
|
||||
int opt, flags, keys;
|
||||
char *path, *label, tmp[PATH_MAX];
|
||||
char *shellcmd = NULL, **var;
|
||||
const char *s, *shell;
|
||||
int opt, flags, keys;
|
||||
const struct options_table_entry *oe;
|
||||
|
||||
if (setlocale(LC_CTYPE, "en_US.UTF-8") == NULL) {
|
||||
if (setlocale(LC_CTYPE, "") == NULL)
|
||||
@ -295,15 +297,23 @@ main(int argc, char **argv)
|
||||
environ_set(global_environ, "PWD", "%s", tmp);
|
||||
|
||||
global_options = options_create(NULL);
|
||||
options_table_populate_tree(OPTIONS_TABLE_SERVER, global_options);
|
||||
|
||||
global_s_options = options_create(NULL);
|
||||
options_table_populate_tree(OPTIONS_TABLE_SESSION, global_s_options);
|
||||
options_set_string(global_s_options, "default-shell", 0, "%s",
|
||||
getshell());
|
||||
|
||||
global_w_options = options_create(NULL);
|
||||
options_table_populate_tree(OPTIONS_TABLE_WINDOW, global_w_options);
|
||||
for (oe = options_table; oe->name != NULL; oe++) {
|
||||
if (oe->scope == OPTIONS_TABLE_SERVER)
|
||||
options_default(global_options, oe);
|
||||
if (oe->scope == OPTIONS_TABLE_SESSION)
|
||||
options_default(global_s_options, oe);
|
||||
if (oe->scope == OPTIONS_TABLE_WINDOW)
|
||||
options_default(global_w_options, oe);
|
||||
}
|
||||
|
||||
/*
|
||||
* The default shell comes from SHELL or from the user's passwd entry
|
||||
* if available.
|
||||
*/
|
||||
shell = getshell();
|
||||
options_set_string(global_s_options, "default-shell", 0, "%s", shell);
|
||||
|
||||
/* Override keys to vi if VISUAL or EDITOR are set. */
|
||||
if ((s = getenv("VISUAL")) != NULL || (s = getenv("EDITOR")) != NULL) {
|
||||
|
77
tmux.h
77
tmux.h
@ -643,23 +643,6 @@ struct hook {
|
||||
RB_ENTRY(hook) entry;
|
||||
};
|
||||
|
||||
/* Option data structures. */
|
||||
struct options_entry {
|
||||
const char *name;
|
||||
|
||||
enum {
|
||||
OPTIONS_STRING,
|
||||
OPTIONS_NUMBER,
|
||||
OPTIONS_STYLE
|
||||
} type;
|
||||
|
||||
char *str;
|
||||
long long num;
|
||||
struct grid_cell style;
|
||||
|
||||
RB_ENTRY(options_entry) entry;
|
||||
};
|
||||
|
||||
/* Scheduled job. */
|
||||
struct job {
|
||||
enum {
|
||||
@ -1479,7 +1462,8 @@ enum options_table_type {
|
||||
OPTIONS_TABLE_ATTRIBUTES,
|
||||
OPTIONS_TABLE_FLAG,
|
||||
OPTIONS_TABLE_CHOICE,
|
||||
OPTIONS_TABLE_STYLE
|
||||
OPTIONS_TABLE_STYLE,
|
||||
OPTIONS_TABLE_ARRAY,
|
||||
};
|
||||
enum options_table_scope {
|
||||
OPTIONS_TABLE_NONE,
|
||||
@ -1623,29 +1607,45 @@ void notify_window(const char *, struct window *);
|
||||
void notify_pane(const char *, struct window_pane *);
|
||||
|
||||
/* options.c */
|
||||
struct options *options_create(struct options *);
|
||||
void options_free(struct options *);
|
||||
struct options_entry *options_first(struct options *);
|
||||
struct options_entry *options_next(struct options_entry *);
|
||||
struct options_entry *options_find1(struct options *, const char *);
|
||||
struct options_entry *options_find(struct options *, const char *);
|
||||
void options_remove(struct options *, const char *);
|
||||
struct options_entry * printflike(4, 5) options_set_string(struct options *,
|
||||
const char *, int, const char *, ...);
|
||||
const char *options_get_string(struct options *, const char *);
|
||||
struct options_entry *options_set_number(struct options *, const char *,
|
||||
long long);
|
||||
long long options_get_number(struct options *, const char *);
|
||||
struct options_entry *options_set_style(struct options *, const char *, int,
|
||||
const char *);
|
||||
struct options *options_create(struct options *);
|
||||
void options_free(struct options *);
|
||||
struct option *options_first(struct options *);
|
||||
struct option *options_next(struct option *);
|
||||
struct option *options_empty(struct options *,
|
||||
const struct options_table_entry *);
|
||||
struct option *options_default(struct options *,
|
||||
const struct options_table_entry *);
|
||||
const char *options_name(struct option *);
|
||||
const struct options_table_entry *options_table_entry(struct option *);
|
||||
struct option *options_get_only(struct options *, const char *);
|
||||
struct option *options_get(struct options *, const char *);
|
||||
void options_remove(struct option *);
|
||||
const char *options_array_get(struct option *, u_int);
|
||||
int options_array_set(struct option *, u_int, const char *);
|
||||
int options_array_size(struct option *, u_int *);
|
||||
int options_isstring(struct option *);
|
||||
const char *options_tostring(struct option *, int);
|
||||
char *options_parse(const char *, int *);
|
||||
struct option *options_parse_get(struct options *, const char *, int *,
|
||||
int);
|
||||
char *options_match(const char *, int *, int *);
|
||||
struct option *options_match_get(struct options *, const char *, int *,
|
||||
int, int *);
|
||||
const char *options_get_string(struct options *, const char *);
|
||||
long long options_get_number(struct options *, const char *);
|
||||
const struct grid_cell *options_get_style(struct options *, const char *);
|
||||
struct option * printflike(4, 5) options_set_string(struct options *,
|
||||
const char *, int, const char *, ...);
|
||||
struct option *options_set_number(struct options *, const char *, long long);
|
||||
struct option *options_set_style(struct options *, const char *, int,
|
||||
const char *);
|
||||
enum options_table_scope options_scope_from_flags(struct args *, int,
|
||||
struct cmd_find_state *, struct options **, char **);
|
||||
void options_style_update_new(struct options *, struct option *);
|
||||
void options_style_update_old(struct options *, struct option *);
|
||||
|
||||
/* options-table.c */
|
||||
extern const struct options_table_entry options_table[];
|
||||
void options_table_populate_tree(enum options_table_scope, struct options *);
|
||||
const char *options_table_print_entry(const struct options_table_entry *,
|
||||
struct options_entry *, int);
|
||||
int options_table_find(const char *, const struct options_table_entry **);
|
||||
|
||||
/* job.c */
|
||||
extern struct joblist all_jobs;
|
||||
@ -2326,9 +2326,6 @@ __dead void printflike(1, 2) fatalx(const char *, ...);
|
||||
int style_parse(const struct grid_cell *,
|
||||
struct grid_cell *, const char *);
|
||||
const char *style_tostring(struct grid_cell *);
|
||||
void style_update_new(struct options *, const char *, const char *);
|
||||
void style_update_old(struct options *, const char *,
|
||||
struct grid_cell *);
|
||||
void style_apply(struct grid_cell *, struct options *,
|
||||
const char *);
|
||||
void style_apply_update(struct grid_cell *, struct options *,
|
||||
|
Loading…
Reference in New Issue
Block a user