[gegl] tools: add missing file operations_html.c
- From: Øyvind Kolås <ok src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gegl] tools: add missing file operations_html.c
- Date: Tue, 2 May 2017 21:41:29 +0000 (UTC)
commit fd1c66268e4d3c58761b27d5e851b54d0878bd53
Author: Øyvind Kolås <pippin gimp org>
Date: Tue May 2 23:41:02 2017 +0200
tools: add missing file operations_html.c
tools/operations_html.c | 703 +++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 703 insertions(+), 0 deletions(-)
---
diff --git a/tools/operations_html.c b/tools/operations_html.c
new file mode 100644
index 0000000..13f1084
--- /dev/null
+++ b/tools/operations_html.c
@@ -0,0 +1,703 @@
+#include "config.h"
+#include <gegl-plugin.h>
+
+static GList *
+gegl_operations_build (GList *list, GType type)
+{
+ GeglOperationClass *klass;
+ GType *ops;
+ guint children;
+ gint no;
+
+ if (!type)
+ return list;
+
+ klass = g_type_class_ref (type);
+ if (klass->name != NULL)
+ list = g_list_prepend (list, klass);
+
+ ops = g_type_children (type, &children);
+
+ for (no=0; no<children; no++)
+ {
+ list = gegl_operations_build (list, ops[no]);
+ }
+ if (ops)
+ g_free (ops);
+ return list;
+}
+
+static gint compare_operation_names (gconstpointer a,
+ gconstpointer b)
+{
+ const GeglOperationClass *klassA, *klassB;
+
+ klassA = a;
+ klassB = b;
+
+ return strcmp (klassA->name, klassB->name);
+}
+
+static GList *gegl_operations (void)
+{
+ static GList *operations = NULL;
+ if (!operations)
+ {
+ operations = gegl_operations_build (NULL, GEGL_TYPE_OPERATION);
+ operations = g_list_sort (operations, compare_operation_names);
+ }
+ return operations;
+}
+
+GeglColor *
+gegl_param_spec_color_get_default (GParamSpec *self);
+
+/* convert operation name to path of example image */
+static gchar*
+operation_to_image_path (const gchar *op_name)
+{
+ gchar *cleaned = g_strdup (op_name);
+ gchar *filename, *output_path;
+
+ g_strdelimit (cleaned, ":", '-');
+ filename = g_strconcat (cleaned, ".png", NULL);
+ output_path = g_build_path (G_DIR_SEPARATOR_S, "images", filename, NULL);
+
+ g_free (cleaned);
+ g_free (filename);
+
+ return output_path;
+}
+
+static void json_escape_string (GString *s, const char *description)
+{
+ const char *p;
+ if (!description)
+ return;
+ for (p = description; *p; p++)
+ {
+ switch (*p)
+ {
+ case '"':
+ case '\\':
+ case '/':
+ g_string_append_printf (s, "\\%c", *p);
+ break;
+ case '\n':
+ g_string_append_printf (s, "\\n");
+ break;
+ default:
+ g_string_append_printf (s, "%c", *p);
+ }
+ }
+}
+
+
+static void xml_escape_string (GString *s, const char *description)
+{
+ const char *p;
+ if (!description)
+ return;
+ for (p = description; *p; p++)
+ {
+ switch (*p)
+ {
+ case '<':
+ g_string_append_printf (s, "<");
+ break;
+ case '>':
+ g_string_append_printf (s, ">");
+ break;
+ case '&':
+ g_string_append_printf (s, "&");
+ break;
+ default:
+ g_string_append_printf (s, "%c", *p);
+ }
+ }
+}
+
+static void
+json_list_pads (GType type, GString *s, const gchar *opname)
+{
+ GeglNode *gegl = gegl_node_new ();
+ GeglNode *node = gegl_node_new_child (gegl,
+ "operation", opname,
+ NULL);
+ gchar **input_pads;
+ gchar **output_pads;
+
+ int i;
+
+ input_pads = gegl_node_list_input_pads (node);
+ output_pads = gegl_node_list_output_pads (node);
+
+ g_string_append_printf (s, "<dl>");
+ g_string_append_printf (s, "<dt>pads</dt><dd>\n");
+ if (input_pads && input_pads[0])
+ {
+ for (i = 0; input_pads[i]; i++)
+ {
+ g_string_append_printf (s, "%s\n", input_pads[i]);
+ }
+ g_free (input_pads);
+ }
+
+ if (output_pads && output_pads[0])
+ {
+ for (i = 0; output_pads[i]; i++)
+ {
+ g_string_append_printf (s, "%s\n", output_pads[i]);
+ }
+ g_free (output_pads);
+ }
+ g_string_append_printf (s, "</dd>");
+ g_string_append_printf (s, "</dl>");
+
+ g_object_unref (gegl);
+}
+
+static void
+json_list_properties (GType type, GString *s, const gchar *opname)
+{
+ GParamSpec **self;
+ GParamSpec **parent;
+ guint n_self;
+ guint n_parent;
+ gint prop_no;
+
+ if (!type)
+ return;
+
+ g_string_append_printf (s, "<div class='properties'>\n");
+
+ self = g_object_class_list_properties (
+ G_OBJECT_CLASS (g_type_class_ref (type)),
+ &n_self);
+ parent = g_object_class_list_properties (
+ /*G_OBJECT_CLASS (g_type_class_peek_parent (g_type_class_ref (type))),*/
+ G_OBJECT_CLASS (g_type_class_ref (GEGL_TYPE_OPERATION)),
+ &n_parent);
+
+
+ for (prop_no=0;prop_no<n_self;prop_no++)
+ {
+ gint parent_no;
+ gboolean found=FALSE;
+ for (parent_no=0;parent_no<n_parent;parent_no++)
+ if (self[prop_no]==parent[parent_no])
+ found=TRUE;
+ /* only print properties if we are an addition compared to
+ * GeglOperation
+ */
+ if (!found)
+ {
+ const gchar *type_name;
+ g_string_append_printf (s, "<div class='property'>\n");
+
+ g_string_append_printf (s, "<b>");
+ json_escape_string (s, g_param_spec_get_nick (self[prop_no]));
+ g_string_append_printf (s, "</b>");
+
+ g_string_append_printf (s, "(");
+
+ type_name = g_type_name (G_OBJECT_TYPE (self[prop_no]));
+ if(strstr (type_name, "Param"))
+ {
+ type_name = strstr (type_name, "Param");
+ type_name+=5;
+ }
+ {
+ for (const char *p = type_name; *p; p++)
+ g_string_append_printf (s, "%c", g_ascii_tolower (*p));
+ }
+ g_string_append_printf (s, " %s)<br/>", g_param_spec_get_name (self[prop_no]));
+
+ g_string_append_printf (s, "\n");
+
+
+ g_string_append_printf (s, "<dl>");
+
+#if 0
+ if (g_type_is_a (G_PARAM_SPEC_VALUE_TYPE (self[prop_no]), G_TYPE_DOUBLE))
+ {
+ gdouble default_value = G_PARAM_SPEC_DOUBLE (self[prop_no])->default_value;
+ gdouble min = G_PARAM_SPEC_DOUBLE (self[prop_no])->minimum;
+ gdouble max = G_PARAM_SPEC_DOUBLE (self[prop_no])->maximum;
+
+ if (default_value<-10000000)
+ g_string_append_printf (s, "<dt>default</dt><dd>-inf</dd>\n");
+ else if (default_value>10000000)
+ g_string_append_printf (s, "<dt>default</dt><dd>+inf</dd>\n");
+ else
+ g_string_append_printf (s, "<dt>default</dt><dd>%2.2f</dd>\n", default_value);
+
+ if (min<-10000000)
+ g_string_append_printf (s, "<dt>minimum</dt><dd>-inf</dd>\n");
+ else
+ g_string_append_printf (s, "<dt>minimum</dt><dd>%2.2f</dd>\n", min);
+
+ if (max>10000000)
+ g_string_append_printf (s, "<dt>maximum</dt><dd>+inf</dd>\n");
+ else
+ g_string_append_printf (s, "<dt>maximum</dt><dd>%2.2f</dd>\n", max);
+ if (GEGL_IS_PARAM_SPEC_DOUBLE (self[prop_no]))
+ {
+ GeglParamSpecDouble *pspec =
+ GEGL_PARAM_SPEC_DOUBLE (self[prop_no]);
+
+ if (pspec->ui_minimum < -10000000)
+ g_string_append_printf (s, "<dt>ui-minimum</dt><dd>-inf</dd>\n");
+ else
+ g_string_append_printf (s, "<dt>ui-minimum</dt><dd>%2.2f</dd>\n", pspec->ui_minimum);
+
+ if (pspec->ui_maximum > 10000000)
+ g_string_append_printf (s, "<dt>ui-maximum</dt><dd>+inf</dd>\n");
+ else
+ g_string_append_printf (s, "<dt>ui-maximum</dt><dd>%2.2f</dd>\n", pspec->ui_maximum);
+
+ g_string_append_printf (s, "<dt>ui-gamma</dt><dd>%2.2f</dd>\n", pspec->ui_gamma);
+ g_string_append_printf (s, "<dt>ui-step-small</dt><dd>%2.2f</dd>\n", pspec->ui_step_small);
+ g_string_append_printf (s, "<dt>ui-step-big</dt><dd>%2.2f</dd>\n", pspec->ui_step_big);
+ g_string_append_printf (s, "<dt>ui-digits</dt><dd>%i</dd>\n", pspec->ui_digits);
+ }
+
+ }
+ else if (g_type_is_a (G_PARAM_SPEC_VALUE_TYPE (self[prop_no]), G_TYPE_INT))
+ {
+ gint default_value = G_PARAM_SPEC_INT (self[prop_no])->default_value;
+ gint min = G_PARAM_SPEC_INT (self[prop_no])->minimum;
+ gint max = G_PARAM_SPEC_INT (self[prop_no])->maximum;
+
+ if (default_value<-10000000)
+ g_string_append_printf (s, "<dt>default</dt><dd>-inf</dd>\n");
+ else if (default_value>10000000)
+ g_string_append_printf (s, "<dt>default</dt><dd>+inf</dd>\n");
+ else
+ g_string_append_printf (s, "<dt>default</dt><dd>%i</dd>\n", default_value);
+
+ if (min<-10000000)
+ g_string_append_printf (s, "<dt>minimum</dt><dd>-inf</dd>\n");
+ else
+ g_string_append_printf (s, "<dt>minimum</dt><dd>%i</dd>\n", min);
+
+ if (max>10000000)
+ g_string_append_printf (s, "<dt>maximum</dt><dd>+inf</dd>\n");
+ else
+ g_string_append_printf (s, "<dt>maximum</dt><dd>%i</dd>\n", max);
+
+ if (GEGL_IS_PARAM_SPEC_INT (self[prop_no]))
+ {
+ GeglParamSpecInt *pspec =
+ GEGL_PARAM_SPEC_INT (self[prop_no]);
+
+ if (pspec->ui_minimum < -10000000)
+ g_string_append_printf (s, "<dt>ui-minimum</dt><dd>-inf</dd>\n");
+ else
+ g_string_append_printf (s, "<dt>ui-minimum</dt><dd>%i</dd>\n", pspec->ui_minimum);
+
+ if (pspec->ui_maximum > 10000000)
+ g_string_append_printf (s, "<dt>ui-maximum</dt><dd>+inf</dd>\n");
+ else
+ g_string_append_printf (s, "<dt>ui-maximum</dt><dd>%i</dd>\n", pspec->ui_maximum);
+
+ g_string_append_printf (s, "<dt>ui-gamma</dt><dd>%2.2f</dd>\n", pspec->ui_gamma);
+ g_string_append_printf (s, "<dt>ui-step-small</dt><dd>%i</dd>\n", pspec->ui_step_small);
+ g_string_append_printf (s, "<dt>ui-step-big</dt><dd>%i</dd>\n", pspec->ui_step_big);
+ }
+
+ }
+ else if (g_type_is_a (G_PARAM_SPEC_VALUE_TYPE (self[prop_no]), G_TYPE_BOOLEAN))
+ {
+ g_string_append_printf (s, " ,'default</dt><dd>%s</dd>\n", G_PARAM_SPEC_BOOLEAN
(self[prop_no])->default_value?"True":"False");
+ }
+ else if (g_type_is_a (G_PARAM_SPEC_VALUE_TYPE (self[prop_no]), G_TYPE_STRING))
+ {
+ const gchar *string = G_PARAM_SPEC_STRING (self[prop_no])->default_value;
+
+ g_string_append_printf (s, " <dt>default</dt><dd>");
+ json_escape_string (s, string);
+ g_string_append_printf (s, "</dd>\n");
+
+ }
+ else if (g_type_is_a (G_PARAM_SPEC_VALUE_TYPE (self[prop_no]), GEGL_TYPE_COLOR))
+ {
+ GeglColor *color = gegl_param_spec_color_get_default (self[prop_no]);
+ if (color)
+ {
+ gchar *string;
+
+ g_object_get (color, "string", &string, NULL);
+ g_string_append_printf (s, "<dt>default</dt><dd>");
+ json_escape_string (s, string);
+ g_string_append_printf (s, "</dd>\n");
+ g_free (string);
+ }
+ }
+ else
+ {
+ }
+#endif
+
+ if (g_param_spec_get_blurb (self[prop_no]) &&
+ g_param_spec_get_blurb (self[prop_no])[0]!='\0')
+ {
+ g_string_append_printf (s, "<p>");
+ json_escape_string (s, g_param_spec_get_blurb (self[prop_no]));
+ g_string_append_printf (s, "</p>\n");
+ }
+
+ {
+ guint count;
+ gchar **property_keys = gegl_operation_list_property_keys (
+ opname,
+ g_param_spec_get_name (self[prop_no]),
+ &count);
+
+ if (property_keys)
+ {
+
+ int i;
+ if (property_keys[0])
+ {
+ /* XXX: list is in reverse order */
+ for (i = 0; property_keys[i]; i++)
+ {
+ g_string_append_printf (s, "<dt>%s</dt><dd>%s</dd>\n",
+ property_keys[i],
+ gegl_operation_get_property_key (opname,
+ g_param_spec_get_name (self[prop_no]),
+ property_keys[i]));
+ }
+ }
+ g_free (property_keys);
+ }
+
+ g_string_append_printf (s, "</dl>");
+ }
+
+ g_string_append_printf (s, "<div>");
+ }
+ }
+ if (self)
+ g_free (self);
+ if (parent)
+ g_free (parent);
+
+ g_string_append_printf (s, "</div>");
+}
+
+GHashTable *seen_categories = NULL;
+
+const gchar *css = "@import url(../gegl.css); .description{margin-bottom:1em;}";
+
+const gchar *html_pre = "<html><head><title>GEGL operation %s</title>\n"
+ "<style>%s%s</style></head><body><a href='../index.html'><img
src='../images/GEGL.png' alt='GEGL' style='float: right; height: 5.5em;'/></a>\n";
+const gchar *html_post = "</body></html>";
+
+gint
+main (gint argc, gchar **argv)
+{
+ GList *operations;
+ GList *iter;
+ GString *s = g_string_new ("");
+
+ gegl_init (&argc, &argv);
+ seen_categories = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
+
+ g_object_set (gegl_config (),
+ "application-license", "GPL3",
+ NULL);
+
+ operations = gegl_operations ();
+
+ for (iter=operations;iter;iter = g_list_next (iter))
+ {
+ GeglOperationClass *klass = iter->data;
+
+ const char *name = gegl_operation_class_get_key (klass, "name");
+ const char *title = gegl_operation_class_get_key (klass, "title");
+ const char *categoris = gegl_operation_class_get_key (klass, "categories");
+ const char *description = gegl_operation_class_get_key (klass, "description");
+
+ g_string_append_printf (s, html_pre, name, css, "");
+ g_string_append_printf (s, "<div class='operation'><h2 style='clear:both;'>%s <span
style='font-size:60%%'>(%s)</span></h2>\n", title?title:name, name);
+
+
+ {
+ char *image = operation_to_image_path (name);
+
+ if (g_file_test (image, G_FILE_TEST_EXISTS))
+ g_string_append_printf (s, "<img style='clear: both; padding-left: 1em; float: right; ' src='%s'
/>\n", image);
+ g_free (image);
+ }
+
+ if (description)
+ {
+ g_string_append_printf (s, "<div class='description'>");
+ xml_escape_string (s, description);
+ g_string_append_printf (s, "</div>\n");
+ }
+#if 0
+ if (klass->compat_name)
+ g_string_append_printf (s, ",'compat-op':'%s'\n", klass->compat_name);
+
+ if (klass->opencl_support)
+ g_string_append_printf (s, ",'opencl-support':'true'\n");
+
+ g_string_append_printf (s, ",'parent':'%s'\n",
+ g_type_name (g_type_parent(G_OBJECT_CLASS_TYPE(klass))));
+#endif
+
+ json_list_properties (G_OBJECT_CLASS_TYPE (klass), s, name);
+
+ g_string_append_printf (s, "<dl>");
+ json_list_pads (G_OBJECT_CLASS_TYPE (klass), s, name);
+
+ if (categoris)
+ {
+ const gchar *ptr = categoris;
+ g_string_append_printf (s, "<dt>categories</dt><dd>");
+
+ while (ptr && *ptr)
+ {
+ gchar category[64]="";
+ gint i=0;
+ while (*ptr && *ptr!=':' && i<63)
+ {
+ category[i++]=*(ptr++);
+ category[i]='\0';
+ }
+ if (*ptr==':')
+ ptr++;
+ {
+ g_string_append_printf (s, "<a href='cat-%s.html'>%s</a> ", category, category);
+ g_hash_table_insert (seen_categories, g_strdup (category), (void*)0xff);
+ }
+ }
+ g_string_append_printf (s, "</dt>\n");
+ }
+
+ if(0){ // XXX: re-enable before push.. it takes a lot of time
+ gchar *commandline = g_strdup_printf (
+ "sh -c \"(cd " TOP_SRCDIR ";cd ..;grep -r '\\\"%s\\\"' operations) | grep operations | grep -v
'~:' | grep '\\\"name\\\"' | cut -f 1 -d ':'\"",
+ name);
+ gchar *output = NULL;
+
+ if (g_spawn_command_line_sync (commandline, &output, NULL, NULL, NULL))
+ {
+ if (strlen(output))
+ {
+ output[strlen(output)-1] = 0;
+ g_string_append_printf (s,
+ "<dt>source</dt><dd><a href='https://git.gnome.org/browse/gegl/tree/%s'>%s</a></dd>\n", output,
output);
+ }
+ g_free (output);
+ }
+
+ g_free (commandline);
+ }
+
+ {
+ guint nkeys;
+ gchar **keys = gegl_operation_list_keys (name, &nkeys);
+
+ if (keys)
+ {
+ for (gint i = 0; keys[i]; i++)
+ {
+ const gchar *value = gegl_operation_get_key (name, keys[i]);
+
+ if (g_str_equal (keys[i], "categories") ||
+ g_str_equal (keys[i], "cl-source") ||
+ g_str_equal (keys[i], "name") ||
+ g_str_equal (keys[i], "source") ||
+ g_str_equal (keys[i], "reference-composition") ||
+ g_str_equal (keys[i], "reference-hash") ||
+ g_str_equal (keys[i], "title") ||
+ g_str_equal (keys[i], "description"))
+ continue;
+
+ g_string_append_printf (s, "<dt>%s</dt>", keys[i]);
+ g_string_append_printf (s, "<dd>");
+ json_escape_string (s, value);
+ g_string_append_printf (s, "</dd>\n");
+ }
+ g_free (keys);
+ }
+ }
+
+ g_string_append_printf (s, "</dl>");
+
+ g_string_append_printf (s, "</div>");
+ g_string_append_printf (s, html_post);
+ {
+ gchar *html_name = g_strdup_printf ("%s.html", name);
+ gchar *colon = strchr (html_name, ':');
+ if (colon) *colon = '-';
+ g_print ("%s\n", html_name);
+ g_file_set_contents (html_name, s->str, -1, NULL);
+ g_string_assign (s, "");
+ g_free (html_name);
+ }
+ }
+
+ if(1){
+ gchar *category = "all";
+ GList *keys = g_hash_table_get_keys (seen_categories);
+ GString *cs;
+ GList *k = keys;
+ GList *keys2 = g_list_copy (keys);
+ keys2 = g_list_sort (keys2, (void*)g_strcmp0);
+ keys = keys2;
+
+ cs = g_string_new ("<div class='categories'>");
+
+ for (k = keys; k; k = k->next)
+ {
+ category = k->data;
+ g_string_append_printf (cs, "<a href='cat-%s.html'>%s</a> ", category, category);
+ }
+ g_string_append_printf (cs, "</div>");
+
+ k = keys;
+ while (k) {
+ category = k->data;
+all:
+ g_string_assign (s, "");
+ if (category)
+ {
+ g_string_append_printf (s, html_pre, category, css, " body{max-width:98%;} ");
+ g_string_append_printf (s, "<h2 style='clear:both;'>%s</h2>\n", category);
+ g_string_append_printf (s, "%s", cs->str);
+
+ for (iter=operations;iter;iter = g_list_next (iter))
+ {
+ GeglOperationClass *klass = iter->data;
+ const char *name = gegl_operation_class_get_key (klass, "name");
+ const char *description = gegl_operation_class_get_key (klass, "description");
+ const char *categoris = gegl_operation_class_get_key (klass, "categories");
+ int found = 0;
+ if (categoris)
+ {
+ const gchar *ptr = categoris;
+ while (ptr && *ptr)
+ {
+ gchar categry[64]="";
+ gint i=0;
+ while (*ptr && *ptr!=':' && i<63)
+ {
+ categry[i++]=*(ptr++);
+ categry[i]='\0';
+ }
+ if (*ptr==':')
+ ptr++;
+ if (!strcmp( categry, category))
+ found = 1;
+ }
+ }
+ if (found || !strcmp(category, "all"))
+ {
+ gchar *name_dup = g_strdup (name);
+ gchar *colon = strchr (name_dup, ':');
+ if (colon) *colon = '-';
+
+ {
+ char *image = operation_to_image_path (name);
+ if (!g_file_test (image, G_FILE_TEST_EXISTS))
+ {
+ g_free (image);
+ image = g_strdup ("images/gegl-ditto.png");
+ }
+ g_string_append_printf (s, "<a href='%s.html' title='", name_dup);
+ if (description)
+ xml_escape_string (s, description);
+ g_string_append_printf (s, "'><div
style='display:inline-block;width:200px;height:200px;background-image:url(%s);background-repeat:
no-repeat;padding-bottom:2px;color:white;text-shadow:1px 1px 2px black;'>", image);
+ g_string_append_printf (s, "%s</div></a>\n", name);
+ g_free (name_dup);
+ g_free (image);
+ }
+ }
+ }
+ }
+ g_string_append_printf (s, html_post);
+
+ {
+ gchar *html_name = g_strdup_printf ("cat-%s.html", category);
+ g_print ("%s\n", html_name);
+ g_file_set_contents (html_name, s->str, -1, NULL);
+ g_free (html_name);
+ }
+ if (k)
+ k = k->next;
+ if (!k && strcmp(category, "all"))
+ {
+ category="all";
+ goto all;
+ }
+ }
+ }
+ if(1){
+ gchar *category = "all";
+ GList *keys = g_hash_table_get_keys (seen_categories);
+ GList *k = keys;
+
+ GString *cs = g_string_new ("<div class='categories'>");
+
+ for (k = keys; k; k = k->next)
+ {
+ category = k->data;
+ g_string_append_printf (cs, "<a href='cat-%s.html'>%s</a> ", category, category);
+ }
+ g_string_append_printf (cs, "</div>");
+
+
+
+ g_string_assign (s, "");
+ {
+ g_string_append_printf (s, html_pre, category, css, "");
+ g_string_append_printf (s, "<h2 style='clear:both;'>%s</h2>\n", "All GEGL operations");
+ g_string_append_printf (s, "<p>categories:</p>%s\n", cs->str);
+
+ g_string_append_printf (s, "<p>All operations:</p>\n");
+ for (iter=operations;iter;iter = g_list_next (iter))
+ {
+ GeglOperationClass *klass = iter->data;
+ const char *name = gegl_operation_class_get_key (klass, "name");
+ const char *title = gegl_operation_class_get_key (klass, "title");
+ const char *description = gegl_operation_class_get_key (klass, "description");
+ {
+ gchar *name_dup = g_strdup (name);
+ gchar *colon = strchr (name_dup, ':');
+ if (colon) *colon = '-';
+
+ {
+ char *image = operation_to_image_path (name);
+ if (!g_file_test (image, G_FILE_TEST_EXISTS))
+ {
+ g_free (image);
+ image = g_strdup ("images/gegl-ditto.png");
+ }
+ g_string_append_printf (s, "<a href='%s.html' title='", name_dup);
+ if (description)
+ xml_escape_string (s, description);
+ g_string_append_printf (s, "'><div style='display: box-inline;width: 20em; overflow: hidden;'>");
+ g_string_append_printf (s, "%s</div></a>\n", title?title:name);
+ g_free (name_dup);
+ g_free (image);
+ }
+ }
+ }
+ }
+ g_string_append_printf (s, html_post);
+
+ {
+ gchar *html_name = "index.html";
+ g_print ("%s\n", html_name);
+ g_file_set_contents (html_name, s->str, -1, NULL);
+ }
+ k = k->next;
+ }
+
+ return 0;
+}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]