[copy&paste] improved selection handler feature
[framework/uifw/elementary.git] / src / lib / elm_entry.c
index fde93ff..30622b8 100644 (file)
@@ -2,6 +2,8 @@
 #include <Elementary_Cursor.h>
 #include "elm_priv.h"
 #include "elm_module_priv.h"
+#include "els_scroller.h"
+
 
 /* Maximum chunk size to be inserted to the entry at once
  * FIXME: This size is arbitrary, should probably choose a better size.
@@ -158,6 +160,8 @@ static void _magnifier_create(void *data);
 static void _magnifier_show(void *data);
 static void _magnifier_hide(void *data);
 static void _magnifier_move(void *data);
+static Evas_Coord_Rectangle _layout_region_get(Evas_Object *data);
+static Evas_Coord_Rectangle _viewport_region_get(Evas_Object *data);
 
 static const char SIG_CHANGED[] = "changed";
 static const char SIG_ACTIVATED[] = "activated";
@@ -178,25 +182,25 @@ static const char SIG_ANCHOR_CLICKED[] = "anchor,clicked";
 static const char SIG_MATCHLIST_CLICKED[] = "matchlist,clicked";
 static const char SIG_PREEDIT_CHANGED[] = "preedit,changed";
 static const Evas_Smart_Cb_Description _signals[] = {
-  {SIG_CHANGED, ""},
-  {SIG_ACTIVATED, ""},
-  {SIG_PRESS, ""},
-  {SIG_LONGPRESSED, ""},
-  {SIG_CLICKED, ""},
-  {SIG_CLICKED_DOUBLE, ""},
-  {SIG_FOCUSED, ""},
-  {SIG_UNFOCUSED, ""},
-  {SIG_SELECTION_PASTE, ""},
-  {SIG_SELECTION_COPY, ""},
-  {SIG_SELECTION_CUT, ""},
-  {SIG_SELECTION_START, ""},
-  {SIG_SELECTION_CHANGED, ""},
-  {SIG_SELECTION_CLEARED, ""},
-  {SIG_CURSOR_CHANGED, ""},
-  {SIG_ANCHOR_CLICKED, ""},
-  {SIG_PREEDIT_CHANGED, ""},
-  {SIG_MATCHLIST_CLICKED, ""},
-  {NULL, NULL}
+       {SIG_CHANGED, ""},
+       {SIG_ACTIVATED, ""},
+       {SIG_PRESS, ""},
+       {SIG_LONGPRESSED, ""},
+       {SIG_CLICKED, ""},
+       {SIG_CLICKED_DOUBLE, ""},
+       {SIG_FOCUSED, ""},
+       {SIG_UNFOCUSED, ""},
+       {SIG_SELECTION_PASTE, ""},
+       {SIG_SELECTION_COPY, ""},
+       {SIG_SELECTION_CUT, ""},
+       {SIG_SELECTION_START, ""},
+       {SIG_SELECTION_CHANGED, ""},
+       {SIG_SELECTION_CLEARED, ""},
+       {SIG_CURSOR_CHANGED, ""},
+       {SIG_ANCHOR_CLICKED, ""},
+       {SIG_PREEDIT_CHANGED, ""},
+       {SIG_MATCHLIST_CLICKED, ""},
+       {NULL, NULL}
 };
 
 typedef enum _Elm_Entry_Magnifier_Type
@@ -576,9 +580,9 @@ _theme_hook(Evas_Object *obj)
         edj = elm_smart_scroller_edje_object_get(wd->scroller);
         str = edje_object_data_get(edj, "focus_highlight");
         if ((str) && (!strcmp(str, "on")))
-           elm_widget_highlight_in_theme_set(obj, EINA_TRUE);
+          elm_widget_highlight_in_theme_set(obj, EINA_TRUE);
         else
-           elm_widget_highlight_in_theme_set(obj, EINA_FALSE);
+          elm_widget_highlight_in_theme_set(obj, EINA_FALSE);
      }
    _sizing_eval(obj);
 }
@@ -611,7 +615,7 @@ _recalc_cursor_geometry(Evas_Object *obj)
      {
         Evas_Coord cx, cy, cw, ch;
         edje_object_part_text_cursor_geometry_get(wd->ent, "elm.text",
-              &cx, &cy, &cw, &ch);
+                                                  &cx, &cy, &cw, &ch);
         if (wd->cur_changed)
           {
              elm_widget_show_region_set(obj, cx, cy, cw, ch, EINA_FALSE);
@@ -619,7 +623,7 @@ _recalc_cursor_geometry(Evas_Object *obj)
           }
      }
    else
-      wd->deferred_cur = EINA_TRUE;
+     wd->deferred_cur = EINA_TRUE;
 }
 
 static void
@@ -713,7 +717,7 @@ _sizing_eval(Evas_Object *obj)
              evas_object_resize(wd->scroller, resw, resh);
              edje_object_size_min_calc
                 (elm_smart_scroller_edje_object_get(wd->scroller),
-                    &vmw, &vmh);
+                 &vmw, &vmh);
              elm_smart_scroller_child_viewport_size_get(wd->scroller, &vw, &vh);
              edje_object_size_min_restricted_calc(wd->ent, &minw, &minh, vw, 0);
              wd->entmw = minw;
@@ -729,9 +733,9 @@ _sizing_eval(Evas_Object *obj)
              evas_object_size_hint_min_get(obj, &w, NULL);
              evas_object_size_hint_min_set(obj, w, h);
              if (wd->single_line)
-                evas_object_size_hint_max_set(obj, -1, h);
+               evas_object_size_hint_max_set(obj, -1, h);
              else
-                evas_object_size_hint_max_set(obj, -1, -1);
+               evas_object_size_hint_max_set(obj, -1, -1);
           }
         else
           {
@@ -761,15 +765,15 @@ _sizing_eval(Evas_Object *obj)
              evas_object_resize(wd->ent, vw, vh);
              edje_object_size_min_calc
                 (elm_smart_scroller_edje_object_get(wd->scroller),
-                    &vmw, &vmh);
+                 &vmw, &vmh);
              if (wd->single_line) h = vmh + minh;
              else h = vmh;
              evas_object_size_hint_min_get(obj, &w, NULL);
              evas_object_size_hint_min_set(obj, w, h);
              if (wd->single_line)
-                evas_object_size_hint_max_set(obj, -1, h);
+               evas_object_size_hint_max_set(obj, -1, h);
              else
-                evas_object_size_hint_max_set(obj, -1, -1);
+               evas_object_size_hint_max_set(obj, -1, -1);
           }
         else
           {
@@ -779,9 +783,9 @@ _sizing_eval(Evas_Object *obj)
              elm_coords_finger_size_adjust(1, &minw, 1, &minh);
              evas_object_size_hint_min_set(obj, minw, minh);
              if (wd->single_line)
-                evas_object_size_hint_max_set(obj, -1, minh);
+               evas_object_size_hint_max_set(obj, -1, minh);
              else
-                evas_object_size_hint_max_set(obj, -1, -1);
+               evas_object_size_hint_max_set(obj, -1, -1);
           }
      }
 
@@ -932,13 +936,18 @@ _content_get_hook(const Evas_Object *obj, const char *part)
         edje = elm_smart_scroller_edje_object_get(wd->scroller);
      }
    else
-     edje = wd->ent;
+      edje = wd->ent;
 
    if (edje)
      content = edje_object_part_swallow_get(edje, part);
    return content;
 }
 
+static void
+_translate_hook(Evas_Object *obj)
+{
+   evas_object_smart_callback_call(obj, "language,changed", NULL);
+}
 
 static void
 _signal_emit_hook(Evas_Object *obj, const char *emission, const char *source)
@@ -958,8 +967,8 @@ _signal_callback_add_hook(Evas_Object *obj, const char *emission, const char *so
    if (!wd) return;
    edje_object_signal_callback_add(wd->ent, emission, source, func_cb, data);
    if (wd->scroller)
-      edje_object_signal_callback_add(elm_smart_scroller_edje_object_get(wd->scroller),
-                                      emission, source, func_cb, data);
+     edje_object_signal_callback_add(elm_smart_scroller_edje_object_get(wd->scroller),
+                                     emission, source, func_cb, data);
 }
 
 static void
@@ -969,8 +978,8 @@ _signal_callback_del_hook(Evas_Object *obj, const char *emission, const char *so
    edje_object_signal_callback_del_full(wd->ent, emission, source, func_cb,
                                         data);
    if (wd->scroller)
-      edje_object_signal_callback_del_full(elm_smart_scroller_edje_object_get(wd->scroller),
-                                           emission, source, func_cb, data);
+     edje_object_signal_callback_del_full(elm_smart_scroller_edje_object_get(wd->scroller),
+                                          emission, source, func_cb, data);
 }
 
 static void
@@ -985,7 +994,7 @@ _focus_region_hook(Evas_Object *obj, Evas_Coord x, Evas_Coord y, Evas_Coord w, E
 {
    Widget_Data *wd = elm_widget_data_get(obj);
    if (wd->scroll)
-      elm_smart_scroller_child_region_show(wd->scroller, x, y, w, h);
+     elm_smart_scroller_child_region_show(wd->scroller, x, y, w, h);
 }
 
 static void
@@ -1063,6 +1072,12 @@ _move(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_i
    Widget_Data *wd = elm_widget_data_get(data);
 
    if (wd->hoversel) _hoversel_position(data);
+
+   if (!_elm_config->desktop_entry)
+     edje_object_part_text_viewport_region_set(wd->ent, "elm.text", _viewport_region_get(data));
+
+   if (!_elm_config->desktop_entry)
+     edje_object_part_text_layout_region_set(wd->ent, "elm.text", _layout_region_get(data));
 }
 
 static void
@@ -1754,14 +1769,23 @@ _matchlist_show(void *data)
 
                   textlen = strlen(str_list) - strlen(str_result);
                   str_front = malloc(textlen + 1);
-                  if (str_front == NULL) return;
+                  if (str_front == NULL)
+                    {
+                       free(str_mkup);
+                       return;
+                    }
 
                   memset(str_front, 0, textlen + 1);
                   strncpy(str_front, str_list, textlen);
 
                   textlen = strlen(text);
                   str_mid = malloc(textlen + 1);
-                  if (str_mid == NULL) return;
+                  if (str_mid == NULL)
+                    {
+                       free(str_mkup);
+                       free(str_front);
+                       return;
+                    }
 
                   memset(str_mid, 0, textlen + 1);
                   strncpy(str_mid, str_list + strlen(str_front), textlen);
@@ -1796,17 +1820,20 @@ static void _matchlist_list_clicked( void *data, Evas_Object *obj, void *event_i
    if ((it == NULL) || (wd == NULL))
      return;
 
+   const char *str = NULL;
    const char *text = elm_list_item_label_get(it);
    evas_object_smart_callback_call((Evas_Object *)data, "selected", (void *)text);
    if (wd->match_list)
      {
         if (text != NULL)
           {
-             elm_entry_entry_set(data, elm_entry_markup_to_utf8(text));
+             str = elm_entry_markup_to_utf8(text);
+             elm_entry_entry_set(data, str);
              elm_entry_cursor_end_set(data);
              wd->matchlist_list_clicked = EINA_TRUE;
 
              evas_object_smart_callback_call(data, SIG_MATCHLIST_CLICKED, elm_entry_markup_to_utf8(text));
+             free(str);
           }
      }
    elm_widget_focus_set(data, EINA_TRUE);
@@ -1856,7 +1883,6 @@ _entry_changed_common_handling(void *data, const char *event)
 
    if ((wd->autosave) && (wd->file))
      wd->delay_write = ecore_timer_add(2.0, _delay_write, data);
-
    /* callback - this could call callbacks that delete the entry... thus...
     * any access to wd after this could be invalid */
    evas_object_smart_callback_call(data, event, NULL);
