evas/edje: Add evas_textblock_cursor_cluster_* internal APIs.
authorYoungbok Shin <youngb.shin@samsung.com>
Fri, 8 Dec 2017 06:32:14 +0000 (15:32 +0900)
committerJiyoun Park <jy0703.park@samsung.com>
Thu, 21 Dec 2017 12:20:05 +0000 (21:20 +0900)
@tizen_feature

Change-Id: Iabe46715e06f7db74ac5a9bcbb9fc07d528af2f1

src/lib/edje/edje_entry.c
src/lib/evas/Evas_Legacy.h
src/lib/evas/canvas/evas_object_textblock.c
src/lib/evas/common/evas_text_utils.h

index 3408027..239246a 100644 (file)
@@ -539,7 +539,11 @@ _curs_jump_line(Evas_Textblock_Cursor *c, Evas_Object *o, Entry *en, int ln)
 
    if (!evas_object_textblock_line_number_geometry_get(o, ln, &lx, &ly, &lw, &lh))
      return EINA_FALSE;
+   /* TIZEN_ONLY(20150127): Add evas_textblock_cursor_cluster_* APIs.
    if (evas_textblock_cursor_char_coord_set(c, cx, ly + (lh / 2)))
+    */
+   if (evas_textblock_cursor_cluster_coord_set(c, cx, ly + (lh / 2)))
+   /* END */
      return EINA_TRUE;
    evas_textblock_cursor_line_set(c, ln);
    if (cx < (lx + (lw / 2)))
@@ -1900,7 +1904,11 @@ _edje_key_down_cb(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED,
                     }
                }
           }
+        /* TIZEN_ONLY(20150127): Add evas_textblock_cursor_cluster_* APIs.
         if (evas_textblock_cursor_char_prev(en->cursor))
+         */
+        if (evas_textblock_cursor_cluster_prev(en->cursor))
+        /* END */
           ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
 #if defined(__APPLE__) && defined(__MACH__)
         if (altgr) evas_textblock_cursor_word_start(en->cursor);
