#include <xml/gnode.h>
#include <xml/attrnode.h>
#include <string.h>


xml_GNode*                xml_g_node_new (gchar* name)
{
    xml_GNode* node = g_new0 (xml_GNode,1);
    node->name = name;
    /* node->attributes = 0 */
    return node;
}
static void
xml_g_nodes_free (xml_GNode *root)
{
    xml_GNode *node, *next;
  
    node = root;
    while (node != NULL)
    
{
	next = node->next;
	xml_g_nodes_free (node->children);
	xml_node_attribute_remove_all (node);
	g_free (node->name);
	g_free (node);
	node = next;
    }
}
void                      xml_g_node_destroy (xml_GNode* root)
{
    g_return_if_fail (root != NULL);

    if (!XML_G_NODE_IS_ROOT (root))
	xml_g_node_unlink (root);
  
    xml_g_nodes_free (root);
}
xml_GNode*                xml_g_node_copy (xml_GNode* node)
{
    xml_GNode *new_node = NULL;
  
    if (node)
    
{
	xml_GNode *child;
      
	new_node = xml_g_node_new (node->name);
      
	for (child = xml_g_node_last_child (node); child; child = child->prev)
	    xml_g_node_prepend (new_node, xml_g_node_copy (child));
    }
return new_node; }
xml_GNode* xml_node_find_child       (xml_GNode       *node,
					GTraverseFlags   flags,
					const gchar*     name)
{
    g_return_val_if_fail (node, 0);
    g_return_val_if_fail (flags <= G_TRAVERSE_MASK, NULL);
    if (! name) return 0;
  
    node = node->children;
    while (node)
    
{
	if (! strcmp (node->name, name))
        
{
	    if (XML_G_NODE_IS_LEAF (node))
            
{
		if (flags & G_TRAVERSE_LEAFS)
		    return node;
            }
else
{
		if (flags & G_TRAVERSE_NON_LEAFS)
		    return node;
            }
}
node = node->next; }
return NULL; }
xml_GNode*
xml_g_node_stick_before (xml_GNode* here, xml_GNode* node)
{
    g_return_val_if_fail (here, node);
    /*return_val_if_fail (node, node)*/
    if (! node) return node;

    if (node->parent) 
	g_assert (here->parent == node->parent);

    return xml_g_node_stick_before_ (here, node);
}
xml_GNode*
xml_g_node_stick_before_ (xml_GNode* here, xml_GNode* node)
{
    node->parent = here->parent;

    if((node->prev = here->prev))
	node->prev->next = node;
    else if (here->parent)
	here->parent->children = node;

    node->next = here; 
    return ((here->prev = node));
}
xml_GNode*
xml_g_node_stick_after (xml_GNode* here, xml_GNode* node)
{
    g_return_val_if_fail (here, node);
    /*return_val_if_fail (node, node)*/
    if (! node) return node;

    if (node->parent) 
	g_assert (here->parent == node->parent);

    return xml_g_node_stick_after_ (here, node);
}
xml_GNode*
xml_g_node_stick_after_ (xml_GNode* here, xml_GNode* node)
{
    node->parent = here->parent;

    if((node->next = here->next))
	node->next->prev = node;

    node->prev = here; 
    return ((here->next = node));
}
xml_GNode*
xml_g_node_unlink_ (xml_GNode* node)
{
    if (node->prev)
	node->prev->next = node->next;
    else if (node->parent)
	node->parent->children = node->next;

    if (node->next)
	node->next->prev = node->prev;
    node->prev = node->next = node->parent = 0;
    return node;
}
xml_GNode*
xml_g_node_group1 (xml_GNode* here, xml_GNode* node)
{
    g_return_val_if_fail (here, node);
    /*return_val_if_fail (node, node)*/
    if (! node) return node;

    g_return_val_if_fail (! node->children, node);

    if (node->next || node->prev || node->parent)
	xml_g_node_unlink (node);

    return xml_g_node_group1_(here, node);
}
xml_GNode*
xml_g_node_group1_ (xml_GNode* here, xml_GNode* node)
{
    node->parent = here->parent; here->parent = node; node->children = here;

    if((node->prev = here->prev))
    
{   node->prev->next = node; here->prev = 0; }
else if (node->parent)
{ /*  */ node->parent->children = node; }
if((node->next = here->next))
{   node->next->prev = node; here->next = 0; }
return node; }
xml_GNode*
xml_g_node_group2 (xml_GNode* left, xml_GNode* right, xml_GNode* node)
{
    if (! right) return xml_g_node_group1 (left, node);

    g_return_val_if_fail (left, node);
    /*return_val_if_fail (node, node)*/
    if (! node) return node;

    g_return_val_if_fail (! node->children, node);

    if (node->next || node->prev || node->parent)
	xml_g_node_unlink (node);

    return xml_g_node_group2_(left, right, node);
}
xml_GNode*
xml_g_node_group2_ (xml_GNode* left, xml_GNode* right, xml_GNode* node)
{
    if (! right) return xml_g_node_group1_ (left, node);
    /* if right == left return xml_g_node_group1_ (left, node) */
    
    node->children = left; node->parent = left->parent;

    if((node->prev = left->prev))
    
{   node->prev->next = node; left->prev = 0; }
else if (node->parent) node->parent->children = node; /* assert (! left->prev ) */ if((node->next = right->next))
{   node->next->prev = node; right->next = 0; }
/* assert (! right->next) // we need that for the re-parent loop too */ do
{ /* re-parent all nodes between left and right */
        left->parent = node;
        left = left->next;
    }
while (left); return node; }
/*
   and another design flaw in glib/ghash - the g_hash_table_steal is
   largely stupid - atleast for being exported. There should be a call
   to lookup a node and remove it thereby return the value string.
   i.e. xml_g_node_steal_value - if the node was not found then it
   would just return null otherwise call the key-destroyer but leave
   the value pointer intact.
  
   Such functionality can not even be approximated since the internal
   g_hash_table_lookup_node call is not exported.
   ___________________________________________________________________
 */
/* 
   Local variables:
   c-file-style: "stroustrup"
   End:
 */