@@ -1918,37 +1944,67 @@ _signal_handler_moving(void *data, Evas_Object *obj __UNUSED__, const char *emis
    _magnifier_show(data);
 }
 
-static Evas_Object *
-_viewport_obj_get(Evas_Object *data)
+static Evas_Coord_Rectangle
+_layout_region_get(Evas_Object *data)
 {
+   Evas_Coord_Rectangle geometry;
+   geometry.x = geometry.y = geometry.w = geometry.h = -1;
+
    Widget_Data *wd = elm_widget_data_get(data);
-   if (!wd) return NULL;
+   if (!wd) return geometry;
 
-   if(!data || !strlen(elm_widget_type_get(data)))
-     return NULL;
+   if (!data || !strlen(elm_widget_type_get(data)))
+     return geometry;
 
-   Evas_Coord x, y, w, h;
-   x = y = w = h = -1;
+   Evas_Object *child_obj = data;
+   Evas_Object *parent_obj;
+
+   while (parent_obj = elm_widget_parent_get(child_obj))
+     {
+        if (!strcmp(elm_widget_type_get(parent_obj), "conformant"))
+          {
+             evas_object_geometry_get(child_obj, &geometry.x, &geometry.y, &geometry.w, &geometry.h);
+             return geometry;
+          }
+        child_obj = parent_obj;
+     }
+
+   return geometry;
+}
+
+static Evas_Coord_Rectangle
+_viewport_region_get(Evas_Object *data)
+{
+   Evas_Coord_Rectangle geometry;
+   geometry.x = geometry.y = geometry.w = geometry.h = -1;
+
+   Widget_Data *wd = elm_widget_data_get(data);
+   if (!wd) return geometry;
+
+   if (!data || !strlen(elm_widget_type_get(data)))
+     return geometry;
 
    if (wd->scroll)
      {
-        //evas_object_geometry_get(wd->scroller, &x, &y, &w, &h);
-        //printf(">>> wd->scroller (%d, %d, %d, %d) \n", x, y, w, h);
-        return wd->scroller;
+        evas_object_geometry_get(wd->scroller, &geometry.x, &geometry.y, NULL, NULL);
+        elm_smart_scroller_child_viewport_size_get(wd->scroller, &geometry.w, &geometry.h);
+
+        return geometry;
      }
 
    Evas_Object *parent_obj = data;
 
-   while(parent_obj = elm_widget_parent_get(parent_obj))
+   while (parent_obj = elm_widget_parent_get(parent_obj))
      {
-        //evas_object_geometry_get(parent_obj, &x, &y, &w, &h);
-        //printf(">>> %s (%d, %d, %d, %d) \n", elm_widget_type_get(parent_obj), x, y, w, h);
         if (!strcmp(elm_widget_type_get(parent_obj), "scroller") ||
             !strcmp(elm_widget_type_get(parent_obj), "genlist"))
-          return parent_obj;
+          {
+             evas_object_geometry_get(parent_obj, &geometry.x, &geometry.y, &geometry.w, &geometry.h);
+             return geometry;
+          }
      }
 
-   return NULL;
+   return geometry;
 }
 
 static void
