Evas textblock: Fixed two textblock issues (range_delete).

Found using raster's cat-debugging skills.
** No cats were harmed during debugging. **

SVN revision: 70535
This commit is contained in:
Tom Hacohen 2012-04-29 09:09:14 +00:00
parent 1dfc652a9b
commit 7985383914
3 changed files with 76 additions and 60 deletions

View File

@ -712,3 +712,8 @@
* Lock less font rendering.
* Removing EVAS_FRAME_QUEUING, EVAS_SLI, METRIC_CACHE and WORD_CACHE.
2012-04-29 Tom Hacohen (TAsn)
* Textblock: Fixed a couple of bugs with range delete.

View File

@ -535,7 +535,6 @@ static const Evas_Object_Func object_func =
static Eina_Bool _evas_textblock_cursor_is_at_the_end(const Evas_Textblock_Cursor *cur);
static void _evas_textblock_node_text_remove(Evas_Object_Textblock *o, Evas_Object_Textblock_Node_Text *n);
static void _evas_textblock_node_text_remove_formats_between(Evas_Object_Textblock *o, Evas_Object_Textblock_Node_Text *n, int start, int end);
static Evas_Object_Textblock_Node_Format *_evas_textblock_cursor_node_format_before_or_at_pos_get(const Evas_Textblock_Cursor *cur);
static size_t _evas_textblock_node_format_pos_get(const Evas_Object_Textblock_Node_Format *fmt);
static void _evas_textblock_node_format_remove(Evas_Object_Textblock *o, Evas_Object_Textblock_Node_Format *n, int visual_adjustment);
@ -6579,7 +6578,6 @@ _evas_textblock_node_text_adjust_offsets_to_start(Evas_Object_Textblock *o,
int use_end = 1;
int delta = 0;
int first = 1;
int update_format_node;
size_t pos = 0;
int orig_end;
@ -6628,7 +6626,6 @@ _evas_textblock_node_text_adjust_offsets_to_start(Evas_Object_Textblock *o,
return EINA_FALSE;
}
update_format_node = ((itr == n->format_node) && (new_node != n));
delta = orig_end - pos;
itr->offset -= pos - start;
@ -6671,65 +6668,11 @@ _evas_textblock_node_text_adjust_offsets_to_start(Evas_Object_Textblock *o,
}
last_node->text_node = new_node;
if (update_format_node)
{
n->format_node = last_node;
}
}
return EINA_FALSE;
}
/**
* @internal
* Removes all the format nodes between start and end in the text node n.
* This function updates the offset of the next format node and the
* text nodes pointing to it. if end == -1 end means the end of the string.
*
* @param o the textblock object.
* @param n the text node the positinos refer to.
* @param start the start of where to delete from.
* @param end the end of the section to delete, if end == -1 it means the end of the string.
*/
static void
_evas_textblock_node_text_remove_formats_between(Evas_Object_Textblock *o,
Evas_Object_Textblock_Node_Text *n, int start, int end)
{
Evas_Object_Textblock_Node_Format *itr;
int use_end = 1;
int offset = end - start;
itr = n->format_node;
if (itr)
start -= itr->offset;
if (offset < 0) offset = 0;
if (end < 0) use_end = 0;
while (itr && (itr->text_node == n))
{
Evas_Object_Textblock_Node_Format *nnode;
int tmp_offset = 0;
/* start is negative when this gets relevant */
if ((offset + start < 0) && use_end)
{
break;
}
nnode = _NODE_FORMAT(EINA_INLIST_GET(itr)->next);
if (nnode)
{
tmp_offset = nnode->offset;
}
if (start <= 0)
{
/* Don't do visible adjustments because we are removing the visual
* chars anyway and taking those into account */
_evas_textblock_node_format_remove(o, itr, 0);
}
start -= tmp_offset;
itr = nnode;
}
}
/**
* @internal
* Returns the first format in the range between start and end in the textblock
@ -7678,10 +7621,33 @@ evas_textblock_cursor_range_delete(Evas_Textblock_Cursor *cur1, Evas_Textblock_C
if (n1 == n2)
{
Evas_Object_Textblock_Node_Format *remove_format = NULL;
Evas_Object_Textblock_Node_Text *merge_node = NULL;
if ((cur1->pos == 0) &&
(cur2->pos == eina_ustrbuf_length_get(n1->unicode)))
{
_evas_textblock_node_text_remove_formats_between(o, n1, 0, -1);
/* Remove the whole node. */
Evas_Object_Textblock_Node_Text *n =
_NODE_TEXT(EINA_INLIST_GET(n1)->next);
if (n)
{
should_merge = EINA_TRUE;
}
else
{
n = _NODE_TEXT(EINA_INLIST_GET(n1)->prev);
if (n)
{
merge_node = n;
remove_format = merge_node->format_node;
}
else
{
/* Clear the whole textblock - do it nicer. */
evas_object_textblock_text_markup_set(cur1->obj, "");
return;
}
}
}
else
{
@ -7690,6 +7656,13 @@ evas_textblock_cursor_range_delete(Evas_Textblock_Cursor *cur1, Evas_Textblock_C
}
eina_ustrbuf_remove(n1->unicode, cur1->pos, cur2->pos);
_evas_textblock_cursors_update_offset(cur1, cur1->node, cur1->pos, - (cur2->pos - cur1->pos));
if (merge_node)
{
_evas_textblock_node_text_adjust_offsets_to_start(o, n1,
0, -1);
_evas_textblock_nodes_merge(o, merge_node);
evas_textblock_cursor_set_at_format(cur1, remove_format);
}
}
else
{
@ -7703,8 +7676,8 @@ evas_textblock_cursor_range_delete(Evas_Textblock_Cursor *cur1, Evas_Textblock_C
Evas_Object_Textblock_Node_Text *nnode;
nnode = _NODE_TEXT(EINA_INLIST_GET(n)->next);
_evas_textblock_cursors_set_node(o, n, n1);
_evas_textblock_node_text_remove(o, n);
_evas_textblock_node_text_adjust_offsets_to_start(o, n, 0, -1);
_evas_textblock_nodes_merge(o, n1);
n = nnode;
}
should_merge = _evas_textblock_node_text_adjust_offsets_to_start(o, n2,
@ -7718,6 +7691,7 @@ evas_textblock_cursor_range_delete(Evas_Textblock_Cursor *cur1, Evas_Textblock_C
_evas_textblock_cursors_update_offset(cur1, cur1->node, cur1->pos,
-cur1->pos);
_evas_textblock_cursors_update_offset(cur2, cur2->node, 0, -cur2->pos);
cur2->pos = 0;
_evas_textblock_nodes_merge(o, n1);
}
fnode = _evas_textblock_cursor_node_format_at_pos_get(cur1);
@ -7725,6 +7699,7 @@ evas_textblock_cursor_range_delete(Evas_Textblock_Cursor *cur1, Evas_Textblock_C
n1 = cur1->node;
n2 = cur2->node;
n1->dirty = n2->dirty = EINA_TRUE;
if (should_merge)
{
/* We call this function instead of the cursor one because we already

View File

@ -765,6 +765,42 @@ START_TEST(evas_textblock_format_removal)
fnode = evas_textblock_node_format_next_get(fnode);
fail_if (fnode);
/* Range deletion across paragraph - a bug found in elm. */
evas_object_textblock_text_markup_set(tb,
"This is an entry widget in this window that<ps/>"
"uses markup <b>like this</> for styling and<ps/>"
"formatting <em>like this</>, as well as<ps/>"
"<a href=X><link>links in the text</></a>, so enter text<ps/>"
"in here to edit it. By the way, links are<ps/>"
"called <a href=anc-02>Anchors</a> so you will need<ps/>"
"to refer to them this way.<ps/>"
"<ps/>"
"Also you can stick in items with (relsize + ascent): "
"<item relsize=16x16 vsize=ascent href=emoticon/evil-laugh></item>"
" (full) "
"<item relsize=16x16 vsize=full href=emoticon/guilty-smile></item>"
" (to the left)<ps/>"
"Also (size + ascent): "
"<item size=16x16 vsize=ascent href=emoticon/haha></item>"
" (full) "
"<item size=16x16 vsize=full href=emoticon/happy-panting></item>"
" (before this)<ps/>"
"And as well (absize + ascent): "
"<item absize=64x64 vsize=ascent href=emoticon/knowing-grin></item>"
" (full) "
"<item absize=64x64 vsize=full href=emoticon/not-impressed></item>"
" or even paths to image files on disk too like: "
"<item absize=96x128 vsize=full href=file://bla/images/sky_01.jpg></item>"
" ... end.");
evas_textblock_cursor_paragraph_first(cur);
evas_textblock_cursor_paragraph_last(main_cur);
evas_textblock_cursor_range_delete(cur, main_cur);
fnode = evas_textblock_node_format_first_get(tb);
fail_if(fnode);
/* Two formats in the same place. */
evas_object_textblock_text_markup_set(tb, "a<b><a>b</a></b>b");
evas_textblock_cursor_pos_set(cur, 1);