@@ -1956,7 +1964,11 @@ _edje_key_down_cb(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED,
 #else
         if (control) evas_textblock_cursor_word_end(en->cursor);
 #endif
+        /* TIZEN_ONLY(20150127): Add evas_textblock_cursor_cluster_* APIs.
         if (evas_textblock_cursor_char_next(en->cursor))
+         */
+        if (evas_textblock_cursor_cluster_next(en->cursor))
+        /* END */
           ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
         /* TIZEN_ONLY(20161031): Add edje_object_part_text_select_disable_set API
         if (en->select_allow)
@@ -1978,7 +1990,11 @@ _edje_key_down_cb(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED,
              // del to start of previous word
              _sel_start(en->cursor, rp->object, en);
 
+             /* TIZEN_ONLY(20150127): Add evas_textblock_cursor_cluster_* APIs.
              evas_textblock_cursor_char_prev(en->cursor);
+              */
+             evas_textblock_cursor_cluster_prev(en->cursor);
+             /* END */
              evas_textblock_cursor_word_start(en->cursor);
 
              _sel_preextend(ed, en->cursor, rp->object, en);
@@ -2018,7 +2034,11 @@ _edje_key_down_cb(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED,
              _sel_start(en->cursor, rp->object, en);
 
              evas_textblock_cursor_word_end(en->cursor);
+             /* TIZEN_ONLY(20150127): Add evas_textblock_cursor_cluster_* APIs.
              evas_textblock_cursor_char_next(en->cursor);
+              */
+             evas_textblock_cursor_cluster_next(en->cursor);
+             /* END */
 
              _sel_extend(ed, en->cursor, rp->object, en);
 
@@ -2569,7 +2589,11 @@ _edje_cursor_char_coord_set(Edje_Real_Part *rp, Evas_Coord canvasx, Evas_Coord c
    evas_textblock_cursor_free(line_cur);
    /* No need to check return value if not able to set the char coord Textblock
     * will take care */
+   /* TIZEN_ONLY(20150127): Add evas_textblock_cursor_cluster_* APIs.
    evas_textblock_cursor_char_coord_set(en->cursor, *cx, *cy);
+    */
+   evas_textblock_cursor_cluster_coord_set(en->cursor, *cx, *cy);
+   /* END */
 
    return tc;
 }
@@ -2671,7 +2695,11 @@ _edje_part_mouse_down_cb(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_
                   else
                     {
                        evas_textblock_cursor_word_end(en->cursor);
+                       /* TIZEN_ONLY(20150127): Add evas_textblock_cursor_cluster_* APIs.
                        evas_textblock_cursor_char_next(en->cursor);
+                        */
+                       evas_textblock_cursor_cluster_next(en->cursor);
+                       /* END */
                     }
                   _sel_extend(en->ed, en->cursor, rp->object, en);
                }
@@ -2685,7 +2713,11 @@ _edje_part_mouse_down_cb(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_
                   evas_textblock_cursor_word_start(en->cursor);
                   _sel_start(en->cursor, rp->object, en);
                   evas_textblock_cursor_word_end(en->cursor);
+                  /* TIZEN_ONLY(20150127): Add evas_textblock_cursor_cluster_* APIs.
                   evas_textblock_cursor_char_next(en->cursor);
+                   */
+                  evas_textblock_cursor_cluster_next(en->cursor);
+                  /* END */
                   _sel_extend(en->ed, en->cursor, rp->object, en);
                }
              goto end;
@@ -2893,7 +2925,11 @@ _edje_part_mouse_move_cb(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_
         evas_object_geometry_get(rp->object, &x, &y, &w, &h);
         cx = ev->cur.canvas.x - x;
         cy = ev->cur.canvas.y - y;
+        /* TIZEN_ONLY(20150127): Add evas_textblock_cursor_cluster_* APIs.
         if (!evas_textblock_cursor_char_coord_set(en->cursor, cx, cy))
+         */
+        if (!evas_textblock_cursor_cluster_coord_set(en->cursor, cx, cy))
+        /* END */
           {
              Evas_Coord lx, ly, lw, lh;
 
@@ -2905,7 +2941,11 @@ _edje_part_mouse_move_cb(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_
                     {
                        evas_textblock_cursor_paragraph_first(en->cursor);
                        evas_textblock_cursor_line_geometry_get(en->cursor, &lx, &ly, &lw, &lh);
+                       /* TIZEN_ONLY(20150127): Add evas_textblock_cursor_cluster_* APIs.
                        if (!evas_textblock_cursor_char_coord_set(en->cursor, cx, ly + (lh / 2)))
+                        */
+                       if (!evas_textblock_cursor_cluster_coord_set(en->cursor, cx, ly + (lh / 2)))
+                       /* END */
                          _curs_end(en->cursor, rp->object, en);
                     }
                }
@@ -4208,7 +4248,11 @@ _edje_text_cursor_next(Edje_Real_Part *rp, Efl_Text_Cursor_Cursor *c)
 
    _edje_entry_imf_context_reset(rp);
 
+   /* TIZEN_ONLY(20150127): Add evas_textblock_cursor_cluster_* APIs.
    if (!evas_textblock_cursor_char_next(c))
+    */
+   if (!evas_textblock_cursor_cluster_next(c))
+   /* END */
      {
         return EINA_FALSE;
      }
@@ -4241,7 +4285,11 @@ _edje_text_cursor_prev(Edje_Real_Part *rp, Efl_Text_Cursor_Cursor *c)
 
    _edje_entry_imf_context_reset(rp);
 
+   /* TIZEN_ONLY(20150127): Add evas_textblock_cursor_cluster_* APIs.
    if (!evas_textblock_cursor_char_prev(c))
+    */
+   if (!evas_textblock_cursor_cluster_prev(c))
+   /* END */
      {
         if (evas_textblock_cursor_paragraph_prev(c)) goto ok;
         else return EINA_FALSE;
@@ -4285,7 +4333,11 @@ _edje_text_cursor_up(Edje_Real_Part *rp, Efl_Text_Cursor_Cursor *c)
                                                        &lx, &ly, &lw, &lh))
      return EINA_FALSE;
    evas_textblock_cursor_char_geometry_get(c, &cx, &cy, &cw, &ch);
+   /* TIZEN_ONLY(20150127): Add evas_textblock_cursor_cluster_* APIs.
    if (!evas_textblock_cursor_char_coord_set(c, cx, ly + (lh / 2)))
+    */
+   if (!evas_textblock_cursor_cluster_coord_set(c, cx, ly + (lh / 2)))
+   /* END */
      evas_textblock_cursor_line_char_last(c);
    _sel_update(en->ed, c, rp->object, rp->typedata.text->entry_data);
 
@@ -4324,7 +4376,11 @@ _edje_text_cursor_down(Edje_Real_Part *rp, Efl_Text_Cursor_Cursor *c)
                                                        &lx, &ly, &lw, &lh))
      return EINA_FALSE;
    evas_textblock_cursor_char_geometry_get(c, &cx, &cy, &cw, &ch);
+   /* TIZEN_ONLY(20150127): Add evas_textblock_cursor_cluster_* APIs.
    if (!evas_textblock_cursor_char_coord_set(c, cx, ly + (lh / 2)))
+    */
+   if (!evas_textblock_cursor_cluster_coord_set(c, cx, ly + (lh / 2)))
+   /* END */
      evas_textblock_cursor_line_char_last(c);
 
    _sel_update(en->ed, c, rp->object, rp->typedata.text->entry_data);
@@ -4526,7 +4582,11 @@ _edje_text_cursor_coord_set(Edje_Real_Part *rp, Efl_Text_Cursor_Cursor *c,
              _edje_emit(en->ed, "selection,changed", rp->part->name);
           }
      }
