All pastes #492411 Raw Edit

Unnamed

public text v1 · immutable
·published 2007-05-17 04:47 UTC
rendered paste body
/* vim: set sw=8 ts=8 sts=8 noexpandtab: */
#include "ewl_text_fmt.h"
#include "ewl_private.h"
#include "ewl_macros.h"
#include "ewl_debug.h"

#define FMT_PRINT(fmt) \
	{ \
		printf("Set current format %d\n" \
				"\tindex: %d chars %d bytes\n" \
				"\tlength: %d chars %d bytes\n", \
				__LINE__, \
				fmt->current_node.char_idx, \
				fmt->current_node.byte_idx, \
				fmt->length.char_len, \
				fmt->length.byte_len); \
	}

static void ewl_text_fmt_node_free(void *node);

Ewl_Text_Fmt *
ewl_text_fmt_new(Ewl_Text *t)
{
	Ewl_Text_Fmt *fmt;

	DENTER_FUNCTION(DLEVEL_STABLE);

	fmt = NEW(Ewl_Text_Fmt, 1);
	if (!fmt) DRETURN_PTR(NULL, DLEVEL_STABLE);

	fmt->nodes = ecore_dlist_new();
	if (!fmt->nodes)
	{
		ewl_text_fmt_destroy(fmt);
		DRETURN_PTR(NULL, DLEVEL_STABLE);
	}
	ecore_dlist_set_free_cb(fmt->nodes, ewl_text_fmt_node_free);

	fmt->text = t;

	DRETURN_PTR(fmt, DLEVEL_STABLE);
}

void
ewl_text_fmt_destroy(Ewl_Text_Fmt *fmt)
{
	DENTER_FUNCTION(DLEVEL_STABLE);
	DCHECK_PARAM_PTR("fmt", fmt);

	if (fmt->nodes) ecore_dlist_destroy(fmt->nodes);
	FREE(fmt);

	DLEAVE_FUNCTION(DLEVEL_STABLE);
}

void
ewl_text_fmt_clear(Ewl_Text_Fmt *fmt)
{
	Ewl_Text_Fmt_Node *node;

	DENTER_FUNCTION(DLEVEL_STABLE);
	DCHECK_PARAM_PTR("fmt", fmt);

	while ((node = ecore_dlist_remove_first(fmt->nodes)))
	{
		if (node->tx) ewl_text_context_release(node->tx);
		FREE(node);
	}

	fmt->current_node.char_idx = 0;
	fmt->current_node.byte_idx = 0;
	FMT_PRINT(fmt);
	
	fmt->length.char_len = 0;
	fmt->length.byte_len = 0;

	DLEAVE_FUNCTION(DLEVEL_STABLE);
}

void
ewl_text_fmt_node_prepend(Ewl_Text_Fmt *fmt, Ewl_Text_Fmt_Node *node)
{
	DENTER_FUNCTION(DLEVEL_STABLE);
	DCHECK_PARAM_PTR("fmt", fmt);
	DCHECK_PARAM_PTR("node", node);

	ecore_dlist_prepend(fmt->nodes, node);

	/* we prepended so we need to add the nodes lengths to the current
	 * format position length so we're still in the right spot */
	fmt->current_node.char_idx += node->char_len;
	fmt->current_node.byte_idx += node->byte_len;

	fmt->length.char_len += node->char_len;
	fmt->length.byte_len += node->byte_len;
	
	DLEAVE_FUNCTION(DLEVEL_STABLE);
}

void
ewl_text_fmt_node_append(Ewl_Text_Fmt *fmt,  Ewl_Text_Fmt_Node *node)
{
	DENTER_FUNCTION(DLEVEL_STABLE);
	DCHECK_PARAM_PTR("fmt", fmt);
	DCHECK_PARAM_PTR("node", node);

	ecore_dlist_append(fmt->nodes, node);

	fmt->length.char_len += node->char_len;
	fmt->length.byte_len += node->byte_len;

	DLEAVE_FUNCTION(DLEVEL_STABLE);
}

void
ewl_text_fmt_node_insert(Ewl_Text_Fmt *fmt, Ewl_Text_Fmt_Node *node,
						unsigned int idx)
{
	Ewl_Text_Fmt_Node *cur_node, *left, *next;

	DENTER_FUNCTION(DLEVEL_STABLE);
	DCHECK_PARAM_PTR("fmt", fmt);
	DCHECK_PARAM_PTR("node", node);

	cur_node = ecore_dlist_current(fmt->nodes);
	
	/* insert at the current location */
	if (fmt->current_node.char_idx == idx)
		ecore_dlist_insert(fmt->nodes, node);

	/* insert at the end of the current node */
	else if ((fmt->current_node.char_idx + cur_node->char_len) == idx)
	{
		ecore_dlist_next(fmt->nodes);
		next = ecore_dlist_current(fmt->nodes);

		if (next) 
		{
			ecore_dlist_insert(fmt->nodes, node);
	
			/* update our index as we're currently on the next node */
			fmt->current_node.char_idx += cur_node->char_len;
			fmt->current_node.byte_idx += cur_node->byte_len;
		}
		else 
		{
			ecore_dlist_append(fmt->nodes, node);
			ecore_dlist_goto_last(fmt->nodes);

			/* we haven't incremented the sizes yet so we're at
			 * the end of the last set of nodes */
			fmt->current_node.char_idx = fmt->length.char_len;
			fmt->current_node.byte_idx = fmt->length.byte_len;
			FMT_PRINT(fmt);
		}
	}
	else
	{
		/* insert into the middle of the current node */
		left = ewl_text_fmt_node_new(node->tx, 
				idx - fmt->current_node.char_idx, 0);
		ewl_text_fmt_char_to_byte(fmt, idx, 
					idx - fmt->current_node.char_idx, 
					NULL, &(left->byte_len));

		cur_node->char_len -= left->char_len;
		cur_node->byte_len -= left->byte_len;

		/* insert inserts to the right, so move past the current node so we
		 * can insert the two new ones. If we have a node to the left we
		 * insert the left node then the new node so the new one is in the
		 * middle. If there is no node to the left we insert the new node
		 * then the left node. */
		ecore_dlist_next(fmt->nodes);
		next = ecore_dlist_current(fmt->nodes);
		if (next)
		{
			ecore_dlist_insert(fmt->nodes, left);
			ecore_dlist_insert(fmt->nodes, node);
		}
		else
		{
			ecore_dlist_append(fmt->nodes, node);
			ecore_dlist_goto_last(fmt->nodes);
			ecore_dlist_append(fmt->nodes, left);
		}
		fmt->current_node.char_idx += cur_node->char_len;
		fmt->current_node.byte_idx += cur_node->byte_len;
	}

	fmt->length.char_len += node->char_len;
	fmt->length.byte_len += node->byte_len;

	DLEAVE_FUNCTION(DLEVEL_STABLE);
}

void
ewl_text_fmt_node_delete(Ewl_Text_Fmt *fmt, unsigned int idx, 
					unsigned int char_len)
{
	Ewl_Text_Fmt_Node *node;

	DENTER_FUNCTION(DLEVEL_STABLE);
	DCHECK_PARAM_PTR("fmt", fmt);

	node = ecore_dlist_current(fmt->nodes);
	while (char_len > 0)
	{
		unsigned int available;

		/* how much space is available in this node to be removed */
		available = node->char_len - (idx - fmt->current_node.char_idx);
		if (available > char_len) available = char_len;

		node->char_len -= available;
		if (node->char_len > 0)
		{
			node->byte_len = 0;
			ewl_text_fmt_char_to_byte(fmt, idx, 
					node->char_len, 
					NULL, &(node->byte_len));

			ecore_dlist_next(fmt->nodes);
			fmt->current_node.char_idx += node->char_len;
			fmt->current_node.byte_idx += node->byte_len;
			node = ecore_dlist_current(fmt->nodes);
		}
		else
		{
			ecore_dlist_remove(fmt->nodes);
			ewl_text_fmt_node_free(node);
			node = ecore_dlist_current(fmt->nodes);
		}
		char_len -= available;
	}

	/* make sure we've still got a current node. if not reset to the
	 * first node in the list */
	node = ecore_dlist_current(fmt->nodes);
	if (!node)
	{
		ecore_dlist_goto_first(fmt->nodes);
		fmt->current_node.char_idx = 0;
		fmt->current_node.byte_idx = 0;
		FMT_PRINT(fmt);
	}

	DLEAVE_FUNCTION(DLEVEL_STABLE);
}