@@ -1984,8 +2040,6 @@ _signal_selection_start(void *data, Evas_Object *obj __UNUSED__, const char *emi
      }
 #endif
 
-   if (!_elm_config->desktop_entry)
-     edje_object_part_text_viewport_object_set(wd->ent, "elm.text", _viewport_obj_get(data));
 }
 
 static void
@@ -2320,7 +2374,7 @@ _event_selection_notify(void *data, int type __UNUSED__, void *event)
 static Eina_Bool
 _event_selection_clear(void *data __UNUSED__, int type __UNUSED__, void *event __UNUSED__)
 {
-/*
+#if 0
    Widget_Data *wd = elm_widget_data_get(data);
    Ecore_X_Event_Selection_Clear *ev = event;
    if (!wd) return ECORE_CALLBACK_PASS_ON;
@@ -2330,7 +2384,7 @@ _event_selection_clear(void *data __UNUSED__, int type __UNUSED__, void *event _
      {
         elm_entry_select_none(data);
      }
-   return 1; */
+#else
 
    // start for cbhm
    Evas_Object *top = elm_widget_top_get(data);
@@ -2351,6 +2405,7 @@ _event_selection_clear(void *data __UNUSED__, int type __UNUSED__, void *event _
      }
 
    // end for cbhm
+#endif
    return ECORE_CALLBACK_PASS_ON;
 }
 
