mirror of
https://codeberg.org/dnkl/foot.git
synced 2026-02-05 04:06:08 -05:00
Merge branch 'config-clone'
This commit is contained in:
commit
4e5f5026b8
9 changed files with 248 additions and 122 deletions
309
config.c
309
config.c
|
|
@ -501,30 +501,70 @@ str_to_pt_or_px(const char *s, struct pt_or_px *res, struct config *conf,
|
|||
return true;
|
||||
}
|
||||
|
||||
static void NOINLINE
|
||||
free_argv(struct argv *argv)
|
||||
{
|
||||
if (argv->args == NULL)
|
||||
return;
|
||||
for (char **a = argv->args; *a != NULL; a++)
|
||||
free(*a);
|
||||
free(argv->args);
|
||||
argv->args = NULL;
|
||||
}
|
||||
|
||||
static void NOINLINE
|
||||
clone_argv(struct argv *dst, const struct argv *src)
|
||||
{
|
||||
if (src->args == NULL) {
|
||||
dst->args = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
size_t count = 0;
|
||||
for (char **args = src->args; *args != NULL; args++)
|
||||
count++;
|
||||
|
||||
dst->args = xmalloc((count + 1) * sizeof(dst->args[0]));
|
||||
for (char **args_src = src->args, **args_dst = dst->args;
|
||||
*args_src != NULL; args_src++,
|
||||
args_dst++)
|
||||
{
|
||||
*args_dst = xstrdup(*args_src);
|
||||
}
|
||||
dst->args[count] = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
spawn_template_free(struct config_spawn_template *template)
|
||||
{
|
||||
free_argv(&template->argv);
|
||||
}
|
||||
|
||||
static void
|
||||
spawn_template_clone(struct config_spawn_template *dst,
|
||||
const struct config_spawn_template *src)
|
||||
{
|
||||
clone_argv(&dst->argv, &src->argv);
|
||||
}
|
||||
|
||||
static bool NOINLINE
|
||||
str_to_spawn_template(struct config *conf,
|
||||
const char *s, struct config_spawn_template *template,
|
||||
const char *path, int lineno, const char *section,
|
||||
const char *key)
|
||||
{
|
||||
free(template->raw_cmd);
|
||||
free(template->argv);
|
||||
spawn_template_free(template);
|
||||
|
||||
template->raw_cmd = NULL;
|
||||
template->argv = NULL;
|
||||
|
||||
char *raw_cmd = xstrdup(s);
|
||||
char **argv = NULL;
|
||||
|
||||
if (!tokenize_cmdline(raw_cmd, &argv)) {
|
||||
if (!tokenize_cmdline(s, &argv)) {
|
||||
LOG_AND_NOTIFY_ERR(
|
||||
"%s:%d: [%s]: %s: syntax error in command line",
|
||||
path, lineno, section, key);
|
||||
return false;
|
||||
}
|
||||
|
||||
template->raw_cmd = raw_cmd;
|
||||
template->argv = argv;
|
||||
template->argv.args = argv;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -1525,12 +1565,12 @@ has_key_binding_collisions(struct config *conf,
|
|||
bool sym = combo1->sym == combo2->sym;
|
||||
|
||||
if (shift && alt && ctrl && meta && sym) {
|
||||
bool has_pipe = combo1->pipe.cmd != NULL;
|
||||
bool has_pipe = combo1->pipe.argv.args != NULL;
|
||||
LOG_AND_NOTIFY_ERR("%s:%d: %s already mapped to '%s%s%s%s'",
|
||||
path, lineno, combo2->text,
|
||||
action_map[combo1->action],
|
||||
has_pipe ? " [" : "",
|
||||
has_pipe ? combo1->pipe.cmd : "",
|
||||
has_pipe ? combo1->pipe.argv.args[0] : "",
|
||||
has_pipe ? "]" : "");
|
||||
return true;
|
||||
}
|
||||
|
|
@ -1585,11 +1625,10 @@ argv_compare(char *const *argv1, char *const *argv2)
|
|||
* - argv: allocatd array containing {"cmd", "arg1", "arg2", NULL}. Caller frees.
|
||||
*/
|
||||
static ssize_t
|
||||
pipe_argv_from_string(const char *value, char **cmd, char ***argv,
|
||||
pipe_argv_from_string(const char *value, char ***argv,
|
||||
struct config *conf,
|
||||
const char *path, unsigned lineno)
|
||||
{
|
||||
*cmd = NULL;
|
||||
*argv = NULL;
|
||||
|
||||
if (value[0] != '[')
|
||||
|
|
@ -1602,11 +1641,11 @@ pipe_argv_from_string(const char *value, char **cmd, char ***argv,
|
|||
}
|
||||
|
||||
size_t pipe_len = pipe_cmd_end - value - 1;
|
||||
*cmd = xstrndup(&value[1], pipe_len);
|
||||
char *cmd = xstrndup(&value[1], pipe_len);
|
||||
|
||||
if (!tokenize_cmdline(*cmd, argv)) {
|
||||
if (!tokenize_cmdline(cmd, argv)) {
|
||||
LOG_AND_NOTIFY_ERR("%s:%d: syntax error in command line", path, lineno);
|
||||
free(*cmd);
|
||||
free(cmd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
|
@ -1617,6 +1656,7 @@ pipe_argv_from_string(const char *value, char **cmd, char ***argv,
|
|||
remove_len++;
|
||||
}
|
||||
|
||||
free(cmd);
|
||||
return remove_len;
|
||||
}
|
||||
|
||||
|
|
@ -1627,11 +1667,10 @@ parse_key_binding_section(
|
|||
struct config_key_binding_list *bindings,
|
||||
struct config *conf, const char *path, unsigned lineno)
|
||||
{
|
||||
char *pipe_cmd;
|
||||
char **pipe_argv;
|
||||
|
||||
ssize_t pipe_remove_len = pipe_argv_from_string(
|
||||
value, &pipe_cmd, &pipe_argv, conf, path, lineno);
|
||||
value, &pipe_argv, conf, path, lineno);
|
||||
|
||||
if (pipe_remove_len < 0)
|
||||
return false;
|
||||
|
|
@ -1653,17 +1692,12 @@ parse_key_binding_section(
|
|||
if (binding->action != action)
|
||||
continue;
|
||||
|
||||
if (binding->pipe.master_copy) {
|
||||
free(binding->pipe.cmd);
|
||||
free(binding->pipe.argv);
|
||||
}
|
||||
if (binding->pipe.master_copy)
|
||||
free_argv(&binding->pipe.argv);
|
||||
binding->action = BIND_ACTION_NONE;
|
||||
binding->pipe.cmd = NULL;
|
||||
binding->pipe.argv = NULL;
|
||||
}
|
||||
|
||||
free(pipe_argv);
|
||||
free(pipe_cmd);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -1675,7 +1709,6 @@ parse_key_binding_section(
|
|||
path, lineno))
|
||||
{
|
||||
free(pipe_argv);
|
||||
free(pipe_cmd);
|
||||
free_key_combo_list(&key_combos);
|
||||
return false;
|
||||
}
|
||||
|
|
@ -1685,18 +1718,14 @@ parse_key_binding_section(
|
|||
struct config_key_binding *binding = &bindings->arr[i];
|
||||
|
||||
if (binding->action == action &&
|
||||
((binding->pipe.argv == NULL && pipe_argv == NULL) ||
|
||||
(binding->pipe.argv != NULL && pipe_argv != NULL &&
|
||||
argv_compare(binding->pipe.argv, pipe_argv) == 0)))
|
||||
((binding->pipe.argv.args == NULL && pipe_argv == NULL) ||
|
||||
(binding->pipe.argv.args != NULL && pipe_argv != NULL &&
|
||||
argv_compare(binding->pipe.argv.args, pipe_argv) == 0)))
|
||||
{
|
||||
|
||||
if (binding->pipe.master_copy) {
|
||||
free(binding->pipe.cmd);
|
||||
free(binding->pipe.argv);
|
||||
}
|
||||
if (binding->pipe.master_copy)
|
||||
free_argv(&binding->pipe.argv);
|
||||
binding->action = BIND_ACTION_NONE;
|
||||
binding->pipe.cmd = NULL;
|
||||
binding->pipe.argv = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1714,8 +1743,9 @@ parse_key_binding_section(
|
|||
.modifiers = combo->modifiers,
|
||||
.sym = combo->sym,
|
||||
.pipe = {
|
||||
.cmd = pipe_cmd,
|
||||
.argv = pipe_argv,
|
||||
.argv = {
|
||||
.args = pipe_argv,
|
||||
},
|
||||
.master_copy = first,
|
||||
},
|
||||
};
|
||||
|
|
@ -1731,7 +1761,6 @@ parse_key_binding_section(
|
|||
|
||||
LOG_AND_NOTIFY_ERR("%s:%u: [%s]: %s: invalid action",
|
||||
path, lineno, section, key);
|
||||
free(pipe_cmd);
|
||||
free(pipe_argv);
|
||||
return false;
|
||||
}
|
||||
|
|
@ -1936,12 +1965,12 @@ has_mouse_binding_collisions(struct config *conf, const struct key_combo_list *k
|
|||
bool count = combo1->count == combo2->m.count;
|
||||
|
||||
if (shift && alt && ctrl && meta && button && count) {
|
||||
bool has_pipe = combo1->pipe.cmd != NULL;
|
||||
bool has_pipe = combo1->pipe.argv.args != NULL;
|
||||
LOG_AND_NOTIFY_ERR("%s:%d: %s already mapped to '%s%s%s%s'",
|
||||
path, lineno, combo2->text,
|
||||
binding_action_map[combo1->action],
|
||||
has_pipe ? " [" : "",
|
||||
has_pipe ? combo1->pipe.cmd : "",
|
||||
has_pipe ? combo1->pipe.argv.args[0] : "",
|
||||
has_pipe ? "]" : "");
|
||||
return true;
|
||||
}
|
||||
|
|
@ -1957,11 +1986,10 @@ parse_section_mouse_bindings(
|
|||
const char *key, const char *value, struct config *conf,
|
||||
const char *path, unsigned lineno, bool errors_are_fatal)
|
||||
{
|
||||
char *pipe_cmd;
|
||||
char **pipe_argv;
|
||||
|
||||
ssize_t pipe_remove_len = pipe_argv_from_string(
|
||||
value, &pipe_cmd, &pipe_argv, conf, path, lineno);
|
||||
value, &pipe_argv, conf, path, lineno);
|
||||
|
||||
if (pipe_remove_len < 0)
|
||||
return false;
|
||||
|
|
@ -1985,17 +2013,12 @@ parse_section_mouse_bindings(
|
|||
&conf->bindings.mouse.arr[i];
|
||||
|
||||
if (binding->action == action) {
|
||||
if (binding->pipe.master_copy) {
|
||||
free(binding->pipe.cmd);
|
||||
free(binding->pipe.argv);
|
||||
}
|
||||
if (binding->pipe.master_copy)
|
||||
free_argv(&binding->pipe.argv);
|
||||
binding->action = BIND_ACTION_NONE;
|
||||
binding->pipe.cmd = NULL;
|
||||
binding->pipe.argv = NULL;
|
||||
}
|
||||
}
|
||||
free(pipe_argv);
|
||||
free(pipe_cmd);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -2004,7 +2027,6 @@ parse_section_mouse_bindings(
|
|||
has_mouse_binding_collisions(conf, &key_combos, path, lineno))
|
||||
{
|
||||
free(pipe_argv);
|
||||
free(pipe_cmd);
|
||||
free_key_combo_list(&key_combos);
|
||||
return false;
|
||||
}
|
||||
|
|
@ -2014,17 +2036,13 @@ parse_section_mouse_bindings(
|
|||
struct config_mouse_binding *binding = &conf->bindings.mouse.arr[i];
|
||||
|
||||
if (binding->action == action &&
|
||||
((binding->pipe.argv == NULL && pipe_argv == NULL) ||
|
||||
(binding->pipe.argv != NULL && pipe_argv != NULL &&
|
||||
argv_compare(binding->pipe.argv, pipe_argv) == 0)))
|
||||
((binding->pipe.argv.args == NULL && pipe_argv == NULL) ||
|
||||
(binding->pipe.argv.args != NULL && pipe_argv != NULL &&
|
||||
argv_compare(binding->pipe.argv.args, pipe_argv) == 0)))
|
||||
{
|
||||
if (binding->pipe.master_copy) {
|
||||
free(binding->pipe.cmd);
|
||||
free(binding->pipe.argv);
|
||||
}
|
||||
if (binding->pipe.master_copy)
|
||||
free_argv(&binding->pipe.argv);
|
||||
binding->action = BIND_ACTION_NONE;
|
||||
binding->pipe.cmd = NULL;
|
||||
binding->pipe.argv = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2044,8 +2062,9 @@ parse_section_mouse_bindings(
|
|||
.button = combo->m.button,
|
||||
.count = combo->m.count,
|
||||
.pipe = {
|
||||
.cmd = pipe_cmd,
|
||||
.argv = pipe_argv,
|
||||
.argv = {
|
||||
.args = pipe_argv,
|
||||
},
|
||||
.master_copy = first,
|
||||
},
|
||||
};
|
||||
|
|
@ -2060,7 +2079,6 @@ parse_section_mouse_bindings(
|
|||
|
||||
LOG_AND_NOTIFY_ERR("%s:%u: [mouse-bindings]: %s: invalid key", path, lineno, key);
|
||||
free(pipe_argv);
|
||||
free(pipe_cmd);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -2594,8 +2612,7 @@ config_load(struct config *conf, const char *conf_path,
|
|||
.urgent = false,
|
||||
.notify = false,
|
||||
.command = {
|
||||
.raw_cmd = NULL,
|
||||
.argv = NULL,
|
||||
.argv = {.args = NULL},
|
||||
},
|
||||
.command_focused = false,
|
||||
},
|
||||
|
|
@ -2671,8 +2688,7 @@ config_load(struct config *conf, const char *conf_path,
|
|||
.selection_target = SELECTION_TARGET_PRIMARY,
|
||||
.hold_at_exit = false,
|
||||
.notify = {
|
||||
.raw_cmd = NULL,
|
||||
.argv = NULL,
|
||||
.argv = {.args = NULL},
|
||||
},
|
||||
|
||||
.tweak = {
|
||||
|
|
@ -2717,12 +2733,9 @@ config_load(struct config *conf, const char *conf_path,
|
|||
}
|
||||
}
|
||||
|
||||
conf->notify.raw_cmd = xstrdup(
|
||||
"notify-send -a ${app-id} -i ${app-id} ${title} ${body}");
|
||||
tokenize_cmdline(conf->notify.raw_cmd, &conf->notify.argv);
|
||||
|
||||
conf->url.launch.raw_cmd = xstrdup("xdg-open ${url}");
|
||||
tokenize_cmdline(conf->url.launch.raw_cmd, &conf->url.launch.argv);
|
||||
tokenize_cmdline("notify-send -a ${app-id} -i ${app-id} ${title} ${body}",
|
||||
&conf->notify.argv.args);
|
||||
tokenize_cmdline("xdg-open ${url}", &conf->url.launch.argv.args);
|
||||
|
||||
static const wchar_t *url_protocols[] = {
|
||||
L"http://",
|
||||
|
|
@ -2847,36 +2860,145 @@ config_override_apply(struct config *conf, config_override_t *overrides, bool er
|
|||
return true;
|
||||
}
|
||||
|
||||
static void NOINLINE
|
||||
free_spawn_template(struct config_spawn_template *template)
|
||||
static void
|
||||
binding_pipe_free(struct config_binding_pipe *pipe)
|
||||
{
|
||||
free(template->raw_cmd);
|
||||
free(template->argv);
|
||||
if (pipe->master_copy)
|
||||
free_argv(&pipe->argv);
|
||||
}
|
||||
|
||||
static void
|
||||
binding_pipe_clone(struct config_binding_pipe *dst,
|
||||
const struct config_binding_pipe *src)
|
||||
{
|
||||
xassert(src->master_copy);
|
||||
clone_argv(&dst->argv, &src->argv);
|
||||
}
|
||||
|
||||
static void NOINLINE
|
||||
binding_pipe_free(struct config_binding_pipe *pipe)
|
||||
key_binding_list_free(struct config_key_binding_list *bindings)
|
||||
{
|
||||
if (pipe->master_copy) {
|
||||
free(pipe->cmd);
|
||||
free(pipe->argv);
|
||||
for (size_t i = 0; i < bindings->count; i++)
|
||||
binding_pipe_free(&bindings->arr[i].pipe);
|
||||
free(bindings->arr);
|
||||
}
|
||||
|
||||
static void NOINLINE
|
||||
key_binding_list_clone(struct config_key_binding_list *dst,
|
||||
const struct config_key_binding_list *src)
|
||||
{
|
||||
struct argv *last_master_argv = NULL;
|
||||
|
||||
dst->count = src->count;
|
||||
dst->arr = xmalloc(src->count * sizeof(dst->arr[0]));
|
||||
|
||||
for (size_t i = 0; i < src->count; i++) {
|
||||
const struct config_key_binding *old = &src->arr[i];
|
||||
struct config_key_binding *new = &dst->arr[i];
|
||||
|
||||
*new = *old;
|
||||
|
||||
if (old->pipe.argv.args == NULL)
|
||||
continue;
|
||||
|
||||
if (old->pipe.master_copy) {
|
||||
binding_pipe_clone(&new->pipe, &old->pipe);
|
||||
last_master_argv = &new->pipe.argv;
|
||||
} else {
|
||||
xassert(last_master_argv != NULL);
|
||||
new->pipe.argv = *last_master_argv;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
key_binding_free(struct config_key_binding *binding)
|
||||
{
|
||||
binding_pipe_free(&binding->pipe);
|
||||
}
|
||||
|
||||
static void
|
||||
key_binding_list_free(struct config_key_binding_list *bindings)
|
||||
mouse_binding_list_free(struct config_mouse_binding_list *bindings)
|
||||
{
|
||||
for (size_t i = 0; i < bindings->count; i++)
|
||||
key_binding_free(&bindings->arr[i]);
|
||||
binding_pipe_free(&bindings->arr[i].pipe);
|
||||
free(bindings->arr);
|
||||
}
|
||||
|
||||
static void NOINLINE
|
||||
mouse_binding_list_clone(struct config_mouse_binding_list *dst,
|
||||
const struct config_mouse_binding_list *src)
|
||||
{
|
||||
struct argv *last_master_argv = NULL;
|
||||
|
||||
dst->count = src->count;
|
||||
dst->arr = xmalloc(src->count * sizeof(dst->arr[0]));
|
||||
|
||||
for (size_t i = 0; i < src->count; i++) {
|
||||
const struct config_mouse_binding *old = &src->arr[i];
|
||||
struct config_mouse_binding *new = &dst->arr[i];
|
||||
|
||||
*new = *old;
|
||||
|
||||
if (old->pipe.argv.args == NULL)
|
||||
continue;
|
||||
|
||||
if (old->pipe.master_copy) {
|
||||
binding_pipe_clone(&new->pipe, &old->pipe);
|
||||
last_master_argv = &new->pipe.argv;
|
||||
} else {
|
||||
xassert(last_master_argv != NULL);
|
||||
new->pipe.argv = *last_master_argv;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct config *
|
||||
config_clone(const struct config *old)
|
||||
{
|
||||
struct config *conf = xmalloc(sizeof(*conf));
|
||||
*conf = *old;
|
||||
|
||||
conf->term = xstrdup(old->term);
|
||||
conf->shell = xstrdup(old->shell);
|
||||
conf->title = xstrdup(old->title);
|
||||
conf->app_id = xstrdup(old->app_id);
|
||||
conf->word_delimiters = xwcsdup(old->word_delimiters);
|
||||
conf->scrollback.indicator.text = xwcsdup(old->scrollback.indicator.text);
|
||||
conf->server_socket_path = xstrdup(old->server_socket_path);
|
||||
spawn_template_clone(&conf->bell.command, &old->bell.command);
|
||||
spawn_template_clone(&conf->notify, &old->notify);
|
||||
|
||||
for (size_t i = 0; i < ALEN(conf->fonts); i++) {
|
||||
struct config_font_list *dst = &conf->fonts[i];
|
||||
const struct config_font_list *src = &old->fonts[i];
|
||||
|
||||
dst->count = src->count;
|
||||
dst->arr = xmalloc(dst->count * sizeof(dst->arr[0]));
|
||||
|
||||
for (size_t j = 0; j < dst->count; j++)
|
||||
dst->arr[j].pattern = xstrdup(src->arr[j].pattern);
|
||||
}
|
||||
|
||||
conf->url.label_letters = xwcsdup(old->url.label_letters);
|
||||
spawn_template_clone(&conf->url.launch, &old->url.launch);
|
||||
conf->url.protocols = xmalloc(
|
||||
old->url.prot_count * sizeof(conf->url.protocols[0]));
|
||||
for (size_t i = 0; i < old->url.prot_count; i++)
|
||||
conf->url.protocols[i] = xwcsdup(old->url.protocols[i]);
|
||||
|
||||
key_binding_list_clone(&conf->bindings.key, &old->bindings.key);
|
||||
key_binding_list_clone(&conf->bindings.search, &old->bindings.search);
|
||||
key_binding_list_clone(&conf->bindings.url, &old->bindings.url);
|
||||
mouse_binding_list_clone(&conf->bindings.mouse, &old->bindings.mouse);
|
||||
|
||||
conf->notifications.length = 0;
|
||||
conf->notifications.head = conf->notifications.tail = 0;
|
||||
tll_foreach(old->notifications, it) {
|
||||
struct user_notification notif = {
|
||||
.kind = it->item.kind,
|
||||
.text = xstrdup(it->item.text),
|
||||
};
|
||||
tll_push_back(conf->notifications, notif);
|
||||
}
|
||||
|
||||
return conf;
|
||||
}
|
||||
|
||||
void
|
||||
config_free(struct config conf)
|
||||
{
|
||||
|
|
@ -2885,15 +3007,15 @@ config_free(struct config conf)
|
|||
free(conf.title);
|
||||
free(conf.app_id);
|
||||
free(conf.word_delimiters);
|
||||
free_spawn_template(&conf.bell.command);
|
||||
spawn_template_free(&conf.bell.command);
|
||||
free(conf.scrollback.indicator.text);
|
||||
free_spawn_template(&conf.notify);
|
||||
spawn_template_free(&conf.notify);
|
||||
for (size_t i = 0; i < ALEN(conf.fonts); i++)
|
||||
config_font_list_destroy(&conf.fonts[i]);
|
||||
free(conf.server_socket_path);
|
||||
|
||||
free(conf.url.label_letters);
|
||||
free_spawn_template(&conf.url.launch);
|
||||
spawn_template_free(&conf.url.launch);
|
||||
for (size_t i = 0; i < conf.url.prot_count; i++)
|
||||
free(conf.url.protocols[i]);
|
||||
free(conf.url.protocols);
|
||||
|
|
@ -2901,10 +3023,7 @@ config_free(struct config conf)
|
|||
key_binding_list_free(&conf.bindings.key);
|
||||
key_binding_list_free(&conf.bindings.search);
|
||||
key_binding_list_free(&conf.bindings.url);
|
||||
|
||||
for (size_t i = 0; i < conf.bindings.mouse.count; i++)
|
||||
binding_pipe_free(&conf.bindings.mouse.arr[i].pipe);
|
||||
free(conf.bindings.mouse.arr);
|
||||
mouse_binding_list_free(&conf.bindings.mouse);
|
||||
|
||||
user_notifications_free(&conf.notifications);
|
||||
}
|
||||
|
|
|
|||
11
config.h
11
config.h
|
|
@ -37,9 +37,12 @@ struct config_key_modifiers {
|
|||
bool meta;
|
||||
};
|
||||
|
||||
struct argv {
|
||||
char **args;
|
||||
};
|
||||
|
||||
struct config_binding_pipe {
|
||||
char *cmd;
|
||||
char **argv;
|
||||
struct argv argv;
|
||||
bool master_copy;
|
||||
};
|
||||
|
||||
|
|
@ -63,8 +66,7 @@ DEFINE_LIST(struct config_mouse_binding);
|
|||
typedef tll(char *) config_override_t;
|
||||
|
||||
struct config_spawn_template {
|
||||
char *raw_cmd;
|
||||
char **argv;
|
||||
struct argv argv;
|
||||
};
|
||||
|
||||
struct config {
|
||||
|
|
@ -263,6 +265,7 @@ bool config_load(
|
|||
user_notifications_t *initial_user_notifications,
|
||||
config_override_t *overrides, bool errors_are_fatal);
|
||||
void config_free(struct config conf);
|
||||
struct config *config_clone(const struct config *old);
|
||||
|
||||
bool config_font_parse(const char *pattern, struct config_font *font);
|
||||
void config_font_list_destroy(struct config_font_list *font_list);
|
||||
|
|
|
|||
7
input.c
7
input.c
|
|
@ -519,7 +519,7 @@ convert_key_binding(const struct seat *seat,
|
|||
.sym = sym,
|
||||
.key_codes = key_codes_for_xkb_sym(seat->kbd.xkb_keymap, sym),
|
||||
.action = conf_binding->action,
|
||||
.pipe_argv = conf_binding->pipe.argv,
|
||||
.pipe_argv = conf_binding->pipe.argv.args,
|
||||
};
|
||||
tll_push_back(*bindings, binding);
|
||||
}
|
||||
|
|
@ -568,7 +568,7 @@ convert_mouse_binding(struct seat *seat,
|
|||
.mods = conf_modifiers_to_mask(seat, &conf_binding->modifiers),
|
||||
.button = conf_binding->button,
|
||||
.count = conf_binding->count,
|
||||
.pipe_argv = conf_binding->pipe.argv,
|
||||
.pipe_argv = conf_binding->pipe.argv.args,
|
||||
};
|
||||
tll_push_back(seat->mouse.bindings, binding);
|
||||
}
|
||||
|
|
@ -1970,7 +1970,8 @@ wl_pointer_button(void *data, struct wl_pointer *wl_pointer,
|
|||
|
||||
if (match != NULL) {
|
||||
consumed = execute_binding(
|
||||
seat, term, match->action, match->pipe.argv, serial);
|
||||
seat, term, match->action, match->pipe.argv.args,
|
||||
serial);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
2
notify.c
2
notify.c
|
|
@ -27,7 +27,7 @@ notify_notify(const struct terminal *term, const char *title, const char *body)
|
|||
if (title == NULL || body == NULL)
|
||||
return;
|
||||
|
||||
if (term->conf->notify.argv == NULL)
|
||||
if (term->conf->notify.argv.args == NULL)
|
||||
return;
|
||||
|
||||
char **argv = NULL;
|
||||
|
|
|
|||
4
slave.c
4
slave.c
|
|
@ -293,9 +293,7 @@ slave_spawn(int ptmx, int argc, const char *cwd, char *const *argv,
|
|||
char **shell_argv = NULL;
|
||||
|
||||
if (argc == 0) {
|
||||
char *shell_copy = xstrdup(conf_shell);
|
||||
if (!tokenize_cmdline(shell_copy, &_shell_argv)) {
|
||||
free(shell_copy);
|
||||
if (!tokenize_cmdline(conf_shell, &_shell_argv)) {
|
||||
(void)!write(fork_pipe[1], &errno, sizeof(errno));
|
||||
_exit(0);
|
||||
}
|
||||
|
|
|
|||
8
spawn.c
8
spawn.c
|
|
@ -114,7 +114,7 @@ spawn_expand_template(const struct config_spawn_template *template,
|
|||
*argc = 0;
|
||||
*argv = NULL;
|
||||
|
||||
for (; template->argv[*argc] != NULL; (*argc)++)
|
||||
for (; template->argv.args[*argc] != NULL; (*argc)++)
|
||||
;
|
||||
|
||||
#define append(s, n) \
|
||||
|
|
@ -133,7 +133,7 @@ spawn_expand_template(const struct config_spawn_template *template,
|
|||
char *expanded = NULL;
|
||||
|
||||
char *start = NULL;
|
||||
char *last_end = template->argv[i];
|
||||
char *last_end = template->argv.args[i];
|
||||
|
||||
while ((start = strstr(last_end, "${")) != NULL) {
|
||||
/* Append everything from the last template's end to this
|
||||
|
|
@ -173,7 +173,9 @@ spawn_expand_template(const struct config_spawn_template *template,
|
|||
last_end = end + 1;
|
||||
}
|
||||
|
||||
append(last_end, template->argv[i] + strlen(template->argv[i]) - last_end);
|
||||
append(
|
||||
last_end,
|
||||
template->argv.args[i] + strlen(template->argv.args[i]) - last_end);
|
||||
(*argv)[i] = expanded;
|
||||
}
|
||||
(*argv)[*argc] = NULL;
|
||||
|
|
|
|||
|
|
@ -2677,11 +2677,11 @@ term_bell(struct terminal *term)
|
|||
notify_notify(term, "Bell", "Bell in terminal");
|
||||
}
|
||||
|
||||
if ((term->conf->bell.command.argv != NULL) &&
|
||||
if ((term->conf->bell.command.argv.args != NULL) &&
|
||||
(!term->kbd_focus || term->conf->bell.command_focused))
|
||||
{
|
||||
int devnull = open("/dev/null", O_RDONLY);
|
||||
spawn(term->reaper, NULL, term->conf->bell.command.argv, devnull, -1, -1);
|
||||
spawn(term->reaper, NULL, term->conf->bell.command.argv.args, devnull, -1, -1);
|
||||
|
||||
if (devnull >= 0)
|
||||
close(devnull);
|
||||
|
|
|
|||
23
tokenize.c
23
tokenize.c
|
|
@ -6,9 +6,10 @@
|
|||
#define LOG_MODULE "tokenize"
|
||||
#define LOG_ENABLE_DBG 0
|
||||
#include "log.h"
|
||||
#include "xmalloc.h"
|
||||
|
||||
static bool
|
||||
push_argv(char ***argv, size_t *size, char *arg, size_t *argc)
|
||||
push_argv(char ***argv, size_t *size, const char *arg, size_t len, size_t *argc)
|
||||
{
|
||||
if (arg != NULL && arg[0] == '%')
|
||||
return true;
|
||||
|
|
@ -24,21 +25,23 @@ push_argv(char ***argv, size_t *size, char *arg, size_t *argc)
|
|||
*size = new_size;
|
||||
}
|
||||
|
||||
(*argv)[(*argc)++] = arg;
|
||||
(*argv)[(*argc)++] = arg != NULL ? xstrndup(arg, len) : NULL;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
tokenize_cmdline(char *cmdline, char ***argv)
|
||||
tokenize_cmdline(const char *cmdline, char ***argv)
|
||||
{
|
||||
*argv = NULL;
|
||||
size_t argv_size = 0;
|
||||
|
||||
const char *final_end = cmdline + strlen(cmdline) + 1;
|
||||
|
||||
bool first_token_is_quoted = cmdline[0] == '"' || cmdline[0] == '\'';
|
||||
char delim = first_token_is_quoted ? cmdline[0] : ' ';
|
||||
|
||||
char *p = first_token_is_quoted ? &cmdline[1] : &cmdline[0];
|
||||
char *search_start = p;
|
||||
const char *p = first_token_is_quoted ? &cmdline[1] : &cmdline[0];
|
||||
const char *search_start = p;
|
||||
|
||||
size_t idx = 0;
|
||||
while (*p != '\0') {
|
||||
|
|
@ -51,8 +54,8 @@ tokenize_cmdline(char *cmdline, char ***argv)
|
|||
return false;
|
||||
}
|
||||
|
||||
if (!push_argv(argv, &argv_size, p, &idx) ||
|
||||
!push_argv(argv, &argv_size, NULL, &idx))
|
||||
if (!push_argv(argv, &argv_size, p, final_end - p, &idx) ||
|
||||
!push_argv(argv, &argv_size, NULL, 0, &idx))
|
||||
{
|
||||
goto err;
|
||||
} else
|
||||
|
|
@ -68,9 +71,9 @@ tokenize_cmdline(char *cmdline, char ***argv)
|
|||
continue;
|
||||
}
|
||||
|
||||
*end = '\0';
|
||||
//*end = '\0';
|
||||
|
||||
if (!push_argv(argv, &argv_size, p, &idx))
|
||||
if (!push_argv(argv, &argv_size, p, end - p, &idx))
|
||||
goto err;
|
||||
|
||||
p = end + 1;
|
||||
|
|
@ -88,7 +91,7 @@ tokenize_cmdline(char *cmdline, char ***argv)
|
|||
search_start = p;
|
||||
}
|
||||
|
||||
if (!push_argv(argv, &argv_size, NULL, &idx))
|
||||
if (!push_argv(argv, &argv_size, NULL, 0, &idx))
|
||||
goto err;
|
||||
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -2,4 +2,4 @@
|
|||
|
||||
#include <stdbool.h>
|
||||
|
||||
bool tokenize_cmdline(char *cmdline, char ***argv);
|
||||
bool tokenize_cmdline(const char *cmdline, char ***argv);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue