#include <xml/nodetext.h>
#include <xml/pathnode.h>
#include <xml/dumpnode.h>
#include <string.h>

#define ___ {
#define ____ }

    /* A:           |-------------| <--------->        right-outside
     * B:           |--------<====|----->              right-overlap
     * C:                |---<==========>---|          inner-complete
     * D:                <--------|=====>-----|        left-overlap
     * E:           <-----------> |-----------|        left-outside
     * F:           <-----|=============|----->        outer-complete
     *
     * R:           |-----------| <>                   after
     * M:                  |------<>-----|             inside
     * L:                         <> |---------|       before
     */
#if 0 /* old code - for documentation only */
GString*
xml_node_text_move (xml_GNode* tree, gssize pos, gssize tot)
{
    g_return_val_if_fail (tree, 0);
    g_return_val_if_fail (tree->text, tree->text);

    ___ xml_GNode *node, *next;
    if (pos == tot) return tree->text;
    if (pos < tot) goto enlarge; else goto shrink;
    
 shrink:
                                                              /* tot < pos */
    node = xml_tree_find_node (tree, tot); 
    /* .off<=tot, if it isnt a leafnode then all children have tot<=.off */

    /* we update nodes only on going .next and .up */
    while (node->children) node = node->children;

    for (; node ; node = next)                       /* the DEL-span is... */
    
{
	if (!(next = node->next)) next = node->parent;
	if (node == tree) next = 0;

	/* .off <= .end && .end <= tot && tot < pos        "right-outside" */
	if (node->end <= tot) 
	
{                                     /* i.e. we are not yet there */
	    continue;
	}
/* tot < .end */ /* tot < pos && pos <= .off && .off <= .end "left-outside" */ if (pos <= node->off)
{                               /* keeps zero-width markups at end */
	    node->off -= pos-tot;
	    node->end -= pos-tot;
	    continue;
	}
/* .off < pos */ if (tot <= node->off)
{
	    /* tot <= .off && .off <= .end && .end <= pos "outer-complete" */
	    if (node->end <= pos) 
	    
{   /*   .off < pos   */                     /* remove markups */
	        xml_g_node_destroy (node); 
		continue;  
	    }
/* tot <= .off && .off <= pos && pos < .end "left-overlap" */ node->off = tot; node->end = node->off + (node->end - pos); continue; }
/* .off < tot */ if (node->end <= pos)
{
	    /* .off < tot && tot < .end && .end <= pos     "right-overlap" */
	    node->end = tot;
	    continue;
	}
else
{
	    /* .off < tot && tot < pos && pos < .end      "inner-complete" */
	    node->end -= pos-tot;
	    continue;
	}
}
return g_string_erase (node->text, tot, pos-tot); enlarge: /* pos < tot */ node = xml_tree_find_node (tree, pos); /* .off<=pos, if it isnt a leafnode then all children have tot<=.end */ /* we update nodes only on going .next and .up */ while (node->children) node = node->children; for (; node ; node = next) /* the INS-point is... */
{
	if (!(next = node->next)) next = node->parent;
	if (node == tree) next = 0;

	/* the INS-point is called "pos" here */
#     if 0
	if (node->end <= pos)                                   /* "after" */
	    continue;

	if (pos <= node->off)                                  /* "before" */
	
{                               
	    node->off += tot-pos;
	    node->end += tot-pos;
	    continue;
	}
if (pos <= node->end) /* "inside" */
{
	    node->end += tot-pos;
	    continue
	}
g_assert_not_reached (); # else if (pos <= node->end) node->end += tot-pos; if (pos <= node->off) node->off += tot-pos; # endif }
/* g_string_insert_len (node->text, tot, node->text->str, tot-pos); */ g_string_set_size (node->text, node->text->len + (tot-pos)); g_memmove (node->text->str + tot, node->text->str + pos, node->text->len - tot); /* memset (node->text->str + pos, ' ', tot-end) */ return node->text; ____; }
# endif
/* ______________________________________________________________________ */
/*       here is the same code, split up and TESTED(!!) and fixed         */
GString*
xml_node_text_move (xml_GNode* tree, gssize pos, gssize end)
{
    if (pos > end)
	return xml_node_text_erase (tree, pos, pos-end);
    else
	return xml_node_text_insert_len (tree, pos, 0, end-pos);
}
GString*
xml_node_text_insert_len (xml_GNode* tree, 
		       gssize pos, const gchar* str, gssize len)
{
    g_return_val_if_fail (tree, 0);
    g_return_val_if_fail (tree->text, tree->text);
    if (len < 0) 
{ if (str) len = strlen (str); else return tree->text; }
if (! len) return tree->text; if (pos > tree->text->len) pos = tree->text->len; ___ xml_GNode* node = tree; ___ xml_GNode* next; for (; node ; node = next)
{
	if (node->children) next = node->children;
	else if (node->next) next = node->next;
	else if ((next = node->parent)) do 
{
	    if (next->next) 
{ next = next->next; break; }
}
while ((next = next->parent)); if (next == tree) next = 0; /* this keeps code inside nodes (and makes it go before zero-width) */ if (pos == node->end)
{
	    if (pos <= node->end) node->end += len;
	    if (pos <= node->off) node->off += len;
	}
else
{
	    if (pos < node->end) node->end += len;
	    if (pos < node->off) node->off += len;
	}
}
____; if (str) return g_string_insert_len (tree->text, pos, str, len); g_string_set_size (tree->text, tree->text->len + len); g_memmove (tree->text->str + pos + len, tree->text->str + pos, tree->text->len - len - pos); memset (tree->text->str + pos, ' ', len); return tree->text; ____; }
#define XX xml_g_string_printerr ("#", xml_tree_dump_node_info (0, node));
GString*
xml_node_text_erase (xml_GNode *tree, gssize pos, gssize len)
{
    g_return_val_if_fail (tree, 0);
    g_return_val_if_fail (tree->text, tree->text);
    g_return_val_if_fail (len >= 0, tree->text);
    if (pos > tree->text->len) pos = tree->text->len;
    if (pos+len > tree->text->len) len = tree->text->len - pos;

    ___ xml_GNode* node = tree; // xml_tree_find_node (tree, pos); 
    /* .off<=pos, if it isnt a leafnode then all children have pos<=.off */

    /* we update nodes only on going .next and .up */
    // while (node->children) node = node->children;

    ___ xml_GNode* next;
    for (; node ; node = next)                       /* the DEL-span is... */
    
{
	// if (!(next = node->next)) next = node->parent;
	// if (node == tree) next = 0;
	if (node->children) next = node->children;
	else if (node->next) next = node->next;
	else if ((next = node->parent)) do 
{
	    if (next->next) 
{ next = next->next; break; }
}
while ((next = next->parent)); if (tree == next) next = 0; if (node->end <= pos) continue; /* "right-outside" */ if (pos+len <= node->off) /* "left-outside" */
{   node->off -= len; node->end -= len; continue; }
if (pos <= node->off)
{
	    if (node->end <= pos+len)                  /* "outer-complete" */
	    
{   
		if (node == tree) /* || 1 */
		
{   /* don't delete root node (|| any node) */
		    node->off = node->end = pos;  
		}
else
{
		    if (node->children) /* a.k.a. next == node->children */
		    
{
			if (node->next) next = node->next;
			else if ((next = node->parent)) do 
{
			    if (next->next) 
{ next = next->next; break; }
}
while ((next = next->parent)); if (tree == next) next = 0; }
xml_g_node_destroy (node); }
}
else
{   
		node->off = pos;                        /* "left-overlap" */
		node->end = node->off + (node->end - (pos+len));
	    }
}
else
{
	    if (node->end <= pos+len)                   /* "right-overlap" */
		node->end = pos;
	    else                                       /* "inner-complete" */
		node->end -= len;
	}
}
____; return g_string_erase (tree->text, pos, len); ____; }
/* 
   Local variables:
   c-file-style: "stroustrup"
   End:
 */