+   /* TIZEN_ONLY(20150127): Add evas_textblock_cursor_cluster_* APIs.
    return evas_textblock_cursor_char_coord_set(c, x, y);
+    */
+   return evas_textblock_cursor_cluster_coord_set(c, x, y);
+   /* END */
 }
 
 Eina_Bool
index 6305154..11db45d 100755 (executable)
@@ -7994,6 +7994,46 @@ evas_textblock_cursor_paragraph_direction_get(const Evas_Textblock_Cursor *cur);
  * END *
  *******/
 
+/*******************************************************************
+ * TIZEN_ONLY(20150127): Add evas_textblock_cursor_cluster_* APIs. *
+ *******************************************************************/
+/**
+ * @internal
+ * TIZEN_ONLY(20150127): Add evas_textblock_cursor_cluster_* APIs.
+ * Set the position of the cursor according to the X and Y coordinates and text ligature.
+ *
+ * @param cur the cursor to set.
+ * @param x coord to set by.
+ * @param y coord to set by.
+ * @return @c EINA_TRUE on success, @c EINA_FALSE otherwise.
+ */
+EAPI Eina_Bool                                evas_textblock_cursor_cluster_coord_set(Evas_Textblock_Cursor *cur, Evas_Coord x, Evas_Coord y) EINA_ARG_NONNULL(1);
+
+/**
+ * @internal
+ * TIZEN_ONLY(20150127): Add evas_textblock_cursor_cluster_* APIs.
+ * Advances 1 cluster forward.
+ * Cluster is an text ligature.
+ *
+ * @param cur the cursor to advance.
+ * @return @c EINA_TRUE on success @c EINA_FALSE otherwise.
+ */
+EAPI Eina_Bool                                evas_textblock_cursor_cluster_next(Evas_Textblock_Cursor *cur) EINA_ARG_NONNULL(1);
+
+/**
+ * @internal
+ * TIZEN_ONLY(20150127): Add evas_textblock_cursor_cluster_* APIs.
+ * Advances 1 cluster backward.
+ * Cluster is an text ligature.
+ *
+ * @param cur the cursor to advance.
+ * @return @c EINA_TRUE on success @c EINA_FALSE otherwise.
+ */
+EAPI Eina_Bool                                evas_textblock_cursor_cluster_prev(Evas_Textblock_Cursor *cur) EINA_ARG_NONNULL(1);
+/*******
+ * END *
+ *******/
+
 #ifdef EFL_BETA_API_SUPPORT
 /**
  * Creates a new smart rectangle object on the given Evas @p e canvas.
index 622ce7c..bcf1b37 100644 (file)
@@ -9389,8 +9389,11 @@ _efl_canvas_text_efl_text_cursor_cursor_word_end(Eo *eo_obj, Efl_Canvas_Text_Dat
    efl_event_callback_legacy_call(eo_obj, EFL_CANVAS_TEXT_EVENT_CURSOR_CHANGED, NULL);
 }
 
-EAPI Eina_Bool
-evas_textblock_cursor_char_next(Efl_Text_Cursor_Cursor *cur)
+/*******************************************************************
+ * TIZEN_ONLY(20150127): Add evas_textblock_cursor_cluster_* APIs. *
+ *******************************************************************/
+static Eina_Bool
+_evas_textblock_cursor_next(Evas_Textblock_Cursor *cur, Eina_Bool per_cluster)
 {
    int ind;
    const Eina_Unicode *text;
@@ -9402,7 +9405,70 @@ evas_textblock_cursor_char_next(Efl_Text_Cursor_Cursor *cur)
 
    ind = cur->pos;
    text = eina_ustrbuf_string_get(cur->node->unicode);
-   if (text[ind]) ind++;
+
+   if (text[ind])
+     {
+        if (per_cluster)
+          {
+             Evas_Object_Textblock_Paragraph *par = cur->node->par;
+
+             if (par)
+               {
+                  Eina_List *l;
+                  Evas_Object_Textblock_Item *it, *last_it = NULL;
+                  EINA_LIST_FOREACH(par->logical_items, l, it)
+                    {
+                       if (it->text_pos > cur->pos)
+                         {
+                            if (!last_it) last_it = it;
+                            break;
+                         }
+                       last_it = it;
+                    }
+
+                  if (last_it)
+                    {
+                       if ((last_it->type == EVAS_TEXTBLOCK_ITEM_TEXT) &&
+                           (CHECK_LANGUAGE_CLUSTER_AVAILABLE(_ITEM_TEXT(last_it)->text_props.script)))
+                         {
+                            size_t cluster_pos = 0;
+                            int i;
+
+                            cluster_pos = last_it->text_pos + (size_t)evas_common_text_props_cluster_next(
+                               &_ITEM_TEXT(last_it)->text_props, cur->pos - last_it->text_pos);
+
+                            if (cluster_pos == cur->pos)
+                              {
+                                 if (it)
+                                   {
+                                      cluster_pos = it->text_pos;
+                                   }
+                                 else
+                                   {
+                                      cluster_pos = eina_ustrbuf_length_get(cur->node->unicode);
+                                   }
+                              }
+
+                            /* Check cluster exception characters */
+                            for (i = cur->pos + 1; i < (int)cluster_pos; i++)
+                              {
+                                 if (text[i] && CHECK_CLUSTER_EXCEPTION_CHAR(text[i]))
+                                   {
+                                      cluster_pos = i;
+                                      break;
+                                   }
+                              }
+
+                            ind = cluster_pos;
+                         }
+                    }
+               }
+          }
+
+        if (ind <= (int)cur->pos)
+          ind = cur->pos + 1;
+     }
+
    /* Only allow pointing a null if it's the last paragraph.
     * because we don't have a PS there. */
    if (text[ind])
@@ -9412,7 +9478,7 @@ evas_textblock_cursor_char_next(Efl_Text_Cursor_Cursor *cur)
      }
    else
      {
-        if (!_evas_textblock_cursor_paragraph_next(cur))
+        if (!evas_textblock_cursor_paragraph_next(cur))
           {
              /* If we already were at the end, that means we don't have
               * where to go next we should return FALSE */
@@ -9429,6 +9495,280 @@ evas_textblock_cursor_char_next(Efl_Text_Cursor_Cursor *cur)
      }
 }
 