unsigned int
ewl_text_fmt_node_count_get(Ewl_Text_Fmt *fmt)
{
	DENTER_FUNCTION(DLEVEL_STABLE);
	DCHECK_PARAM_PTR_RET("fmt", fmt, 0);

	DRETURN_INT(ecore_dlist_nodes(fmt->nodes), DLEVEL_STABLE);
}

Ewl_Text_Fmt_Node *
ewl_text_fmt_get_last(Ewl_Text_Fmt *fmt)
{
	DENTER_FUNCTION(DLEVEL_STABLE);
	DCHECK_PARAM_PTR_RET("fmt", fmt, NULL);

	DRETURN_PTR(ecore_dlist_goto_last(fmt->nodes),DLEVEL_STABLE);
}

Ewl_Text_Fmt_Node *
ewl_text_fmt_get_first(Ewl_Text_Fmt *fmt)
{
	DENTER_FUNCTION(DLEVEL_STABLE);
	DCHECK_PARAM_PTR_RET("fmt", fmt, NULL);

	DRETURN_PTR(ecore_dlist_goto_first(fmt->nodes),DLEVEL_STABLE);
}

Ewl_Text_Fmt_Node *
ewl_text_fmt_get_current(Ewl_Text_Fmt *fmt)
{
	DENTER_FUNCTION(DLEVEL_STABLE);
	DCHECK_PARAM_PTR_RET("fmt", fmt, NULL);

	DRETURN_PTR(ecore_dlist_current(fmt->nodes),DLEVEL_STABLE);
}

Ewl_Text_Fmt_Node *
ewl_text_fmt_get(Ewl_Text_Fmt *fmt, unsigned int idx)
{
	Ewl_Text_Fmt_Node *node, *current_node;
	unsigned int cur_byte, cur_char;
	
	DENTER_FUNCTION(DLEVEL_STABLE);
	DCHECK_PARAM_PTR_RET("fmt", fmt, NULL);
	
	cur_char = fmt->current_node.char_idx;
	cur_byte = fmt->current_node.byte_idx;
	current_node = ecore_dlist_current(fmt->nodes);
	
	ewl_text_fmt_goto(fmt, idx);
	node = ecore_dlist_current(fmt->nodes);
	
	ecore_dlist_goto(fmt->nodes, current_node);
	fmt->current_node.char_idx = cur_char;
	fmt->current_node.byte_idx = cur_byte;
	FMT_PRINT(fmt);
	
	DRETURN_PTR(node, DLEVEL_STABLE);
}