@@ -2419,16 +2474,16 @@ _strbuf_key_value_replace(Eina_Strbuf *srcbuf, char *key, const char *value, int
 {
    const char *srcstring = NULL;
    Eina_Strbuf *repbuf = NULL, *diffbuf = NULL;
-   char *curlocater, *replocater;
+   char *curlocater = NULL, *replocater;
    char *starttag, *endtag;
    int tagtxtlen = 0, insertflag = 0;
 
    srcstring = eina_strbuf_string_get(srcbuf);
-   curlocater = strstr(srcstring, key);
-
+   if (srcstring)
+     curlocater = strstr(srcstring, key);
    if (!curlocater || !srcstring)
      {
-       insertflag = 1;
+        insertflag = 1;
      }
    else
      {
@@ -2606,7 +2661,7 @@ _text_append_idler(void *data)
    wd->append_text_left[wd->append_text_position] = '\0';
 
    edje_object_part_text_append(wd->ent, "elm.text",
-         wd->append_text_left + start);
+                                wd->append_text_left + start);
 
    wd->append_text_left[wd->append_text_position] = backup;
 
@@ -2644,20 +2699,20 @@ _add_chars_till_limit(Evas_Object *obj, char **text, int can_add, Length_Unit un
           }
         else
           {
-             int index = 0;
+             int idx = 0;
              if (*new_text == '&')
                {
-                  while (*(new_text + index) != ';')
+                  while (*(new_text + idx) != ';')
                     {
-                       index++;
-                       if (!*(new_text + index)) break;
+                       idx++;
+                       if (!*(new_text + idx)) break;
                     }
                }
              char *markup;
-             index = evas_string_char_next_get(new_text, index, NULL);
-             markup = malloc(index + 1);
-             strncpy(markup, new_text, index);
-             markup[index] = 0;
+             idx = evas_string_char_next_get(new_text, idx, NULL);
+             markup = malloc(idx + 1);
+             strncpy(markup, new_text, idx);
+             markup[idx] = 0;
              if (unit == LENGTH_UNIT_BYTE)
                unit_size = strlen(elm_entry_markup_to_utf8(markup));
              else if (unit == LENGTH_UNIT_CHAR)
@@ -2677,13 +2732,13 @@ _add_chars_till_limit(Evas_Object *obj, char **text, int can_add, Length_Unit un
                        return;
                     }
                   can_add = 0;
-                  strncpy(new_text, new_text + index, current_len - ((new_text + index) - *text));
-                  current_len -= index;
+                  strncpy(new_text, new_text + idx, current_len - ((new_text + idx) - *text));
+                  current_len -= idx;
                   (*text)[current_len] = 0;
                }
              else
                {
-                  new_text += index;
+                  new_text += idx;
                   can_add -= unit_size;
                }
              i++;
@@ -2705,6 +2760,7 @@ _elm_entry_text_set(Evas_Object *obj, const char *item, const char *entry)
         edje_object_part_text_set(wd->ent, item, entry);
         return;
      }
+
    if (wd->text) eina_stringshare_del(wd->text);
    wd->text = NULL;
    if (wd->password_text) eina_stringshare_del(wd->password_text);
@@ -2811,8 +2867,10 @@ elm_entry_add(Evas_Object *parent)
    elm_widget_content_set_hook_set(obj, _content_set_hook);
    elm_widget_content_unset_hook_set(obj, _content_unset_hook);
    elm_widget_content_get_hook_set(obj, _content_get_hook);
+   elm_widget_translate_hook_set(obj, _translate_hook);
 
    evas_object_smart_callback_add(obj, "sub-object-del", _sub_del, wd);
+
    wd->scroller = elm_smart_scroller_add(e);
    elm_widget_sub_object_add(obj, wd->scroller);
    elm_smart_scroller_widget_set(wd->scroller, obj);
@@ -2948,7 +3006,6 @@ EAPI void elm_entry_extension_module_data_get(Evas_Object *obj,Elm_Entry_Extensi
    ext_mod->select = _select;
    ext_mod->selectall = _selectall;
    ext_mod->ent = wd->ent;
-   ext_mod->viewport_obj = _viewport_obj_get(obj);
    ext_mod->items = wd->items;
    ext_mod->editable = wd->editable;
    ext_mod->have_selection = wd->have_selection;
@@ -3078,11 +3135,11 @@ elm_entry_is_empty(const Evas_Object *obj)
    ELM_CHECK_WIDTYPE(obj, widtype) EINA_TRUE;
    Widget_Data *wd = elm_widget_data_get(obj);
    const Evas_Object *tb;
-   //Evas_Textblock_Cursor *cur;
+   Evas_Textblock_Cursor *cur;
    Eina_Bool ret;
    if (!wd) return EINA_TRUE;
 
-#if 0
+if (0) {
    /* It's a hack until we get the support suggested above.
     * We just create a cursor, point it to the begining, and then
     * try to advance it, if it can advance, the tb is not empty,
@@ -3096,13 +3153,14 @@ elm_entry_is_empty(const Evas_Object *obj)
    evas_textblock_cursor_free(cur);
 
    return !ret;
-#endif
+}
 
    char *str = elm_entry_markup_to_utf8(elm_entry_entry_get(obj));
    if (!str) return EINA_TRUE;
 
    ret = (strlen(str) == 0);
 
+   free(str);
    return ret;
 }