#include <xml/savenode.h>
#include <xml/attrnode.h>
#include <xml/savetree.h>
#include <xml/listpcre.h>
#include <string.h>

#define ___ {
#define ____ }

/* --------- better version - leave controls and make space inz attribute */
void
xml_node_save_attribute_to_text (xml_GNode* node, const gchar* attrib)
{
    if (!attrib || !node || !node->text || node->off == node->end) return;
    
    ___ gchar* str = xml_node_attribute_lookup (node, attrib);
    if (! str) return;
    ___ int len = strlen (str);
    if (len > node->end - node->off) len = node->end - node->off;
    ___ gchar* ptr = node->text->str + node->off;

    while (len)
    
{
        len--;
        if (str[len] == ' ' && g_ascii_iscntrl (ptr[len])) continue;
        ptr[len] = str[len];
    }
xml_node_attribute_remove (node, attrib); ____;____;____; }
void
xml_node_save_text_to_attribute (xml_GNode* node, const gchar* attrib,
				 const gchar* fill)
{
    if (!attrib || !node || !node->text || node->off == node->end) return;

    ___ gsize len = node->end - node->off;
    ___ gchar* text = node->text->str + node->off;
    ___ gchar* attr = g_strndup (text, len);
    xml_node_attribute_insert (node, g_strdup (attrib), attr);

 filling:
    if (! fill)
    
{   /* the default behaviour */
	while (len)
	
{
	    --len;
	    if (g_ascii_iscntrl (attr[len])) 
		attr[len] = ' '; 
	    else
		text[len] = ' ';
	}
}
else if (! fill[0] || ! fill[1])
{   /* fill char given */
	while (len)
	
{
	    --len;
	    if (g_ascii_iscntrl (attr[len])) 
		attr[len] = ' ';
	    else
		text[len] = fill[0];
	}
}
else if (! fill[2])
{   /* alternating fill chars given */
	while (len)
	
{
	    --len;
	    if (g_ascii_iscntrl (attr[len])) 
		attr[len] = ' ';
	    else
		text[len] = fill[len&1];
	}
}
else if (! fill[3])
{   /* leading char + fill char + trailing char */
	while (len)
	
{
	    --len;
	    if (g_ascii_iscntrl (attr[len])) 
		attr[len] = ' ';
	    else
		text[len] = fill[1];
	}
___ int end = node->end - node->off - 1; while (len < end && g_ascii_iscntrl(attr[len])) len++; while (len < end && g_ascii_iscntrl(attr[end])) end--; if (end-len >= 2)
{ text[len] = fill[0]; text[end] = fill[2]; }
____; }
else if (! fill[4])
{   /* leading twochar + trailing twochar */
	while (len)
	
{
	    --len;
	    if (g_ascii_iscntrl (attr[len])) 
		attr[len] = ' ';
	    else
		text[len] = ' ';
	}
___ int end = node->end - node->off - 1; while (len < end && g_ascii_iscntrl(attr[len])) len++; while (len < end && g_ascii_iscntrl(attr[end])) end--; if (end-len >= 4 && ! g_ascii_iscntrl(attr[len+1]) && ! g_ascii_iscntrl(attr[end-1]))
{ 
	    text[len] = fill[0]; text[len+1] = fill[1];
	    text[end] = fill[3]; text[end-1] = fill[2];
	}
____; }
else if (! fill[5])
{   /* leading twochar + fill char + trailing twochar */
	while (len)
	
{
	    --len;
	    if (g_ascii_iscntrl (attr[len])) 
		attr[len] = ' ';
	    else
		text[len] = fill[2];
	}
___ int end = node->end - node->off - 1; while (len < end && g_ascii_iscntrl(attr[len])) len++; while (len < end && g_ascii_iscntrl(attr[end])) end--; if (end-len >= 4 && ! g_ascii_iscntrl(attr[len+1]) && ! g_ascii_iscntrl(attr[end-1]))
{ 
	    text[len] = fill[0]; text[len+1] = fill[1];
	    text[end] = fill[4]; text[end-1] = fill[3];
	}
____; }
else if (! fill[6])
{   /* leading twochar + alternating fill char + trailing twochar */
	while (len)
	
{
	    --len;
	    if (g_ascii_iscntrl (attr[len])) 
		attr[len] = ' ';
	    else
		text[len] = fill[2+(len&1)];
	}
___ int end = node->end - node->off - 1; while (len < end && g_ascii_iscntrl(attr[len])) len++; while (len < end && g_ascii_iscntrl(attr[end])) end--; if (end-len >= 4 && ! g_ascii_iscntrl(attr[len+1]) && ! g_ascii_iscntrl(attr[end-1]))
{ 
	    text[len] = fill[0]; text[len+1] = fill[1];
	    text[end] = fill[5]; text[end-1] = fill[4];
	}
____; }
else
{
	fill = 0; goto filling;
    }
____;____;____; }
typedef struct 
{ const gchar* attrib; const gchar* fill; }
 Data;
static void
xml_node_save_text_to_attrib_FN (xml_GNode* node, Data* data)
{
    xml_node_save_text_to_attribute (node, data->attrib, data->fill);
}
/**
    save the text in the selected nodes to the new attribute - and blank
    the text area. The text can be pasted back from the attribute with its
 */
void
xml_path_pcre_text_to_attr (xml_GNode* tree, 
			    const gchar* nodesRE, const gchar* attrib,
			    const gchar* fill)
{
    g_return_if_fail (tree);
    g_return_if_fail (attrib);
    ___ Data data = 
{ attrib, fill }
; xml_path_pcre_foreach (tree, nodesRE, (xml_GNodeForeachFunc) xml_node_save_text_to_attrib_FN, (gpointer) &data); ____; }
/**
    get the attribute from the selected nodes and paste the string back to
    the text area - as this is the inverse of xml_path_pcre_text_to_attr.
 */
void
xml_path_pcre_text_restore (xml_GNode* tree,
			    const gchar* nodesRE, const gchar* attrib)
{
    g_return_if_fail (tree);
    g_return_if_fail (attrib);
    xml_path_pcre_foreach (tree, nodesRE, 
		    (xml_GNodeForeachFunc) xml_node_save_attribute_to_text, 
		    (gpointer) attrib);
}
/* 
   Local variables:
   c-file-style: "stroustrup"
   End:
 */