yakov pushed a commit to branch master.

commit 7016872619b7b84e46688de29b133997c43f95ed
Author: Yakov Goldberg <[email protected]>
Date:   Wed Apr 10 14:54:37 2013 +0300

    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 <[email protected]>
---
 ChangeLog                                   |   3 +
 NEWS                                        |   1 +
 src/lib/edje/edje_entry.c                   |   6 +-
 src/lib/evas/Evas.h                         |  26 ++-
 src/lib/evas/canvas/evas_object_textblock.c | 209 +++++++++++++-----
 src/tests/evas/evas_test_textblock.c        | 327 ++++++++++++++++++++++++++++
 6 files changed, 516 insertions(+), 56 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 04fc489..779bf02 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 cf24cf2..3735e38 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 d7b0f77..b324d97 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 9d3603b..86d0beb 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 994b258..a274319 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 ed16077..b1dcacc 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);

-- 

------------------------------------------------------------------------------
Precog is a next-generation analytics platform capable of advanced
analytics on semi-structured data. The platform includes APIs for building
apps and a phenomenal toolset for data science. Developers can use
our toolset for easy data analysis & visualization. Get a free account!
http://www2.precog.com/precogplatform/slashdotnewsletter

Reply via email to