25static int cmdline_argc;
26static char **cmdline_argv;
27static char *usage_str = NULL;
29#define STRING_PARSE_RET(string, value) if (STR_EQ(s, string)) { *ret = value; return true; }
31int string_parse_enum(
const void *data,
const char *s,
void * ret) {
33 for (
int i = 0; string_to_enum[i].string != NULL; i++) {
34 if (strcmp(s, string_to_enum[i].
string) == 0) {
35 *(
int*) ret = string_to_enum[i].enum_value;
36 LOG_D(
"Setting enum to %i (%s)", *(
int*) ret, string_to_enum[i].
string);
46int string_parse_enum_list(
const void *data,
char **s,
void *ret_void)
48 int **ret = (
int **) ret_void;
55 tmp = g_malloc_n((len + 1),
sizeof(
int));
56 for (
int i = 0; i < len; i++) {
57 if (!string_parse_enum(data, s[i], tmp + i)) {
58 LOG_W(
"Unknown mouse action value: '%s'", s[i]);
63 tmp[len] = MOUSE_ACTION_END;
80 int tmp = 0, tmp_ret = 0;
85 for (
int i = 0; i < len; i++) {
86 if (!string_parse_enum(data, s[i], &tmp)) {
87 LOG_W(
"Unknown value: '%s'", s[i]);
96int string_parse_corners(
const void *data,
const char *s,
void *ret)
113 int *tmp = g_malloc_n((len + 1),
sizeof(
int));
114 for (
int i = 0; i < len; i++) {
121 LOG_W(
"Invalid int value: '%s'", s[i]);
138 const enum list_type type = GPOINTER_TO_INT(data);
144 success = string_parse_enum_list(&mouse_action_enum_data, arr, ret);
159 offset->x = int_arr[0];
160 offset->y = int_arr[1];
164 g_strfreev(*(
char ***) ret);
170 LOG_W(
"Don't know this list type: %i", type);
177int string_parse_sepcolor(
const void *data,
const char *s,
void *ret)
179 LOG_D(
"parsing sep_color");
181 struct color invalid = COLOR_UNINIT;
183 enum separator_color type;
184 bool is_enum = string_parse_enum(data, s, &type);
186 sep_color->type = type;
187 sep_color->color = invalid;
191 LOG_W(
"Sep color is empty, make sure to quote the value if it's a color.");
196 sep_color->type = SEP_CUSTOM;
203#define UINT_MAX_N(bits) ((1 << bits) - 1)
212 LOG_W(
"A color string should start with '#' and contain at least 3 hex characters");
217 unsigned long val = strtoul(s + 1, &end, 16);
219 if (end[0] !=
'\0' && end[1] !=
'\0') {
220 LOG_W(
"Invalid color string: '%s'", s);
225 switch (end - (s + 1)) {
228 val = (val << 4) | 0xF;
232 val = (val << 8) | 0xFF;
241 LOG_W(
"Invalid color string: '%s'", s);
245 const unsigned single_max = UINT_MAX_N(bpc);
247 ret->r = ((val >> 3 * bpc) & single_max) / (
double)single_max;
248 ret->g = ((val >> 2 * bpc) & single_max) / (
double)single_max;
249 ret->b = ((val >> 1 * bpc) & single_max) / (
double)single_max;
250 ret->a = ((val) & single_max) / (
double)single_max;
255int string_parse_gradient(
const char *s,
struct gradient **ret)
257 struct color colors[16];
260 gchar **strs = g_strsplit(s,
",", -1);
261 for (
int i = 0; strs[i] != NULL; i++) {
263 LOG_W(
"Do you really need so many colors? ;)");
275 LOG_W(
"Provide at least one color");
279 *ret = gradient_alloc(
length);
280 memcpy((*ret)->colors, colors,
length *
sizeof(
struct color));
281 gradient_pattern(*ret);
286int string_parse_bool(
const void *data,
const char *s,
void *ret)
291 bool success = string_parse_enum(data, s, &tmp_int);
293 *(
bool*) ret = (
bool) tmp_int;
300 int *intval = (
int *)data;
305 g_free(*(
char**) ret);
306 *(
char**) ret = g_strdup(s);
310int get_setting_id(
const char *key,
const char *
section) {
312 int partial_match_id = -1;
314 if (!match_section) {
315 LOG_D(
"not matching section %s",
section);
317 for (
size_t i = 0; i < G_N_ELEMENTS(allowed_settings); i++) {
318 if (strcmp(allowed_settings[i].name, key) == 0) {
319 bool is_rule = allowed_settings[i].rule_offset > 0;
322 if (is_rule || strcmp(
section, allowed_settings[i].
section) == 0) {
328 partial_match_id = i;
334 if (error_code == -2) {
335 LOG_W(
"Setting %s is in the wrong section (%s, should be %s)",
337 allowed_settings[partial_match_id].
section);
358 LOG_W(
"Specify either a single value or two comma-separated values between parentheses");
373 LOG_W(
"Specify either a single value or two comma-separated values between parentheses");
384 ret->min = int_arr[0] == -1 ? INT_MIN : int_arr[0];
385 ret->max = int_arr[1] == -1 ? INT_MAX : int_arr[1];
391bool set_from_string(
void *target,
struct setting setting,
const char *value) {
392 GError *error = NULL;
394 if (!strlen(value) &&
setting.
type != TYPE_STRING) {
395 LOG_W(
"Cannot set empty value for setting %s",
setting.
name);
399 bool success =
false;
408 g_free(*(
char**) target);
409 *(
char**) target = g_strdup(value);
413 LOG_W(
"Setting %s doesn't have parser",
setting.
name);
418 if (!success) LOG_W(
"Invalid %s value: '%s'",
setting.
name, value);
421 g_free(*(
char**) target);
430 if (!g_shell_parse_argv(*(
char**) target, NULL, (
char***)
setting.
parser_data, &error)) {
431 LOG_W(
"Unable to parse %s command: '%s'. "
432 "It's functionality will be disabled.",
443 *(gint64*) target = tmp_time;
451 LOG_M(
"Using legacy offset syntax NxN, you should switch to the new syntax (N, N)");
457 LOG_M(
"Setting 'height' has changed behaviour after dunst 1.12.0, see https://dunst-project.org/release/#v1.12.0.");
458 LOG_M(
"Legacy height support may be dropped in the future. If you want to hide this message transition to");
459 LOG_M(
"'height = (0, X)' for dynamic height (old behaviour equivalent) or to 'height = (X, X)' for a fixed height.");
465 ((
struct length *)target)->min = 0;
466 ((
struct length *)target)->max = height;
473 return string_parse_gradient(value, target);
495 return set_from_string(target,
setting, value);
502 LOG_D(
"Creating new rule '%s'",
section);
504 return set_rule_value(r,
setting, value);
507void set_defaults(
void) {
508 LOG_D(
"Initializing settings");
511 for (
size_t i = 0; i < G_N_ELEMENTS(allowed_settings); i++) {
516 if (!allowed_settings[i].value)
519 if(!set_setting(allowed_settings[i], allowed_settings[i].default_value)) {
520 LOG_E(
"Could not set default of setting %s", allowed_settings[i].name);
525void save_settings(
struct ini *
ini) {
526 for (
int i = 0; i <
ini->section_count; i++) {
527 const struct section curr_section =
ini->sections[i];
530 LOG_W(
"Section %s is deprecated.\n%s\nIgnoring this section.",
532 get_section_deprecation_message(curr_section.name));
536 LOG_D(
"Entering section [%s]", curr_section.name);
537 for (
int j = 0; j < curr_section.entry_count; j++) {
538 const struct entry curr_entry = curr_section.entries[j];
539 int setting_id = get_setting_id(curr_entry.key, curr_section.name);
540 struct setting curr_setting = allowed_settings[setting_id];
541 if (setting_id < 0) {
542 if (setting_id == -1) {
543 LOG_W(
"Setting %s in section %s doesn't exist", curr_entry.key, curr_section.name);
553 LOG_D(
"Adding rule '%s = %s' to special section %s",
557 set_rule(curr_setting, curr_entry.value, curr_section.name);
559 LOG_W(
"Cannot use filtering rules in special section. Ignoring %s in section %s.",
565 char *
value = g_strstrip(curr_entry.value);
566 set_setting(curr_setting,
value);
570 LOG_D(
"Adding rule '%s = %s' to section %s",
574 set_rule(curr_setting, curr_entry.value, curr_section.name);
580void cmdline_load(
int argc,
char *argv[])
586static int cmdline_find_option(
const char *key,
int start)
590 gchar **keys = g_strsplit(key,
"/", -1);
592 for (
int i = 0; keys[i] != NULL; i++) {
593 for (
int j = start; j < cmdline_argc; j++) {
594 if (
STR_EQ(keys[i], cmdline_argv[j])) {
605static const char *cmdline_get_value(
const char *key,
int start,
int *found)
607 int idx = cmdline_find_option(key, start);
615 if (idx + 1 >= cmdline_argc) {
617 LOG_W(
"%s: Missing argument. Ignoring.", key);
620 return cmdline_argv[idx + 1];
623char *cmdline_get_string_offset(
const char *key,
const char *def,
int start,
int *found)
625 const char *str = cmdline_get_value(key, start, found);
628 return g_strdup(str);
630 return g_strdup(def);
635char *cmdline_get_string(
const char *key,
const char *def,
const char *
description)
638 return cmdline_get_string_offset(key, def, 1, NULL);
641char *cmdline_get_path(
const char *key,
const char *def,
const char *
description)
644 const char *str = cmdline_get_value(key, 1, NULL);
652char **cmdline_get_list(
const char *key,
const char *def,
const char *
description)
655 const char *str = cmdline_get_value(key, 1, NULL);
663gint64 cmdline_get_time(
const char *key, gint64 def,
const char *
description)
666 const char *timestring = cmdline_get_value(key, 1, NULL);
676int cmdline_get_int(
const char *key,
int def,
const char *
description)
679 const char *str = cmdline_get_value(key, 1, NULL);
687double cmdline_get_double(
const char *key,
double def,
const char *
description)
690 const char *str = cmdline_get_value(key, 1, NULL);
698int cmdline_get_bool(
const char *key,
int def,
const char *
description)
701 int idx = cmdline_find_option(key, 1);
709bool cmdline_is_set(
const char *key)
711 return cmdline_get_value(key, 1, NULL) != NULL;
714void cmdline_usage_append(
const char *key,
const char *
type,
const char *
description)
718 key_type = g_strdup_printf(
"%s (%s)", key,
type);
720 key_type = g_strdup(key);
724 g_strdup_printf(
"%-50s - %s\n", key_type,
description);
730 tmp = g_strdup_printf(
"%s%-50s - %s\n", usage_str, key_type,
description);
738const char *cmdline_create_usage(
void)
Logging subsystem and helpers.
#define LOG_E
Prefix message with "[<source path>:<function name>:<line number>] ".
bool string_parse_int_list(char **s, int **ret, bool allow_empty)
Parse a list of integers.
int string_parse_length(void *ret_in, const char *s)
int string_parse_color(const char *s, struct color *ret)
Parse a color string.
int string_parse_enum_list_to_single(const void *data, char **s, int *ret)
Parse a string list of enum values and return a single integer with the values bit-flipped into it.
int string_parse_list(const void *data, const char *s, void *ret)
int string_parse_maybe_int(const void *data, const char *s, void *ret)
Parse a string that may represent an integer value.
Parser for settings and cmdline arguments.
struct rule * get_rule(const char *name)
Check if a rule exists with that name.
struct rule * rule_new(const char *name)
Allocate a new rule with given name.
bool rule_offset_is_modifying(const size_t offset)
see rules.h
Rules managment and helpers.
Type definitions for settings.
List of all the valid settings and values.
void * value
(nullable) A pointer to the corresponding setting in the setting struct.
char * section
A string with the ini section where the variable is allowed.
char * name
A string with the setting key as found in the config file.
enum setting_type type
Enum of the setting type.
const void * parser_data
(nullable) A pointer to the data required for the parser to parse this setting.
size_t rule_offset
The offset of this setting in the rule struct, if it exists.
char * description
A string with a short description of the config variable.
int(* parser)(const void *data, const char *cfg_value, void *ret)
(nullable) Function pointer for the parser - to be used in case of enums or other special settings.
bool string_is_int(const char *str)
Check if string contains digits.
int string_array_length(char **s)
Returns the length of a string array, -1 if the input is NULL.
char * string_strip_brackets(const char *s)
Strips a string of it's brackets if the first and last character are a bracket.
bool safe_string_to_double(double *in, const char *str)
Same as safe_string_to_int, but then for a double.
bool safe_string_to_int(int *in, const char *str)
Convert string to int in a safe way.
char * string_to_path(char *string)
Replace tilde and path-specific values with it's equivalents.
bool is_deprecated_section(const char *s)
This function tells if a section is deprecated.
bool is_special_section(const char *s)
Some sections are handled differently in dunst.
char ** string_to_array(const char *string, const char *delimiter)
Parse a string into a dynamic array of tokens, using the delimiter string.
gint64 string_to_time(const char *string)
Convert time units (ms, s, m) to the internal gint64 microseconds format.
String, time and other various helpers.
#define STR_EMPTY(s)
Test if a string is NULL or empty.
#define STR_EQ(a, b)
Test if string a and b contain the same chars.
#define STR_FULL(s)
Test if a string is non-NULL and not empty.
#define ASSERT_OR_RET(expr, val)
Assert that expr evaluates to true, if not return val.