+static Eina_Bool
+_evas_textblock_cursor_prev(Evas_Textblock_Cursor *cur, Eina_Bool per_cluster)
+{
+   const Eina_Unicode *text;
+
+   if (!cur) return EINA_FALSE;
+   TB_NULL_CHECK(cur->node, EINA_FALSE);
+
+   text = eina_ustrbuf_string_get(cur->node->unicode);
+
+   if (cur->pos != 0)
+     {
+        if (per_cluster)
+          {
+             Evas_Object_Textblock_Paragraph *par = cur->node->par;
+
+             if (par)
+               {
+                  Eina_List *l;
+                  Evas_Object_Textblock_Item *it, *last_it = NULL;
+                  EINA_LIST_FOREACH(par->logical_items, l, it)
+                    {
+                       if (it->text_pos >= cur->pos)
+                         {
+                            if (!last_it) last_it = it;
+                            break;
+                         }
+                       last_it = it;
+                    }
+
+                  if (last_it)
+                    {
+                       if ((last_it->type == EVAS_TEXTBLOCK_ITEM_TEXT) &&
+                           (CHECK_LANGUAGE_CLUSTER_AVAILABLE(_ITEM_TEXT(last_it)->text_props.script)))
+                         {
+                            size_t cluster_temp = 0;
+                            size_t cluster_pos;
+                            int i = 0;
+
+                            cluster_pos = last_it->text_pos + (size_t)evas_common_text_props_cluster_prev(
+                               &_ITEM_TEXT(last_it)->text_props, cur->pos - last_it->text_pos);
+                            cluster_temp = cluster_pos;
+
+                            while ((cur->pos - i > last_it->text_pos) &&
+                                   (cluster_temp == cur->pos - i))
+                              {
+                                 cluster_pos--;
+                                 i++;
+                                 cluster_temp = last_it->text_pos + evas_common_text_props_cluster_prev(
+                                    &_ITEM_TEXT(last_it)->text_props, cur->pos - last_it->text_pos - i);
+                              }
+
+                            /* Check cluster exception characters */
+                            for (i = cur->pos - 1; i > (int)cluster_pos; i--)
+                              {
+                                 if (text[i] && CHECK_CLUSTER_EXCEPTION_CHAR(text[i]))
+                                   {
+                                      cluster_pos = i;
+                                      break;
+                                   }
+                              }
+
+                            cur->pos = cluster_pos;
+                            return EINA_TRUE;
+                         }
+                    }
+               }
+          }
+
+        cur->pos--;
+        return EINA_TRUE;
+     }
+   return evas_textblock_cursor_paragraph_prev(cur);
+}
+
+static Eina_Bool
+_evas_textblock_cursor_coord_set(Evas_Textblock_Cursor *cur, Evas_Coord x, Evas_Coord y, Eina_Bool per_cluster)
+{
+   Evas_Object_Textblock_Paragraph *found_par;
+   Evas_Object_Textblock_Line *ln;
+   Evas_Object_Textblock_Item *it = NULL;
+
+   if (!cur) return EINA_FALSE;
+   Evas_Object_Protected_Data *obj = efl_data_scope_get(cur->obj, EFL_CANVAS_OBJECT_CLASS);
+   evas_object_async_block(obj);
+   Efl_Canvas_Text_Data *o = efl_data_scope_get(cur->obj, MY_CLASS);
+
+   _relayout_if_needed(cur->obj, o);
+
+   x += o->style_pad.l;
+   y += o->style_pad.t;
+
+   found_par = _layout_find_paragraph_by_y(o, y);
+   if (found_par)
+     {
+        _layout_paragraph_render(o, found_par);
+        EINA_INLIST_FOREACH(found_par->lines, ln)
+          {
+             if (ln->par->y + ln->y > y) break;
+             if ((ln->par->y + ln->y <= y) && ((ln->par->y + ln->y + ln->h) > y))
+               {
+                  /* If before or after the line, go to start/end according
+                   * to paragraph direction. */
+                  if (x < ln->x)
+                    {
+                       cur->pos = ln->items->text_pos;
+                       cur->node = found_par->text_node;
+                       if (found_par->direction == EVAS_BIDI_DIRECTION_RTL)
+                         {
+                            evas_textblock_cursor_line_char_last(cur);
+                         }
+                       else
+                         {
+                            evas_textblock_cursor_line_char_first(cur);
+                         }
+                       return EINA_TRUE;
+                    }
+                  else if (x >= ln->x + ln->w)
+                    {
+                       cur->pos = ln->items->text_pos;
+                       cur->node = found_par->text_node;
+                       if (found_par->direction == EVAS_BIDI_DIRECTION_RTL)
+                         {
+                            evas_textblock_cursor_line_char_first(cur);
+                         }
+                       else
+                         {
+                            evas_textblock_cursor_line_char_last(cur);
+                         }
+                       return EINA_TRUE;
+                    }
+
+                  EINA_INLIST_FOREACH(ln->items, it)
+                    {
+                       if (((it->x + ln->x) <= x) && (((it->x + ln->x) + it->adv) > x))
+                         {
+                            if (it->type == EVAS_TEXTBLOCK_ITEM_TEXT)
+                              {
+                                 int pos;
+                                 int cx, cy, cw, ch;
+                                 Evas_Object_Textblock_Text_Item *ti;
+                                 ti = _ITEM_TEXT(it);
+
+                                 pos = -1;
+                                 if (ti->parent.format->font.font)
+                                   pos = ENFN->font_char_at_coords_get(
+                                         ENC,
+                                         ti->parent.format->font.font,
+                                         &ti->text_props,
+                                         x - it->x - ln->x, 0,
+                                         &cx, &cy, &cw, &ch);
+
+                                 if (pos < 0)
+                                   return EINA_FALSE;
+
+                                 while (per_cluster && (evas_common_text_props_index_find(&ti->text_props, pos) == -1) &&
+                                        CHECK_LANGUAGE_CLUSTER_AVAILABLE(ti->text_props.script))
+                                   pos--;
+
+                                 cur->pos = pos + it->text_pos;
+                                 cur->node = it->text_node;
+                                 return EINA_TRUE;
+                              }
+                            else
+                              {
+                                 Evas_Object_Textblock_Format_Item *fi;
+                                 fi = _ITEM_FORMAT(it);
+                                 /* Lets keep cur position half way for easy positioning */
+                                 if (x > (ln->x + it->x + (it->adv / 2)))
+                                   {
+                                      cur->pos = fi->parent.text_pos + 1;
+                                   }
+                                 else
+                                   {
+                                      cur->pos = fi->parent.text_pos;
+                                   }
+                                 cur->node = found_par->text_node;
+                                 return EINA_TRUE;
+                              }
+                         }
+                    }
+               }
+          }
+     }
+
+   if (o->paragraphs)
+     {
+        Evas_Object_Textblock_Line *first_line = o->paragraphs->lines;
+        if (y >= o->paragraphs->y + o->formatted.h)
+          {
+             /* If we are after the last paragraph, use the last position in the
+              * text. */
+             evas_textblock_cursor_paragraph_last(cur);
+             return EINA_TRUE;
+          }
+        else if (o->paragraphs && (y < (o->paragraphs->y + first_line->y)))
+          {
+             evas_textblock_cursor_paragraph_first(cur);
+             return EINA_TRUE;
+          }
+     }
+
+   return EINA_FALSE;
+}
+
+EAPI Eina_Bool
+evas_textblock_cursor_cluster_next(Evas_Textblock_Cursor *cur)
+{
+   return _evas_textblock_cursor_next(cur, EINA_TRUE);
+}
+
+EAPI Eina_Bool
+evas_textblock_cursor_cluster_prev(Evas_Textblock_Cursor *cur)
+{
+   return _evas_textblock_cursor_prev(cur, EINA_TRUE);
+}
+
+EAPI Eina_Bool
+evas_textblock_cursor_cluster_coord_set(Evas_Textblock_Cursor *cur, Evas_Coord x, Evas_Coord y)
+{
+   return _evas_textblock_cursor_coord_set(cur, x, y, EINA_TRUE);
+}
+/*******
+ * END *
+ *******/
+
+EAPI Eina_Bool
+evas_textblock_cursor_char_next(Efl_Text_Cursor_Cursor *cur)
+{
+   /*******************************************************************
+    * TIZEN_ONLY(20150127): Add evas_textblock_cursor_cluster_* APIs. *
+    *******************************************************************
+   int ind;
+   const Eina_Unicode *text;
+
+   if (!cur) return EINA_FALSE;
+   Evas_Object_Protected_Data *obj = efl_data_scope_get(cur->obj, EFL_CANVAS_OBJECT_CLASS);
+   evas_object_async_block(obj);
+   TB_NULL_CHECK(cur->node, EINA_FALSE);
+
+   ind = cur->pos;
+   text = eina_ustrbuf_string_get(cur->node->unicode);
+   if (text[ind]) ind++;
+   // Only allow pointing a null if it's the last paragraph.
+   // because we don't have a PS there.
+   if (text[ind])
+     {
+        cur->pos = ind;
+        return EINA_TRUE;
+     }
+   else
+     {
+        if (!_evas_textblock_cursor_paragraph_next(cur))
+          {
+             // If we already were at the end, that means we don't have
+             // where to go next we should return FALSE
+             if (cur->pos == (size_t) ind)
+               return EINA_FALSE;
+
+             cur->pos = ind;
+             return EINA_TRUE;
+          }
+        else
+          {
+             return EINA_TRUE;
+          }
+     }
+    */
+   return _evas_textblock_cursor_next(cur, EINA_FALSE);
+   /*******
+    * END *
+    *******/
+}
+
 EOLIAN static void
 _efl_canvas_text_efl_text_cursor_cursor_char_next(Eo *eo_obj, Efl_Canvas_Text_Data *o EINA_UNUSED, Efl_Text_Cursor_Cursor *cur)
 {
@@ -9440,7 +9780,9 @@ _efl_canvas_text_efl_text_cursor_cursor_char_next(Eo *eo_obj, Efl_Canvas_Text_Da
 static Eina_Bool
 _evas_textblock_cursor_char_prev(Efl_Text_Cursor_Cursor *cur)
 {
-
+   /*******************************************************************
+    * TIZEN_ONLY(20150127): Add evas_textblock_cursor_cluster_* APIs. *
+    *******************************************************************
    if (!cur) return EINA_FALSE;
    TB_NULL_CHECK(cur->node, EINA_FALSE);
 
@@ -9450,6 +9792,11 @@ _evas_textblock_cursor_char_prev(Efl_Text_Cursor_Cursor *cur)
         return EINA_TRUE;
      }
    return evas_textblock_cursor_paragraph_prev(cur);
+    */
+   return _evas_textblock_cursor_prev(cur, EINA_FALSE);
+   /*******
+    * END *
+    *******/
 }
 
 EAPI Eina_Bool
@@ -12157,6 +12504,9 @@ _efl_canvas_text_visible_range_get(Eo *eo_obj EINA_UNUSED,
 EAPI Eina_Bool
 evas_textblock_cursor_char_coord_set(Evas_Textblock_Cursor *cur,  Evas_Coord x, Evas_Coord y)
 {
+   /*******************************************************************
+    * TIZEN_ONLY(20150127): Add evas_textblock_cursor_cluster_* APIs. *
+    *******************************************************************
    Evas_Object_Textblock_Paragraph *found_par;
    Evas_Object_Textblock_Line *ln;
    Evas_Object_Textblock_Item *it = NULL;
@@ -12180,8 +12530,8 @@ evas_textblock_cursor_char_coord_set(Evas_Textblock_Cursor *cur,  Evas_Coord x,
              if (ln->par->y + ln->y > y) break;
              if ((ln->par->y + ln->y <= y) && ((ln->par->y + ln->y + ln->h) > y))
                {
-                  /* If before or after the line, go to start/end according
-                   * to paragraph direction. */
+                  // If before or after the line, go to start/end according
+                  // to paragraph direction.
                   if (x < ln->x)
                     {
                        cur->pos = ln->items->text_pos;
@@ -12243,7 +12593,7 @@ evas_textblock_cursor_char_coord_set(Evas_Textblock_Cursor *cur,  Evas_Coord x,
                               {
                                  Evas_Object_Textblock_Format_Item *fi;
                                  fi = _ITEM_FORMAT(it);
-                                 /* Lets keep cur position half way for easy positioning */
+                                 // Lets keep cur position half way for easy positioning
                                  if (x > (ln->x + it->x + (it->adv / 2)))
                                    {
                                       cur->pos = fi->parent.text_pos + 1;
@@ -12267,8 +12617,8 @@ evas_textblock_cursor_char_coord_set(Evas_Textblock_Cursor *cur,  Evas_Coord x,
         Evas_Object_Textblock_Line *first_line = o->paragraphs->lines;
         if (y >= o->paragraphs->y + o->formatted.h)
           {
-             /* If we are after the last paragraph, use the last position in the
-              * text. */
+             // If we are after the last paragraph, use the last position in the
+             // text.
              evas_textblock_cursor_paragraph_last(cur);
              ret = EINA_TRUE;
              goto end;
@@ -12287,6 +12637,11 @@ end:
         efl_event_callback_legacy_call(cur->obj, EFL_CANVAS_TEXT_EVENT_CURSOR_CHANGED, NULL);
      }
    return ret;
+    */
+   return _evas_textblock_cursor_coord_set(cur, x, y, EINA_FALSE);
+   /*******
+    * END *
+    *******/
 }
 
 EOLIAN static void
@@ -12294,7 +12649,16 @@ _efl_canvas_text_efl_text_cursor_cursor_coord_set(Eo *eo_obj EINA_UNUSED, Efl_Ca
       Evas_Coord x, Evas_Coord y)
 {
    ASYNC_BLOCK;
+   /*******************************************************************
+    * TIZEN_ONLY(20150127): Add evas_textblock_cursor_cluster_* APIs. *
+    *******************************************************************
    evas_textblock_cursor_char_coord_set(cur, x, y);
+    */
+   if (evas_textblock_cursor_char_coord_set(cur, x, y))
+     efl_event_callback_legacy_call(cur->obj, EFL_CANVAS_TEXT_EVENT_CURSOR_CHANGED, NULL);
+   /*******
+    * END *
+    *******/
 }
 
 EAPI int
index 3fd9fb0..e03284c 100644 (file)
@@ -22,6 +22,32 @@ typedef enum
 /* Used for showing "malformed" or missing chars */
 #define REPLACEMENT_CHAR 0xFFFD
 
+/*******************************************************************
+ * TIZEN_ONLY(20150127): Add evas_textblock_cursor_cluster_* APIs. *
+ *******************************************************************/
+#define CHECK_LANGUAGE_CLUSTER_AVAILABLE(script) \
+   (((script == EVAS_SCRIPT_THAI) || \
+     (script == EVAS_SCRIPT_ARABIC) || \
+     (script == EVAS_SCRIPT_DEVANAGARI) || \
+     (script == EVAS_SCRIPT_BENGALI) || \
+     (script == EVAS_SCRIPT_GUJARATI) || \
+     (script == EVAS_SCRIPT_TELUGU) || \
+     (script == EVAS_SCRIPT_KHMER) || \
+     (script == EVAS_SCRIPT_SINHALA) || \
+     (script == EVAS_SCRIPT_KANNADA) || \
+     (script == EVAS_SCRIPT_MALAYALAM) || \
+     (script == EVAS_SCRIPT_GURMUKHI) || \
+     (script == EVAS_SCRIPT_ORIYA) || \
+     (script == EVAS_SCRIPT_TAMIL)) ? \
+    EINA_TRUE : EINA_FALSE)
+
+#define CHECK_CLUSTER_EXCEPTION_CHAR(x) \
+   (0x0E33 == (x))
+/*******
+ * END *
+ *******/
+
+
 typedef struct _Evas_Glyph Evas_Glyph;
 typedef struct _Evas_Glyph_Array Evas_Glyph_Array;