mirror of
https://github.com/swaywm/sway.git
synced 2024-11-29 19:31:29 +00:00
commit
7654f5e7cd
|
@ -5,7 +5,7 @@
|
||||||
|
|
||||||
struct cmd_handler {
|
struct cmd_handler {
|
||||||
char *command;
|
char *command;
|
||||||
bool (*handle)(struct sway_config *config, int argc, char **argv);
|
bool (*handle)(int argc, char **argv);
|
||||||
enum {
|
enum {
|
||||||
CMD_COMPOSITOR_READY,
|
CMD_COMPOSITOR_READY,
|
||||||
CMD_KEYBIND,
|
CMD_KEYBIND,
|
||||||
|
@ -14,7 +14,7 @@ struct cmd_handler {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct cmd_handler *find_handler(char *line);
|
struct cmd_handler *find_handler(char *line);
|
||||||
bool handle_command(struct sway_config *config, char *command);
|
bool handle_command(char *command);
|
||||||
|
|
||||||
void remove_view_from_scratchpad();
|
void remove_view_from_scratchpad();
|
||||||
|
|
||||||
|
|
|
@ -60,7 +60,7 @@ struct sway_config {
|
||||||
|
|
||||||
bool load_config(const char *file);
|
bool load_config(const char *file);
|
||||||
bool read_config(FILE *file, bool is_active);
|
bool read_config(FILE *file, bool is_active);
|
||||||
char *do_var_replacement(struct sway_config *config, char *str);
|
char *do_var_replacement(char *str);
|
||||||
|
|
||||||
extern struct sway_config *config;
|
extern struct sway_config *config;
|
||||||
|
|
||||||
|
|
|
@ -2,17 +2,25 @@
|
||||||
#define _SWAY_STRINGOP_H
|
#define _SWAY_STRINGOP_H
|
||||||
#include "list.h"
|
#include "list.h"
|
||||||
|
|
||||||
char *strip_whitespace(char *str, int *trimmed_start);
|
// array of whitespace characters to use for delims
|
||||||
|
extern const char *whitespace;
|
||||||
|
|
||||||
|
char *strip_whitespace(char *str);
|
||||||
char *strip_comments(char *str);
|
char *strip_comments(char *str);
|
||||||
|
|
||||||
// Must be freed with free_flat_list
|
// Simply split a string with delims, free with `free_flat_list`
|
||||||
list_t *split_string(const char *str, const char *delims);
|
list_t *split_string(const char *str, const char *delims);
|
||||||
void free_flat_list(list_t *list);
|
void free_flat_list(list_t *list);
|
||||||
|
|
||||||
|
// Splits an argument string, keeping quotes intact
|
||||||
|
char **split_args(const char *str, int *argc);
|
||||||
|
void free_argv(int argc, char **argv);
|
||||||
|
|
||||||
char *code_strchr(const char *string, char delimiter);
|
char *code_strchr(const char *string, char delimiter);
|
||||||
char *code_strstr(const char *haystack, const char *needle);
|
char *code_strstr(const char *haystack, const char *needle);
|
||||||
int unescape_string(char *string);
|
int unescape_string(char *string);
|
||||||
char *join_args(char **argv, int argc);
|
char *join_args(char **argv, int argc);
|
||||||
char *join_list(list_t *list, char *separator);
|
char *join_list(list_t *list, char *separator);
|
||||||
|
|
||||||
|
char *strdup(const char *);
|
||||||
#endif
|
#endif
|
||||||
|
|
200
sway/commands.c
200
sway/commands.c
|
@ -96,7 +96,7 @@ static int bindsym_sort(const void *_lbind, const void *_rbind) {
|
||||||
return (rbind->keys->length + rmod) - (lbind->keys->length + lmod);
|
return (rbind->keys->length + rmod) - (lbind->keys->length + lmod);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool cmd_bindsym(struct sway_config *config, int argc, char **argv) {
|
static bool cmd_bindsym(int argc, char **argv) {
|
||||||
if (!checkarg(argc, "bindsym", EXPECTED_MORE_THAN, 1)) {
|
if (!checkarg(argc, "bindsym", EXPECTED_MORE_THAN, 1)) {
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
@ -146,7 +146,7 @@ static bool cmd_bindsym(struct sway_config *config, int argc, char **argv) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool cmd_exec_always(struct sway_config *config, int argc, char **argv) {
|
static bool cmd_exec_always(int argc, char **argv) {
|
||||||
if (!checkarg(argc, "exec_always", EXPECTED_MORE_THAN, 0)) {
|
if (!checkarg(argc, "exec_always", EXPECTED_MORE_THAN, 0)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -171,14 +171,14 @@ static bool cmd_exec_always(struct sway_config *config, int argc, char **argv) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool cmd_exec(struct sway_config *config, int argc, char **argv) {
|
static bool cmd_exec(int argc, char **argv) {
|
||||||
if (config->reloading) {
|
if (config->reloading) {
|
||||||
char *args = join_args(argv, argc);
|
char *args = join_args(argv, argc);
|
||||||
sway_log(L_DEBUG, "Ignoring exec %s due to reload", args);
|
sway_log(L_DEBUG, "Ignoring exec %s due to reload", args);
|
||||||
free(args);
|
free(args);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return cmd_exec_always(config, argc, argv);
|
return cmd_exec_always(argc, argv);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void kill_views(swayc_t *container, void *data) {
|
static void kill_views(swayc_t *container, void *data) {
|
||||||
|
@ -187,7 +187,7 @@ static void kill_views(swayc_t *container, void *data) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool cmd_exit(struct sway_config *config, int argc, char **argv) {
|
static bool cmd_exit(int argc, char **argv) {
|
||||||
if (!checkarg(argc, "exit", EXPECTED_EQUAL_TO, 0)) {
|
if (!checkarg(argc, "exit", EXPECTED_EQUAL_TO, 0)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -197,7 +197,7 @@ static bool cmd_exit(struct sway_config *config, int argc, char **argv) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool cmd_floating(struct sway_config *config, int argc, char **argv) {
|
static bool cmd_floating(int argc, char **argv) {
|
||||||
if (!checkarg(argc, "floating", EXPECTED_EQUAL_TO, 1)) {
|
if (!checkarg(argc, "floating", EXPECTED_EQUAL_TO, 1)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -258,7 +258,7 @@ static bool cmd_floating(struct sway_config *config, int argc, char **argv) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool cmd_floating_mod(struct sway_config *config, int argc, char **argv) {
|
static bool cmd_floating_mod(int argc, char **argv) {
|
||||||
if (!checkarg(argc, "floating_modifier", EXPECTED_EQUAL_TO, 1)) {
|
if (!checkarg(argc, "floating_modifier", EXPECTED_EQUAL_TO, 1)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -282,7 +282,7 @@ static bool cmd_floating_mod(struct sway_config *config, int argc, char **argv)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool cmd_focus(struct sway_config *config, int argc, char **argv) {
|
static bool cmd_focus(int argc, char **argv) {
|
||||||
static int floating_toggled_index = 0;
|
static int floating_toggled_index = 0;
|
||||||
static int tiled_toggled_index = 0;
|
static int tiled_toggled_index = 0;
|
||||||
if (!checkarg(argc, "focus", EXPECTED_EQUAL_TO, 1)) {
|
if (!checkarg(argc, "focus", EXPECTED_EQUAL_TO, 1)) {
|
||||||
|
@ -340,7 +340,7 @@ static bool cmd_focus(struct sway_config *config, int argc, char **argv) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool cmd_focus_follows_mouse(struct sway_config *config, int argc, char **argv) {
|
static bool cmd_focus_follows_mouse(int argc, char **argv) {
|
||||||
if (!checkarg(argc, "focus_follows_mouse", EXPECTED_EQUAL_TO, 1)) {
|
if (!checkarg(argc, "focus_follows_mouse", EXPECTED_EQUAL_TO, 1)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -365,7 +365,39 @@ static void hide_view_in_scratchpad(swayc_t *sp_view) {
|
||||||
set_focused_container(container_under_pointer());
|
set_focused_container(container_under_pointer());
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool cmd_move(struct sway_config *config, int argc, char **argv) {
|
static bool cmd_mode(int argc, char **argv) {
|
||||||
|
if (!checkarg(argc, "move", EXPECTED_AT_LEAST, 1)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const char *mode_name = argv[0];
|
||||||
|
struct sway_mode *mode = NULL;
|
||||||
|
// Find mode
|
||||||
|
int i, len = config->modes->length;
|
||||||
|
for (i = 0; i < len; ++i) {
|
||||||
|
struct sway_mode *find = config->modes->items[i];
|
||||||
|
if (strcasecmp(find->name, mode_name)==0) {
|
||||||
|
mode = find;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Create mode if it doesnt exist
|
||||||
|
if (!mode && argc >= 2 && strncmp(argv[1],"{",1) == 0) {
|
||||||
|
mode = malloc(sizeof*mode);
|
||||||
|
mode->name = strdup(mode_name);
|
||||||
|
mode->bindings = create_list();
|
||||||
|
list_add(config->modes, mode);
|
||||||
|
}
|
||||||
|
if (!mode) {
|
||||||
|
sway_log(L_ERROR, "Invalide mode `%s'", mode_name);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
sway_log(L_DEBUG, "Switching to mode `%s'",mode->name);
|
||||||
|
// Set current mode
|
||||||
|
config->current_mode = mode;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool cmd_move(int argc, char **argv) {
|
||||||
if (!checkarg(argc, "move", EXPECTED_AT_LEAST, 1)) {
|
if (!checkarg(argc, "move", EXPECTED_AT_LEAST, 1)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -435,7 +467,7 @@ static bool cmd_move(struct sway_config *config, int argc, char **argv) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool cmd_orientation(struct sway_config *config, int argc, char **argv) {
|
static bool cmd_orientation(int argc, char **argv) {
|
||||||
if (strcasecmp(argv[0], "horizontal") == 0) {
|
if (strcasecmp(argv[0], "horizontal") == 0) {
|
||||||
config->default_orientation = L_HORIZ;
|
config->default_orientation = L_HORIZ;
|
||||||
} else if (strcasecmp(argv[0], "vertical") == 0) {
|
} else if (strcasecmp(argv[0], "vertical") == 0) {
|
||||||
|
@ -448,7 +480,7 @@ static bool cmd_orientation(struct sway_config *config, int argc, char **argv) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool cmd_output(struct sway_config *config, int argc, char **argv) {
|
static bool cmd_output(int argc, char **argv) {
|
||||||
if (!checkarg(argc, "output", EXPECTED_AT_LEAST, 1)) {
|
if (!checkarg(argc, "output", EXPECTED_AT_LEAST, 1)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -513,7 +545,7 @@ static bool cmd_output(struct sway_config *config, int argc, char **argv) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool cmd_gaps(struct sway_config *config, int argc, char **argv) {
|
static bool cmd_gaps(int argc, char **argv) {
|
||||||
if (!checkarg(argc, "gaps", EXPECTED_AT_LEAST, 1)) {
|
if (!checkarg(argc, "gaps", EXPECTED_AT_LEAST, 1)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -655,13 +687,13 @@ static bool cmd_gaps(struct sway_config *config, int argc, char **argv) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool cmd_kill(struct sway_config *config, int argc, char **argv) {
|
static bool cmd_kill(int argc, char **argv) {
|
||||||
swayc_t *view = get_focused_container(&root_container);
|
swayc_t *view = get_focused_container(&root_container);
|
||||||
wlc_view_close(view->handle);
|
wlc_view_close(view->handle);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool cmd_layout(struct sway_config *config, int argc, char **argv) {
|
static bool cmd_layout(int argc, char **argv) {
|
||||||
if (!checkarg(argc, "layout", EXPECTED_MORE_THAN, 0)) {
|
if (!checkarg(argc, "layout", EXPECTED_MORE_THAN, 0)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -686,7 +718,7 @@ static bool cmd_layout(struct sway_config *config, int argc, char **argv) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool cmd_reload(struct sway_config *config, int argc, char **argv) {
|
static bool cmd_reload(int argc, char **argv) {
|
||||||
if (!checkarg(argc, "reload", EXPECTED_EQUAL_TO, 0)) {
|
if (!checkarg(argc, "reload", EXPECTED_EQUAL_TO, 0)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -697,7 +729,7 @@ static bool cmd_reload(struct sway_config *config, int argc, char **argv) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool cmd_resize(struct sway_config *config, int argc, char **argv) {
|
static bool cmd_resize(int argc, char **argv) {
|
||||||
if (!checkarg(argc, "resize", EXPECTED_AT_LEAST, 3)) {
|
if (!checkarg(argc, "resize", EXPECTED_AT_LEAST, 3)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -769,7 +801,7 @@ void remove_view_from_scratchpad(swayc_t *view) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool cmd_scratchpad(struct sway_config *config, int argc, char **argv) {
|
static bool cmd_scratchpad(int argc, char **argv) {
|
||||||
if (!checkarg(argc, "scratchpad", EXPECTED_EQUAL_TO, 1)) {
|
if (!checkarg(argc, "scratchpad", EXPECTED_EQUAL_TO, 1)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -796,20 +828,18 @@ static bool cmd_scratchpad(struct sway_config *config, int argc, char **argv) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool cmd_set(struct sway_config *config, int argc, char **argv) {
|
static bool cmd_set(int argc, char **argv) {
|
||||||
if (!checkarg(argc, "set", EXPECTED_EQUAL_TO, 2)) {
|
if (!checkarg(argc, "set", EXPECTED_EQUAL_TO, 2)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
struct sway_variable *var = malloc(sizeof(struct sway_variable));
|
struct sway_variable *var = malloc(sizeof(struct sway_variable));
|
||||||
var->name = malloc(strlen(argv[0]) + 1);
|
var->name = strdup(argv[0]);
|
||||||
strcpy(var->name, argv[0]);
|
var->value = strdup(argv[1]);
|
||||||
var->value = malloc(strlen(argv[1]) + 1);
|
|
||||||
strcpy(var->value, argv[1]);
|
|
||||||
list_add(config->symbols, var);
|
list_add(config->symbols, var);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool _do_split(struct sway_config *config, int argc, char **argv, int layout) {
|
static bool _do_split(int argc, char **argv, int layout) {
|
||||||
char *name = layout == L_VERT ? "splitv" :
|
char *name = layout == L_VERT ? "splitv" :
|
||||||
layout == L_HORIZ ? "splith" : "split";
|
layout == L_HORIZ ? "splith" : "split";
|
||||||
if (!checkarg(argc, name, EXPECTED_EQUAL_TO, 0)) {
|
if (!checkarg(argc, name, EXPECTED_EQUAL_TO, 0)) {
|
||||||
|
@ -840,15 +870,15 @@ static bool _do_split(struct sway_config *config, int argc, char **argv, int lay
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool cmd_split(struct sway_config *config, int argc, char **argv) {
|
static bool cmd_split(int argc, char **argv) {
|
||||||
if (!checkarg(argc, "split", EXPECTED_EQUAL_TO, 1)) {
|
if (!checkarg(argc, "split", EXPECTED_EQUAL_TO, 1)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strcasecmp(argv[0], "v") == 0 || strcasecmp(argv[0], "vertical") == 0) {
|
if (strcasecmp(argv[0], "v") == 0 || strcasecmp(argv[0], "vertical") == 0) {
|
||||||
_do_split(config, argc - 1, argv + 1, L_VERT);
|
_do_split(argc - 1, argv + 1, L_VERT);
|
||||||
} else if (strcasecmp(argv[0], "h") == 0 || strcasecmp(argv[0], "horizontal") == 0) {
|
} else if (strcasecmp(argv[0], "h") == 0 || strcasecmp(argv[0], "horizontal") == 0) {
|
||||||
_do_split(config, argc - 1, argv + 1, L_HORIZ);
|
_do_split(argc - 1, argv + 1, L_HORIZ);
|
||||||
} else {
|
} else {
|
||||||
sway_log(L_ERROR, "Invalid split command (expected either horiziontal or vertical).");
|
sway_log(L_ERROR, "Invalid split command (expected either horiziontal or vertical).");
|
||||||
return false;
|
return false;
|
||||||
|
@ -857,15 +887,15 @@ static bool cmd_split(struct sway_config *config, int argc, char **argv) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool cmd_splitv(struct sway_config *config, int argc, char **argv) {
|
static bool cmd_splitv(int argc, char **argv) {
|
||||||
return _do_split(config, argc, argv, L_VERT);
|
return _do_split(argc, argv, L_VERT);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool cmd_splith(struct sway_config *config, int argc, char **argv) {
|
static bool cmd_splith(int argc, char **argv) {
|
||||||
return _do_split(config, argc, argv, L_HORIZ);
|
return _do_split(argc, argv, L_HORIZ);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool cmd_log_colors(struct sway_config *config, int argc, char **argv) {
|
static bool cmd_log_colors(int argc, char **argv) {
|
||||||
if (!checkarg(argc, "log_colors", EXPECTED_EQUAL_TO, 1)) {
|
if (!checkarg(argc, "log_colors", EXPECTED_EQUAL_TO, 1)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -878,7 +908,7 @@ static bool cmd_log_colors(struct sway_config *config, int argc, char **argv) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool cmd_fullscreen(struct sway_config *config, int argc, char **argv) {
|
static bool cmd_fullscreen(int argc, char **argv) {
|
||||||
if (!checkarg(argc, "fullscreen", EXPECTED_AT_LEAST, 0)) {
|
if (!checkarg(argc, "fullscreen", EXPECTED_AT_LEAST, 0)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -897,7 +927,7 @@ static bool cmd_fullscreen(struct sway_config *config, int argc, char **argv) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool cmd_workspace(struct sway_config *config, int argc, char **argv) {
|
static bool cmd_workspace(int argc, char **argv) {
|
||||||
if (!checkarg(argc, "workspace", EXPECTED_AT_LEAST, 1)) {
|
if (!checkarg(argc, "workspace", EXPECTED_AT_LEAST, 1)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -953,7 +983,7 @@ static bool cmd_workspace(struct sway_config *config, int argc, char **argv) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool cmd_ws_auto_back_and_forth(struct sway_config *config, int argc, char **argv) {
|
static bool cmd_ws_auto_back_and_forth(int argc, char **argv) {
|
||||||
if (!checkarg(argc, "workspace_auto_back_and_forth", EXPECTED_EQUAL_TO, 1)) {
|
if (!checkarg(argc, "workspace_auto_back_and_forth", EXPECTED_EQUAL_TO, 1)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -979,6 +1009,7 @@ static struct cmd_handler handlers[] = {
|
||||||
{ "kill", cmd_kill, CMD_KEYBIND },
|
{ "kill", cmd_kill, CMD_KEYBIND },
|
||||||
{ "layout", cmd_layout, CMD_KEYBIND },
|
{ "layout", cmd_layout, CMD_KEYBIND },
|
||||||
{ "log_colors", cmd_log_colors, CMD_ANYTIME },
|
{ "log_colors", cmd_log_colors, CMD_ANYTIME },
|
||||||
|
{ "mode", cmd_mode, CMD_ANYTIME },
|
||||||
{ "move", cmd_move, CMD_KEYBIND },
|
{ "move", cmd_move, CMD_KEYBIND },
|
||||||
{ "output", cmd_output, CMD_ANYTIME },
|
{ "output", cmd_output, CMD_ANYTIME },
|
||||||
{ "reload", cmd_reload, CMD_KEYBIND },
|
{ "reload", cmd_reload, CMD_KEYBIND },
|
||||||
|
@ -992,58 +1023,6 @@ static struct cmd_handler handlers[] = {
|
||||||
{ "workspace_auto_back_and_forth", cmd_ws_auto_back_and_forth, CMD_ANYTIME },
|
{ "workspace_auto_back_and_forth", cmd_ws_auto_back_and_forth, CMD_ANYTIME },
|
||||||
};
|
};
|
||||||
|
|
||||||
static char **split_directive(char *line, int *argc) {
|
|
||||||
const char *delimiters = " ";
|
|
||||||
*argc = 0;
|
|
||||||
while (isspace(*line) && *line) ++line;
|
|
||||||
|
|
||||||
int capacity = 10;
|
|
||||||
char **parts = malloc(sizeof(char *) * capacity);
|
|
||||||
|
|
||||||
if (!*line) return parts;
|
|
||||||
|
|
||||||
int in_string = 0, in_character = 0;
|
|
||||||
int i, j, _;
|
|
||||||
for (i = 0, j = 0; line[i]; ++i) {
|
|
||||||
if (line[i] == '\\') {
|
|
||||||
++i;
|
|
||||||
} else if (line[i] == '"' && !in_character) {
|
|
||||||
in_string = !in_string;
|
|
||||||
} else if (line[i] == '\'' && !in_string) {
|
|
||||||
in_character = !in_character;
|
|
||||||
} else if (!in_character && !in_string) {
|
|
||||||
if (strchr(delimiters, line[i]) != NULL) {
|
|
||||||
char *item = malloc(i - j + 1);
|
|
||||||
strncpy(item, line + j, i - j);
|
|
||||||
item[i - j] = '\0';
|
|
||||||
item = strip_whitespace(item, &_);
|
|
||||||
if (item[0] == '\0') {
|
|
||||||
free(item);
|
|
||||||
} else {
|
|
||||||
if (*argc == capacity) {
|
|
||||||
capacity *= 2;
|
|
||||||
parts = realloc(parts, sizeof(char *) * capacity);
|
|
||||||
}
|
|
||||||
parts[*argc] = item;
|
|
||||||
j = i + 1;
|
|
||||||
++*argc;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
char *item = malloc(i - j + 1);
|
|
||||||
strncpy(item, line + j, i - j);
|
|
||||||
item[i - j] = '\0';
|
|
||||||
item = strip_whitespace(item, &_);
|
|
||||||
if (*argc == capacity) {
|
|
||||||
capacity++;
|
|
||||||
parts = realloc(parts, sizeof(char *) * capacity);
|
|
||||||
}
|
|
||||||
parts[*argc] = item;
|
|
||||||
++*argc;
|
|
||||||
return parts;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int handler_compare(const void *_a, const void *_b) {
|
static int handler_compare(const void *_a, const void *_b) {
|
||||||
const struct cmd_handler *a = _a;
|
const struct cmd_handler *a = _a;
|
||||||
const struct cmd_handler *b = _b;
|
const struct cmd_handler *b = _b;
|
||||||
|
@ -1058,44 +1037,25 @@ struct cmd_handler *find_handler(char *line) {
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool handle_command(struct sway_config *config, char *exec) {
|
bool handle_command(char *exec) {
|
||||||
sway_log(L_INFO, "Handling command '%s'", exec);
|
sway_log(L_INFO, "Handling command '%s'", exec);
|
||||||
char *ptr, *cmd;
|
|
||||||
bool exec_success;
|
|
||||||
|
|
||||||
if ((ptr = strchr(exec, ' ')) == NULL) {
|
|
||||||
cmd = exec;
|
|
||||||
} else {
|
|
||||||
int index = ptr - exec;
|
|
||||||
cmd = malloc(index + 1);
|
|
||||||
strncpy(cmd, exec, index);
|
|
||||||
cmd[index] = '\0';
|
|
||||||
}
|
|
||||||
struct cmd_handler *handler = find_handler(cmd);
|
|
||||||
if (handler == NULL) {
|
|
||||||
sway_log(L_ERROR, "Unknown command '%s'", cmd);
|
|
||||||
exec_success = false; // TODO: return error, probably
|
|
||||||
} else {
|
|
||||||
int argc;
|
int argc;
|
||||||
char **argv = split_directive(exec + strlen(handler->command), &argc);
|
char **argv = split_args(exec, &argc);
|
||||||
|
if (argc == 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
struct cmd_handler *handler = find_handler(argv[0]);
|
||||||
|
bool exec_success = false;
|
||||||
|
if (handler) {
|
||||||
int i;
|
int i;
|
||||||
|
for (i = 1; i < argc; ++i) {
|
||||||
// Perform var subs on all parts of the command
|
argv[i] = do_var_replacement(argv[i]);
|
||||||
for (i = 0; i < argc; ++i) {
|
|
||||||
argv[i] = do_var_replacement(config, argv[i]);
|
|
||||||
}
|
}
|
||||||
|
exec_success = handler->handle(argc - 1, argv + 1);
|
||||||
exec_success = handler->handle(config, argc, argv);
|
|
||||||
for (i = 0; i < argc; ++i) {
|
|
||||||
free(argv[i]);
|
|
||||||
}
|
}
|
||||||
free(argv);
|
if (exec_success == false) {
|
||||||
if (!exec_success) {
|
sway_log(L_ERROR, "Command failed: %s", argv[0]);
|
||||||
sway_log(L_ERROR, "Command failed: %s", cmd);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (ptr) {
|
|
||||||
free(cmd);
|
|
||||||
}
|
}
|
||||||
|
free_argv(argc, argv);
|
||||||
return exec_success;
|
return exec_success;
|
||||||
}
|
}
|
||||||
|
|
120
sway/config.c
120
sway/config.c
|
@ -13,6 +13,7 @@
|
||||||
|
|
||||||
struct sway_config *config = NULL;
|
struct sway_config *config = NULL;
|
||||||
|
|
||||||
|
|
||||||
static void free_variable(struct sway_variable *var) {
|
static void free_variable(struct sway_variable *var) {
|
||||||
free(var->name);
|
free(var->name);
|
||||||
free(var->value);
|
free(var->value);
|
||||||
|
@ -46,39 +47,7 @@ static void free_workspace_output(struct workspace_output *wo) {
|
||||||
free(wo);
|
free(wo);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool file_exists(const char *path) {
|
static void free_config(struct sway_config *config) {
|
||||||
return access(path, R_OK) != -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void config_defaults(struct sway_config *config) {
|
|
||||||
config->symbols = create_list();
|
|
||||||
config->modes = create_list();
|
|
||||||
config->workspace_outputs = create_list();
|
|
||||||
config->output_configs = create_list();
|
|
||||||
|
|
||||||
config->cmd_queue = create_list();
|
|
||||||
|
|
||||||
config->current_mode = malloc(sizeof(struct sway_mode));
|
|
||||||
config->current_mode->name = NULL;
|
|
||||||
config->current_mode->bindings = create_list();
|
|
||||||
list_add(config->modes, config->current_mode);
|
|
||||||
|
|
||||||
config->floating_mod = 0;
|
|
||||||
config->default_layout = L_NONE;
|
|
||||||
config->default_orientation = L_NONE;
|
|
||||||
// Flags
|
|
||||||
config->focus_follows_mouse = true;
|
|
||||||
config->mouse_warping = true;
|
|
||||||
config->reloading = false;
|
|
||||||
config->active = false;
|
|
||||||
config->failed = false;
|
|
||||||
config->auto_back_and_forth = false;
|
|
||||||
|
|
||||||
config->gaps_inner = 0;
|
|
||||||
config->gaps_outer = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void free_config(struct sway_config *config) {
|
|
||||||
int i;
|
int i;
|
||||||
for (i = 0; i < config->symbols->length; ++i) {
|
for (i = 0; i < config->symbols->length; ++i) {
|
||||||
free_variable(config->symbols->items[i]);
|
free_variable(config->symbols->items[i]);
|
||||||
|
@ -104,6 +73,40 @@ void free_config(struct sway_config *config) {
|
||||||
free(config);
|
free(config);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static bool file_exists(const char *path) {
|
||||||
|
return access(path, R_OK) != -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void config_defaults(struct sway_config *config) {
|
||||||
|
config->symbols = create_list();
|
||||||
|
config->modes = create_list();
|
||||||
|
config->workspace_outputs = create_list();
|
||||||
|
config->output_configs = create_list();
|
||||||
|
|
||||||
|
config->cmd_queue = create_list();
|
||||||
|
|
||||||
|
config->current_mode = malloc(sizeof(struct sway_mode));
|
||||||
|
config->current_mode->name = malloc(sizeof("default"));
|
||||||
|
strcpy(config->current_mode->name, "default");
|
||||||
|
config->current_mode->bindings = create_list();
|
||||||
|
list_add(config->modes, config->current_mode);
|
||||||
|
|
||||||
|
config->floating_mod = 0;
|
||||||
|
config->default_layout = L_NONE;
|
||||||
|
config->default_orientation = L_NONE;
|
||||||
|
// Flags
|
||||||
|
config->focus_follows_mouse = true;
|
||||||
|
config->mouse_warping = true;
|
||||||
|
config->reloading = false;
|
||||||
|
config->active = false;
|
||||||
|
config->failed = false;
|
||||||
|
config->auto_back_and_forth = false;
|
||||||
|
|
||||||
|
config->gaps_inner = 0;
|
||||||
|
config->gaps_outer = 0;
|
||||||
|
}
|
||||||
|
|
||||||
static char *get_config_path(void) {
|
static char *get_config_path(void) {
|
||||||
char *config_path = NULL;
|
char *config_path = NULL;
|
||||||
char *paths[3] = {getenv("HOME"), getenv("XDG_CONFIG_HOME"), ""};
|
char *paths[3] = {getenv("HOME"), getenv("XDG_CONFIG_HOME"), ""};
|
||||||
|
@ -210,47 +213,48 @@ bool load_config(const char *file) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool read_config(FILE *file, bool is_active) {
|
bool read_config(FILE *file, bool is_active) {
|
||||||
struct sway_config *temp_config = malloc(sizeof(struct sway_config));
|
struct sway_config *old_config = config;
|
||||||
config_defaults(temp_config);
|
struct sway_mode *default_mode;
|
||||||
|
config = malloc(sizeof(struct sway_config));
|
||||||
|
|
||||||
|
config_defaults(config);
|
||||||
|
default_mode = config->current_mode;
|
||||||
|
|
||||||
if (is_active) {
|
if (is_active) {
|
||||||
sway_log(L_DEBUG, "Performing configuration file reload");
|
sway_log(L_DEBUG, "Performing configuration file reload");
|
||||||
temp_config->reloading = true;
|
config->reloading = true;
|
||||||
temp_config->active = true;
|
config->active = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool success = true;
|
bool success = true;
|
||||||
|
|
||||||
int temp_depth = 0; // Temporary: skip all config sections with depth
|
char *line;
|
||||||
|
|
||||||
while (!feof(file)) {
|
while (!feof(file)) {
|
||||||
int _;
|
line = read_line(file);
|
||||||
char *line = read_line(file);
|
line = strip_whitespace(line);
|
||||||
line = strip_whitespace(line, &_);
|
|
||||||
line = strip_comments(line);
|
line = strip_comments(line);
|
||||||
if (!line[0]) {
|
if (line[0] == '\0') {
|
||||||
goto _continue;
|
goto _continue;
|
||||||
}
|
}
|
||||||
if (temp_depth && line[0] == '}') {
|
if (line[0] == '}') {
|
||||||
temp_depth--;
|
config->current_mode = default_mode;
|
||||||
goto _continue;
|
goto _continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Any command which would require wlc to be initialized
|
// Any command which would require wlc to be initialized
|
||||||
// should be queued for later execution
|
// should be queued for later execution
|
||||||
list_t *args = split_string(line, " ");
|
list_t *args = split_string(line, whitespace);
|
||||||
struct cmd_handler *handler;
|
struct cmd_handler *handler;
|
||||||
if ((handler = find_handler(args->items[0]))) {
|
if ((handler = find_handler(args->items[0]))) {
|
||||||
if (handler->config_type == CMD_KEYBIND) {
|
if (handler->config_type == CMD_KEYBIND) {
|
||||||
sway_log(L_ERROR, "Invalid command during config ``%s''", line);
|
sway_log(L_ERROR, "Invalid command during config ``%s''", line);
|
||||||
} else if (handler->config_type == CMD_COMPOSITOR_READY && !is_active) {
|
} else if (handler->config_type == CMD_COMPOSITOR_READY && !is_active) {
|
||||||
sway_log(L_DEBUG, "Deferring command ``%s''", line);
|
sway_log(L_DEBUG, "Deferring command ``%s''", line);
|
||||||
char *cmd = malloc(strlen(line) + 1);
|
char *cmd = strdup(line);
|
||||||
strcpy(cmd, line);
|
list_add(config->cmd_queue, cmd);
|
||||||
list_add(temp_config->cmd_queue, cmd);
|
} else if (!handle_command(line)) {
|
||||||
} else if (!temp_depth && !handle_command(temp_config, line)) {
|
|
||||||
sway_log(L_DEBUG, "Config load failed for line ``%s''", line);
|
sway_log(L_DEBUG, "Config load failed for line ``%s''", line);
|
||||||
success = false;
|
success = false;
|
||||||
temp_config->failed = true;
|
config->failed = true;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
sway_log(L_ERROR, "Invalid command ``%s''", line);
|
sway_log(L_ERROR, "Invalid command ``%s''", line);
|
||||||
|
@ -258,25 +262,21 @@ bool read_config(FILE *file, bool is_active) {
|
||||||
free_flat_list(args);
|
free_flat_list(args);
|
||||||
|
|
||||||
_continue:
|
_continue:
|
||||||
if (line && line[strlen(line) - 1] == '{') {
|
|
||||||
temp_depth++;
|
|
||||||
}
|
|
||||||
free(line);
|
free(line);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_active) {
|
if (is_active) {
|
||||||
temp_config->reloading = false;
|
config->reloading = false;
|
||||||
arrange_windows(&root_container, -1, -1);
|
arrange_windows(&root_container, -1, -1);
|
||||||
}
|
}
|
||||||
if (config) {
|
if (old_config) {
|
||||||
free_config(config);
|
free_config(old_config);
|
||||||
}
|
}
|
||||||
config = temp_config;
|
|
||||||
|
|
||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
char *do_var_replacement(struct sway_config *config, char *str) {
|
char *do_var_replacement(char *str) {
|
||||||
// TODO: Handle escaping $ and using $ in string literals
|
// TODO: Handle escaping $ and using $ in string literals
|
||||||
int i;
|
int i;
|
||||||
for (i = 0; str[i]; ++i) {
|
for (i = 0; str[i]; ++i) {
|
||||||
|
|
|
@ -130,13 +130,6 @@ static void handle_output_resolution_change(wlc_handle output, const struct wlc_
|
||||||
if (!c) return;
|
if (!c) return;
|
||||||
c->width = to->w;
|
c->width = to->w;
|
||||||
c->height = to->h;
|
c->height = to->h;
|
||||||
if (config->default_layout == L_NONE && config->default_orientation == L_NONE) {
|
|
||||||
if (c->width >= c->height) {
|
|
||||||
((swayc_t*)c->children->items[0])->layout = L_HORIZ;
|
|
||||||
} else {
|
|
||||||
((swayc_t*)c->children->items[0])->layout = L_VERT;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
arrange_windows(&root_container, -1, -1);
|
arrange_windows(&root_container, -1, -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -348,7 +341,7 @@ static bool handle_key(wlc_handle view, uint32_t time, const struct wlc_modifier
|
||||||
}
|
}
|
||||||
if (match) {
|
if (match) {
|
||||||
if (state == WLC_KEY_STATE_PRESSED) {
|
if (state == WLC_KEY_STATE_PRESSED) {
|
||||||
handle_command(config, binding->command);
|
handle_command(binding->command);
|
||||||
return EVENT_HANDLED;
|
return EVENT_HANDLED;
|
||||||
} else if (state == WLC_KEY_STATE_RELEASED) {
|
} else if (state == WLC_KEY_STATE_RELEASED) {
|
||||||
// TODO: --released
|
// TODO: --released
|
||||||
|
@ -486,7 +479,7 @@ static void handle_wlc_ready(void) {
|
||||||
sway_log(L_DEBUG, "Compositor is ready, executing cmds in queue");
|
sway_log(L_DEBUG, "Compositor is ready, executing cmds in queue");
|
||||||
// Execute commands until there are none left
|
// Execute commands until there are none left
|
||||||
while (config->cmd_queue->length) {
|
while (config->cmd_queue->length) {
|
||||||
handle_command(config, config->cmd_queue->items[0]);
|
handle_command(config->cmd_queue->items[0]);
|
||||||
free(config->cmd_queue->items[0]);
|
free(config->cmd_queue->items[0]);
|
||||||
list_del(config->cmd_queue, 0);
|
list_del(config->cmd_queue, 0);
|
||||||
}
|
}
|
||||||
|
|
|
@ -198,7 +198,7 @@ void ipc_client_handle_command(struct ipc_client *client) {
|
||||||
case IPC_COMMAND:
|
case IPC_COMMAND:
|
||||||
{
|
{
|
||||||
buf[client->payload_length] = '\0';
|
buf[client->payload_length] = '\0';
|
||||||
bool success = handle_command(config, buf);
|
bool success = handle_command(buf);
|
||||||
char reply[64];
|
char reply[64];
|
||||||
int length = snprintf(reply, sizeof(reply), "{\"success\":%s}", success ? "true" : "false");
|
int length = snprintf(reply, sizeof(reply), "{\"success\":%s}", success ? "true" : "false");
|
||||||
ipc_send_reply(client, reply, (uint32_t) length);
|
ipc_send_reply(client, reply, (uint32_t) length);
|
||||||
|
|
126
sway/stringop.c
126
sway/stringop.c
|
@ -1,27 +1,23 @@
|
||||||
#include "stringop.h"
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <strings.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include "stringop.h"
|
||||||
|
#include "log.h"
|
||||||
#include "string.h"
|
#include "string.h"
|
||||||
#include "list.h"
|
#include "list.h"
|
||||||
#include <strings.h>
|
|
||||||
#include <log.h>
|
const char *whitespace = " \f\n\r\t\v";
|
||||||
|
|
||||||
/* Note: This returns 8 characters for trimmed_start per tab character. */
|
/* Note: This returns 8 characters for trimmed_start per tab character. */
|
||||||
char *strip_whitespace(char *_str, int *trimmed_start) {
|
char *strip_whitespace(char *_str) {
|
||||||
*trimmed_start = 0;
|
|
||||||
if (*_str == '\0')
|
if (*_str == '\0')
|
||||||
return _str;
|
return _str;
|
||||||
char *strold = _str;
|
char *strold = _str;
|
||||||
while (*_str == ' ' || *_str == '\t') {
|
while (*_str == ' ' || *_str == '\t') {
|
||||||
if (*_str == '\t') {
|
|
||||||
*trimmed_start += 8;
|
|
||||||
} else {
|
|
||||||
*trimmed_start += 1;
|
|
||||||
}
|
|
||||||
_str++;
|
_str++;
|
||||||
}
|
}
|
||||||
char *str = malloc(strlen(_str) + 1);
|
char *str = strdup(_str);
|
||||||
strcpy(str, _str);
|
|
||||||
free(strold);
|
free(strold);
|
||||||
int i;
|
int i;
|
||||||
for (i = 0; str[i] != '\0'; ++i);
|
for (i = 0; str[i] != '\0'; ++i);
|
||||||
|
@ -41,7 +37,7 @@ char *strip_comments(char *str) {
|
||||||
} else if (str[i] == '\'' && !in_string) {
|
} else if (str[i] == '\'' && !in_string) {
|
||||||
in_character = !in_character;
|
in_character = !in_character;
|
||||||
} else if (!in_character && !in_string) {
|
} else if (!in_character && !in_string) {
|
||||||
if (str[i] == '#' && i == 0) {
|
if (str[i] == '#') {
|
||||||
str[i] = '\0';
|
str[i] = '\0';
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -51,26 +47,44 @@ char *strip_comments(char *str) {
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
list_t *split_string(const char *str, const char *delims) {
|
void strip_quotes(char *str) {
|
||||||
list_t *res = create_list();
|
bool in_str = false;
|
||||||
int i, j;
|
bool in_chr = false;
|
||||||
int len = strlen(str);
|
bool escaped = false;
|
||||||
for (i = 0, j = 0; i < len + 1; ++i) {
|
char *end = strchr(str,0);
|
||||||
if (strchr(delims, str[i]) || i == len) {
|
while (*str) {
|
||||||
if (i - j == 0) {
|
if (*str == '\'' && !in_str && !escaped) {
|
||||||
|
in_chr = !in_chr;
|
||||||
|
goto shift_over;
|
||||||
|
} else if (*str == '\"' && !in_chr && !escaped) {
|
||||||
|
in_str = !in_str;
|
||||||
|
goto shift_over;
|
||||||
|
} else if (*str == '\\') {
|
||||||
|
escaped = !escaped;
|
||||||
|
++str;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
char *left = malloc(i - j + 1);
|
escaped = false;
|
||||||
memcpy(left, str + j, i - j);
|
++str;
|
||||||
left[i - j] = 0;
|
continue;
|
||||||
list_add(res, left);
|
shift_over:
|
||||||
j = i + 1;
|
memmove(str, str+1, end-- - str);
|
||||||
while (j <= len && str[j] && strchr(delims, str[j])) {
|
|
||||||
j++;
|
|
||||||
i++;
|
|
||||||
}
|
}
|
||||||
|
*end = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
list_t *split_string(const char *str, const char *delims) {
|
||||||
|
list_t *res = create_list();
|
||||||
|
char *copy = strdup(str);
|
||||||
|
char *token;
|
||||||
|
|
||||||
|
token = strtok(copy, delims);
|
||||||
|
while(token) {
|
||||||
|
token = strdup(token);
|
||||||
|
list_add(res, token);
|
||||||
|
token = strtok(NULL, delims);
|
||||||
}
|
}
|
||||||
|
free(copy);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -82,6 +96,60 @@ void free_flat_list(list_t *list) {
|
||||||
list_free(list);
|
list_free(list);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char **split_args(const char *start, int *argc) {
|
||||||
|
*argc = 0;
|
||||||
|
int alloc = 2;
|
||||||
|
char **parts = malloc(sizeof(char *) * alloc);
|
||||||
|
bool in_token = false;
|
||||||
|
bool in_string = false;
|
||||||
|
bool in_char = false;
|
||||||
|
bool escaped = false;
|
||||||
|
const char *end = start;
|
||||||
|
while (*start) {
|
||||||
|
if (!in_token) {
|
||||||
|
start = (end += strspn(end, whitespace));
|
||||||
|
in_token = true;
|
||||||
|
}
|
||||||
|
if (*end == '"' && !in_char && !escaped) {
|
||||||
|
in_string = !in_string;
|
||||||
|
} else if (*end == '\'' && !in_string && !escaped) {
|
||||||
|
in_char = !in_char;
|
||||||
|
} else if (*end == '\\') {
|
||||||
|
escaped = !escaped;
|
||||||
|
} else if (*end == '\0' || (!in_string && !in_char && !escaped
|
||||||
|
&& strchr(whitespace, *end))) {
|
||||||
|
goto add_part;
|
||||||
|
}
|
||||||
|
if (*end != '\\') {
|
||||||
|
escaped = false;
|
||||||
|
}
|
||||||
|
++end;
|
||||||
|
continue;
|
||||||
|
add_part:
|
||||||
|
if (end - start > 0) {
|
||||||
|
char *token = malloc(end - start + 1);
|
||||||
|
strncpy(token, start, end - start + 1);
|
||||||
|
token[end - start] = '\0';
|
||||||
|
strip_quotes(token);
|
||||||
|
unescape_string(token);
|
||||||
|
parts[*argc] = token;
|
||||||
|
if (++*argc == alloc) {
|
||||||
|
parts = realloc(parts, (alloc *= 2) * sizeof(char *));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
in_token = false;
|
||||||
|
escaped = false;
|
||||||
|
}
|
||||||
|
return parts;
|
||||||
|
}
|
||||||
|
|
||||||
|
void free_argv(int argc, char **argv) {
|
||||||
|
while (--argc) {
|
||||||
|
free(argv[argc]);
|
||||||
|
}
|
||||||
|
free(argv);
|
||||||
|
}
|
||||||
|
|
||||||
char *code_strstr(const char *haystack, const char *needle) {
|
char *code_strstr(const char *haystack, const char *needle) {
|
||||||
/* TODO */
|
/* TODO */
|
||||||
return strstr(haystack, needle);
|
return strstr(haystack, needle);
|
||||||
|
@ -177,7 +245,7 @@ int unescape_string(char *string) {
|
||||||
string[i - 1] = c;
|
string[i - 1] = c;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
memmove(string + i, string + i + shift, len - i);
|
memmove(string + i, string + i + shift, len - i + 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return len;
|
return len;
|
||||||
|
|
Loading…
Reference in a new issue