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