summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYakov Goldberg <yakov.g@samsung.com>2013-04-10 14:54:37 +0300
committerYakov Goldberg <yakov.g@samsung.com>2013-04-10 14:59:48 +0300
commit7016872619b7b84e46688de29b133997c43f95ed (patch)
treedcaa050daa1a4f6701680cd14bc3d9bc1f37ba1f
parenta70abbb3811bd9426bc3e30bd70fb3b027cc29e6 (diff)
downloadefl-7016872619b7b84e46688de29b133997c43f95ed.tar.gz
Efl textblock/entry: additions to split BiDi cursor
- handling multiple runs, multiple lines, last char of line/par - tests added Signed-off-by: Yakov Goldberg <yakov.g@samsung.com>
-rw-r--r--ChangeLog3
-rw-r--r--NEWS1
-rw-r--r--src/lib/edje/edje_entry.c6
-rw-r--r--src/lib/evas/Evas.h26
-rw-r--r--src/lib/evas/canvas/evas_object_textblock.c209
-rw-r--r--src/tests/evas/evas_test_textblock.c327
6 files changed, 516 insertions, 56 deletions
diff --git a/ChangeLog b/ChangeLog
index 04fc489a6a..779bf02487 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,6 @@
+2013-04-10 Tom Hacohen (Tasn) Yakov Goldberg
+ * Evas textblock : Added split cursor for BiDi text
+
2013-04-10 WooHyun Jung
* Edje: When cursor is located to each edge, entry now doesn't grab events for cursor movement.
diff --git a/NEWS b/NEWS
index cf24cf20d3..3735e3891a 100644
--- a/NEWS
+++ b/NEWS
@@ -144,6 +144,7 @@ Improvements:
* Use the right macro to disable fcntl.
* Edje: use Eina_Cow to reduce memory usage.
* Embryo: use eina_file_mkstemp().
+ * Evas textblock : Added split cursor for BiDi text
Fixes:
* Fix a memory leak in ecore_con_dns when using ecore_con_server_connect
diff --git a/src/lib/edje/edje_entry.c b/src/lib/edje/edje_entry.c
index d7b0f771c6..b324d97b9f 100644
--- a/src/lib/edje/edje_entry.c
+++ b/src/lib/edje/edje_entry.c
@@ -2409,14 +2409,14 @@ _edje_entry_real_part_init(Edje *ed, Edje_Real_Part *rp)
/* A proxy to the main cursor. */
if (rp->part->cursor_mode == EDJE_ENTRY_CURSOR_MODE_BEFORE)
{
- en->cursor_fg2 = evas_object_image_add(rp->edje->base->evas);
+ en->cursor_fg2 = evas_object_image_add(ed->base->evas);
evas_object_image_source_set(en->cursor_fg2, en->cursor_fg);
evas_object_image_fill_set(en->cursor_fg2, 0, 0, 1, 1);
- evas_object_smart_member_add(en->cursor_fg2, rp->edje->obj);
+ evas_object_smart_member_add(en->cursor_fg2, ed->obj);
evas_object_stack_above(en->cursor_fg2, rp->object);
evas_object_clip_set(en->cursor_fg2, evas_object_clip_get(rp->object));
evas_object_pass_events_set(en->cursor_fg2, EINA_TRUE);
- _edje_subobj_register(en->rp->edje, en->cursor_fg2);
+ _edje_subobj_register(en->ed, en->cursor_fg2);
}
evas_object_textblock_legacy_newline_set(rp->object, EINA_TRUE);
diff --git a/src/lib/evas/Evas.h b/src/lib/evas/Evas.h
index 9d3603b06b..86d0beb8c5 100644
--- a/src/lib/evas/Evas.h
+++ b/src/lib/evas/Evas.h
@@ -11628,8 +11628,30 @@ EAPI char *evas_textblock_cursor_range_text_g
*/
EAPI char *evas_textblock_cursor_content_get(const Evas_Textblock_Cursor *cur) EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1) EINA_MALLOC;
-/** FIXME: doc.
- * The cw2 and etc are not valid if false is returned. */
+/**
+ * Returns the geometry of two cursors ("split cursor"), if logical cursor is
+ * between LTR/RTL text, also considering paragraph direction.
+ * Upper cursor is shown for the text of the same direction as paragraph,
+ * lower cursor - for opposite.
+ *
+ * Split cursor geometry is valid only in '|' cursor mode.
+ * In this case @c EINA_TRUE is returned and cx2, cy2, cw2, ch2 are set,
+ * otherwise it behaves like cursor_geometry_get.
+ *
+ * @param[in] cur the cursor.
+ * @param[out] cx the x of the cursor (or upper cursor)
+ * @param[out] cy the y of the cursor (or upper cursor)
+ * @param[out] cw the width of the cursor (or upper cursor)
+ * @param[out] ch the height of the cursor (or upper cursor)
+ * @param[out] cx2 the x of the lower cursor
+ * @param[out] cy2 the y of the lower cursor
+ * @param[out] cw2 the width of the lower cursor
+ * @param[out] ch2 the height of the lower cursor
+ * @param[in] dir the direction of the cursor, can be NULL.
+ * @param[in] ctype the type of the cursor.
+ * @return @c EINA_TRUE for split cursor, @c EINA_FALSE otherwise
+ * @since 1.8
+ */
EAPI Eina_Bool
evas_textblock_cursor_geometry_bidi_get(const Evas_Textblock_Cursor *cur, Evas_Coord *cx, Evas_Coord *cy, Evas_Coord *cw, Evas_Coord *ch, Evas_Coord *cx2, Evas_Coord *cy2, Evas_Coord *cw2, Evas_Coord *ch2, Evas_Textblock_Cursor_Type ctype);
diff --git a/src/lib/evas/canvas/evas_object_textblock.c b/src/lib/evas/canvas/evas_object_textblock.c
index 994b258a65..a274319446 100644
--- a/src/lib/evas/canvas/evas_object_textblock.c
+++ b/src/lib/evas/canvas/evas_object_textblock.c
@@ -8950,21 +8950,43 @@ evas_textblock_cursor_format_is_visible_get(const Evas_Textblock_Cursor *cur)
return EVAS_TEXTBLOCK_IS_VISIBLE_FORMAT_CHAR(text[cur->pos]);
}
+#ifdef BIDI_SUPPORT
+static Evas_Object_Textblock_Line*
+_find_layout_line_by_item(Evas_Object_Textblock_Paragraph *par, Evas_Object_Textblock_Item *_it)
+{
+ Evas_Object_Textblock_Line *ln;
+
+ EINA_INLIST_FOREACH(par->lines, ln)
+ {
+ Evas_Object_Textblock_Item *it;
+
+ EINA_INLIST_FOREACH(ln->items, it)
+ {
+ if (_it == it)
+ return ln;
+ }
+ }
+ return NULL;
+}
+#endif
+
EAPI Eina_Bool
evas_textblock_cursor_geometry_bidi_get(const Evas_Textblock_Cursor *cur, Evas_Coord *cx, Evas_Coord *cy, Evas_Coord *cw, Evas_Coord *ch, Evas_Coord *cx2, Evas_Coord *cy2, Evas_Coord *cw2, Evas_Coord *ch2, Evas_Textblock_Cursor_Type ctype)
{
- const Evas_Textblock_Cursor *dir_cur;
- Evas_Textblock_Cursor cur2;
if (!cur) return EINA_FALSE;
Evas_Object_Textblock *o = eo_data_get(cur->obj, MY_CLASS);
if (!o->formatted.valid) _relayout(cur->obj);
- dir_cur = cur;
if (ctype == EVAS_TEXTBLOCK_CURSOR_UNDER)
{
evas_textblock_cursor_pen_geometry_get(cur, cx, cy, cw, ch);
return EINA_FALSE;
}
+
+#ifdef BIDI_SUPPORT
+#define IS_RTL(par) ((par) % 2)
+#define IS_DIFFERENT_DIR(l1, l2) ((IS_RTL(l1) && (!IS_RTL(l2))) || \
+ ((!IS_RTL(l1)) && IS_RTL(l2)))
else
{
Evas_Object_Textblock_Line *ln = NULL;
@@ -8972,74 +8994,159 @@ evas_textblock_cursor_geometry_bidi_get(const Evas_Textblock_Cursor *cur, Evas_C
_find_layout_item_match(cur, &ln, &it);
if (ln && it)
{
- if (cw) *cw = 0;
- if (cw2) *cw2 = 0;
- /* If we are at the start or the end of the item there's a chance
- * we'll want a split cursor.
- * FIXME: Handle the last char of the last paragraph.
- * FIXME: Handle multiple items of the same direction.
- * FIXME: Handle items across different lines.. */
- if (cur->pos == it->text_pos)
+ if (ln->par->is_bidi)
{
- Evas_BiDi_Direction itdir = (it->type == EVAS_TEXTBLOCK_ITEM_TEXT) ?
- _ITEM_TEXT(it)->text_props.bidi_dir : _ITEM_FORMAT(it)->bidi_dir;
+ if (cw) *cw = 0;
+ if (cw2) *cw2 = 0;
+
+ /* If we are at the start or the end of the item there's a chance
+ * we'll want a split cursor. */
Evas_Object_Textblock_Item *previt = NULL;
- Evas_BiDi_Direction previtdir = EVAS_BIDI_DIRECTION_NEUTRAL;
- /* Get the logically previous item. */
+ Evas_Object_Textblock_Item *it1 = NULL, *it2 = NULL;
+ Evas_Coord adv1 = 0, adv2 = 0;
+
+ if (cur->pos == it->text_pos)
{
- Eina_List *itr;
- Evas_Object_Textblock_Item *ititr;
- EINA_LIST_FOREACH(ln->par->logical_items, itr, ititr)
+ EvasBiDiLevel par_level, it_level, previt_level;
+
+ _layout_update_bidi_props(o, ln->par);
+ par_level = *(ln->par->bidi_props->embedding_levels);
+ it_level = ln->par->bidi_props->embedding_levels[it->text_pos];
+ /* Get the logically previous item. */
{
- if (ititr == it)
- break;
- previt = ititr;
+ Eina_List *itr;
+ Evas_Object_Textblock_Item *ititr;
+
+ EINA_LIST_FOREACH(ln->par->logical_items, itr, ititr)
+ {
+ if (ititr == it)
+ break;
+ previt = ititr;
+ }
+
+ if (previt)
+ {
+ previt_level = ln->par->bidi_props->embedding_levels[previt->text_pos];
+ }
}
- if (previt)
+ if (previt && (it_level != previt_level))
{
- previtdir = (previt->type == EVAS_TEXTBLOCK_ITEM_TEXT) ?
- _ITEM_TEXT(previt)->text_props.bidi_dir : _ITEM_FORMAT(previt)->bidi_dir;
+ Evas_Object_Textblock_Item *curit = NULL, *curit_opp = NULL;
+ EvasBiDiLevel cur_level;
+
+ if (it_level > previt_level)
+ {
+ curit = it;
+ curit_opp = previt;
+ cur_level = it_level;
+ }
+ else
+ {
+ curit = previt;
+ curit_opp = it;
+ cur_level = previt_level;
+ }
+
+ if (((curit == it) && (!IS_RTL(par_level))) ||
+ ((curit == previt) && (IS_RTL(par_level))))
+ {
+ adv1 = (IS_DIFFERENT_DIR(cur_level, par_level)) ?
+ curit_opp->adv : 0;
+ adv2 = curit->adv;
+ }
+ else if (((curit == previt) && (!IS_RTL(par_level))) ||
+ ((curit == it) && (IS_RTL(par_level))))
+ {
+ adv1 = (IS_DIFFERENT_DIR(cur_level, par_level)) ?
+ 0 : curit->adv;
+ adv2 = 0;
+ }
+
+ if (!IS_DIFFERENT_DIR(cur_level, par_level))
+ curit_opp = curit;
+
+ it1 = curit_opp;
+ it2 = curit;
}
+ /* Clear the bidi props because we don't need them anymore. */
+ evas_bidi_paragraph_props_unref(ln->par->bidi_props);
+ ln->par->bidi_props = NULL;
}
-
- if (previt && (itdir != previtdir))
+ /* Handling last char in line (or in paragraph).
+ * T.e. prev condition didn't work, so we are not standing in the beginning of item,
+ * but in the end of line or paragraph. */
+ else if (evas_textblock_cursor_eol_get(cur))
{
- Evas_Object_Textblock_Item *curit = NULL;
- /* If the current dir is different than the paragraph dir
- * this is our item. */
- if (itdir != ln->par->direction)
- {
- curit = it;
- }
- else
- {
- curit = previt;
- }
+ EvasBiDiLevel par_level, it_level;
- if (((curit == it) && (ln->par->direction == EVAS_BIDI_DIRECTION_LTR)) ||
- ((curit == previt) && (ln->par->direction == EVAS_BIDI_DIRECTION_RTL)))
- {
- if (cx) *cx = ln->x + curit->x;
- if (cx2) *cx2 = ln->x + curit->x + curit->w;
- }
- else
+ _layout_update_bidi_props(o, ln->par);
+ par_level = *(ln->par->bidi_props->embedding_levels);
+ it_level = ln->par->bidi_props->embedding_levels[it->text_pos];
+
+ if (it_level > par_level)
{
- if (cx) *cx = ln->x + curit->x + curit->w;
- if (cx2) *cx2 = ln->x + curit->x;
+ Evas_Object_Textblock_Item *lastit = it;
+
+ if (IS_RTL(par_level)) /* RTL par*/
+ {
+ /* We know, that all the items before current are of the same or bigger embedding level.
+ * So search backwards for the first one. */
+ while (EINA_INLIST_GET(lastit)->prev)
+ {
+ lastit = _EINA_INLIST_CONTAINER(it, EINA_INLIST_GET(lastit)->prev);
+ }
+
+ adv1 = 0;
+ adv2 = it->adv;
+ }
+ else /* LTR par */
+ {
+ /* We know, that all the items after current are of bigger or same embedding level.
+ * So search forward for the last one. */
+ while (EINA_INLIST_GET(lastit)->next)
+ {
+ lastit = _EINA_INLIST_CONTAINER(it, EINA_INLIST_GET(lastit)->next);
+ }
+
+ adv1 = lastit->adv;
+ adv2 = 0;
+ }
+
+ it1 = lastit;
+ it2 = it;
}
+ /* Clear the bidi props because we don't need them anymore. */
+ evas_bidi_paragraph_props_unref(ln->par->bidi_props);
+ ln->par->bidi_props = NULL;
+ }
+
+ if (it1 && it2)
+ {
+ Evas_Object_Textblock_Line *ln1 = NULL, *ln2 = NULL;
+ ln1 = _find_layout_line_by_item(ln->par, it1);
+ if (cx) *cx = ln1->x + it1->x + adv1;
+ if (cy) *cy = ln1->par->y + ln1->y;
+ if (ch) *ch = ln1->h;
- if (cy) *cy = ln->par->y + ln->y;
- if (ch) *ch = curit->h;
+ ln2 = _find_layout_line_by_item(ln->par, it2);
+ if (cx2) *cx2 = ln2->x + it2->x + adv2;
+ if (cy2) *cy2 = ln2->par->y + ln2->y;
+ if (ch2) *ch2 = ln2->h;
- if (cy2) *cy2 = ln->par->y + ln->y;
- if (ch2) *ch2 = curit->h;
return EINA_TRUE;
}
}
}
}
-
+#undef IS_DIFFERENT_DIR
+#undef IS_RTL
+#else
+ (void) cx2;
+ (void) cy2;
+ (void) cw2;
+ (void) ch2;
+#endif
evas_textblock_cursor_geometry_get(cur, cx, cy, cw, ch, NULL, ctype);
return EINA_FALSE;
}
diff --git a/src/tests/evas/evas_test_textblock.c b/src/tests/evas/evas_test_textblock.c
index ed16077e16..b1dcacc029 100644
--- a/src/tests/evas/evas_test_textblock.c
+++ b/src/tests/evas/evas_test_textblock.c
@@ -648,6 +648,332 @@ START_TEST(evas_textblock_cursor)
}
END_TEST
+START_TEST(evas_textblock_split_cursor)
+{
+#ifdef HAVE_FRIBIDI
+ START_TB_TEST();
+ Evas_Coord x, w, x2, w2;
+ Evas_Coord nw, nh;
+ Evas_Coord cx, cy, cx2, cy2;
+
+ /* Split cursor in LTR paragraph. */
+ /*0123456789 10 123 14 5678901234 */
+ evas_object_textblock_text_markup_set(tb, "test נסיון\u202babc\u202cנסיון bang");
+ evas_object_textblock_size_native_get(tb, &nw, &nh);
+ evas_object_resize(tb, nw, nh);
+
+ /* Logical cursor after "test " */
+ evas_textblock_cursor_pos_set(cur, 5);
+ fail_if(!evas_textblock_cursor_geometry_bidi_get(cur, &cx, NULL, NULL,
+ NULL, &cx2, NULL, NULL, NULL,
+ EVAS_TEXTBLOCK_CURSOR_BEFORE));
+ evas_textblock_cursor_pos_set(cur, 4);
+ evas_textblock_cursor_pen_geometry_get(cur, &x, NULL, &w, NULL);
+ evas_textblock_cursor_pos_set(cur, 5);
+ evas_textblock_cursor_pen_geometry_get(cur, &x2, NULL, &w2, NULL);
+ fail_if(cx != (x + w));
+ fail_if(cx2 != (x2 + w2));
+
+ /* Logical cursor before " bang" */
+ evas_textblock_cursor_pos_set(cur, 20);
+ evas_textblock_cursor_pen_geometry_get(cur, &x, NULL, NULL, NULL);
+ fail_if(!evas_textblock_cursor_geometry_bidi_get(cur, &cx, NULL, NULL,
+ NULL, &cx2, NULL, NULL, NULL,
+ EVAS_TEXTBLOCK_CURSOR_BEFORE));
+ evas_textblock_cursor_pos_set(cur, 19);
+ evas_textblock_cursor_pen_geometry_get(cur, &x2, NULL, NULL, NULL);
+ fail_if(cx != x);
+ fail_if(cx2 != x2);
+
+ /* Logical cursor before "a" */
+ evas_textblock_cursor_pos_set(cur, 11);
+ evas_textblock_cursor_pen_geometry_get(cur, &x, NULL, NULL, NULL);
+ fail_if(!evas_textblock_cursor_geometry_bidi_get(cur, &cx, NULL, NULL,
+ NULL, &cx2, NULL, NULL, NULL,
+ EVAS_TEXTBLOCK_CURSOR_BEFORE));
+ evas_textblock_cursor_pos_set(cur, 9);
+ evas_textblock_cursor_pen_geometry_get(cur, &x2, NULL, NULL, NULL);
+ fail_if(cx != x);
+ fail_if(cx2 != x2);
+
+ /* Logical cursor after "c" */
+ evas_textblock_cursor_pos_set(cur, 15);
+ evas_textblock_cursor_pen_geometry_get(cur, &x2, NULL, &w2, NULL);
+ fail_if(!evas_textblock_cursor_geometry_bidi_get(cur, &cx, NULL, NULL,
+ NULL, &cx2, NULL, NULL, NULL,
+ EVAS_TEXTBLOCK_CURSOR_BEFORE));
+ evas_textblock_cursor_pos_set(cur, 13);
+ evas_textblock_cursor_pen_geometry_get(cur, &x, NULL, &w, NULL);
+ fail_if(cx != (x + w));
+ fail_if(cx2 != (x2 + w2));
+
+ /* Logical cursor in the beginning */
+ evas_textblock_cursor_line_char_first(cur);
+ fail_if(evas_textblock_cursor_geometry_bidi_get(cur, &cx, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL,
+ EVAS_TEXTBLOCK_CURSOR_BEFORE));
+ evas_textblock_cursor_pen_geometry_get(cur, &x, NULL, NULL, NULL);
+ fail_if(cx != x);
+
+ /* Logical cursor in the end */
+ evas_textblock_cursor_line_char_last(cur);
+ fail_if(evas_textblock_cursor_geometry_bidi_get(cur, &cx, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL,
+ EVAS_TEXTBLOCK_CURSOR_BEFORE));
+ evas_textblock_cursor_pos_set(cur, 24);
+ evas_textblock_cursor_pen_geometry_get(cur, &x, NULL, &w, NULL);
+ fail_if(cx != (x + w));
+
+ /* Logical cursor on the first pos */
+ evas_textblock_cursor_pos_set(cur, 1);
+ fail_if(evas_textblock_cursor_geometry_bidi_get(cur, &cx, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL,
+ EVAS_TEXTBLOCK_CURSOR_BEFORE));
+ evas_textblock_cursor_pen_geometry_get(cur, &x, NULL, NULL, NULL);
+ fail_if(cx != x);
+
+ /* Split cursor in RTL paragraph. */
+ /* 1 2
+ 0123456789 0 12345 6 7890123456 */
+ evas_object_textblock_text_markup_set(tb, "שלום test \u202aעברית\u202c efl נסיון");
+ evas_object_textblock_size_native_get(tb, &nw, &nh);
+ evas_object_resize(tb, nw, nh);
+
+ /* Logical cursor before "test" */
+ evas_textblock_cursor_pos_set(cur, 4);
+ evas_textblock_cursor_pen_geometry_get(cur, &x, NULL, &w, NULL);
+ evas_textblock_cursor_pos_set(cur, 5);
+
+ fail_if(!evas_textblock_cursor_geometry_bidi_get(cur, &cx, NULL, NULL,
+ NULL, &cx2, NULL, NULL, NULL,
+ EVAS_TEXTBLOCK_CURSOR_BEFORE));
+ evas_textblock_cursor_pos_set(cur, 5);
+ evas_textblock_cursor_pen_geometry_get(cur, &x2, NULL, NULL, NULL);
+ fail_if(cx != x);
+ fail_if(cx2 != x2);
+
+ /* Logical cursor after " efl" */
+ evas_textblock_cursor_pos_set(cur, 21);
+ evas_textblock_cursor_pen_geometry_get(cur, &x, NULL, &w, NULL);
+
+ fail_if(!evas_textblock_cursor_geometry_bidi_get(cur, &cx, NULL, NULL,
+ NULL, &cx2, NULL, NULL, NULL,
+ EVAS_TEXTBLOCK_CURSOR_BEFORE));
+ evas_textblock_cursor_pos_set(cur, 20);
+ evas_textblock_cursor_pen_geometry_get(cur, &x2, NULL, &w2, NULL);
+ fail_if(cx != (x + w));
+ fail_if(cx2 != (x2 + w2));
+
+ /* Logical cursor before " efl" */
+ evas_textblock_cursor_pos_set(cur, 17);
+ evas_textblock_cursor_pen_geometry_get(cur, &x, NULL, &w, NULL);
+
+ fail_if(!evas_textblock_cursor_geometry_bidi_get(cur, &cx, NULL, NULL,
+ NULL, &cx2, NULL, NULL, NULL,
+ EVAS_TEXTBLOCK_CURSOR_BEFORE));
+ evas_textblock_cursor_pos_set(cur, 15);
+ evas_textblock_cursor_pen_geometry_get(cur, &x2, NULL, NULL, NULL);
+ fail_if(cx != x2);
+ fail_if(cx2 != x);
+
+ /* Logical cursor after "test " */
+ evas_textblock_cursor_pos_set(cur, 11);
+ evas_textblock_cursor_pen_geometry_get(cur, &x, NULL, &w, NULL);
+
+ fail_if(!evas_textblock_cursor_geometry_bidi_get(cur, &cx, NULL, NULL,
+ NULL, &cx2, NULL, NULL, NULL,
+ EVAS_TEXTBLOCK_CURSOR_BEFORE));
+ evas_textblock_cursor_pos_set(cur, 9);
+ evas_textblock_cursor_pen_geometry_get(cur, &x2, NULL, &w2, NULL);
+ fail_if(cx != (x + w));
+ fail_if(cx2 != (x2 + w2));
+
+ /* Logical cursor in the beginning */
+ evas_textblock_cursor_line_char_first(cur);
+ fail_if(evas_textblock_cursor_geometry_bidi_get(cur, &cx, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL,
+ EVAS_TEXTBLOCK_CURSOR_BEFORE));
+ evas_textblock_cursor_pen_geometry_get(cur, &x, NULL, &w, NULL);
+ fail_if(cx != (x + w));
+
+ /* Logical cursor in the end */
+ evas_textblock_cursor_line_char_last(cur);
+ fail_if(evas_textblock_cursor_geometry_bidi_get(cur, &cx, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL,
+ EVAS_TEXTBLOCK_CURSOR_BEFORE));
+ evas_textblock_cursor_pos_set(cur, 26);
+ evas_textblock_cursor_pen_geometry_get(cur, &x, NULL, NULL, NULL);
+ fail_if(cx != x);
+
+ /* Corner cases for split cursor. */
+
+ /* End of line in LTR paragraph */
+ /* 1
+ 01234567890123 4 567 */
+ evas_object_textblock_text_markup_set(tb, "test נסיוןشسيب\u202babc");
+ evas_textblock_cursor_line_char_last(cur);
+ evas_textblock_cursor_pen_geometry_get(cur, &x2, NULL, &w2, NULL);
+ evas_object_textblock_size_native_get(tb, &nw, &nh);
+ evas_object_resize(tb, nw, nh);
+
+ evas_textblock_cursor_line_char_last(cur);
+ fail_if(!evas_textblock_cursor_geometry_bidi_get(cur, &cx, NULL, NULL,
+ NULL, &cx2, NULL, NULL, NULL,
+ EVAS_TEXTBLOCK_CURSOR_BEFORE));
+ evas_textblock_cursor_pos_set(cur, 4);
+ evas_textblock_cursor_pen_geometry_get(cur, &x2, NULL, &w2, NULL);
+ evas_textblock_cursor_pos_set(cur, 5);
+ evas_textblock_cursor_pen_geometry_get(cur, &x, NULL, &w, NULL);
+ fail_if(cx != (x + w));
+ fail_if(cx2 != (x2 + w2));
+
+ /* End of line in RTL paragraph */
+ /* 1 2
+ 0123456789012345678 9 0123 */
+ evas_object_textblock_text_markup_set(tb, "נסיוןشسي testпривет\u202aשלום");
+ evas_object_textblock_size_native_get(tb, &nw, &nh);
+ evas_object_resize(tb, nw, nh);
+
+ evas_textblock_cursor_line_char_last(cur);
+ fail_if(!evas_textblock_cursor_geometry_bidi_get(cur, &cx, NULL, NULL,
+ NULL, &cx2, NULL, NULL, NULL,
+ EVAS_TEXTBLOCK_CURSOR_BEFORE));
+ evas_textblock_cursor_pos_set(cur, 8);
+ evas_textblock_cursor_pen_geometry_get(cur, &x2, NULL, NULL, NULL);
+ evas_textblock_cursor_pos_set(cur, 9);
+ evas_textblock_cursor_pen_geometry_get(cur, &x, NULL, NULL, NULL);
+ fail_if(cx != x);
+ fail_if(cx2 != x2);
+
+ /* Cursor is between items of the same direction */
+ evas_textblock_cursor_pos_set(cur, 13);
+ fail_if(evas_textblock_cursor_geometry_bidi_get(cur, &cx, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL,
+ EVAS_TEXTBLOCK_CURSOR_BEFORE));
+ evas_textblock_cursor_pen_geometry_get(cur, &x, NULL, NULL, NULL);
+ fail_if(cx != x);
+
+ /* Cursor type is UNDER */
+ evas_textblock_cursor_pos_set(cur, 0);
+ fail_if(evas_textblock_cursor_geometry_bidi_get(cur, &cx, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL,
+ EVAS_TEXTBLOCK_CURSOR_UNDER));
+ evas_textblock_cursor_pen_geometry_get(cur, &x, NULL, NULL, NULL);
+ fail_if(cx != x);
+
+ /* Multiline */
+ Evas_Coord ly;
+ int i;
+ /* 012345678901234 */
+ evas_object_textblock_text_markup_set(tb, "<wrap=char>testשלוםشسيبefl");
+ evas_object_textblock_size_native_get(tb, &nw, &nh);
+ nh = nh * 15;
+ evas_object_resize(tb, nw, nh);
+
+ for (i = 0; i < nw; i++)
+ {
+ evas_object_resize(tb, i, nh);
+
+ evas_textblock_cursor_pos_set(cur, 12);
+ fail_if(!evas_textblock_cursor_geometry_bidi_get(cur, &cx, &cy, NULL,
+ NULL, &cx2, &cy2, NULL, NULL,
+ EVAS_TEXTBLOCK_CURSOR_BEFORE));
+ evas_textblock_cursor_line_geometry_get(cur, NULL, &ly, NULL, NULL);
+ fail_if(cy != ly);
+ evas_textblock_cursor_pen_geometry_get(cur, &x, NULL, NULL, NULL);
+ fail_if(cx != x);
+ evas_textblock_cursor_pos_set(cur, 11);
+ evas_textblock_cursor_line_geometry_get(cur, NULL, &ly, NULL, NULL);
+ fail_if(cy2 != ly);
+ evas_textblock_cursor_pen_geometry_get(cur, &x2, NULL, NULL, NULL);
+ fail_if(cx2 != x2);
+ }
+ /* 01234567890123456789 */
+ evas_object_textblock_text_markup_set(tb, "<wrap=char>נסיוןhelloприветשלום");
+ evas_object_textblock_size_native_get(tb, &nw, &nh);
+ nh = nh * 20;
+ evas_object_resize(tb, nw, nh);
+
+ for (i = 0; i < nw; i++)
+ {
+ evas_object_resize(tb, i, nh);
+
+ evas_textblock_cursor_pos_set(cur, 16);
+ fail_if(!evas_textblock_cursor_geometry_bidi_get(cur, &cx, &cy, NULL,
+ NULL, &cx2, &cy2, NULL, NULL,
+ EVAS_TEXTBLOCK_CURSOR_BEFORE));
+ evas_textblock_cursor_line_geometry_get(cur, NULL, &ly, NULL, NULL);
+ fail_if(cy != ly);
+ evas_textblock_cursor_pen_geometry_get(cur, &x, NULL, &w, NULL);
+ fail_if(cx != (x + w));
+ evas_textblock_cursor_pos_set(cur, 15);
+ evas_textblock_cursor_line_geometry_get(cur, NULL, &ly, NULL, NULL);
+ fail_if(cy2 != ly);
+ evas_textblock_cursor_pen_geometry_get(cur, &x2, NULL, &w2, NULL);
+ fail_if(cx2 != (x2 + w2));
+ }
+
+ /* Testing multiline, when only RTL item is in the line. */
+ /* 012345678901234567890123 */
+ evas_object_textblock_text_markup_set(tb, "<wrap=char>testtesttestтестשלוםشسيب");
+ evas_object_textblock_size_native_get(tb, &nw, &nh);
+ nh = nh * 23;
+ evas_object_resize(tb, nw, nh);
+
+ evas_textblock_cursor_pos_set(cur, 15);
+ evas_textblock_cursor_pen_geometry_get(cur, &x, NULL, &w, NULL);
+ /* Resizing textblock, so RTL item will be on the next line.*/
+ evas_object_resize(tb, x + w, nh);
+
+ evas_textblock_cursor_pos_set(cur, 24);
+ fail_if(!evas_textblock_cursor_geometry_bidi_get(cur, &cx, &cy, NULL,
+ NULL, &cx2, &cy2, NULL, NULL,
+ EVAS_TEXTBLOCK_CURSOR_BEFORE));
+ evas_textblock_cursor_pos_set(cur, 16);
+ evas_textblock_cursor_pen_geometry_get(cur, &x, NULL, &w, NULL);
+ fail_if(cx != (x + w));
+ evas_textblock_cursor_line_geometry_get(cur, NULL, &ly, NULL, NULL);
+ fail_if(cy != ly);
+
+ evas_textblock_cursor_pos_set(cur, 23);
+ evas_textblock_cursor_pen_geometry_get(cur, &x2, NULL, NULL, NULL);
+ fail_if(cx2 != x2);
+ evas_textblock_cursor_line_geometry_get(cur, NULL, &ly, NULL, NULL);
+ fail_if(cy2 != ly);
+
+ /* Testing multiline, when only LTR item is in the line. */
+ /* 012345678901234567890123 */
+ evas_object_textblock_text_markup_set(tb, "<wrap=char>שלוםשלוםשלוםشسيبtestтест");
+ evas_object_textblock_size_native_get(tb, &nw, &nh);
+ nh = nh * 23;
+ evas_object_resize(tb, nw, nh);
+
+ evas_textblock_cursor_pos_set(cur, 15);
+ evas_textblock_cursor_pen_geometry_get(cur, &x, NULL, &w, NULL);
+ /* Resizing textblock, so LTR item will be on the next line.*/
+ evas_object_resize(tb, nw - x, nh);
+
+ evas_textblock_cursor_pos_set(cur, 24);
+ fail_if(!evas_textblock_cursor_geometry_bidi_get(cur, &cx, &cy, NULL,
+ NULL, &cx2, &cy2, NULL, NULL,
+ EVAS_TEXTBLOCK_CURSOR_BEFORE));
+ evas_textblock_cursor_pos_set(cur, 16);
+ evas_textblock_cursor_pen_geometry_get(cur, &x, NULL, NULL, NULL);
+ fail_if(cx != x);
+ evas_textblock_cursor_line_geometry_get(cur, NULL, &ly, NULL, NULL);
+ fail_if(cy != ly);
+
+ evas_textblock_cursor_pos_set(cur, 23);
+ evas_textblock_cursor_pen_geometry_get(cur, &x2, NULL, &w2, NULL);
+ fail_if(cx2 != (x2 + w2));
+ evas_textblock_cursor_line_geometry_get(cur, NULL, &ly, NULL, NULL);
+ fail_if(cy2 != ly);
+
+ END_TB_TEST();
+#endif
+}
+END_TEST
+
START_TEST(evas_textblock_format_removal)
{
START_TB_TEST();
@@ -2318,6 +2644,7 @@ void evas_test_textblock(TCase *tc)
{
tcase_add_test(tc, evas_textblock_simple);
tcase_add_test(tc, evas_textblock_cursor);
+ tcase_add_test(tc, evas_textblock_split_cursor);
tcase_add_test(tc, evas_textblock_size);
tcase_add_test(tc, evas_textblock_editing);
tcase_add_test(tc, evas_textblock_style);