#include <glib.h>
#include <string.h>
#include <stdlib.h>
#include "entity.h"
GHashTable *userrend_tag_nodes_ht;
static void
userrend_passthru_parenter (ENode * parent_node, ENode * child_node)
{
ENode *renderer_node;
char *onparent;
renderer_node = g_hash_table_lookup (userrend_tag_nodes_ht,
parent_node->element->str);
if (!renderer_node)
return;
onparent = enode_attrib_str (renderer_node, "onparent", NULL);
/* If they don't implement the parenting, we have to mimic the behavior
* of the real element parenter */
if (!onparent) {
erend_short_curcuit_parent (parent_node, child_node);
return;
}
enode_call_ignore_return (renderer_node, onparent, "nn", parent_node,
child_node);
}
static void
userrend_passthru_renderer (ENode * node)
{
ENode *renderer_node;
char *onrender;
renderer_node =
g_hash_table_lookup (userrend_tag_nodes_ht, node->element->str);
if (!renderer_node)
return;
onrender = enode_attrib_str (renderer_node, "onrender", NULL);
if (!onrender)
return;
EDEBUG (("renderers", "node = %s", node->element->str));
enode_call_ignore_return (renderer_node, onrender, "n", node);
/* enode_attribs_sync (node); */
}
static void
userrend_passthru_destroy (ENode * node)
{
ENode *renderer_node;
char *ondestroy;
renderer_node =
g_hash_table_lookup (userrend_tag_nodes_ht, node->element->str);
if (!renderer_node)
return;
ondestroy = enode_attrib_str (renderer_node, "ondestroy", NULL);
if (!ondestroy)
return;
enode_call_ignore_return (renderer_node, ondestroy, "n", node);
}
static gint
userrend_passthru_attr_set (ENode * node, EBuf * attr, EBuf * value)
{
ENode *renderer_node;
ENode *attrib_node;
GHashTable *attrib_ht;
char *onset;
EDEBUG (("renderers", "userrend_passthru_attr_set"));
renderer_node = g_hash_table_lookup (userrend_tag_nodes_ht,
node->element->str);
if (!renderer_node)
return FALSE;
attrib_ht = enode_get_kv (renderer_node, "userrend-renderer-attrib-ht");
attrib_node = g_hash_table_lookup (attrib_ht, attr->str);
if (!attrib_node)
return FALSE;
onset = enode_attrib_str (attrib_node, "onset", NULL);
if (!onset)
return FALSE;
EDEBUG (("renderers", "node = %s", node->element->str));
/* Call the onset function. */
enode_call_ignore_return (renderer_node, onset, "nee", node, attr, value);
return TRUE;
}
/* TODO: Think about ref'ing these nodes.. */
static void
userrend_renderer_parenter (ENode * parent_node, ENode * child_node)
{
Element *element;
ElementAttr *e_attr;
char *tag;
char *name;
char *description;
char *value_desc;
char *values;
ENode *renderer_node;
GHashTable *attrib_ht;
EDEBUG (("userrend", "userrend_renderer_parenter"));
tag = enode_attrib_str (parent_node, "tag", NULL);
if (!tag)
return;
renderer_node = g_hash_table_lookup (userrend_tag_nodes_ht, tag);
if (!renderer_node)
return;
attrib_ht = enode_get_kv (renderer_node, "userrend-renderer-attrib-ht");
if (!attrib_ht)
return;
element = enode_get_kv (parent_node, "userrend-renderer-element");
if (!element)
return;
if (!ebuf_equal_str (child_node->element, "attrib"))
return;
name = enode_attrib_str (child_node, "name", NULL);
if (!name)
return;
description = enode_attrib_str (child_node, "description", NULL);
if (!description)
g_warning
("Element <%s tag=%s>'s attrib <%s> doesn't have a description.",
parent_node->element->str, tag, child_node->element->str);
value_desc = enode_attrib_str (child_node, "value_desc", NULL);
values = enode_attrib_str (child_node, "values", NULL);
e_attr = g_new0 (ElementAttr, 1);
e_attr->attribute = name;
e_attr->description = description;
e_attr->value_desc = value_desc;
e_attr->possible_values = values;
e_attr->set_attr_func = userrend_passthru_attr_set;
element_register_attrib (element, e_attr);
g_hash_table_insert (attrib_ht, name, child_node);
}
static void /* Silly name but thats what this function
* is. */
userrend_renderer_renderer (ENode * node)
{
Element *element;
GHashTable *attrib_ht;
char *tag;
EDEBUG (("userrend", "in userrend_renderer_renderer"));
tag = enode_attrib_str (node, "tag", NULL);
if (!tag)
return;
EDEBUG (("userrend", "rendering (%s)", tag));
enode_set_kv (node, "userrend_renderer_renderer-do", "true");
element = g_new0 (Element, 1);
element->render_func = userrend_passthru_renderer;
element->destroy_func = userrend_passthru_destroy;
element->parent_func = userrend_passthru_parenter;
element->tag = tag;
element_register (element);
enode_set_kv (node, "userrend-renderer-element", element);
attrib_ht = g_hash_table_new (g_str_hash, g_str_equal);
enode_set_kv (node, "userrend-renderer-attrib-ht", attrib_ht);
g_hash_table_insert (userrend_tag_nodes_ht, tag, node);
/* xml_node_set_all_attr (node); */
}
static void
userrend_attrib_renderer (ENode * node)
{
enode_set_kv (node, "userrend-attrib-renderer-do", "true");
/* xml_node_set_all_attr (node); */
}
void
userrend_renderer_register (void)
{
Element *element;
ElementAttr *e_attr;
userrend_tag_nodes_ht = g_hash_table_new (g_str_hash, g_str_equal);
element = g_new0 (Element, 1);
element->render_func = userrend_renderer_renderer;
/* element->destroy_func = userrend_renderer_destroy; */
element->parent_func = userrend_renderer_parenter;
element->tag = "renderer";
element->description = "Define a new element in any supported langauge.";
element_register (element);
e_attr = g_new0 (ElementAttr, 1);
e_attr->attribute = "tag";
e_attr->description = "The name of the tag for the new renderer.";
e_attr->value_desc = "string";
e_attr->set_attr_func = NULL;
element_register_attrib (element, e_attr);
e_attr = g_new0 (ElementAttr, 1);
e_attr->attribute = "lang";
e_attr->description = "The default language of the renderer.";
e_attr->value_desc = "string";
e_attr->possible_values = "language";
e_attr->set_attr_func = NULL;
element_register_attrib (element, e_attr);
e_attr = g_new0 (ElementAttr, 1);
e_attr->attribute = "onrender";
e_attr->description = "The function or method used to render the tag.";
e_attr->value_desc = "function";
e_attr->set_attr_func = NULL;
element_register_attrib (element, e_attr);
e_attr = g_new0 (ElementAttr, 1);
e_attr->attribute = "ondestroy";
e_attr->description = "The function or method used to remove the tag.";
e_attr->value_desc = "function";
e_attr->set_attr_func = NULL;
element_register_attrib (element, e_attr);
e_attr = g_new0 (ElementAttr, 1);
e_attr->attribute = "onparent";
e_attr->description = "The function or method used to parent child tags.";
e_attr->value_desc = "function";
e_attr->set_attr_func = NULL;
element_register_attrib (element, e_attr);
/* Attrib tag element. */
element = g_new0 (Element, 1);
element->render_func = userrend_attrib_renderer;
/* element->destroy_func = userrend_attrib_destroy; */
/* element->parent_func = userrend_attrib_parenter; */
element->tag = "attrib";
element->description = "Define an attribute of a new renderer.";
element_register (element);
e_attr = g_new0 (ElementAttr, 1);
e_attr->attribute = "name";
e_attr->description = "The attribute's name.";
e_attr->value_desc = "string";
e_attr->set_attr_func = NULL;
element_register_attrib (element, e_attr);
e_attr = g_new0 (ElementAttr, 1);
e_attr->attribute = "description";
e_attr->description = "The description of the attribute.";
e_attr->value_desc = "string";
e_attr->set_attr_func = NULL;
element_register_attrib (element, e_attr);
e_attr = g_new0 (ElementAttr, 1);
e_attr->attribute = "value_desc";
e_attr->description = "The type of value accepted.";
e_attr->value_desc = "string";
e_attr->set_attr_func = NULL;
element_register_attrib (element, e_attr);
e_attr = g_new0 (ElementAttr, 1);
e_attr->attribute = "values";
e_attr->description = "The possible values for this attribute.";
e_attr->value_desc = "string";
e_attr->set_attr_func = NULL;
element_register_attrib (element, e_attr);
e_attr = g_new0 (ElementAttr, 1);
e_attr->attribute = "onset";
e_attr->description =
"The function or method to call when this attribute is set.";
e_attr->value_desc = "string";
e_attr->set_attr_func = NULL;
element_register_attrib (element, e_attr);
}
syntax highlighted by Code2HTML, v. 0.9.1