Mercurial > sci
diff scid/theme.c @ 28:4c16bb25e4f1
scid: implement themes in javascript
author | David Demelier <markand@malikania.fr> |
---|---|
date | Thu, 04 Aug 2022 06:09:54 +0200 |
parents | |
children | 695637f1d8a7 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scid/theme.c Thu Aug 04 06:09:54 2022 +0200 @@ -0,0 +1,104 @@ +#include <assert.h> +#include <errno.h> +#include <limits.h> +#include <string.h> + +#include <duktape.h> + +#include "log.h" +#include "theme.h" +#include "util.h" + +struct theme { + char base[PATH_MAX]; + duk_context *ctx; +}; + +static char * +render(struct theme *t, const char *json, const char *function) +{ + char *ret = NULL; + + duk_get_global_string(t->ctx, function); + + if (!duk_is_callable(t->ctx, -1)) { + duk_pop(t->ctx); + return NULL; + } + + duk_push_string(t->ctx, json); + duk_json_decode(t->ctx, -1); + + if (duk_pcall(t->ctx, 1) != 0) { + log_warn("theme: %s", duk_safe_to_string(t->ctx, -1)); + } else if (duk_is_string(t->ctx, -1)) + ret = util_strdup(duk_get_string(t->ctx, -1)); + + duk_pop_n(t->ctx, 1); + + /* + * For convenience, otherwise all callers have to check for non-NULL + * after calling the function. + */ + if (!ret) + ret = util_strdup(""); + + return ret; +} + +const char * +theme_path(struct theme *t, const char *filename) +{ + assert(filename); + + /* Build path to the template file. */ + static _Thread_local char path[PATH_MAX]; + + snprintf(path, sizeof (path), "%s/%s", t->base, filename); + + return path; +} + +struct theme * +theme_open(const char *directory) +{ + assert(directory); + + struct theme *t; + char themefile[PATH_MAX], *data; + + t = util_calloc(1, sizeof (*t)); + t->ctx = duk_create_heap_default(); + util_strlcpy(t->base, directory, sizeof (t->base)); + + /* Open theme.js in the directory. */ + snprintf(themefile, sizeof (themefile), "%s/theme.js", t->base); + + if (!(data = util_read(themefile))) + log_warn("theme: %s: %s", themefile, strerror(errno)); + else { + if (duk_peval_string(t->ctx, data) != 0) + log_warn("theme: %s", duk_safe_to_string(t->ctx, -1)); + + duk_pop(t->ctx); + } + + return t; +} + +char * +theme_render_index(struct theme *t, const char *json) +{ + assert(t); + assert(json); + + return render(t, json, "index"); +} + +void +theme_free(struct theme *t) +{ + assert(t); + + duk_destroy_heap(t->ctx); +}