void
ewl_text_fmt_goto(Ewl_Text_Fmt *fmt, unsigned int idx)
{
	Ewl_Text_Fmt_Node *node; 
	
	DENTER_FUNCTION(DLEVEL_STABLE);
	DCHECK_PARAM_PTR("fmt", fmt);
	
	/* set to start of text */
	if (idx == 0)
	{
		fmt->current_node.char_idx = 0;
		fmt->current_node.byte_idx = 0;
		FMT_PRINT(fmt);
		ecore_dlist_goto_first(fmt->nodes);
	}
	
	/* set to end of text */
	else if (idx >= fmt->length.char_len)
	{
		node = ecore_dlist_goto_last(fmt->nodes);

		fmt->current_node.char_idx = 
			fmt->length.char_len - node->char_len;
		fmt->current_node.byte_idx = 
			fmt->length.byte_len - node->byte_len;
		printf("Node len: %d chars %d bytes\n", node->char_len,
				node->byte_len);

		FMT_PRINT(fmt);
	}

	/* set to after our current position
 	 * walk forward until we cover the given position */
	else if (fmt->current_node.char_idx < idx)
	{
		node = ecore_dlist_current(fmt->nodes);
		while ((node->char_len + fmt->current_node.char_idx) < idx)
		{
			fmt->current_node.char_idx += node->char_len;
			fmt->current_node.byte_idx += node->byte_len;

			ecore_dlist_next(fmt->nodes);
			node = ecore_dlist_current(fmt->nodes);
			if (!node) break;
		}
	}
	
	/* set before our position
	 * walk back until we're less then the given position */
	else
	{
		while (fmt->current_node.char_idx > idx)
		{
			ecore_dlist_previous(fmt->nodes);
			node = ecore_dlist_current(fmt->nodes);
			if (!node) break;

			fmt->current_node.char_idx -= node->char_len;
			fmt->current_node.byte_idx -= node->byte_len;
		}
	}
	
	node = ecore_dlist_current(fmt->nodes);
	if (!node)
	{
		DWARNING("Unable to place cursor at %d", idx);
		
		ecore_dlist_goto_first(fmt->nodes);
		fmt->current_node.char_idx = 0;
		fmt->current_node.byte_idx = 0;

		FMT_PRINT(fmt);
	}
	
	DLEAVE_FUNCTION(DLEVEL_STABLE);
}

/**
 * @param t: The text to dump the formatting from
 * @return Returns no value
 * @brief Prints out the formatting information for the given text object
 */
void
ewl_text_fmt_dump(Ewl_Text_Fmt *fmt)
{
	Ewl_Text_Fmt_Node *node, *cur_node;

	DENTER_FUNCTION(DLEVEL_STABLE);
	DCHECK_PARAM_PTR("fmt", fmt);

	cur_node = ecore_dlist_current(fmt->nodes);
	ecore_dlist_goto_first(fmt->nodes);
	
	while ((node = ecore_dlist_next(fmt->nodes)))
	{
		printf("%d chars, %d bytes\n", node->char_len, node->byte_len);
		ewl_text_context_print(node->tx, "    ");
		printf("\n\n");
	}
	
	ecore_dlist_goto(fmt->nodes, cur_node);

	DLEAVE_FUNCTION(DLEVEL_STABLE);
}


/* This will determine the number of bytes to get to char_pos in the text
 * and, if needed will get the number of bytes between char_pos and 
 * char_pos + char_len 
 *
 * This _HAS_ to leave the list with the same current pointer is when it
 * started */
