aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/action.c8
-rw-r--r--src/block.c12
-rw-r--r--src/block.h6
-rw-r--r--src/blocks/date.c2
-rw-r--r--src/blocks/fs.c2
-rw-r--r--src/blocks/ram.c2
-rw-r--r--src/blocks/script.c2
-rw-r--r--src/blocks/slider.c8
-rw-r--r--src/blocks/text.c14
-rw-r--r--src/config.c269
-rw-r--r--src/config.h21
11 files changed, 208 insertions, 138 deletions
diff --git a/src/action.c b/src/action.c
index 81995e6..0ae0c0a 100644
--- a/src/action.c
+++ b/src/action.c
@@ -9,6 +9,7 @@
void action_perform(action_t *action, block_t *block, config_t *config)
{
block_t *target = block;
+ bool warned = false;
for (size_t i = 0; i < action->length; i++) {
const char *key = action->parts[i].key;
@@ -29,19 +30,20 @@ void action_perform(action_t *action, block_t *block, config_t *config)
}
}
}
+ warned = false;
break;
}
case ACTION_SET_PAIR: {
assert(target != NULL);
-
- if (target->scheme->change_fn == NULL) {
+ if (!warned && target->scheme->change_fn == NULL) {
log_warn("Block '%s' does not support changing values", target->label);
+ warned = true;
continue;
}
// Skip "set-"
- block_change(target, key + 4, value);
+ target->scheme->change_fn(target, config, key + 4, value);
break;
}
diff --git a/src/block.c b/src/block.c
index f3283e9..00a0dde 100644
--- a/src/block.c
+++ b/src/block.c
@@ -50,17 +50,11 @@ void block_update(block_t *block)
}
}
-int block_change(block_t *block, const char *key, const char *value)
+config_status_t block_change(block_t *block, const char *key, const char *value)
{
- if (block->scheme->change_fn == NULL) {
- log_value_debug("Ignored block change",
- "s:label", block->label,
- "s:key", key,
- "s:value", value);
- return 0;
- }
- return block->scheme->change_fn(block, key, value);
+
+ return CONFIG_UNKNOWN;
}
void block_free(block_t *block)
diff --git a/src/block.h b/src/block.h
index 73490ad..ca4f4ab 100644
--- a/src/block.h
+++ b/src/block.h
@@ -102,11 +102,11 @@ typedef void (*block_clean_t)(block_t *block);
// Called to validate the block after parsing the config
//
-typedef int (*block_validate_t)(block_t *block);
+typedef int (*block_validate_t)(block_t *block, config_t *config);
// Called to validate changes to a block variable
//
-typedef int (*block_change_t)(block_t *block, const char *key, const char *value);
+typedef config_status_t (*block_change_t)(block_t *block, config_t *config, const char *key, const char *value);
struct block_scheme {
const char *name;
@@ -122,7 +122,7 @@ extern const block_scheme_t *block_schemes[];
void block_update(block_t *block);
-int block_change(block_t *block, const char *key, const char *value);
+config_status_t block_change(block_t *block, const char *key, const char *value);
void block_free(block_t *block);
diff --git a/src/blocks/date.c b/src/blocks/date.c
index 1cb9da9..cd1adce 100644
--- a/src/blocks/date.c
+++ b/src/blocks/date.c
@@ -46,7 +46,7 @@ static void block_date_clean(block_t *block)
free(date->block.text);
}
-static int block_date_validate(block_t *block)
+static int block_date_validate(block_t *block, config_t *config)
{
block_date_t *date = (block_date_t *)block;
int errors = 0;
diff --git a/src/blocks/fs.c b/src/blocks/fs.c
index 688956d..1196c68 100644
--- a/src/blocks/fs.c
+++ b/src/blocks/fs.c
@@ -135,7 +135,7 @@ static void block_fs_clean(block_t *block)
free(fs->block.text);
}
-static int block_fs_validate(block_t *block)
+static int block_fs_validate(block_t *block, config_t *config)
{
block_fs_t *fs = (block_fs_t *)block;
int errors = 0;
diff --git a/src/blocks/ram.c b/src/blocks/ram.c
index 2aae5ac..28af60c 100644
--- a/src/blocks/ram.c
+++ b/src/blocks/ram.c
@@ -143,7 +143,7 @@ static void block_ram_clean(block_t *block)
free(ram->block.text);
}
-static int block_ram_validate(block_t *block)
+static int block_ram_validate(block_t *block, config_t *config)
{
block_ram_t *ram = (block_ram_t *)block;
int errors = 0;
diff --git a/src/blocks/script.c b/src/blocks/script.c
index bcbb1b2..6fa5f6d 100644
--- a/src/blocks/script.c
+++ b/src/blocks/script.c
@@ -58,7 +58,7 @@ static void block_script_clean(block_t *block)
free(script->block.text);
}
-static int block_script_validate(block_t *block)
+static int block_script_validate(block_t *block, config_t *config)
{
block_script_t *script = (block_script_t *)block;
int errors = 0;
diff --git a/src/blocks/slider.c b/src/blocks/slider.c
index 7050faf..f568105 100644
--- a/src/blocks/slider.c
+++ b/src/blocks/slider.c
@@ -216,7 +216,7 @@ static void block_slider_clean(block_t *block)
gradient_free(&slider->knob_line_color);
}
-static int block_slider_validate(block_t *block)
+static int block_slider_validate(block_t *block, config_t *config)
{
block_slider_t *slider = (block_slider_t *)block;
int errors = 0;
@@ -242,6 +242,11 @@ static int block_slider_validate(block_t *block)
return errors;
}
+static config_status_t block_slider_change(block_t *block, config_t *config, const char *key, const char *value)
+{
+ return 0;
+}
+
static config_enum_t knob_shape_enum[] = {
{ "none", KNOB_NONE },
{ "capsule", KNOB_CAPSULE },
@@ -279,4 +284,5 @@ const block_scheme_t block_slider_scheme = {
.init_fn = block_slider_init,
.clean_fn = block_slider_clean,
.validate_fn = block_slider_validate,
+ .change_fn = block_slider_change,
};
diff --git a/src/blocks/text.c b/src/blocks/text.c
index be4c398..bfaefe8 100644
--- a/src/blocks/text.c
+++ b/src/blocks/text.c
@@ -13,7 +13,7 @@ static void block_text_clean(block_t *block)
free(text->text);
}
-static int block_text_validate(block_t *block)
+static int block_text_validate(block_t *block, config_t *config)
{
block_text_t *text = (block_text_t *)block;
int errors = 0;
@@ -26,6 +26,17 @@ static int block_text_validate(block_t *block)
return errors;
}
+static config_status_t block_text_change(block_t *block, config_t *config, const char *key, const char *value)
+{
+
+ // text
+ // text_color
+ // text_align
+ // text_size
+
+ return CONFIG_UNKNOWN;
+}
+
const block_scheme_t block_text_scheme = {
.name = "text",
.entries = NULL,
@@ -33,4 +44,5 @@ const block_scheme_t block_text_scheme = {
.init_fn = block_text_init,
.clean_fn = block_text_clean,
.validate_fn = block_text_validate,
+ .change_fn = block_text_change,
};
diff --git a/src/config.c b/src/config.c
index f76065c..c8f53f9 100644
--- a/src/config.c
+++ b/src/config.c
@@ -14,13 +14,14 @@
#define ANY_INI_IMPLEMENT
#include "any_ini.h"
-typedef enum {
- CONFIG_SUCCESS,
- CONFIG_INVALID,
- CONFIG_UNKNOWN,
-} config_status_t;
+config_enum_t text_align_enum[] = {
+ { "left", ALIGN_LEFT },
+ { "center", ALIGN_CENTER },
+ { "right", ALIGN_RIGHT },
+ { 0 },
+};
-static const config_entry_t bar_entries[] = {
+const config_entry_t bar_entries[] = {
{ "width", CONFIG_UINT, NULL, offsetof(config_t, width) },
{ "height", CONFIG_UINT, NULL, offsetof(config_t, height) },
{ "font", CONFIG_STRING, NULL, offsetof(config_t, font) },
@@ -31,7 +32,7 @@ static const config_entry_t bar_entries[] = {
{ 0 },
};
-static const config_entry_t block_entries[] = {
+const config_entry_t block_entries[] = {
{ "hidden", CONFIG_BOOL, NULL, offsetof(block_t, hidden) },
{ "color", CONFIG_GRADIENT, NULL, offsetof(block_t, bg_color) },
{ "line-color", CONFIG_GRADIENT, NULL, offsetof(block_t, line_color) },
@@ -45,21 +46,14 @@ static const config_entry_t block_entries[] = {
{ 0 },
};
-static const config_entry_t block_group_entries[] = {
+const config_entry_t block_group_entries[] = {
{ "spacing", CONFIG_UINT, NULL, offsetof(block_group_t, spacing) },
{ "blocks", CONFIG_LIST, NULL, offsetof(block_group_t, children) },
{ "collapse", CONFIG_BOOL, NULL, offsetof(block_group_t, collapse) },
{ 0 },
};
-static config_enum_t text_align_enum[] = {
- { "left", ALIGN_LEFT },
- { "center", ALIGN_CENTER },
- { "right", ALIGN_RIGHT },
- { 0 },
-};
-
-static const config_entry_t block_text_entries[] = {
+const config_entry_t block_text_entries[] = {
{ "text", CONFIG_STRING, NULL, offsetof(block_text_t, text) },
{ "text-color", CONFIG_COLOR, NULL, offsetof(block_text_t, text_color) },
{ "text-size", CONFIG_UINT, NULL, offsetof(block_text_t, text_size) },
@@ -67,6 +61,25 @@ static const config_entry_t block_text_entries[] = {
{ 0 },
};
+const char *config_type_to_string(config_type_t type)
+{
+ static const char *types[] = {
+ "string",
+ "integer",
+ "unsigned integer",
+ "double float",
+ "boolean",
+ "color",
+ "gradient",
+ "enum",
+ "time",
+ "list",
+ };
+
+ assert(type >= CONFIG_STRING && type <= CONFIG_LIST);
+ return types[type];
+}
+
static bool config_read_string(const char *value, char **result)
{
if (value == NULL)
@@ -290,29 +303,98 @@ static bool config_read_list(const char *value, char ***result)
return true;
}
-static config_status_t config_read_entry(const config_entry_t *entries, void *result, const char **type,
- const char *section, const char *key, const char *value)
+static config_status_t config_read_block(const block_scheme_t *scheme, block_t *block, const char **type,
+ const char *key, const char *value)
{
- static const char *types[] = {
- "string",
- "integer",
- "unsigned integer",
- "double float",
- "boolean",
- "color",
- "gradient",
- "enum",
- "time",
- "list",
+ const char *section = "block";
+ size_t index = 0;
+
+ config_status_t status = config_read_entry(block_entries, block, &index, section, block->label, key, value);
+ *type = config_type_to_string(block_entries[index].type);
+
+ if (status != CONFIG_UNKNOWN) return status;
+
+ if (block->type == BLOCK_GROUP)
+ status = config_read_entry(block_group_entries, block, &index, section, block->label, key, value);
+ else if (block->type == BLOCK_TEXT)
+ status = config_read_entry(block_text_entries, block, &index, section, block->label, key, value);
+
+ *type = config_type_to_string(block_entries[index].type);
+ if (status != CONFIG_UNKNOWN || scheme->entries == NULL)
+ return status;
+
+ status = config_read_entry(scheme->entries, block, &index, section, block->label, key, value);
+ *type = config_type_to_string(block_entries[index].type);
+ return status;
+}
+
+static block_t *config_alloc_block(config_t *config, const block_scheme_t *scheme, char *label)
+{
+ config->blocks = realloc(config->blocks, ++config->n_blocks * sizeof(block_t *));
+ assert(config->blocks != NULL);
+
+ block_t *block = config->blocks[config->n_blocks - 1] = calloc(1, scheme->size);
+ assert(block != NULL);
+
+ block->label = label;
+ block->scheme = scheme;
+ scheme->init_fn(block);
+
+ return block;
+}
+
+static config_status_t config_read_action(action_t *action, const char *key, const char *value)
+{
+ action_type_t type;
+
+ if (!strcmp(key, "target"))
+ type = ACTION_TARGET;
+ else if (!strncmp(key, "set-", 4))
+ type = ACTION_SET_PAIR;
+ else if (!strcmp(key, "run-script"))
+ type = ACTION_RUN_SCRIPT;
+ else
+ return CONFIG_UNKNOWN;
+
+ action->parts = realloc(action->parts, ++action->length * sizeof(action_part_t));
+ assert(action->parts != NULL);
+
+ action->parts[action->length - 1].type = type;
+ action->parts[action->length - 1].key = strcopy(key);
+ action->parts[action->length - 1].value = strcopy(value);
+
+ return CONFIG_SUCCESS;
+}
+
+// TODO: More robust way to define defaults
+void config_init(config_t *config)
+{
+ const config_t config_default = {
+ .font = "monospace 10",
+ .monitor = NULL,
+ .width = 100,
+ .height = 50,
+ .override_redirect = false,
};
+ memcpy(config, &config_default, sizeof(config_t));
+ config->font = strcopy(config_default.font);
+
+ extern const block_scheme_t block_group_scheme;
+ block_group_t *bar = (block_group_t *)config_alloc_block(config, &block_group_scheme, strcopy("bar"));
+ bar->spacing = 10;
+}
+
+config_status_t config_read_entry(const config_entry_t *entries, void *result, size_t *index,
+ const char *section, const char *label, const char *key, const char *value)
+{
for (size_t i = 0; entries[i].key != NULL; i++) {
if (!strcmp(key, entries[i].key)) {
- if (type != NULL)
- *type = types[entries[i].type];
+ if (index != NULL) *index = i;
result += entries[i].offset;
- bool nullable = type == CONFIG_STRING;
+ bool nullable = entries[i].type == CONFIG_STRING || entries[i].type == CONFIG_LIST;
+
if ((value == NULL || *value == '\0') && !nullable)
return CONFIG_INVALID;
@@ -320,35 +402,45 @@ static config_status_t config_read_entry(const config_entry_t *entries, void *re
case CONFIG_STRING:
// NOTE: The previous string is freed by config_read_string
if (config_read_string(value, (char **)result)) {
- log_debug("Set '%s.%s' to '%s'", section, key, *(char **)result);
+ log_debug("Set '%s%s%s.%s' to '%s'",
+ section != NULL ? section : "", section != NULL ? "." : "",
+ label, key, *(char **)result);
return CONFIG_SUCCESS;
}
break;
case CONFIG_INT:
if (config_read_int(value, (int *)result)) {
- log_debug("Set '%s.%s' to '%d'", section, key, *(int *)result);
+ log_debug("Set '%s%s%s.%s' to '%d'",
+ section != NULL ? section : "", section != NULL ? "." : "",
+ label, key, *(int *)result);
return CONFIG_SUCCESS;
}
break;
case CONFIG_UINT:
if (config_read_uint(value, (unsigned int *)result)) {
- log_debug("Set '%s.%s' to '%u'", section, key, *(unsigned int *)result);
+ log_debug("Set '%s%s%s.%s' to '%u'",
+ section != NULL ? section : "", section != NULL ? "." : "",
+ label, key, *(unsigned int *)result);
return CONFIG_SUCCESS;
}
break;
case CONFIG_DOUBLE:
if (config_read_double(value, (double *)result)) {
- log_debug("Set '%s.%s' to '%lf'", section, key, *(double *)result);
+ log_debug("Set '%s%s%s.%s' to '%g'",
+ section != NULL ? section : "", section != NULL ? "." : "",
+ label, key, *(double *)result);
return CONFIG_SUCCESS;
}
break;
case CONFIG_BOOL:
if (config_read_bool(value, (bool *)result)) {
- log_debug("Set '%s.%s' to '%s'", section, key, *(bool *)result ? "true" : "false");
+ log_debug("Set '%s%s%s.%s' to '%s'",
+ section != NULL ? section : "", section != NULL ? "." : "",
+ label, key, *(bool *)result ? "true" : "false");
return CONFIG_SUCCESS;
}
break;
@@ -356,7 +448,9 @@ static config_status_t config_read_entry(const config_entry_t *entries, void *re
case CONFIG_COLOR:
if (config_read_color(value, (color_t *)result)) {
char *color = color_to_string((color_t *)result);
- log_debug("Set '%s.%s' to '%s'", section, key, color);
+ log_debug("Set '%s%s%s.%s' to '%s'",
+ section != NULL ? section : "", section != NULL ? "." : "",
+ label, key, color);
free(color);
return CONFIG_SUCCESS;
}
@@ -365,7 +459,9 @@ static config_status_t config_read_entry(const config_entry_t *entries, void *re
case CONFIG_GRADIENT:
if (config_read_gradient(value, (gradient_t *)result)) {
char *gradient = gradient_to_string((gradient_t *)result);
- log_debug("Set '%s.%s' to '%s'", section, key, gradient);
+ log_debug("Set '%s%s%s.%s' to '%s'",
+ section != NULL ? section : "", section != NULL ? "." : "",
+ label, key, gradient);
free(gradient);
return CONFIG_SUCCESS;
}
@@ -373,21 +469,28 @@ static config_status_t config_read_entry(const config_entry_t *entries, void *re
case CONFIG_ENUM:
if (config_read_enum(value, (config_enum_t *)entries[i].data, (int *)result)) {
- log_debug("Set '%s.%s' to '%d'", section, key, *(int *)result);
+ log_debug("Set '%s%s%s.%s' to '%d'",
+ section != NULL ? section : "", section != NULL ? "." : "",
+ label, key, *(int *)result);
return CONFIG_SUCCESS;
}
break;
case CONFIG_TIME:
if (config_read_time(value, (struct timespec *)result)) {
- log_debug("Set '%s.%s' to '%s'", section, key, value);
+ // TODO: Print
+ log_debug("Set '%s%s%s.%s' to '%s'",
+ section != NULL ? section : "", section != NULL ? "." : "",
+ label, key, value);
return CONFIG_SUCCESS;
}
break;
case CONFIG_LIST:
if (config_read_list(value, (char ***)result)) {
- log_debug("Set '%s.%s' to '%s'", section, key, value);
+ log_debug("Set '%s%s%s.%s' to '%s'",
+ section != NULL ? section : "", section != NULL ? "." : "",
+ label, key, value);
return CONFIG_SUCCESS;
}
break;
@@ -403,77 +506,6 @@ static config_status_t config_read_entry(const config_entry_t *entries, void *re
return CONFIG_UNKNOWN;
}
-static config_status_t config_read_block(const block_scheme_t *scheme, block_t *block, const char **type,
- const char *section, const char *key, const char *value)
-{
- config_status_t status = config_read_entry(block_entries, block, type, section, key, value);
- if (status != CONFIG_UNKNOWN) return status;
-
- status = config_read_entry(block->type == BLOCK_GROUP ? block_group_entries : block_text_entries,
- block, type, section, key, value);
-
- return status != CONFIG_UNKNOWN || scheme == NULL || scheme->entries == NULL
- ? status
- : config_read_entry(scheme->entries, block, type, section, key, value);
-}
-
-static block_t *config_alloc_block(config_t *config, const block_scheme_t *scheme, char *label)
-{
- config->blocks = realloc(config->blocks, ++config->n_blocks * sizeof(block_t *));
- assert(config->blocks != NULL);
-
- block_t *block = config->blocks[config->n_blocks - 1] = calloc(1, scheme->size);
- assert(block != NULL);
-
- block->label = label;
- block->scheme = scheme;
- scheme->init_fn(block);
-
- return block;
-}
-
-static config_status_t config_read_action(action_t *action, const char *section, const char *key, const char *value)
-{
- action_type_t type;
-
- if (!strcmp(key, "target"))
- type = ACTION_TARGET;
- else if (!strncmp(key, "set-", 4))
- type = ACTION_SET_PAIR;
- else if (!strcmp(key, "run-script"))
- type = ACTION_RUN_SCRIPT;
- else
- return CONFIG_UNKNOWN;
-
- action->parts = realloc(action->parts, ++action->length * sizeof(action_part_t));
- assert(action->parts != NULL);
-
- action->parts[action->length - 1].type = type;
- action->parts[action->length - 1].key = strcopy(key);
- action->parts[action->length - 1].value = strcopy(value);
-
- return CONFIG_SUCCESS;
-}
-
-// TODO: More robust way to define defaults
-void config_init(config_t *config)
-{
- const config_t config_default = {
- .font = "monospace 10",
- .monitor = NULL,
- .width = 100,
- .height = 50,
- .override_redirect = false,
- };
-
- memcpy(config, &config_default, sizeof(config_t));
- config->font = strcopy(config_default.font);
-
- extern const block_scheme_t block_group_scheme;
- block_group_t *bar = (block_group_t *)config_alloc_block(config, &block_group_scheme, strcopy("bar"));
- bar->spacing = 10;
-}
-
int config_read(config_t *config, FILE *file)
{
any_ini_stream_t ini;
@@ -601,19 +633,22 @@ int config_read(config_t *config, FILE *file)
config_status_t status;
if (bar_section) {
- status = config_read_entry(bar_entries, config, &type, section, key, value);
+ size_t index = 0;
+ status = config_read_entry(bar_entries, config, &index, NULL, "bar", key, value);
// Try the block entries
if (status == CONFIG_UNKNOWN)
block = config->blocks[0];
+ else
+ type = config_type_to_string(bar_entries[index].type);
}
if (block != NULL) {
- status = config_read_block(scheme, block, &type, section, key, value);
+ status = config_read_block(scheme, block, &type, key, value);
}
if (action != NULL) {
- status = config_read_action(action, section, key, value);
+ status = config_read_action(action, key, value);
}
switch (status) {
@@ -672,7 +707,7 @@ int config_validate(config_t *config)
if (scheme->validate_fn == NULL) continue;
log_debug("Validating 'block.%s'", block->label);
- int tmp = scheme->validate_fn(block);
+ int tmp = scheme->validate_fn(block, config);
errors += tmp;
block->validated = tmp == 0;
}
diff --git a/src/config.h b/src/config.h
index e005dff..e56de55 100644
--- a/src/config.h
+++ b/src/config.h
@@ -30,6 +30,12 @@ typedef struct {
size_t offset;
} config_entry_t;
+typedef enum {
+ CONFIG_SUCCESS,
+ CONFIG_INVALID,
+ CONFIG_UNKNOWN,
+} config_status_t;
+
typedef struct {
size_t n_blocks;
block_t **blocks;
@@ -49,8 +55,23 @@ typedef struct {
int value;
} config_enum_t;
+extern config_enum_t text_align_enum[];
+
+extern const config_entry_t bar_entries[];
+
+extern const config_entry_t block_entries[];
+
+extern const config_entry_t block_group_entries[];
+
+extern const config_entry_t block_text_entries[];
+
+const char *config_type_to_string(config_type_t type);
+
void config_init(config_t *config);
+config_status_t config_read_entry(const config_entry_t *entries, void *result, size_t *index,
+ const char *section, const char *label, const char *key, const char *value);
+
int config_read(config_t *config, FILE *file);
int config_validate(config_t *config);