diff scid/theme.c @ 30:43333d18e4b8

scid: document theme
author David Demelier <markand@malikania.fr>
date Thu, 04 Aug 2022 14:54:43 +0200
parents 695637f1d8a7
children 081e1c258e64
line wrap: on
line diff
--- a/scid/theme.c	Thu Aug 04 14:13:58 2022 +0200
+++ b/scid/theme.c	Thu Aug 04 14:54:43 2022 +0200
@@ -1,3 +1,21 @@
+/*
+ * theme.c -- theme management
+ *
+ * Copyright (c) 2021 David Demelier <markand@malikania.fr>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
 #include <assert.h>
 #include <errno.h>
 #include <limits.h>
@@ -14,10 +32,9 @@
 
 #define SIGNATURE DUK_HIDDEN_SYMBOL("File")
 
-struct theme {
-	char base[PATH_MAX];
+static struct {
 	duk_context *ctx;
-};
+} theme;
 
 /* {{{ mustache support */
 
@@ -198,7 +215,7 @@
 	};
 	MUSTACHE_TEMPLATE *tmpl;
 	int status;
-	
+
 	if (!(tmpl = mustache_compile(input, strlen(input), &parser, (void *)path, 0)))
 		return -1;
 
@@ -241,7 +258,7 @@
 	if (json && !(doc = json_loads(json, 0, &err)))
 		return duk_error(ctx, DUK_ERR_ERROR, "%d:%d:%s", err.line, err.column, err.text);
 
-	mch_templatize(fp, theme_path(scid.theme, path), doc);
+	mch_templatize(fp, theme_path(path), doc);
 
 	if (doc)
 		json_decref(doc);
@@ -266,118 +283,99 @@
 /* }}} */
 
 static char *
-call(struct theme *t, json_t *json, const char *function)
+call(const json_t *json, const char *function)
 {
-	char *out = NULL, *dump = NULL;
+	char *out = NULL, *dump;
 	size_t outsz = 0;
-	FILE *fp = NULL;
-	int nargs = 1;
+	FILE *fp;
 
-	duk_get_global_string(t->ctx, function);
+	duk_get_global_string(theme.ctx, function);
 
-	if (!duk_is_callable(t->ctx, -1))
-		goto over;
-	if (!(fp = open_memstream(&out, &outsz)))
-		goto over;
-
-	duk_push_pointer(t->ctx, fp);
+	if (duk_is_callable(theme.ctx, -1)) {
+		fp   = util_open_memstream(&out, &outsz);
+		dump = util_json_dump(json);
 
-	if (json && (dump = json_dumps(json, JSON_COMPACT))) {
-		duk_push_string(t->ctx, dump);
-		duk_json_decode(t->ctx, -1);
-		nargs++;
-	}
+		duk_push_pointer(theme.ctx, fp);
+		duk_push_string(theme.ctx, dump);
+		duk_json_decode(theme.ctx, -1);
 
-	if (duk_pcall(t->ctx, nargs) != 0)
-		log_warn("theme: %s", duk_safe_to_string(t->ctx, -1));
+		if (duk_pcall(theme.ctx, 2) != 0)
+			log_warn("theme: %s", duk_safe_to_string(theme.ctx, -1));
 
-over:
-	duk_pop(t->ctx);
+		duk_pop(theme.ctx);
+		fclose(fp);
+		free(dump);
+	} else
+		duk_pop(theme.ctx);
 
-	/*
-	 * For convenience, otherwise all callers have to check for non-NULL
-	 * after calling the function.
-	 */
-	free(dump);
-
-	if (fp)
-		fclose(fp);
 	if (!out)
 		out = util_strdup("");
 
 	return out;
 }
 
+void
+theme_open(const char *directory)
+{
+	assert(directory);
+
+	const char *path;
+	char *data;
+
+	theme.ctx = duk_create_heap_default();
+	path = theme_path("theme.js");
+
+	if (!(data = util_read(path)))
+		log_warn("theme: %s: %s", path, strerror(errno));
+	else {
+		if (duk_peval_string(theme.ctx, data) != 0)
+			log_warn("theme: %s", duk_safe_to_string(theme.ctx, -1));
+
+		duk_pop(theme.ctx);
+		duk_push_object(theme.ctx);
+		duk_put_function_list(theme.ctx, -1, functions);
+		duk_put_global_string(theme.ctx, "Scid");
+		free(data);
+	}
+}
+
 const char *
-theme_path(struct theme *t, const char *filename)
+theme_path(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);
+	snprintf(path, sizeof (path), "%s/%s", scid.themedir, filename);
 
 	return path;
 }
 
-struct theme *
-theme_open(const char *directory)
+char *
+theme_page_index(const json_t *json)
 {
-	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);
+	assert(json);
 
-	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);
-		duk_push_object(t->ctx);
-		duk_put_function_list(t->ctx, -1, functions);
-		duk_put_global_string(t->ctx, "Scid");
-		free(data);
-	}
-
-	return t;
+	return call(json, "onPageIndex");
 }
 
 char *
-theme_page_index(struct theme *t, json_t *json)
-{
-	assert(t);
-
-	return call(t, json, "onPageIndex");
-}
-
-char *
-theme_page_status(struct theme *t, enum khttp status)
+theme_page_status(enum khttp status)
 {
-	assert(t);
-
-	(void)t;
-	(void)status;
+	json_t *doc;
+	char *ret;
 
-#if 0
-	return call(t, json, "onPageStatus");
-#endif
-	return "ERROR";
+	doc = util_json_pack("{si}", "status", status);
+	ret = call(doc, "onPageStatus");
+
+	json_decref(doc);
+
+	return ret;
 }
 
 void
-theme_free(struct theme *t)
+theme_free(void)
 {
-	assert(t);
-
-	duk_destroy_heap(t->ctx);
+	duk_destroy_heap(theme.ctx);
 }