| 
									
										
										
										
											2018-11-25 12:12:48 +01:00
										 |  |  | #define _POSIX_C_SOURCE 200809L
 | 
					
						
							| 
									
										
										
										
											2018-07-28 22:56:12 -04:00
										 |  |  | #include <getopt.h>
 | 
					
						
							| 
									
										
										
										
											2018-12-09 12:09:11 +00:00
										 |  |  | #include <stdio.h>
 | 
					
						
							| 
									
										
										
										
											2018-07-28 22:56:12 -04:00
										 |  |  | #include <stdlib.h>
 | 
					
						
							|  |  |  | #include <wordexp.h>
 | 
					
						
							| 
									
										
										
										
											2019-01-23 10:09:23 -06:00
										 |  |  | #include <unistd.h>
 | 
					
						
							| 
									
										
										
										
											2018-07-28 22:56:12 -04:00
										 |  |  | #include "log.h"
 | 
					
						
							|  |  |  | #include "list.h"
 | 
					
						
							| 
									
										
										
										
											2018-07-28 23:15:12 -04:00
										 |  |  | #include "swaynag/swaynag.h"
 | 
					
						
							| 
									
										
										
										
											2018-07-28 22:56:12 -04:00
										 |  |  | #include "swaynag/types.h"
 | 
					
						
							| 
									
										
										
										
											2018-07-29 22:42:03 -04:00
										 |  |  | #include "util.h"
 | 
					
						
							| 
									
										
										
										
											2018-07-28 22:56:12 -04:00
										 |  |  | #include "wlr-layer-shell-unstable-v1-client-protocol.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-30 13:58:49 +03:00
										 |  |  | static char *read_from_stdin(void) { | 
					
						
							| 
									
										
										
										
											2018-07-28 22:56:12 -04:00
										 |  |  | 	char *buffer = NULL; | 
					
						
							| 
									
										
										
										
											2018-12-09 12:09:11 +00:00
										 |  |  | 	size_t buffer_len = 0; | 
					
						
							|  |  |  | 	char *line = NULL; | 
					
						
							|  |  |  | 	size_t line_size = 0; | 
					
						
							|  |  |  | 	ssize_t nread; | 
					
						
							|  |  |  | 	while ((nread = getline(&line, &line_size, stdin)) != -1) { | 
					
						
							| 
									
										
										
										
											2019-03-11 22:28:35 -04:00
										 |  |  | 		buffer = realloc(buffer, buffer_len + nread + 1); | 
					
						
							| 
									
										
										
										
											2018-12-09 12:09:11 +00:00
										 |  |  | 		snprintf(&buffer[buffer_len], nread + 1, "%s", line); | 
					
						
							|  |  |  | 		buffer_len += nread; | 
					
						
							| 
									
										
										
										
											2018-07-28 22:56:12 -04:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2018-12-09 12:09:11 +00:00
										 |  |  | 	free(line); | 
					
						
							| 
									
										
										
										
											2018-07-28 22:56:12 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-09 12:09:11 +00:00
										 |  |  | 	while (buffer && buffer[buffer_len - 1] == '\n') { | 
					
						
							|  |  |  | 		buffer[--buffer_len] = '\0'; | 
					
						
							| 
									
										
										
										
											2018-07-28 22:56:12 -04:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return buffer; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-28 23:15:12 -04:00
										 |  |  | int swaynag_parse_options(int argc, char **argv, struct swaynag *swaynag, | 
					
						
							| 
									
										
										
										
											2018-07-29 22:42:03 -04:00
										 |  |  | 		list_t *types, struct swaynag_type *type, char **config, bool *debug) { | 
					
						
							|  |  |  | 	enum type_options { | 
					
						
							|  |  |  | 		TO_COLOR_BACKGROUND = 256, | 
					
						
							|  |  |  | 		TO_COLOR_BORDER, | 
					
						
							|  |  |  | 		TO_COLOR_BORDER_BOTTOM, | 
					
						
							|  |  |  | 		TO_COLOR_BUTTON, | 
					
						
							|  |  |  | 		TO_COLOR_TEXT, | 
					
						
							|  |  |  | 		TO_THICK_BAR_BORDER, | 
					
						
							|  |  |  | 		TO_PADDING_MESSAGE, | 
					
						
							|  |  |  | 		TO_THICK_DET_BORDER, | 
					
						
							|  |  |  | 		TO_THICK_BTN_BORDER, | 
					
						
							|  |  |  | 		TO_GAP_BTN, | 
					
						
							|  |  |  | 		TO_GAP_BTN_DISMISS, | 
					
						
							|  |  |  | 		TO_MARGIN_BTN_RIGHT, | 
					
						
							|  |  |  | 		TO_PADDING_BTN, | 
					
						
							|  |  |  | 	}; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-28 22:56:12 -04:00
										 |  |  | 	static struct option opts[] = { | 
					
						
							|  |  |  | 		{"button", required_argument, NULL, 'b'}, | 
					
						
							| 
									
										
										
										
											2018-11-27 23:27:44 -05:00
										 |  |  | 		{"button-no-terminal", required_argument, NULL, 'B'}, | 
					
						
							| 
									
										
										
										
											2018-07-28 22:56:12 -04:00
										 |  |  | 		{"config", required_argument, NULL, 'c'}, | 
					
						
							|  |  |  | 		{"debug", no_argument, NULL, 'd'}, | 
					
						
							|  |  |  | 		{"edge", required_argument, NULL, 'e'}, | 
					
						
							|  |  |  | 		{"font", required_argument, NULL, 'f'}, | 
					
						
							|  |  |  | 		{"help", no_argument, NULL, 'h'}, | 
					
						
							|  |  |  | 		{"detailed-message", no_argument, NULL, 'l'}, | 
					
						
							|  |  |  | 		{"detailed-button", required_argument, NULL, 'L'}, | 
					
						
							|  |  |  | 		{"message", required_argument, NULL, 'm'}, | 
					
						
							|  |  |  | 		{"output", required_argument, NULL, 'o'}, | 
					
						
							|  |  |  | 		{"dismiss-button", required_argument, NULL, 's'}, | 
					
						
							|  |  |  | 		{"type", required_argument, NULL, 't'}, | 
					
						
							|  |  |  | 		{"version", no_argument, NULL, 'v'}, | 
					
						
							| 
									
										
										
										
											2018-07-29 22:42:03 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		{"background", required_argument, NULL, TO_COLOR_BACKGROUND}, | 
					
						
							|  |  |  | 		{"border", required_argument, NULL, TO_COLOR_BORDER}, | 
					
						
							|  |  |  | 		{"border-bottom", required_argument, NULL, TO_COLOR_BORDER_BOTTOM}, | 
					
						
							|  |  |  | 		{"button-background", required_argument, NULL, TO_COLOR_BUTTON}, | 
					
						
							|  |  |  | 		{"text", required_argument, NULL, TO_COLOR_TEXT}, | 
					
						
							|  |  |  | 		{"border-bottom-size", required_argument, NULL, TO_THICK_BAR_BORDER}, | 
					
						
							|  |  |  | 		{"message-padding", required_argument, NULL, TO_PADDING_MESSAGE}, | 
					
						
							|  |  |  | 		{"details-border-size", required_argument, NULL, TO_THICK_DET_BORDER}, | 
					
						
							|  |  |  | 		{"button-border-size", required_argument, NULL, TO_THICK_BTN_BORDER}, | 
					
						
							|  |  |  | 		{"button-gap", required_argument, NULL, TO_GAP_BTN}, | 
					
						
							|  |  |  | 		{"button-dismiss-gap", required_argument, NULL, TO_GAP_BTN_DISMISS}, | 
					
						
							|  |  |  | 		{"button-margin-right", required_argument, NULL, TO_MARGIN_BTN_RIGHT}, | 
					
						
							|  |  |  | 		{"button-padding", required_argument, NULL, TO_PADDING_BTN}, | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-28 22:56:12 -04:00
										 |  |  | 		{0, 0, 0, 0} | 
					
						
							|  |  |  | 	}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	const char *usage = | 
					
						
							|  |  |  | 		"Usage: swaynag [options...]\n" | 
					
						
							|  |  |  | 		"\n" | 
					
						
							|  |  |  | 		"  -b, --button <text> <action>  Create a button with text that " | 
					
						
							| 
									
										
										
										
											2018-11-27 23:27:44 -05:00
										 |  |  | 			"executes action in a terminal when pressed. Multiple buttons can " | 
					
						
							|  |  |  | 			"be defined.\n" | 
					
						
							|  |  |  | 		"  -B, --button-no-terminal <text> <action>  Like --button, but does" | 
					
						
							|  |  |  | 			"not run the action in a terminal.\n" | 
					
						
							| 
									
										
										
										
											2018-07-28 22:56:12 -04:00
										 |  |  | 		"  -c, --config <path>           Path to config file.\n" | 
					
						
							|  |  |  | 		"  -d, --debug                   Enable debugging.\n" | 
					
						
							|  |  |  | 		"  -e, --edge top|bottom         Set the edge to use.\n" | 
					
						
							|  |  |  | 		"  -f, --font <font>             Set the font to use.\n" | 
					
						
							|  |  |  | 		"  -h, --help                    Show help message and quit.\n" | 
					
						
							|  |  |  | 		"  -l, --detailed-message        Read a detailed message from stdin.\n" | 
					
						
							|  |  |  | 		"  -L, --detailed-button <text>  Set the text of the detail button.\n" | 
					
						
							|  |  |  | 		"  -m, --message <msg>           Set the message text.\n" | 
					
						
							|  |  |  | 		"  -o, --output <output>         Set the output to use.\n" | 
					
						
							|  |  |  | 		"  -s, --dismiss-button <text>   Set the dismiss button text.\n" | 
					
						
							|  |  |  | 		"  -t, --type <type>             Set the message type.\n" | 
					
						
							| 
									
										
										
										
											2018-07-29 22:42:03 -04:00
										 |  |  | 		"  -v, --version                 Show the version number and quit.\n" | 
					
						
							|  |  |  | 		"\n" | 
					
						
							|  |  |  | 		"The following appearance options can also be given:\n" | 
					
						
							|  |  |  | 		"  --background RRGGBB[AA]       Background color.\n" | 
					
						
							|  |  |  | 		"  --border RRGGBB[AA]           Border color.\n" | 
					
						
							|  |  |  | 		"  --border-bottom RRGGBB[AA]    Bottom border color.\n" | 
					
						
							|  |  |  | 		"  --button-background RRGGBB[AA]           Button background color.\n" | 
					
						
							|  |  |  | 		"  --text RRGGBB[AA]             Text color.\n" | 
					
						
							|  |  |  | 		"  --border-bottom-size size     Thickness of the bar border.\n" | 
					
						
							|  |  |  | 		"  --message-padding padding     Padding for the message.\n" | 
					
						
							|  |  |  | 		"  --details-border-size size    Thickness for the details border.\n" | 
					
						
							|  |  |  | 		"  --button-border-size size     Thickness for the button border.\n" | 
					
						
							|  |  |  | 		"  --button-gap gap              Size of the gap between buttons\n" | 
					
						
							|  |  |  | 		"  --button-dismiss-gap gap      Size of the gap for dismiss button.\n" | 
					
						
							|  |  |  | 		"  --button-margin-right margin  Margin from dismiss button to edge.\n" | 
					
						
							|  |  |  | 		"  --button-padding padding      Padding for the button text.\n"; | 
					
						
							| 
									
										
										
										
											2018-07-28 22:56:12 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	optind = 1; | 
					
						
							|  |  |  | 	while (1) { | 
					
						
							| 
									
										
										
										
											2018-11-27 23:27:44 -05:00
										 |  |  | 		int c = getopt_long(argc, argv, "b:B:c:de:f:hlL:m:o:s:t:v", opts, NULL); | 
					
						
							| 
									
										
										
										
											2018-07-28 22:56:12 -04:00
										 |  |  | 		if (c == -1) { | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		switch (c) { | 
					
						
							|  |  |  | 		case 'b': // Button
 | 
					
						
							| 
									
										
										
										
											2018-11-27 23:27:44 -05:00
										 |  |  | 		case 'B': // Button (No Terminal)
 | 
					
						
							| 
									
										
										
										
											2018-07-28 23:15:12 -04:00
										 |  |  | 			if (swaynag) { | 
					
						
							| 
									
										
										
										
											2018-07-28 22:56:12 -04:00
										 |  |  | 				if (optind >= argc) { | 
					
						
							|  |  |  | 					fprintf(stderr, "Missing action for button %s\n", optarg); | 
					
						
							|  |  |  | 					return EXIT_FAILURE; | 
					
						
							|  |  |  | 				} | 
					
						
							| 
									
										
										
										
											2018-07-28 23:15:12 -04:00
										 |  |  | 				struct swaynag_button *button; | 
					
						
							|  |  |  | 				button = calloc(sizeof(struct swaynag_button), 1); | 
					
						
							| 
									
										
										
										
											2018-07-28 22:56:12 -04:00
										 |  |  | 				button->text = strdup(optarg); | 
					
						
							| 
									
										
										
										
											2018-07-28 23:15:12 -04:00
										 |  |  | 				button->type = SWAYNAG_ACTION_COMMAND; | 
					
						
							| 
									
										
										
										
											2018-07-28 22:56:12 -04:00
										 |  |  | 				button->action = strdup(argv[optind]); | 
					
						
							| 
									
										
										
										
											2018-11-27 23:27:44 -05:00
										 |  |  | 				button->terminal = c == 'b'; | 
					
						
							| 
									
										
										
										
											2018-07-28 23:15:12 -04:00
										 |  |  | 				list_add(swaynag->buttons, button); | 
					
						
							| 
									
										
										
										
											2018-07-28 22:56:12 -04:00
										 |  |  | 			} | 
					
						
							|  |  |  | 			optind++; | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		case 'c': // Config
 | 
					
						
							|  |  |  | 			if (config) { | 
					
						
							|  |  |  | 				*config = strdup(optarg); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		case 'd': // Debug
 | 
					
						
							|  |  |  | 			if (debug) { | 
					
						
							|  |  |  | 				*debug = true; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		case 'e': // Edge
 | 
					
						
							| 
									
										
										
										
											2018-07-29 22:42:03 -04:00
										 |  |  | 			if (type) { | 
					
						
							| 
									
										
										
										
											2018-07-28 22:56:12 -04:00
										 |  |  | 				if (strcmp(optarg, "top") == 0) { | 
					
						
							| 
									
										
										
										
											2018-07-29 22:42:03 -04:00
										 |  |  | 					type->anchors = ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP | 
					
						
							| 
									
										
										
										
											2018-07-28 22:56:12 -04:00
										 |  |  | 						| ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT | 
					
						
							|  |  |  | 						| ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT; | 
					
						
							|  |  |  | 				} else if (strcmp(optarg, "bottom") == 0) { | 
					
						
							| 
									
										
										
										
											2018-07-29 22:42:03 -04:00
										 |  |  | 					type->anchors = ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM | 
					
						
							| 
									
										
										
										
											2018-07-28 22:56:12 -04:00
										 |  |  | 						| ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT | 
					
						
							|  |  |  | 						| ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT; | 
					
						
							|  |  |  | 				} else { | 
					
						
							|  |  |  | 					fprintf(stderr, "Invalid edge: %s\n", optarg); | 
					
						
							|  |  |  | 					return EXIT_FAILURE; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		case 'f': // Font
 | 
					
						
							| 
									
										
										
										
											2018-07-29 22:42:03 -04:00
										 |  |  | 			if (type) { | 
					
						
							|  |  |  | 				free(type->font); | 
					
						
							|  |  |  | 				type->font = strdup(optarg); | 
					
						
							| 
									
										
										
										
											2018-07-28 22:56:12 -04:00
										 |  |  | 			} | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		case 'l': // Detailed Message
 | 
					
						
							| 
									
										
										
										
											2018-07-28 23:15:12 -04:00
										 |  |  | 			if (swaynag) { | 
					
						
							|  |  |  | 				free(swaynag->details.message); | 
					
						
							|  |  |  | 				swaynag->details.message = read_from_stdin(); | 
					
						
							|  |  |  | 				swaynag->details.button_up.text = strdup("▲"); | 
					
						
							|  |  |  | 				swaynag->details.button_down.text = strdup("▼"); | 
					
						
							| 
									
										
										
										
											2018-07-28 22:56:12 -04:00
										 |  |  | 			} | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		case 'L': // Detailed Button Text
 | 
					
						
							| 
									
										
										
										
											2018-07-28 23:15:12 -04:00
										 |  |  | 			if (swaynag) { | 
					
						
							| 
									
										
										
										
											2018-08-20 15:06:12 -04:00
										 |  |  | 				free(swaynag->details.button_details->text); | 
					
						
							|  |  |  | 				swaynag->details.button_details->text = strdup(optarg); | 
					
						
							| 
									
										
										
										
											2018-07-28 22:56:12 -04:00
										 |  |  | 			} | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		case 'm': // Message
 | 
					
						
							| 
									
										
										
										
											2018-07-28 23:15:12 -04:00
										 |  |  | 			if (swaynag) { | 
					
						
							|  |  |  | 				free(swaynag->message); | 
					
						
							|  |  |  | 				swaynag->message = strdup(optarg); | 
					
						
							| 
									
										
										
										
											2018-07-28 22:56:12 -04:00
										 |  |  | 			} | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		case 'o': // Output
 | 
					
						
							| 
									
										
										
										
											2018-07-29 22:42:03 -04:00
										 |  |  | 			if (type) { | 
					
						
							|  |  |  | 				free(type->output); | 
					
						
							|  |  |  | 				type->output = strdup(optarg); | 
					
						
							| 
									
										
										
										
											2018-07-28 22:56:12 -04:00
										 |  |  | 			} | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		case 's': // Dismiss Button Text
 | 
					
						
							| 
									
										
										
										
											2018-07-28 23:15:12 -04:00
										 |  |  | 			if (swaynag) { | 
					
						
							|  |  |  | 				struct swaynag_button *button_close; | 
					
						
							|  |  |  | 				button_close = swaynag->buttons->items[0]; | 
					
						
							| 
									
										
										
										
											2018-07-28 22:56:12 -04:00
										 |  |  | 				free(button_close->text); | 
					
						
							|  |  |  | 				button_close->text = strdup(optarg); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		case 't': // Type
 | 
					
						
							| 
									
										
										
										
											2018-07-28 23:15:12 -04:00
										 |  |  | 			if (swaynag) { | 
					
						
							|  |  |  | 				swaynag->type = swaynag_type_get(types, optarg); | 
					
						
							|  |  |  | 				if (!swaynag->type) { | 
					
						
							| 
									
										
										
										
											2018-07-28 22:56:12 -04:00
										 |  |  | 					fprintf(stderr, "Unknown type %s\n", optarg); | 
					
						
							|  |  |  | 					return EXIT_FAILURE; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		case 'v': // Version
 | 
					
						
							|  |  |  | 			fprintf(stdout, "swaynag version " SWAY_VERSION "\n"); | 
					
						
							|  |  |  | 			return -1; | 
					
						
							| 
									
										
										
										
											2018-07-29 22:42:03 -04:00
										 |  |  | 		case TO_COLOR_BACKGROUND: // Background color
 | 
					
						
							|  |  |  | 			if (type) { | 
					
						
							|  |  |  | 				type->background = parse_color(optarg); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		case TO_COLOR_BORDER: // Border color
 | 
					
						
							|  |  |  | 			if (type) { | 
					
						
							|  |  |  | 				type->border = parse_color(optarg); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		case TO_COLOR_BORDER_BOTTOM: // Bottom border color
 | 
					
						
							|  |  |  | 			if (type) { | 
					
						
							|  |  |  | 				type->border_bottom = parse_color(optarg); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		case TO_COLOR_BUTTON:  // Button background color
 | 
					
						
							|  |  |  | 			if (type) { | 
					
						
							|  |  |  | 				type->button_background = parse_color(optarg); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		case TO_COLOR_TEXT:  // Text color
 | 
					
						
							|  |  |  | 			if (type) { | 
					
						
							|  |  |  | 				type->text = parse_color(optarg); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		case TO_THICK_BAR_BORDER:  // Bottom border thickness
 | 
					
						
							|  |  |  | 			if (type) { | 
					
						
							|  |  |  | 				type->bar_border_thickness = strtol(optarg, NULL, 0); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		case TO_PADDING_MESSAGE:  // Message padding
 | 
					
						
							|  |  |  | 			if (type) { | 
					
						
							|  |  |  | 				type->message_padding = strtol(optarg, NULL, 0); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		case TO_THICK_DET_BORDER:  // Details border thickness
 | 
					
						
							|  |  |  | 			if (type) { | 
					
						
							|  |  |  | 				type->details_border_thickness = strtol(optarg, NULL, 0); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		case TO_THICK_BTN_BORDER:  // Button border thickness
 | 
					
						
							|  |  |  | 			if (type) { | 
					
						
							|  |  |  | 				type->button_border_thickness = strtol(optarg, NULL, 0); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		case TO_GAP_BTN: // Gap between buttons
 | 
					
						
							|  |  |  | 			if (type) { | 
					
						
							|  |  |  | 				type->button_gap = strtol(optarg, NULL, 0); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		case TO_GAP_BTN_DISMISS:  // Gap between dismiss button
 | 
					
						
							|  |  |  | 			if (type) { | 
					
						
							|  |  |  | 				type->button_gap_close = strtol(optarg, NULL, 0); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		case TO_MARGIN_BTN_RIGHT:  // Margin on the right side of button area
 | 
					
						
							|  |  |  | 			if (type) { | 
					
						
							|  |  |  | 				type->button_margin_right = strtol(optarg, NULL, 0); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		case TO_PADDING_BTN:  // Padding for the button text
 | 
					
						
							|  |  |  | 			if (type) { | 
					
						
							|  |  |  | 				type->button_padding = strtol(optarg, NULL, 0); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			break; | 
					
						
							| 
									
										
										
										
											2018-07-28 22:56:12 -04:00
										 |  |  | 		default: // Help or unknown flag
 | 
					
						
							|  |  |  | 			fprintf(c == 'h' ? stdout : stderr, "%s", usage); | 
					
						
							|  |  |  | 			return -1; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static bool file_exists(const char *path) { | 
					
						
							|  |  |  | 	return path && access(path, R_OK) != -1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-28 23:15:12 -04:00
										 |  |  | char *swaynag_get_config_path(void) { | 
					
						
							| 
									
										
										
										
											2018-07-28 22:56:12 -04:00
										 |  |  | 	static const char *config_paths[] = { | 
					
						
							|  |  |  | 		"$HOME/.swaynag/config", | 
					
						
							|  |  |  | 		"$XDG_CONFIG_HOME/swaynag/config", | 
					
						
							|  |  |  | 		SYSCONFDIR "/swaynag/config", | 
					
						
							|  |  |  | 	}; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-14 09:42:55 +00:00
										 |  |  | 	char *config_home = getenv("XDG_CONFIG_HOME"); | 
					
						
							| 
									
										
										
										
											2019-01-19 08:41:18 +01:00
										 |  |  | 	if (!config_home || config_home[0] == '\0') { | 
					
						
							| 
									
										
										
										
											2019-01-14 09:42:55 +00:00
										 |  |  | 		config_paths[1] = "$HOME/.config/swaynag/config"; | 
					
						
							| 
									
										
										
										
											2018-07-28 22:56:12 -04:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	wordexp_t p; | 
					
						
							|  |  |  | 	for (size_t i = 0; i < sizeof(config_paths) / sizeof(char *); ++i) { | 
					
						
							|  |  |  | 		if (wordexp(config_paths[i], &p, 0) == 0) { | 
					
						
							| 
									
										
										
										
											2019-01-14 09:42:55 +00:00
										 |  |  | 			char *path = strdup(p.we_wordv[0]); | 
					
						
							| 
									
										
										
										
											2018-07-28 22:56:12 -04:00
										 |  |  | 			wordfree(&p); | 
					
						
							|  |  |  | 			if (file_exists(path)) { | 
					
						
							|  |  |  | 				return path; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			free(path); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return NULL; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-28 23:15:12 -04:00
										 |  |  | int swaynag_load_config(char *path, struct swaynag *swaynag, list_t *types) { | 
					
						
							| 
									
										
										
										
											2018-07-28 22:56:12 -04:00
										 |  |  | 	FILE *config = fopen(path, "r"); | 
					
						
							|  |  |  | 	if (!config) { | 
					
						
							|  |  |  | 		fprintf(stderr, "Failed to read config. Running without it.\n"); | 
					
						
							|  |  |  | 		return 0; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2018-07-29 22:42:03 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-19 22:44:11 -04:00
										 |  |  | 	struct swaynag_type *type = swaynag_type_new("<config>"); | 
					
						
							| 
									
										
										
										
											2018-07-29 22:42:03 -04:00
										 |  |  | 	list_add(types, type); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-09 12:09:11 +00:00
										 |  |  | 	char *line = NULL; | 
					
						
							|  |  |  | 	size_t line_size = 0; | 
					
						
							|  |  |  | 	ssize_t nread; | 
					
						
							| 
									
										
										
										
											2018-07-28 22:56:12 -04:00
										 |  |  | 	int line_number = 0; | 
					
						
							| 
									
										
										
										
											2018-12-09 12:09:11 +00:00
										 |  |  | 	int result = 0; | 
					
						
							|  |  |  | 	while ((nread = getline(&line, &line_size, config)) != -1) { | 
					
						
							| 
									
										
										
										
											2018-07-28 22:56:12 -04:00
										 |  |  | 		line_number++; | 
					
						
							| 
									
										
										
										
											2018-12-09 12:09:11 +00:00
										 |  |  | 		if (!*line || line[0] == '\n' || line[0] == '#') { | 
					
						
							| 
									
										
										
										
											2018-07-28 22:56:12 -04:00
										 |  |  | 			continue; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-05 00:31:06 -05:00
										 |  |  | 		if (line[nread - 1] == '\n') { | 
					
						
							|  |  |  | 			line[nread - 1] = '\0'; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-28 22:56:12 -04:00
										 |  |  | 		if (line[0] == '[') { | 
					
						
							|  |  |  | 			char *close = strchr(line, ']'); | 
					
						
							|  |  |  | 			if (!close) { | 
					
						
							|  |  |  | 				fprintf(stderr, "Closing bracket not found on line %d\n", | 
					
						
							|  |  |  | 						line_number); | 
					
						
							| 
									
										
										
										
											2018-12-09 12:09:11 +00:00
										 |  |  | 				result = 1; | 
					
						
							|  |  |  | 				break; | 
					
						
							| 
									
										
										
										
											2018-07-28 22:56:12 -04:00
										 |  |  | 			} | 
					
						
							|  |  |  | 			char *name = calloc(1, close - line); | 
					
						
							|  |  |  | 			strncat(name, line + 1, close - line - 1); | 
					
						
							| 
									
										
										
										
											2018-07-28 23:15:12 -04:00
										 |  |  | 			type = swaynag_type_get(types, name); | 
					
						
							| 
									
										
										
										
											2018-07-28 22:56:12 -04:00
										 |  |  | 			if (!type) { | 
					
						
							| 
									
										
										
										
											2019-04-19 22:44:11 -04:00
										 |  |  | 				type = swaynag_type_new(name); | 
					
						
							| 
									
										
										
										
											2018-07-28 22:56:12 -04:00
										 |  |  | 				list_add(types, type); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			free(name); | 
					
						
							|  |  |  | 		} else { | 
					
						
							| 
									
										
										
										
											2019-01-16 01:57:53 +00:00
										 |  |  | 			char *flag = malloc(sizeof(char) * (nread + 3)); | 
					
						
							| 
									
										
										
										
											2018-07-28 22:56:12 -04:00
										 |  |  | 			sprintf(flag, "--%s", line); | 
					
						
							|  |  |  | 			char *argv[] = {"swaynag", flag}; | 
					
						
							| 
									
										
										
										
											2018-07-29 22:42:03 -04:00
										 |  |  | 			result = swaynag_parse_options(2, argv, swaynag, types, type, | 
					
						
							|  |  |  | 					NULL, NULL); | 
					
						
							| 
									
										
										
										
											2019-01-16 01:57:53 +00:00
										 |  |  | 			free(flag); | 
					
						
							| 
									
										
										
										
											2018-07-28 22:56:12 -04:00
										 |  |  | 			if (result != 0) { | 
					
						
							| 
									
										
										
										
											2018-12-09 12:09:11 +00:00
										 |  |  | 				break; | 
					
						
							| 
									
										
										
										
											2018-07-28 22:56:12 -04:00
										 |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2018-12-09 12:09:11 +00:00
										 |  |  | 	free(line); | 
					
						
							| 
									
										
										
										
											2018-07-28 22:56:12 -04:00
										 |  |  | 	fclose(config); | 
					
						
							| 
									
										
										
										
											2018-12-09 12:09:11 +00:00
										 |  |  | 	return result; | 
					
						
							| 
									
										
										
										
											2018-07-28 22:56:12 -04:00
										 |  |  | } |