void
ewl_text_fmt_char_to_byte(Ewl_Text_Fmt *fmt, 
			unsigned int char_idx, unsigned int char_len,
			unsigned int *byte_idx, unsigned int *byte_len)
{
	Ewl_Text *t;
	Ewl_Text_Fmt_Node *current_node, *node = NULL;
	unsigned int cur_char_idx = 0, bidx = 0;
	void *(*move)(Ecore_DList *list);

	DENTER_FUNCTION(DLEVEL_STABLE);
	DCHECK_PARAM_PTR("fmt", fmt);

	t = fmt->text;
	current_node = ecore_dlist_current(fmt->nodes);
	cur_char_idx = fmt->current_node.char_idx;
	bidx = fmt->current_node.byte_idx;

printf("cur_node %p char_idx %u cur_char_idx %u\n", current_node, char_idx, cur_char_idx);
	if (cur_char_idx > 10000)
		ewl_text_fmt_dump(fmt);

	/* first step is to find the actual node that this text represents */
	if (fmt->current_node.char_idx < char_idx)
	{
		/* walk forward until we cover the given position */
		node = ecore_dlist_current(fmt->nodes);
		while ((node->char_len + cur_char_idx) < char_idx)
		{
			cur_char_idx += node->char_len;
			bidx += node->byte_len;

			ecore_dlist_next(fmt->nodes);
			node = ecore_dlist_current(fmt->nodes);
			if (!node) break;
		}
		move = ecore_dlist_previous;

		if (!node) 
		{
			node = ecore_dlist_goto_last(fmt->nodes);
			fmt->current_node.char_idx = fmt->length.char_len - node->char_len;
			fmt->current_node.byte_idx = fmt->length.byte_len - node->byte_len;
			FMT_PRINT(fmt);
		}
	}
	else
	{
		/* walk back until we're less then the given position */
		while (cur_char_idx > char_idx)
		{
			ecore_dlist_previous(fmt->nodes);
			node = ecore_dlist_current(fmt->nodes);
			if (!node) break;

			cur_char_idx -= node->char_len;
			bidx -= node->byte_len;
		}
		move = ecore_dlist_next;

		if (!node) 
		{
			node = ecore_dlist_goto_first(fmt->nodes);
			fmt->current_node.char_idx = 0;
			fmt->current_node.byte_idx = 0;
			FMT_PRINT(fmt);
		}
	}
	
	/* we still need to count within this node */
	while (cur_char_idx < char_idx)
	{
		unsigned int bytes;

		ewl_text_text_next_char(t->text + bidx, &bytes);
		bidx += bytes;
		cur_char_idx ++;
	}

	if (byte_len)
	{
		if (char_len == 0) *byte_len = 0;
		else
		{
			char *txt;

			txt = t->text + bidx;
			cur_char_idx = 0;
			while (cur_char_idx < char_len)
			{
				unsigned int bytes;

				txt = ewl_text_text_next_char(txt, &bytes);
				*byte_len += bytes;
				cur_char_idx ++;
			}
		}
	}

	if (byte_idx) *byte_idx = bidx;

	node = ecore_dlist_current(fmt->nodes);
	while (node != current_node)
	{
		move(fmt->nodes);
		node = ecore_dlist_current(fmt->nodes);
	}

	DLEAVE_FUNCTION(DLEVEL_STABLE);
}

/* This will determine the number of chars to get to byte_idx in the text
 * and, if needed will get the number of chars between byte_idx and 
 * byte_idx + byte_len */
void
ewl_text_fmt_byte_to_char(Ewl_Text_Fmt *fmt, 
			unsigned int byte_idx, unsigned int byte_len, 
			unsigned int *char_idx, unsigned int *char_len)
{
	Ewl_Text *t;
	Ewl_Text_Fmt_Node *current_node, *node = NULL;
	unsigned int byte_count = 0, cidx = 0;
	void *(*move)(Ecore_DList *list);

	DENTER_FUNCTION(DLEVEL_STABLE);
	DCHECK_PARAM_PTR("fmt", fmt);

	t = fmt->text;
	current_node = ecore_dlist_current(fmt->nodes);
	if (fmt->current_node.byte_idx < byte_idx)
	{
		byte_count = fmt->current_node.byte_idx;
		cidx = fmt->current_node.char_idx;

		/* walk forward until we cover the given position */
		node = ecore_dlist_current(fmt->nodes);
		while ((node->byte_len + byte_count) < byte_idx)
		{
			byte_count += node->byte_len;
			cidx += node->char_len;

			ecore_dlist_next(fmt->nodes);
			node = ecore_dlist_current(fmt->nodes);
			if (!node) break;
		}

		if (!node) 
		{
			ecore_dlist_goto_last(fmt->nodes);
			fmt->current_node.char_idx = fmt->length.char_len - node->char_len;
			fmt->current_node.byte_idx = fmt->length.byte_len - node->byte_len;
			FMT_PRINT(fmt);
		}
		move = ecore_dlist_previous;
	}
	else
	{
		/* walk back until we're less then the given position */
		node = ecore_dlist_current(fmt->nodes);
		while (byte_count > byte_idx)
		{
			ecore_dlist_previous(fmt->nodes);
			node = ecore_dlist_current(fmt->nodes);
			if (!node) break;

			byte_count -= node->byte_len;
			cidx -= node->char_len;
		}

		if (!node)
		{
			ecore_dlist_goto_first(fmt->nodes);
			fmt->current_node.char_idx = 0;
			fmt->current_node.byte_idx = 0;
			FMT_PRINT(fmt);
		}
		move = ecore_dlist_next;
	}

	/* we still need to count within this node */
	while (byte_count < byte_idx)
	{
		unsigned int bytes;

		ewl_text_text_next_char(t->text + byte_count, &bytes);
		byte_count += bytes;
		cidx ++;
	}

	if (char_len)
	{
		if (byte_len == 0) *char_len = 0;
		else
		{
			char *txt;

			txt = t->text + byte_idx;
			byte_count = 0;
			while (byte_count < byte_len)
			{
				unsigned int bytes;

				txt = ewl_text_text_next_char(txt, &bytes);
				byte_count += bytes;
				(*char_len) ++;
			}
		}
	}

	if (char_idx) *char_idx = cidx;

	node = ecore_dlist_current(fmt->nodes);
	while (node != current_node)
	{
		move(fmt->nodes);
		node = ecore_dlist_current(fmt->nodes);
	}

	DLEAVE_FUNCTION(DLEVEL_STABLE);
}

