view 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 source

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