1 #include "evas_common_private.h"
2 #include "evas_private.h"
3 #include "efl_canvas_textblock_internal.h"
4 #include "eo_internal.h"
5 
6 #define MY_CLASS EFL_TEXT_CURSOR_OBJECT_CLASS
7 #define MY_CLASS_NAME "Efl.Text.Cursor"
8 
9 typedef struct
10 {
11    Efl_Text_Cursor_Handle *handle;
12    Efl_Canvas_Object *text_obj;
13 } Efl_Text_Cursor_Object_Data;
14 
15 struct _Evas_Textblock_Selection_Iterator
16 {
17    Eina_Iterator                       iterator; /**< Eina Iterator. */
18    Eina_List                           *list; /**< Head of list. */
19    Eina_List                           *current; /**< Current node in loop. */
20 };
21 
22 typedef struct _Evas_Textblock_Selection_Iterator Evas_Textblock_Selection_Iterator;
23 
24 EFL_CLASS_SIMPLE_CLASS(efl_text_cursor_object, "Efl.Text.Cursor", EFL_TEXT_CURSOR_OBJECT_CLASS)
25 
26 EOLIAN static void
_efl_text_cursor_object_position_set(Eo * obj EINA_UNUSED,Efl_Text_Cursor_Object_Data * pd,int position)27 _efl_text_cursor_object_position_set(Eo *obj EINA_UNUSED, Efl_Text_Cursor_Object_Data *pd, int position)
28 {
29    evas_textblock_cursor_pos_set(pd->handle, position);
30 }
31 
32 EOLIAN static int
_efl_text_cursor_object_position_get(const Eo * obj EINA_UNUSED,Efl_Text_Cursor_Object_Data * pd)33 _efl_text_cursor_object_position_get(const Eo *obj EINA_UNUSED, Efl_Text_Cursor_Object_Data *pd)
34 {
35    return evas_textblock_cursor_pos_get(pd->handle);
36 }
37 
38 EOLIAN static Eina_Unicode
_efl_text_cursor_object_content_get(const Eo * obj EINA_UNUSED,Efl_Text_Cursor_Object_Data * pd)39 _efl_text_cursor_object_content_get(const Eo *obj EINA_UNUSED, Efl_Text_Cursor_Object_Data *pd)
40 {
41    if (pd->handle && pd->handle->node)
42     return eina_ustrbuf_string_get(pd->handle->node->unicode)[pd->handle->pos];
43    else
44     return 0;
45 }
46 
47 EOLIAN static Eina_Rect
_efl_text_cursor_object_content_geometry_get(const Eo * obj EINA_UNUSED,Efl_Text_Cursor_Object_Data * pd)48 _efl_text_cursor_object_content_geometry_get(const Eo *obj EINA_UNUSED, Efl_Text_Cursor_Object_Data *pd)
49 {
50    Eina_Rect rect = {0};
51    Eina_Bool item_is = evas_textblock_cursor_format_item_geometry_get(pd->handle, &(rect.x), &(rect.y), &(rect.w), &(rect.h));
52    if (item_is)
53       return rect;
54 
55    evas_textblock_cursor_pen_geometry_get(pd->handle, &(rect.x), &(rect.y), &(rect.w), &(rect.h));
56 
57    return rect;
58 }
59 
60 EOLIAN static void
_efl_text_cursor_object_line_number_set(Eo * obj EINA_UNUSED,Efl_Text_Cursor_Object_Data * pd,int line_number)61 _efl_text_cursor_object_line_number_set(Eo *obj EINA_UNUSED, Efl_Text_Cursor_Object_Data *pd, int line_number)
62 {
63    evas_textblock_cursor_line_set(pd->handle, line_number);
64 }
65 
66 EOLIAN static int
_efl_text_cursor_object_line_number_get(const Eo * obj EINA_UNUSED,Efl_Text_Cursor_Object_Data * pd)67 _efl_text_cursor_object_line_number_get(const Eo *obj EINA_UNUSED, Efl_Text_Cursor_Object_Data *pd)
68 {
69    Eina_Rect rect = {0};
70 
71    return evas_textblock_cursor_line_geometry_get(pd->handle, &(rect.x), &(rect.y), &(rect.w), &(rect.h));
72 }
73 
74 EOLIAN static Eina_Rect
_efl_text_cursor_object_cursor_geometry_get(const Eo * obj EINA_UNUSED,Efl_Text_Cursor_Object_Data * pd,Efl_Text_Cursor_Type ctype)75 _efl_text_cursor_object_cursor_geometry_get(const Eo *obj EINA_UNUSED, Efl_Text_Cursor_Object_Data *pd, Efl_Text_Cursor_Type ctype)
76 {
77    Eina_Rect rc = {0};
78    Evas_Textblock_Cursor_Type cursor_type = (ctype == EFL_TEXT_CURSOR_TYPE_BEFORE) ? EVAS_TEXTBLOCK_CURSOR_BEFORE : EVAS_TEXTBLOCK_CURSOR_UNDER;
79    evas_textblock_cursor_geometry_bidi_get(pd->handle, &rc.x, &rc.y, &rc.w, &rc.h, NULL, NULL, NULL, NULL, cursor_type);
80    return rc;
81 }
82 
83 EOLIAN static Eina_Bool
_efl_text_cursor_object_lower_cursor_geometry_get(const Eo * obj EINA_UNUSED,Efl_Text_Cursor_Object_Data * pd,Eina_Rect * geometry2)84 _efl_text_cursor_object_lower_cursor_geometry_get(const Eo *obj EINA_UNUSED, Efl_Text_Cursor_Object_Data *pd, Eina_Rect *geometry2)
85 {
86    Eina_Rect rc = {0};
87    Eina_Bool b_ret = EINA_FALSE;
88    b_ret = evas_textblock_cursor_geometry_bidi_get(pd->handle, NULL, NULL, NULL, NULL, &rc.x, &rc.y, &rc.w, &rc.h, EVAS_TEXTBLOCK_CURSOR_BEFORE);
89    if (geometry2)
90      {
91         *geometry2 = rc;
92      }
93    return b_ret;
94 }
95 
96 EOLIAN static Eina_Bool
_efl_text_cursor_object_equal(const Eo * obj EINA_UNUSED,Efl_Text_Cursor_Object_Data * pd,const Efl_Text_Cursor_Object * dst)97 _efl_text_cursor_object_equal(const Eo *obj EINA_UNUSED, Efl_Text_Cursor_Object_Data *pd, const Efl_Text_Cursor_Object *dst)
98 {
99    return evas_textblock_cursor_equal(pd->handle, efl_text_cursor_object_handle_get(dst));
100 }
101 
102 EOLIAN static int
_efl_text_cursor_object_compare(const Eo * obj EINA_UNUSED,Efl_Text_Cursor_Object_Data * pd,const Efl_Text_Cursor_Object * dst)103 _efl_text_cursor_object_compare(const Eo *obj EINA_UNUSED, Efl_Text_Cursor_Object_Data *pd, const Efl_Text_Cursor_Object *dst)
104 {
105    return evas_textblock_cursor_compare(pd->handle, efl_text_cursor_object_handle_get(dst));
106 }
107 
108 static void
_efl_text_cursor_object_copy(const Efl_Text_Cursor_Object * obj,Efl_Text_Cursor_Object * dst)109 _efl_text_cursor_object_copy(const Efl_Text_Cursor_Object *obj, Efl_Text_Cursor_Object *dst)
110 {
111    Efl_Text_Cursor_Object_Data *pd = efl_data_scope_safe_get(obj, MY_CLASS);
112    EINA_SAFETY_ON_NULL_RETURN(pd);
113 
114    Efl_Text_Cursor_Object_Data *pd_dest = efl_data_scope_safe_get(dst, MY_CLASS);
115    EINA_SAFETY_ON_NULL_RETURN(pd_dest);
116 
117    if (!pd->handle) return;
118 
119    Efl_Text_Cursor_Handle *handle = evas_object_textblock_cursor_new(pd->handle->obj);
120    evas_textblock_cursor_copy(pd->handle, handle);
121    pd_dest->text_obj = pd->text_obj;
122    efl_text_cursor_object_handle_set(dst, handle);
123    evas_textblock_cursor_unref(handle, NULL);
124 }
125 
126 EOLIAN static Efl_Text_Cursor_Object *
_efl_text_cursor_object_efl_duplicate_duplicate(const Eo * obj,Efl_Text_Cursor_Object_Data * pd EINA_UNUSED)127 _efl_text_cursor_object_efl_duplicate_duplicate(const Eo *obj, Efl_Text_Cursor_Object_Data *pd EINA_UNUSED)
128 {
129   Efl_Text_Cursor_Object *dup = efl_text_cursor_object_create(efl_parent_get(obj));
130 
131   _efl_text_cursor_object_copy(obj, dup);
132 
133   return dup;
134 }
135 
136 EOLIAN static Eina_Bool
_efl_text_cursor_object_move(Eo * obj EINA_UNUSED,Efl_Text_Cursor_Object_Data * pd,Efl_Text_Cursor_Move_Type type)137 _efl_text_cursor_object_move(Eo *obj EINA_UNUSED, Efl_Text_Cursor_Object_Data *pd, Efl_Text_Cursor_Move_Type type)
138 {
139    Eina_Bool moved = EINA_FALSE;
140    int pos = evas_textblock_cursor_pos_get(pd->handle);
141 
142    switch (type) {
143       case EFL_TEXT_CURSOR_MOVE_TYPE_CHARACTER_NEXT :
144          moved = evas_textblock_cursor_char_next(pd->handle);
145          break;
146       case EFL_TEXT_CURSOR_MOVE_TYPE_CHARACTER_PREVIOUS :
147          moved = evas_textblock_cursor_char_prev(pd->handle);
148          break;
149       case EFL_TEXT_CURSOR_MOVE_TYPE_CLUSTER_NEXT :
150          moved = evas_textblock_cursor_cluster_next(pd->handle);
151          break;
152       case EFL_TEXT_CURSOR_MOVE_TYPE_CLUSTER_PREVIOUS :
153          moved = evas_textblock_cursor_cluster_prev(pd->handle);
154          break;
155       case EFL_TEXT_CURSOR_MOVE_TYPE_PARAGRAPH_START :
156          evas_textblock_cursor_paragraph_char_first(pd->handle);
157          if (pos != evas_textblock_cursor_pos_get(pd->handle))
158            moved = EINA_TRUE;
159          break;
160       case EFL_TEXT_CURSOR_MOVE_TYPE_PARAGRAPH_END :
161          evas_textblock_cursor_paragraph_char_last(pd->handle);
162          if (pos != evas_textblock_cursor_pos_get(pd->handle))
163            moved = EINA_TRUE;
164          break;
165       case EFL_TEXT_CURSOR_MOVE_TYPE_WORD_START :
166          moved = evas_textblock_cursor_word_start(pd->handle);
167          break;
168       case EFL_TEXT_CURSOR_MOVE_TYPE_WORD_END :
169          moved = evas_textblock_cursor_word_end(pd->handle);
170          break;
171       case EFL_TEXT_CURSOR_MOVE_TYPE_LINE_START :
172          evas_textblock_cursor_line_char_first(pd->handle);
173          if (pos != evas_textblock_cursor_pos_get(pd->handle))
174            moved = EINA_TRUE;
175          break;
176       case EFL_TEXT_CURSOR_MOVE_TYPE_LINE_END :
177          evas_textblock_cursor_line_char_last(pd->handle);
178          if (pos != evas_textblock_cursor_pos_get(pd->handle))
179            moved = EINA_TRUE;
180          break;
181       case EFL_TEXT_CURSOR_MOVE_TYPE_FIRST :
182          evas_textblock_cursor_paragraph_first(pd->handle);
183          if (pos != evas_textblock_cursor_pos_get(pd->handle))
184            moved = EINA_TRUE;
185          break;
186       case EFL_TEXT_CURSOR_MOVE_TYPE_LAST :
187          evas_textblock_cursor_paragraph_last(pd->handle);
188          if (pos != evas_textblock_cursor_pos_get(pd->handle))
189            moved = EINA_TRUE;
190          break;
191       case EFL_TEXT_CURSOR_MOVE_TYPE_PARAGRAPH_NEXT :
192          moved = evas_textblock_cursor_paragraph_next(pd->handle);
193          break;
194       case EFL_TEXT_CURSOR_MOVE_TYPE_PARAGRAPH_PREVIOUS :
195          moved = evas_textblock_cursor_paragraph_prev(pd->handle);
196          break;
197      }
198 
199    return moved;
200 }
201 
202 EOLIAN static void
_efl_text_cursor_object_char_delete(Eo * obj EINA_UNUSED,Efl_Text_Cursor_Object_Data * pd)203 _efl_text_cursor_object_char_delete(Eo *obj EINA_UNUSED, Efl_Text_Cursor_Object_Data *pd)
204 {
205    evas_textblock_cursor_char_delete(pd->handle);
206 }
207 
208 EOLIAN static Eina_Bool
_efl_text_cursor_object_line_jump_by(Eo * obj EINA_UNUSED,Efl_Text_Cursor_Object_Data * pd,int by)209 _efl_text_cursor_object_line_jump_by(Eo *obj EINA_UNUSED, Efl_Text_Cursor_Object_Data *pd, int by)
210 {
211    if (!pd->handle) return EINA_FALSE;
212 
213    Eina_Bool moved = EINA_FALSE;
214    int pos = evas_textblock_cursor_pos_get(pd->handle);
215    evas_textblock_cursor_line_jump_by(pd->handle, by);
216    moved = (pos != evas_textblock_cursor_pos_get(pd->handle));
217    return moved;
218 }
219 
220 EOLIAN static void
_efl_text_cursor_object_char_coord_set(Eo * obj EINA_UNUSED,Efl_Text_Cursor_Object_Data * pd,Eina_Position2D coord)221 _efl_text_cursor_object_char_coord_set(Eo *obj EINA_UNUSED, Efl_Text_Cursor_Object_Data *pd, Eina_Position2D coord)
222 {
223    evas_textblock_cursor_char_coord_set(pd->handle, coord.x, coord.y);
224 }
225 
226 EOLIAN static void
_efl_text_cursor_object_cluster_coord_set(Eo * obj EINA_UNUSED,Efl_Text_Cursor_Object_Data * pd,Eina_Position2D coord)227 _efl_text_cursor_object_cluster_coord_set(Eo *obj EINA_UNUSED, Efl_Text_Cursor_Object_Data *pd, Eina_Position2D coord)
228 {
229    evas_textblock_cursor_cluster_coord_set(pd->handle, coord.x, coord.y);
230 }
231 
232 static int
_prepend_text_run2(Efl_Text_Cursor_Handle * cur,const char * s,const char * p)233 _prepend_text_run2(Efl_Text_Cursor_Handle *cur, const char *s, const char *p)
234 {
235    if ((s) && (p > s))
236      {
237         char *ts;
238 
239         ts = alloca(p - s + 1);
240         strncpy(ts, s, p - s);
241         ts[p - s] = 0;
242         return evas_textblock_cursor_text_prepend(cur, ts);
243      }
244    return 0;
245 }
246 
247 int
_cursor_text_append(Efl_Text_Cursor_Handle * cur,const char * text)248 _cursor_text_append(Efl_Text_Cursor_Handle *cur,
249       const char *text)
250 {
251    if (!text || !cur) return 0;
252 
253    const char *off = text;
254    int len = 0;
255 
256    Evas_Object_Protected_Data *obj = efl_data_scope_safe_get(cur->obj, EFL_CANVAS_OBJECT_CLASS);
257    EINA_SAFETY_ON_NULL_RETURN_VAL(obj, 0);
258    evas_object_async_block(obj);
259 
260    while (*off)
261      {
262         char *format = NULL;
263         int n = 1;
264         if (!strncmp(_PARAGRAPH_SEPARATOR_UTF8, off,
265                     strlen(_PARAGRAPH_SEPARATOR_UTF8)))
266           {
267              format = "ps";
268              n = strlen(_PARAGRAPH_SEPARATOR_UTF8);
269           }
270         else if (!strncmp(_NEWLINE_UTF8, off, strlen(_NEWLINE_UTF8)))
271           {
272              format = "br";
273              n = strlen(_NEWLINE_UTF8);
274           }
275         else if (!strncmp(_TAB_UTF8, off, strlen(_TAB_UTF8)))
276           {
277              format = "tab";
278              n = strlen(_TAB_UTF8);
279           }
280 
281         if (format)
282           {
283              len += _prepend_text_run2(cur, text, off);
284              if (evas_textblock_cursor_format_prepend(cur, format))
285                {
286                   len++;
287                }
288              text = off + n; /* sync text with next segment */
289           }
290           off += n;
291      }
292    len += _prepend_text_run2(cur, text, off);
293    return len;
294 }
295 
296 EOLIAN static void
_efl_text_cursor_object_text_insert(Eo * obj EINA_UNUSED,Efl_Text_Cursor_Object_Data * pd,const char * text)297 _efl_text_cursor_object_text_insert(Eo *obj EINA_UNUSED, Efl_Text_Cursor_Object_Data *pd, const char *text)
298 {
299    _cursor_text_append(pd->handle, text);
300 }
301 
302 EOLIAN static char *
_efl_text_cursor_object_range_text_get(const Eo * obj EINA_UNUSED,Efl_Text_Cursor_Object_Data * pd,Efl_Text_Cursor_Object * cur2)303 _efl_text_cursor_object_range_text_get(const Eo *obj EINA_UNUSED, Efl_Text_Cursor_Object_Data *pd, Efl_Text_Cursor_Object *cur2)
304 {
305    return evas_textblock_cursor_range_text_get(pd->handle, efl_text_cursor_object_handle_get(cur2), EVAS_TEXTBLOCK_TEXT_PLAIN);
306 }
307 
308 EOLIAN static void
_efl_text_cursor_object_markup_insert(Eo * obj EINA_UNUSED,Efl_Text_Cursor_Object_Data * pd,const char * markup)309 _efl_text_cursor_object_markup_insert(Eo *obj EINA_UNUSED, Efl_Text_Cursor_Object_Data *pd, const char *markup)
310 {
311    evas_object_textblock_text_markup_prepend(pd->handle, markup);
312 }
313 
314 EOLIAN static char *
_efl_text_cursor_object_range_markup_get(const Eo * obj EINA_UNUSED,Efl_Text_Cursor_Object_Data * pd,Efl_Text_Cursor_Object * cur2)315 _efl_text_cursor_object_range_markup_get(const Eo *obj EINA_UNUSED, Efl_Text_Cursor_Object_Data *pd, Efl_Text_Cursor_Object *cur2)
316 {
317    return evas_textblock_cursor_range_text_get(pd->handle,efl_text_cursor_object_handle_get(cur2), EVAS_TEXTBLOCK_TEXT_MARKUP);
318 }
319 
320 EOLIAN static Eina_Iterator *
_efl_text_cursor_object_range_geometry_get(Eo * obj EINA_UNUSED,Efl_Text_Cursor_Object_Data * pd,Efl_Text_Cursor_Object * cur2)321 _efl_text_cursor_object_range_geometry_get(Eo *obj EINA_UNUSED, Efl_Text_Cursor_Object_Data *pd, Efl_Text_Cursor_Object *cur2)
322 {
323    return evas_textblock_cursor_range_simple_geometry_get(pd->handle, efl_text_cursor_object_handle_get(cur2));
324 }
325 
326 /** selection iterator */
327 /**
328   * @internal
329   * Returns the value of the current data of list node,
330   * and goes to the next list node.
331   *
332   * @param it the iterator.
333   * @param data the data of the current list node.
334   * @return EINA_FALSE if the current list node does not exists.
335   * Otherwise, returns EINA_TRUE.
336   */
337 static Eina_Bool
_evas_textblock_selection_iterator_next(Evas_Textblock_Selection_Iterator * it,void ** data)338 _evas_textblock_selection_iterator_next(Evas_Textblock_Selection_Iterator *it, void **data)
339 {
340    if (!it->current)
341      return EINA_FALSE;
342 
343    *data = eina_list_data_get(it->current);
344    it->current = eina_list_next(it->current);
345 
346    return EINA_TRUE;
347 }
348 
349 /**
350   * @internal
351   * Gets the iterator container (Eina_List) which created the iterator.
352   * @param it the iterator.
353   * @return A pointer to Eina_List.
354   */
355 static Eina_List *
_evas_textblock_selection_iterator_get_container(Evas_Textblock_Selection_Iterator * it)356 _evas_textblock_selection_iterator_get_container(Evas_Textblock_Selection_Iterator *it)
357 {
358    return it->list;
359 }
360 
361 /**
362   * @internal
363   * Frees the iterator container (Eina_List).
364   * @param it the iterator.
365   */
366 static void
_evas_textblock_selection_iterator_free(Evas_Textblock_Selection_Iterator * it)367 _evas_textblock_selection_iterator_free(Evas_Textblock_Selection_Iterator *it)
368 {
369    Eina_Rectangle *tr;
370 
371    EINA_LIST_FREE(it->list, tr)
372      free(tr);
373    EINA_MAGIC_SET(&it->iterator, 0);
374    free(it);
375 }
376 
377 /**
378   * @internal
379   * Creates newly allocated  iterator associated to a list.
380   * @param list The list.
381   * @return If the memory cannot be allocated, NULL is returned.
382   * Otherwise, a valid iterator is returned.
383   */
384 static Eina_Iterator *
_evas_textblock_selection_iterator_new(Eina_List * list)385 _evas_textblock_selection_iterator_new(Eina_List *list)
386 {
387    Evas_Textblock_Selection_Iterator *it;
388 
389    it = calloc(1, sizeof(Evas_Textblock_Selection_Iterator));
390    if (!it) return NULL;
391 
392    EINA_MAGIC_SET(&it->iterator, EINA_MAGIC_ITERATOR);
393    it->list = list;
394    it->current = list;
395 
396    it->iterator.version = EINA_ITERATOR_VERSION;
397    it->iterator.next = FUNC_ITERATOR_NEXT(
398                                      _evas_textblock_selection_iterator_next);
399    it->iterator.get_container = FUNC_ITERATOR_GET_CONTAINER(
400                             _evas_textblock_selection_iterator_get_container);
401    it->iterator.free = FUNC_ITERATOR_FREE(
402                                      _evas_textblock_selection_iterator_free);
403 
404    return &it->iterator;
405 }
406 
407 EOLIAN static Eina_Iterator *
_efl_text_cursor_object_range_precise_geometry_get(Eo * obj EINA_UNUSED,Efl_Text_Cursor_Object_Data * pd,Efl_Text_Cursor_Object * cur2)408 _efl_text_cursor_object_range_precise_geometry_get(Eo *obj EINA_UNUSED, Efl_Text_Cursor_Object_Data *pd, Efl_Text_Cursor_Object *cur2)
409 {
410    Eina_List *rects = evas_textblock_cursor_range_geometry_get(pd->handle, efl_text_cursor_object_handle_get(cur2));
411    return _evas_textblock_selection_iterator_new(rects);
412 }
413 
414 EOLIAN static void
_efl_text_cursor_object_range_delete(Eo * obj EINA_UNUSED,Efl_Text_Cursor_Object_Data * pd,Efl_Text_Cursor_Object * cur2)415 _efl_text_cursor_object_range_delete(Eo *obj EINA_UNUSED, Efl_Text_Cursor_Object_Data *pd, Efl_Text_Cursor_Object *cur2)
416 {
417    evas_textblock_cursor_range_delete(pd->handle, efl_text_cursor_object_handle_get(cur2));
418 }
419 
420 EAPI void
efl_text_cursor_object_handle_set(Eo * obj,Efl_Text_Cursor_Handle * handle)421 efl_text_cursor_object_handle_set(Eo *obj, Efl_Text_Cursor_Handle *handle)
422 {
423    Efl_Text_Cursor_Object_Data *pd = efl_data_scope_safe_get(obj, MY_CLASS);
424    EINA_SAFETY_ON_NULL_RETURN(pd);
425    if (handle == pd->handle)
426      return;
427 
428    Efl_Text_Cursor_Handle *old_handle = pd->handle;
429 
430    pd->handle = evas_textblock_cursor_ref(handle, obj);
431 
432    if (old_handle)
433      {
434         evas_textblock_cursor_unref(old_handle, obj);
435      }
436 }
437 
438 EAPI Efl_Text_Cursor_Handle *
efl_text_cursor_object_handle_get(const Eo * obj)439 efl_text_cursor_object_handle_get(const Eo *obj)
440 {
441    Efl_Text_Cursor_Object_Data *pd = efl_data_scope_safe_get(obj, MY_CLASS);
442    EINA_SAFETY_ON_NULL_RETURN_VAL(pd, NULL);
443    return pd->handle;
444 }
445 
efl_text_cursor_object_create(Eo * parent)446 Eo* efl_text_cursor_object_create(Eo *parent)
447 {
448    return efl_add(efl_text_cursor_object_realized_class_get(), parent);
449 }
450 
efl_text_cursor_object_text_object_set(Eo * cursor,Eo * canvas_text_obj,Eo * text_obj)451 void efl_text_cursor_object_text_object_set(Eo *cursor, Eo *canvas_text_obj, Eo *text_obj)
452 {
453    Efl_Text_Cursor_Object_Data *pd = efl_data_scope_safe_get(cursor, MY_CLASS);
454    EINA_SAFETY_ON_NULL_RETURN(pd);
455    Efl_Text_Cursor_Handle *handle = NULL;
456    if (efl_isa(canvas_text_obj, EFL_CANVAS_TEXTBLOCK_CLASS))
457      {
458         pd->text_obj = text_obj;
459         handle = evas_object_textblock_cursor_new(canvas_text_obj);
460      }
461    else
462      {
463         ERR("Expect Canvas Text Object");
464      }
465 
466    if (handle)
467      {
468         efl_text_cursor_object_handle_set(cursor, handle);
469         evas_textblock_cursor_unref(handle, NULL);
470      }
471 }
472 
473 EOLIAN static Efl_Canvas_Object *
_efl_text_cursor_object_text_object_get(const Eo * obj EINA_UNUSED,Efl_Text_Cursor_Object_Data * pd)474 _efl_text_cursor_object_text_object_get(const Eo *obj EINA_UNUSED, Efl_Text_Cursor_Object_Data *pd)
475 {
476    return pd->text_obj;
477 }
478 
479 EOLIAN static void
_efl_text_cursor_object_efl_object_destructor(Eo * obj,Efl_Text_Cursor_Object_Data * pd)480 _efl_text_cursor_object_efl_object_destructor(Eo *obj, Efl_Text_Cursor_Object_Data *pd)
481 {
482    if (pd->handle)
483      {
484         evas_textblock_cursor_unref(pd->handle, obj);
485         pd->handle = NULL;
486      }
487 
488    if (pd->text_obj)
489      {
490         pd->text_obj = NULL;
491      }
492 
493    efl_destructor(efl_super(obj, MY_CLASS));
494 
495 }
496 
497 #include "efl_text_cursor_object.eo.c"
498