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);
+}