void
ewl_text_fmt_walk(Ewl_Text_Fmt *fmt, 
	void (*cb)(Ewl_Text_Fmt_Node *, Ewl_Text *, unsigned int byte_idx))
{
	Ewl_Text_Fmt_Node *current_node, *node;
	unsigned int byte_idx = 0;
	
	DENTER_FUNCTION(DLEVEL_STABLE);
	DCHECK_PARAM_PTR("fmt", fmt);
	DCHECK_PARAM_PTR("cb", cb);
	
	current_node = ecore_dlist_current(fmt->nodes);
	ecore_dlist_goto_first(fmt->nodes);
	while ((node = ecore_dlist_next(fmt->nodes)))
	{
		cb(node, fmt->text, byte_idx);
		byte_idx += node->byte_len;
	}
	ecore_dlist_goto(fmt->nodes, current_node);

	DLEAVE_FUNCTION(DLEVEL_STABLE);
}

void
ewl_text_fmt_apply(Ewl_Text_Fmt *fmt, unsigned int context_mask, 
			Ewl_Text_Context *change, unsigned int char_idx,
			unsigned int char_len)
{
	Ewl_Text *t;
	Ewl_Text_Fmt_Node *node;
	
	DENTER_FUNCTION(DLEVEL_STABLE);
	DCHECK_PARAM_PTR("change", change);

	if ((char_len == 0) || (context_mask == EWL_TEXT_CONTEXT_MASK_NONE))
		DRETURN(DLEVEL_STABLE);

	t = fmt->text;
	node = ecore_dlist_current(fmt->nodes);
	while (char_len > 0)
	{
		/* we've walked off the end of the list */
		if (!node) break;

		/* covers entire node */
		if ((char_idx == fmt->current_node.char_idx) 
				&& (node->char_len <= char_len))
		{
			Ewl_Text_Context *new_tx;

			new_tx = ewl_text_context_find(node->tx,
						context_mask, change);
			ewl_text_context_release(node->tx);
			node->tx = new_tx;

			char_idx += node->char_len;
			char_len -= node->char_len;
			ecore_dlist_next(fmt->nodes);
			
			fmt->current_node.char_idx += node->char_len;
			fmt->current_node.byte_idx += node->byte_len;
		}
		
		/* start is the same, node is longer then needed */
		else if (char_idx == fmt->current_node.char_idx)
		{
			unsigned int blen = 0;
			Ewl_Text_Fmt_Node *new;

			ewl_text_fmt_char_to_byte(fmt,
					char_idx, char_len, NULL, &blen);
					
			new = ewl_text_fmt_node_new(
				ewl_text_context_find(node->tx,
						context_mask, change),
						char_len, blen);
			
			node->char_len -= new->char_len;
			node->byte_len -= new->byte_len;

			ecore_dlist_insert(fmt->nodes, new);
			ecore_dlist_next(fmt->nodes);
			
			fmt->current_node.char_idx += new->char_len;
			fmt->current_node.byte_idx += new->byte_len;

			char_idx += new->char_len;
			char_len -= new->char_len;
		}
		
		/* starts are different, need to set context on end of node */
		else
		{
			Ewl_Text_Fmt_Node *new;
			unsigned int blen = 0, right_skip;

			right_skip = char_idx - fmt->current_node.char_idx;
			ewl_text_fmt_char_to_byte(fmt, fmt->current_node.char_idx, 
							right_skip, NULL, &blen);
				
			new = ewl_text_fmt_node_new(node->tx, right_skip, blen);
				
			ecore_dlist_insert(fmt->nodes, new);
			ecore_dlist_next(fmt->nodes);
			if (!ecore_dlist_current(fmt->nodes))
				ecore_dlist_goto_last(fmt->nodes);

			fmt->current_node.char_idx += new->char_len;
			fmt->current_node.byte_idx += new->byte_len;

			/* update node to be the new formatting piece */
			node->tx = ewl_text_context_find(node->tx,
						context_mask, change);
			node->char_len -= new->char_len;
			node->byte_len -= new->byte_len;

			/* the rest of the node is covered */
			if (node->char_len <= char_len)
			{
				char_len -= node->char_len;
				char_idx += node->char_len;

				ecore_dlist_next(fmt->nodes);
				fmt->current_node.char_idx += node->char_len;
				fmt->current_node.byte_idx += node->byte_len;
			}
			
			/* we need to split the node */
			else
			{
				Ewl_Text_Context *tx;
				unsigned int blen = 0;

				tx = new->tx;
				ewl_text_fmt_char_to_byte(fmt,
						char_idx, char_len, 
						NULL, &blen);

				/* we create a new node which will be our
				 * formatting and reset node to be original
				 * formatting */
				new = ewl_text_fmt_node_new(node->tx, 
						char_len, blen);

				ecore_dlist_insert(fmt->nodes, new);
				ecore_dlist_next(fmt->nodes);
				if (!ecore_dlist_current(fmt->nodes))
					ecore_dlist_goto_last(fmt->nodes);
				
				fmt->current_node.char_idx += new->char_len;
				fmt->current_node.byte_idx += new->byte_len;

				node->tx = tx;
				node->char_len -= new->char_len;
				node->byte_len -= new->byte_len;

				char_len -= new->char_len;
				char_idx += new->char_len;
			}
		}
		node = ecore_dlist_current(fmt->nodes);
	}

	/* make sure we're still pointing at a node */
	if (!node) node = ecore_dlist_goto_last(fmt->nodes);

	DLEAVE_FUNCTION(DLEVEL_STABLE);
}

/*
 * Ewl_Text_Fmt_Node stuff
 */
Ewl_Text_Fmt_Node *
ewl_text_fmt_node_new(Ewl_Text_Context *tx, unsigned int char_len, 
					unsigned int byte_len)
{
	Ewl_Text_Fmt_Node *node;

	DENTER_FUNCTION(DLEVEL_STABLE);
	
	node = NEW(Ewl_Text_Fmt_Node, 1);
	if (!node) DRETURN_PTR(NULL, DLEVEL_STABLE);

	node->tx = tx;
	ewl_text_context_acquire(node->tx);
	node->char_len = char_len;
	node->byte_len = byte_len;

	DRETURN_PTR(node, DLEVEL_STABLE);
}

static void 
ewl_text_fmt_node_free(void *node)
{
	Ewl_Text_Fmt_Node *n;
	
	DENTER_FUNCTION(DLEVEL_STABLE);
	DCHECK_PARAM_PTR("node", node);
	
	n = node;
	if (n->tx) ewl_text_context_release(n->tx);
	n->tx = NULL;
	
	FREE(node);
	
	DLEAVE_FUNCTION(DLEVEL_STABLE);
}