diff options
| -rw-r--r-- | include/commands.h | 4 | ||||
| -rw-r--r-- | include/config.h | 2 | ||||
| -rw-r--r-- | include/stringop.h | 12 | ||||
| -rw-r--r-- | sway/commands.c | 197 | ||||
| -rw-r--r-- | sway/config.c | 104 | ||||
| -rw-r--r-- | sway/handlers.c | 11 | ||||
| -rw-r--r-- | sway/ipc.c | 2 | ||||
| -rw-r--r-- | sway/stringop.c | 151 | 
8 files changed, 256 insertions, 227 deletions
| diff --git a/include/commands.h b/include/commands.h index 808e64eb..8fb0c1d8 100644 --- a/include/commands.h +++ b/include/commands.h @@ -5,7 +5,7 @@  struct cmd_handler {  	char *command; -	bool (*handle)(struct sway_config *config, int argc, char **argv); +	bool (*handle)(int argc, char **argv);  	enum {  		CMD_COMPOSITOR_READY,  		CMD_KEYBIND, @@ -14,7 +14,7 @@ struct cmd_handler {  };  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(); diff --git a/include/config.h b/include/config.h index 653e790f..4070c9ef 100644 --- a/include/config.h +++ b/include/config.h @@ -60,7 +60,7 @@ struct sway_config {  bool load_config(const char *file);  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; diff --git a/include/stringop.h b/include/stringop.h index 7d17af95..dde50f13 100644 --- a/include/stringop.h +++ b/include/stringop.h @@ -2,17 +2,25 @@  #define _SWAY_STRINGOP_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); -// 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);  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_strstr(const char *haystack, const char *needle);  int unescape_string(char *string);  char *join_args(char **argv, int argc);  char *join_list(list_t *list, char *separator); +char *strdup(const char *);  #endif diff --git a/sway/commands.c b/sway/commands.c index 5c782e99..72d53ff0 100644 --- a/sway/commands.c +++ b/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);  } -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)) {  		return false;  	}; @@ -146,7 +146,7 @@ static bool cmd_bindsym(struct sway_config *config, int argc, char **argv) {  	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)) {  		return false;  	} @@ -171,14 +171,14 @@ static bool cmd_exec_always(struct sway_config *config, int argc, char **argv) {  	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) {  		char *args = join_args(argv, argc);  		sway_log(L_DEBUG, "Ignoring exec %s due to reload", args);  		free(args);  		return true;  	} -	return cmd_exec_always(config, argc, argv); +	return cmd_exec_always(argc, argv);  }  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)) {  		return false;  	} @@ -197,7 +197,7 @@ static bool cmd_exit(struct sway_config *config, int argc, char **argv) {  	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)) {  		return false;  	} @@ -258,7 +258,7 @@ static bool cmd_floating(struct sway_config *config, int argc, char **argv) {  	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)) {  		return false;  	} @@ -282,7 +282,7 @@ static bool cmd_floating_mod(struct sway_config *config, int argc, char **argv)  	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 tiled_toggled_index = 0;  	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;  } -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)) {  		return false;  	} @@ -365,7 +365,40 @@ static void hide_view_in_scratchpad(swayc_t *sp_view) {  	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 = malloc(strlen(mode_name) + 1); +		mode->bindings = create_list(); +		strcpy(mode->name, mode_name); +		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)) {  		return false;  	} @@ -435,7 +468,7 @@ static bool cmd_move(struct sway_config *config, int argc, char **argv) {  	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) {  		config->default_orientation = L_HORIZ;  	} else if (strcasecmp(argv[0], "vertical") == 0) { @@ -448,7 +481,7 @@ static bool cmd_orientation(struct sway_config *config, int argc, char **argv) {  	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)) {  		return false;  	} @@ -513,7 +546,7 @@ static bool cmd_output(struct sway_config *config, int argc, char **argv) {  	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)) {  		return false;  	} @@ -655,13 +688,13 @@ static bool cmd_gaps(struct sway_config *config, int argc, char **argv) {  	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);  	wlc_view_close(view->handle);  	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)) {  		return false;  	} @@ -686,7 +719,7 @@ static bool cmd_layout(struct sway_config *config, int argc, char **argv) {  	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)) {  		return false;  	} @@ -697,7 +730,7 @@ static bool cmd_reload(struct sway_config *config, int argc, char **argv) {  	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)) {  		return false;  	} @@ -769,7 +802,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)) {  		return false;  	} @@ -796,7 +829,7 @@ 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)) {  		return false;  	} @@ -809,7 +842,7 @@ static bool cmd_set(struct sway_config *config, int argc, char **argv) {  	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" :  		layout == L_HORIZ ? "splith" : "split";  	if (!checkarg(argc, name, EXPECTED_EQUAL_TO, 0)) { @@ -840,15 +873,15 @@ static bool _do_split(struct sway_config *config, int argc, char **argv, int lay  	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)) {  		return false;  	}  	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) { -		_do_split(config, argc - 1, argv + 1, L_HORIZ); +		_do_split(argc - 1, argv + 1, L_HORIZ);  	} else {  		sway_log(L_ERROR, "Invalid split command (expected either horiziontal or vertical).");  		return false; @@ -857,15 +890,15 @@ static bool cmd_split(struct sway_config *config, int argc, char **argv) {  	return true;  } -static bool cmd_splitv(struct sway_config *config, int argc, char **argv) { -	return _do_split(config, argc, argv, L_VERT); +static bool cmd_splitv(int argc, char **argv) { +	return _do_split(argc, argv, L_VERT);  } -static bool cmd_splith(struct sway_config *config, int argc, char **argv) { -	return _do_split(config, argc, argv, L_HORIZ); +static bool cmd_splith(int argc, char **argv) { +	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)) {  		return false;  	} @@ -878,7 +911,7 @@ static bool cmd_log_colors(struct sway_config *config, int argc, char **argv) {  	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)) {  		return false;  	} @@ -897,7 +930,7 @@ static bool cmd_fullscreen(struct sway_config *config, int argc, char **argv) {  	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)) {  		return false;  	} @@ -953,7 +986,7 @@ static bool cmd_workspace(struct sway_config *config, int argc, char **argv) {  	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)) {  		return false;  	} @@ -979,6 +1012,7 @@ static struct cmd_handler handlers[] = {  	{ "kill", cmd_kill, CMD_KEYBIND },  	{ "layout", cmd_layout, CMD_KEYBIND },  	{ "log_colors", cmd_log_colors, CMD_ANYTIME }, +	{ "mode", cmd_mode, CMD_ANYTIME },  	{ "move", cmd_move, CMD_KEYBIND },  	{ "output", cmd_output, CMD_ANYTIME },  	{ "reload", cmd_reload, CMD_KEYBIND }, @@ -992,58 +1026,6 @@ static struct cmd_handler handlers[] = {  	{ "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) {  	const struct cmd_handler *a = _a;  	const struct cmd_handler *b = _b; @@ -1058,44 +1040,25 @@ struct cmd_handler *find_handler(char *line) {  	return res;  } -bool handle_command(struct sway_config *config, char *exec) { +bool handle_command(char *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; -		char **argv = split_directive(exec + strlen(handler->command), &argc); +	int 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; - -		// Perform var subs on all parts of the command -		for (i = 0; i < argc; ++i) { -			argv[i] = do_var_replacement(config, argv[i]); -		} - -		exec_success = handler->handle(config, argc, argv); -		for (i = 0; i < argc; ++i) { -			free(argv[i]); -		} -		free(argv); -		if (!exec_success) { -			sway_log(L_ERROR, "Command failed: %s", cmd); +		for (i = 1; i < argc; ++i) { +			argv[i] = do_var_replacement(argv[i]);  		} +		exec_success = handler->handle(argc - 1, argv + 1);  	} -	if (ptr) { -		free(cmd); +	if (exec_success == false) { +		sway_log(L_ERROR, "Command failed: %s", argv[0]);  	} +	free_argv(argc, argv);  	return exec_success;  } diff --git a/sway/config.c b/sway/config.c index b64dd4b1..119730ca 100644 --- a/sway/config.c +++ b/sway/config.c @@ -13,6 +13,7 @@  struct sway_config *config = NULL; +  static void free_variable(struct sway_variable *var) {  	free(var->name);  	free(var->value); @@ -46,6 +47,33 @@ static void free_workspace_output(struct workspace_output *wo) {  	free(wo);  } +static void free_config(struct sway_config *config) { +	int i; +	for (i = 0; i < config->symbols->length; ++i) { +		free_variable(config->symbols->items[i]); +	} +	list_free(config->symbols); + +	for (i = 0; i < config->modes->length; ++i) { +		free_mode(config->modes->items[i]); +	} +	list_free(config->modes); + +	free_flat_list(config->cmd_queue); + +	for (i = 0; i < config->workspace_outputs->length; ++i) { +		free_workspace_output(config->workspace_outputs->items[i]); +	} +	list_free(config->workspace_outputs); + +	for (i = 0; i < config->output_configs->length; ++i) { +		free_outut_config(config->output_configs->items[i]); +	} +	list_free(config->output_configs); +	free(config); +} + +  static bool file_exists(const char *path) {  	return access(path, R_OK) != -1;  } @@ -59,7 +87,8 @@ static void config_defaults(struct sway_config *config) {  	config->cmd_queue = create_list();  	config->current_mode = malloc(sizeof(struct sway_mode)); -	config->current_mode->name = NULL; +	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); @@ -78,32 +107,6 @@ static void config_defaults(struct sway_config *config) {  	config->gaps_outer = 0;  } -void free_config(struct sway_config *config) { -	int i; -	for (i = 0; i < config->symbols->length; ++i) { -		free_variable(config->symbols->items[i]); -	} -	list_free(config->symbols); - -	for (i = 0; i < config->modes->length; ++i) { -		free_mode(config->modes->items[i]); -	} -	list_free(config->modes); - -	free_flat_list(config->cmd_queue); - -	for (i = 0; i < config->workspace_outputs->length; ++i) { -		free_workspace_output(config->workspace_outputs->items[i]); -	} -	list_free(config->workspace_outputs); - -	for (i = 0; i < config->output_configs->length; ++i) { -		free_outut_config(config->output_configs->items[i]); -	} -	list_free(config->output_configs); -	free(config); -} -  static char *get_config_path(void) {  	char *config_path = NULL;  	char *paths[3] = {getenv("HOME"), getenv("XDG_CONFIG_HOME"), ""}; @@ -210,34 +213,35 @@ bool load_config(const char *file) {  }  bool read_config(FILE *file, bool is_active) { -	struct sway_config *temp_config = malloc(sizeof(struct sway_config)); -	config_defaults(temp_config); +	struct sway_config *old_config = config; +	struct sway_mode *default_mode; +	config = malloc(sizeof(struct sway_config)); + +	config_defaults(config); +	default_mode = config->current_mode; +  	if (is_active) {  		sway_log(L_DEBUG, "Performing configuration file reload"); -		temp_config->reloading = true; -		temp_config->active = true; +		config->reloading = true; +		config->active = true;  	} -  	bool success = true; -	int temp_depth = 0; // Temporary: skip all config sections with depth - +	char *line;  	while (!feof(file)) { -		int _; -		char *line = read_line(file); -		line = strip_whitespace(line, &_); +		line = read_line(file);  		line = strip_comments(line); -		if (!line[0]) { +		if (line[0] == '\0') {  			goto _continue;  		} -		if (temp_depth && line[0] == '}') { -			temp_depth--; +		if (line[0] == '}') { +			config->current_mode = default_mode;  			goto _continue;  		}  		// Any command which would require wlc to be initialized  		// should be queued for later execution -		list_t *args = split_string(line, " "); +		list_t *args = split_string(line, whitespace);  		struct cmd_handler *handler;  		if ((handler = find_handler(args->items[0]))) {  			if (handler->config_type == CMD_KEYBIND) { @@ -246,11 +250,11 @@ bool read_config(FILE *file, bool is_active) {  				sway_log(L_DEBUG, "Deferring command ``%s''", line);  				char *cmd = malloc(strlen(line) + 1);  				strcpy(cmd, line); -				list_add(temp_config->cmd_queue, cmd); -			} else if (!temp_depth && !handle_command(temp_config, line)) { +				list_add(config->cmd_queue, cmd); +			} else if (!handle_command(line)) {  				sway_log(L_DEBUG, "Config load failed for line ``%s''", line);  				success = false; -				temp_config->failed = true; +				config->failed = true;  			}  		} else {  			sway_log(L_ERROR, "Invalid command ``%s''", line); @@ -258,25 +262,21 @@ bool read_config(FILE *file, bool is_active) {  		free_flat_list(args);  _continue: -		if (line && line[strlen(line) - 1] == '{') { -			temp_depth++; -		}  		free(line);  	}  	if (is_active) { -		temp_config->reloading = false; +		config->reloading = false;  		arrange_windows(&root_container, -1, -1);  	} -	if (config) { -		free_config(config); +	if (old_config) { +		free_config(old_config);  	} -	config = temp_config;  	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  	int i;  	for (i = 0; str[i]; ++i) { diff --git a/sway/handlers.c b/sway/handlers.c index 482d52c6..c0472817 100644 --- a/sway/handlers.c +++ b/sway/handlers.c @@ -130,13 +130,6 @@ static void handle_output_resolution_change(wlc_handle output, const struct wlc_  	if (!c) return;  	c->width = to->w;  	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);  } @@ -348,7 +341,7 @@ static bool handle_key(wlc_handle view, uint32_t time, const struct wlc_modifier  			}  			if (match) {  				if (state == WLC_KEY_STATE_PRESSED) { -					handle_command(config, binding->command); +					handle_command(binding->command);  					return EVENT_HANDLED;  				} else if (state == WLC_KEY_STATE_RELEASED) {  					// TODO: --released @@ -486,7 +479,7 @@ static void handle_wlc_ready(void) {  	sway_log(L_DEBUG, "Compositor is ready, executing cmds in queue");  	// Execute commands until there are none left  	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]);  		list_del(config->cmd_queue, 0);  	} @@ -198,7 +198,7 @@ void ipc_client_handle_command(struct ipc_client *client) {  	case IPC_COMMAND:  	{  		buf[client->payload_length] = '\0'; -		bool success = handle_command(config, buf); +		bool success = handle_command(buf);  		char reply[64];  		int length = snprintf(reply, sizeof(reply), "{\"success\":%s}", success ? "true" : "false");  		ipc_send_reply(client, reply, (uint32_t) length); diff --git a/sway/stringop.c b/sway/stringop.c index c39e2c34..d2b74655 100644 --- a/sway/stringop.c +++ b/sway/stringop.c @@ -1,34 +1,26 @@ -#include "stringop.h"  #include <stdlib.h>  #include <stdio.h> +#include <strings.h> +#include <ctype.h> +#include "stringop.h" +#include "log.h"  #include "string.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. */ -char *strip_whitespace(char *_str, int *trimmed_start) { -	*trimmed_start = 0; -	if (*_str == '\0') -		return _str; -	char *strold = _str; -	while (*_str == ' ' || *_str == '\t') { -		if (*_str == '\t') { -			*trimmed_start += 8; -		} else { -			*trimmed_start += 1; -		} -		_str++; -	} -	char *str = malloc(strlen(_str) + 1); -	strcpy(str, _str); -	free(strold); -	int i; -	for (i = 0; str[i] != '\0'; ++i); +char *strip_whitespace(char *_str) { +	int ws = strspn(_str, whitespace); +	int len = strlen(_str) - ws + 1; +	sway_log(L_DEBUG,"%d, %d..",ws,len); +	char *str = malloc(len); +	strcpy(str, _str+ws); +	free(_str);  	do { -		i--; -	} while (i >= 0 && (str[i] == ' ' || str[i] == '\t')); -	str[i + 1] = '\0'; +		len--; +	} while (len >= 0 && (str[len] == ' ' || str[len] == '\t')); +	str[len + 1] = '\0';  	return str;  } @@ -41,7 +33,7 @@ char *strip_comments(char *str) {  		} else if (str[i] == '\'' && !in_string) {  			in_character = !in_character;  		} else if (!in_character && !in_string) { -			if (str[i] == '#' && i == 0) { +			if (str[i] == '#') {  				str[i] = '\0';  				break;  			} @@ -51,26 +43,45 @@ char *strip_comments(char *str) {  	return str;  } +void strip_quotes(char *str) { +	bool in_str = false; +	bool in_chr = false; +	bool escaped = false; +	char *end = strchr(str,0); +	while (*str) { +		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; +		} +		escaped = false; +		++str; +		continue; +		shift_over: +		memmove(str, str+1, end-- - str); +	} +	*end = '\0'; +} +  list_t *split_string(const char *str, const char *delims) {  	list_t *res = create_list(); -	int i, j; -	int len = strlen(str); -	for (i = 0, j = 0; i < len + 1; ++i) { -		if (strchr(delims, str[i]) || i == len) { -			if (i - j == 0) { -				continue; -			} -			char *left = malloc(i - j + 1); -			memcpy(left, str + j, i - j); -			left[i - j] = 0; -			list_add(res, left); -			j = i + 1; -			while (j <= len && str[j] && strchr(delims, str[j])) { -				j++; -				i++; -			} -		} +	char *copy = malloc(strlen(str) + 1); +	char *token; +	strcpy(copy, str); + +	token = strtok(copy, delims); +	while(token) { +		token = strdup(token); +		list_add(res, token); +		token = strtok(NULL, delims);  	} +	free(copy);  	return res;  } @@ -82,6 +93,60 @@ void free_flat_list(list_t *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) {  	/* TODO */  	return strstr(haystack, needle); @@ -177,7 +242,7 @@ int unescape_string(char *string) {  					string[i - 1] = c;  				}  			} -			memmove(string + i, string + i + shift, len - i); +			memmove(string + i, string + i + shift, len - i + 1);  		}  	}  	return len; | 
