[label] bugfix using ellipsis & wrap_height_set
[framework/uifw/elementary.git] / src / lib / elm_label.c
index 9e0847d..389e88a 100644 (file)
@@ -3,7 +3,6 @@
 
 /**
  * @defgroup Label Label
- * @ingroup Elementary
  *
  * Display text, with simple html-like markup. The theme of course
  * can invent new markup tags and style them any way it likes
@@ -16,61 +15,83 @@ struct _Widget_Data
    Evas_Object *lbl;
    Evas_Object *bg;
    const char *label;
-   Evas_Coord lastw;
+   const char *format;
    Ecore_Job *deferred_recalc_job;
+   double slide_duration;
+   Evas_Coord lastw;
    Evas_Coord wrap_w;
    Evas_Coord wrap_h;
    Eina_Bool linewrap : 1;
-   Eina_Bool wrapmode : 1;
-   Eina_Bool slidingmode : 1;
-   Eina_Bool slidingellipsis : 1;
    Eina_Bool changed : 1;
    Eina_Bool bgcolor : 1;
    Eina_Bool ellipsis : 1;
+   Eina_Bool slidingmode : 1;
+   Eina_Bool slidingellipsis : 1;
 };
 
 static const char *widtype = NULL;
 static void _del_hook(Evas_Object *obj);
+static void _mirrored_set(Evas_Object *obj, Eina_Bool rtl);
 static void _theme_hook(Evas_Object *obj);
 static void _sizing_eval(Evas_Object *obj);
-static int _get_value_in_key_string(const char *oldstring, char *key, char **value);
-static int _strbuf_key_value_replace(Eina_Strbuf *srcbuf, char *key, const char *value, int deleteflag);
-static int _stringshare_key_value_replace(const char **srcstring, char *key, const char *value, int deleteflag);
-static int _is_width_over(Evas_Object *obj, int linemode);
-static void _ellipsis_label_to_width(Evas_Object *obj, int linemode);
+static int _get_value_in_key_string(const char *oldstring, const char *key, char **value);
+static int _strbuf_key_value_replace(Eina_Strbuf *srcbuf, const char *key, const char *value, int deleteflag);
+static int _stringshare_key_value_replace(const char **srcstring, const char *key, const char *value, int deleteflag);
+static int _is_width_over(Evas_Object *obj);
+static void _ellipsis_label_to_width(Evas_Object *obj);
+static void _label_sliding_change(Evas_Object *obj);
 
 static void
 _elm_win_recalc_job(void *data)
 {
    Widget_Data *wd = elm_widget_data_get(data);
-   Evas_Coord minw = -1, minh = -1, maxh = -1;
-   Evas_Coord resw, resh, minminw, minminh;
+   Evas_Coord minw = -1, minh = -1;
+   Evas_Coord resw, resh;
+
    if (!wd) return;
    wd->deferred_recalc_job = NULL;
+   
    evas_object_geometry_get(wd->lbl, NULL, NULL, &resw, &resh);
-   resh = 0;
-   minminw = 0;
-   edje_object_size_min_restricted_calc(wd->lbl, &minw, &minh, 0, 0);
-   minminw = minw;
-   minminh = minh;
-   if (wd->wrap_w >= resw) 
+   if (wd->wrap_w > resw)
+     resw = wd->wrap_w;
+   if (wd->wrap_h > resh)
+     resh = wd->wrap_h;
+
+   if (wd->wrap_h == -1) /* open source routine */
      {
-        resw = wd->wrap_w;
         edje_object_size_min_restricted_calc(wd->lbl, &minw, &minh, resw, 0);
-        evas_object_size_hint_min_set(data, minw, minh);
+        /* This is a hack to workaround the way min size hints are treated.
+         * If the minimum width is smaller than the restricted width, it means
+         * the mininmum doesn't matter. */
+        if ((minw <= resw) && (minw != wd->wrap_w))
+          {
+             Evas_Coord ominw = -1;
+             evas_object_size_hint_min_get(data, &ominw, NULL);
+             minw = ominw;
+          }
      }
-   else
+   else /* ellipsis && linewrap && wrap_height_set routine */
      {
-        if (wd->wrap_w > minminw) minminw = wd->wrap_w;
-        edje_object_size_min_restricted_calc(wd->lbl, &minw, &minh, resw, 0);
-        evas_object_size_hint_min_set(data, minminw, minh);
+        edje_object_size_min_restricted_calc(wd->lbl, &minw, &minh, 0, resh);
+        if ((minh <= resh) && (minh != wd->wrap_h))
+          {
+             Evas_Coord ominh = -1;
+             evas_object_size_hint_min_get(data, NULL, &ominh);
+             minh = ominh;
+          }
+
+               evas_object_geometry_get(wd->lbl, NULL, NULL, &resw, &resh);
+               minw = resw;
+               if (minh > wd->wrap_h)
+                       minh = wd->wrap_h;
      }
 
-   if (wd->ellipsis && wd->linewrap && wd->wrap_h > 0 && _is_width_over(data, 1) == 1) 
-     _ellipsis_label_to_width(data, 1);
+   evas_object_size_hint_min_set(data, minw, minh);
+   evas_object_size_hint_max_set(data, wd->wrap_w, wd->wrap_h);
 
-   maxh = minh;
-   evas_object_size_hint_max_set(data, -1, maxh);
+   if ((wd->ellipsis) && (wd->linewrap) && (wd->wrap_h > 0) &&
+       (_is_width_over(data) == 1))
+     _ellipsis_label_to_width(data);
 }
 
 static void
@@ -90,16 +111,16 @@ _theme_change(Evas_Object *obj)
    Widget_Data *wd = elm_widget_data_get(obj);
    if (!wd) return;
 
-   if (wd->linewrap)
-     {
-       if (wd->ellipsis)
-         _elm_theme_object_set(obj, wd->lbl, "label", "base_wrap_ellipsis", elm_widget_style_get(obj));
-       else
-         _elm_theme_object_set(obj, wd->lbl, "label", "base_wrap", elm_widget_style_get(obj));
-     }
-   else
-     _elm_theme_object_set(obj, wd->lbl, "label", "base", elm_widget_style_get(obj));
+   _elm_theme_object_set(obj, wd->lbl, "label", "base",
+         elm_widget_style_get(obj));
+}
 
+static void
+_mirrored_set(Evas_Object *obj, Eina_Bool rtl)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   edje_object_mirrored_set(wd->lbl, rtl);
 }
 
 static void
@@ -107,10 +128,14 @@ _theme_hook(Evas_Object *obj)
 {
    Widget_Data *wd = elm_widget_data_get(obj);
    if (!wd) return;
+   _elm_widget_mirrored_reload(obj);
+   _mirrored_set(obj, elm_widget_mirrored_get(obj));
    _theme_change(obj);
-   edje_object_part_text_set(wd->lbl, "elm.text", wd->label);
-   edje_object_scale_set(wd->lbl, elm_widget_scale_get(obj) * 
+   edje_object_part_text_set(wd->lbl, "elm.text", wd->format);
+   edje_object_part_text_append(wd->lbl, "elm.text", wd->label);
+   edje_object_scale_set(wd->lbl, elm_widget_scale_get(obj) *
                          _elm_config->scale);
+   _label_sliding_change(obj);
    _sizing_eval(obj);
 }
 
@@ -118,9 +143,10 @@ static void
 _sizing_eval(Evas_Object *obj)
 {
    Widget_Data *wd = elm_widget_data_get(obj);
-   Evas_Coord minw = -1, minh = -1, maxw = -1, maxh = -1;
+   Evas_Coord minw = -1, minh = -1;
    Evas_Coord resw, resh;
    if (!wd) return;
+
    if (wd->linewrap)
      {
         evas_object_geometry_get(wd->lbl, NULL, NULL, &resw, &resh);
@@ -128,27 +154,25 @@ _sizing_eval(Evas_Object *obj)
         wd->changed = EINA_FALSE;
         wd->lastw = resw;
         _elm_win_recalc_job(obj);
-// FIXME: works ok. but NOT for genlist. what should genlist do?        
-//        if (wd->deferred_recalc_job) ecore_job_del(wd->deferred_recalc_job);
-//        wd->deferred_recalc_job = ecore_job_add(_elm_win_recalc_job, obj);
+        // FIXME: works ok. but NOT for genlist. what should genlist do?
+        //        if (wd->deferred_recalc_job) ecore_job_del(wd->deferred_recalc_job);
+        //        wd->deferred_recalc_job = ecore_job_add(_elm_win_recalc_job, obj);
      }
    else
      {
         evas_object_geometry_get(wd->lbl, NULL, NULL, &resw, &resh);
         edje_object_size_min_calc(wd->lbl, &minw, &minh);
-               if (wd->wrap_w > 0 && minw > wd->wrap_w)
-                       minw = wd->wrap_w;
+        if (wd->wrap_w > 0 && minw > wd->wrap_w) minw = wd->wrap_w;
+        if (wd->wrap_h > 0 && minh > wd->wrap_h) minh = wd->wrap_h;
         evas_object_size_hint_min_set(obj, minw, minh);
-        maxh = minh;
-        evas_object_size_hint_max_set(obj, maxw, maxh);
-
-        if (wd->ellipsis && _is_width_over(obj, 0) == 1) 
-          _ellipsis_label_to_width(obj, 0);
+        evas_object_size_hint_max_set(obj, wd->wrap_w, wd->wrap_h);
+        if ((wd->ellipsis) && (_is_width_over(obj) == 1))
+          _ellipsis_label_to_width(obj);
      }
 }
 
-static void 
-_resize(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+static void
+_lbl_resize(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
 {
    Widget_Data *wd = elm_widget_data_get(data);
    if (!wd) return;
@@ -156,7 +180,7 @@ _resize(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event
 }
 
 static int
-_get_value_in_key_string(const char *oldstring, char *key, char **value)
+_get_value_in_key_string(const char *oldstring, const char *key, char **value)
 {
    char *curlocater, *starttag, *endtag;
    int firstindex = 0, foundflag = -1;
@@ -164,54 +188,54 @@ _get_value_in_key_string(const char *oldstring, char *key, char **value)
    curlocater = strstr(oldstring, key);
    if (curlocater)
      {
+        int key_len = strlen(key);
         starttag = curlocater;
-        endtag = curlocater + strlen(key);
-        if (endtag == NULL || *endtag != '=') 
+        endtag = curlocater + key_len;
+        if ((!endtag) || (*endtag != '='))
           {
-            foundflag = 0;
-            return -1;
+             foundflag = 0;
+             return -1;
           }
-
         firstindex = abs(oldstring - curlocater);
-        firstindex += strlen(key)+1; // strlen("key") + strlen("=")
-        *value = (char*)oldstring + firstindex;
+        firstindex += key_len + 1; // strlen("key") + strlen("=")
+        *value = (char *)oldstring + firstindex;
 
         while (oldstring != starttag)
           {
-            if (*starttag == '>')
-              {
-                foundflag = 0;
-                break;
-              }
-            if (*starttag == '<') 
-              break;
-            else 
-              starttag--;
-            if (starttag == NULL) break;
+             if (*starttag == '>')
+               {
+                  foundflag = 0;
+                  break;
+               }
+             if (*starttag == '<')
+               break;
+             else
+               starttag--;
+             if (!starttag) break;
           }
 
-        while (NULL != endtag)
+        while (endtag)
           {
-            if (*endtag == '<')
-              {
-                foundflag = 0;
-                break;
-              }
-            if (*endtag == '>') 
-              break;
-            else 
-              endtag++;
-            if (endtag == NULL) break;
+             if (*endtag == '<')
+               {
+                  foundflag = 0;
+                  break;
+               }
+             if (*endtag == '>')
+               break;
+             else
+               endtag++;
+             if (!endtag) break;
           }
 
-        if (foundflag != 0 && *starttag == '<' && *endtag == '>') 
+        if ((foundflag) && (*starttag == '<') && (*endtag == '>'))
           foundflag = 1;
-        else 
+        else
           foundflag = 0;
      }
    else
      {
-       foundflag = 0;
+        foundflag = 0;
      }
 
    if (foundflag == 1) return 0;
@@ -219,8 +243,9 @@ _get_value_in_key_string(const char *oldstring, char *key, char **value)
    return -1;
 }
 
+
 static int
-_strbuf_key_value_replace(Eina_Strbuf *srcbuf, char *key, const char *value, int deleteflag)
+_strbuf_key_value_replace(Eina_Strbuf *srcbuf, const char *key, const char *value, int deleteflag)
 {
    const char *srcstring = NULL;
    Eina_Strbuf *repbuf = NULL, *diffbuf = NULL;
@@ -231,99 +256,101 @@ _strbuf_key_value_replace(Eina_Strbuf *srcbuf, char *key, const char *value, int
    srcstring = eina_strbuf_string_get(srcbuf);
    curlocater = strstr(srcstring, key);
 
-   if (curlocater == NULL)
-     {
-       insertflag = 1;
-     }
+   if (!curlocater)
+     insertflag = 1;
    else
      {
-       do 
-         {
-           starttag = strchr(srcstring, '<');
-           endtag = strchr(srcstring, '>');
-           tagtxtlen = endtag - starttag;
-           if (tagtxtlen <= 0) tagtxtlen = 0;
-           if (starttag < curlocater && curlocater < endtag) break;
-           if (endtag != NULL && endtag+1 != NULL)
-             srcstring = endtag+1;
-           else
-             break;
-         } while (strlen(srcstring) > 1);
-
-       if (starttag && endtag && tagtxtlen > strlen(key))
-         {
-           repbuf = eina_strbuf_new();
-           diffbuf = eina_strbuf_new();
-           eina_strbuf_append_n(repbuf, starttag, tagtxtlen);
-           srcstring = eina_strbuf_string_get(repbuf);
-           curlocater = strstr(srcstring, key);
-
-           if (curlocater != NULL)
-             {
-               replocater = curlocater + strlen(key) + 1;
-
-               while (*replocater == ' ' || *replocater == '=')
-                          {
-                 replocater++;
-                          }
-
-                while (*replocater != NULL && *replocater != ' ' && *replocater != '>')
-                  replocater++;
-
-               if (replocater-curlocater > strlen(key)+1)
-                 {
-                   replocater--;
-                   eina_strbuf_append_n(diffbuf, curlocater, replocater-curlocater+1);
-                 }
-               else
-                 insertflag = 1;
-             }
-           else
-             {
+        int key_len = strlen(key);
+        do
+          {
+             starttag = strchr(srcstring, '<');
+             endtag = strchr(srcstring, '>');
+             tagtxtlen = endtag - starttag;
+             if (tagtxtlen <= 0) tagtxtlen = 0;
+             if ((starttag < curlocater) && (curlocater < endtag)) break;
+             if ((endtag) && ((endtag + 1)))
+               srcstring = endtag + 1;
+             else
+               break;
+          } while (strlen(srcstring) > 1);
+
+        if ((starttag) && (endtag) && (tagtxtlen > key_len))
+          {
+             char *eqchar = NULL;
+             repbuf = eina_strbuf_new();
+             diffbuf = eina_strbuf_new();
+             eina_strbuf_append_n(repbuf, starttag, tagtxtlen);
+             srcstring = eina_strbuf_string_get(repbuf);
+             curlocater = strstr(srcstring, key);
+             // key=value
+             //    ^ : move to here
+             eqchar = curlocater + key_len;
+             if ((curlocater) && (eqchar))
+               {
+                  // some case at useless many whitespaces (key  =value)
+                  // find the separator(=) position
+                  eqchar = strchr(curlocater + key_len, '=');
+                  if (eqchar)
+                    {
+                       // key=value
+                       //     ^ : move to here
+                       replocater = eqchar + 1;
+                       while ((*replocater) &&
+                              (*replocater != ' ') &&
+                              (*replocater != '>'))
+                         replocater++;
+
+                       if ((replocater - curlocater) > key_len)
+                         eina_strbuf_append_n(diffbuf, curlocater,
+                                              replocater-curlocater);
+                       else
+                         insertflag = 1;
+                    }
+                  else
+                    insertflag = 1;
+               }
+             else
                insertflag = 1;
-             }
-           eina_strbuf_reset(repbuf);
-         }
-       else
-         {
-           insertflag = 1; 
-         }
+             eina_strbuf_reset(repbuf);
+          }
+        else
+          insertflag = 1;
      }
 
-   if (repbuf == NULL) repbuf = eina_strbuf_new();
-   if (diffbuf == NULL) diffbuf = eina_strbuf_new();
+   if (!repbuf) repbuf = eina_strbuf_new();
+   if (!diffbuf) diffbuf = eina_strbuf_new();
 
    if (insertflag)
      {
-       eina_strbuf_append_printf(repbuf, "<%s=%s>", key, value);
-       eina_strbuf_prepend(srcbuf, eina_strbuf_string_get(repbuf));
+        eina_strbuf_append_printf(repbuf, "<%s=%s>", key, value);
+        eina_strbuf_prepend(srcbuf, eina_strbuf_string_get(repbuf));
      }
    else
      {
         if (deleteflag)
           {
-            eina_strbuf_prepend(diffbuf, "<");
-            eina_strbuf_append(diffbuf, ">");
-            eina_strbuf_replace_first(srcbuf, eina_strbuf_string_get(diffbuf), "");
+             eina_strbuf_prepend(diffbuf, "<");
+             eina_strbuf_append(diffbuf, ">");
+             eina_strbuf_replace_first(srcbuf, eina_strbuf_string_get(diffbuf), "");
           }
         else
           {
-            eina_strbuf_append_printf(repbuf, "%s=%s", key, value);
-            eina_strbuf_replace_first(srcbuf, eina_strbuf_string_get(diffbuf), eina_strbuf_string_get(repbuf));
+             eina_strbuf_append_printf(repbuf, "%s=%s", key, value);
+             eina_strbuf_replace_first(srcbuf, eina_strbuf_string_get(diffbuf), eina_strbuf_string_get(repbuf));
           }
      }
 
    if (repbuf) eina_strbuf_free(repbuf);
    if (diffbuf) eina_strbuf_free(diffbuf);
-  
-   return 0;           
+
+   return 0;
 }
 
 static int
-_stringshare_key_value_replace(const char **srcstring, char *key, const char *value, int deleteflag)
+_stringshare_key_value_replace(const char **srcstring, const char *key, const char *value, int deleteflag)
 {
-   Eina_Strbuf *sharebuf = NULL;   
-   
+   Eina_Strbuf *sharebuf = NULL;
+
    sharebuf = eina_strbuf_new();
    eina_strbuf_append(sharebuf, *srcstring);
    _strbuf_key_value_replace(sharebuf, key, value, deleteflag);
@@ -335,62 +362,95 @@ _stringshare_key_value_replace(const char **srcstring, char *key, const char *va
 }
 
 static int
-_is_width_over(Evas_Object *obj, int linemode)
+_is_width_over(Evas_Object *obj)
 {
    Evas_Coord x, y, w, h;
    Evas_Coord vx, vy, vw, vh;
    Widget_Data *wd = elm_widget_data_get(obj);
-   const char *ellipsis_string = "...";
-   size_t ellen = strlen(ellipsis_string)+1;
-
    if (!wd) return 0;
 
-   edje_object_part_geometry_get(wd->lbl,"elm.text",&x,&y,&w,&h);
+   edje_object_part_geometry_get(wd->lbl, "elm.text", &x, &y, NULL, NULL);
+   /* Calc the formatted size with ellipsis turned off */
+   if (wd->ellipsis)
+     {
+        const Evas_Object *tb;
+        char *_kvalue;
+        double ellipsis = 0.0;
+        Eina_Bool found_key = EINA_FALSE;
+        if (_get_value_in_key_string(wd->format, "ellipsis", &_kvalue) == 0)
+          {
+             ellipsis = atof(_kvalue);
+             found_key = EINA_TRUE;
+          }
 
-   evas_object_geometry_get (obj, &vx,&vy,&vw,&vh);
+        if (_stringshare_key_value_replace(&wd->format,
+                 "ellipsis", NULL, 1) == 0)
+          {
+             edje_object_part_text_set(wd->lbl, "elm.text", wd->format);
+             edje_object_part_text_append(wd->lbl, "elm.text", wd->label);
+          }
 
-   if (linemode == 0) // single line
-     {
-       if ((x >= 0) && (y >= 0))
-          {
-                  if ((wd->wrap_w > 0) && (wd->wrap_w < w))
-                  {
-                          Evas_Coord minw, minh;
-                          edje_object_size_min_calc(wd->lbl, &minw, &minh);
-
-                          if (minw < wd->wrap_w)
-                          { // min insufficient
-                                  return 0;
-                          }
-                          else
-                                  return 1;
-                  }
-                  else
-                          return 0;
-          }
-
-       if (ellen < wd->wrap_w && w > wd->wrap_w) return 1;
+        tb = edje_object_part_object_get(wd->lbl, "elm.text");
+        evas_object_textblock_size_formatted_get(tb, &w, &h);
+
+        if (found_key)
+          {
+             Eina_Strbuf *elpbuf;
+             elpbuf = eina_strbuf_new();
+             eina_strbuf_append_printf(elpbuf, "%f", ellipsis);
+             if (_stringshare_key_value_replace(&wd->format, "ellipsis",
+                      eina_strbuf_string_get(elpbuf), 0) == 0)
+               {
+                  edje_object_part_text_set(wd->lbl, "elm.text", wd->format);
+                  edje_object_part_text_append(wd->lbl, "elm.text", wd->label);
+               }
+             eina_strbuf_free(elpbuf);
+          }
      }
-   else // multiline
+   else
      {
-       if (vy > h && h > wd->wrap_h) return 1;
+        const Evas_Object *tb;
+        tb = edje_object_part_object_get(wd->lbl, "elm.text");
+        evas_object_textblock_size_formatted_get(tb, &w, &h);
      }
+   evas_object_geometry_get(obj, &vx, &vy, &vw, &vh);
+
+   if (w > wd->wrap_w || h > wd->wrap_h)
+      return 1;
 
    return 0;
 }
 
 static void
-_ellipsis_label_to_width(Evas_Object *obj, int linemode)
+_ellipsis_fontsize_set(Evas_Object *obj, int fontsize)
 {
    Widget_Data *wd = elm_widget_data_get(obj);
-   int cur_fontsize = 0, len, showcount;
-   Eina_Strbuf *fontbuf = NULL, *txtbuf = NULL;
-   char **kvalue = NULL;
+   Eina_Strbuf *fontbuf = NULL;
+   int removeflag = 0;
+   if (!wd) return;
+
+   fontbuf = eina_strbuf_new();
+   eina_strbuf_append_printf(fontbuf, "%d", fontsize);
+   if (fontsize == 0) removeflag = 1;  // remove fontsize tag
+
+   if (_stringshare_key_value_replace(&wd->format, "font_size", eina_strbuf_string_get(fontbuf), removeflag) == 0)
+     {
+        edje_object_part_text_set(wd->lbl, "elm.text", wd->format);
+        edje_object_part_text_append(wd->lbl, "elm.text", wd->label);
+     }
+   eina_strbuf_free(fontbuf);
+}
+
+static void
+_ellipsis_label_to_width(Evas_Object *obj)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   int cur_fontsize = 0;
+   char *kvalue;
    const char *minfont, *deffont, *maxfont;
-   const char *ellipsis_string = "...";
-   int minfontsize, maxfontsize, minshowcount;
+   int minfontsize, maxfontsize;
 
-   minshowcount = strlen(ellipsis_string) + 1;
    minfont = edje_object_data_get(wd->lbl, "min_font_size");
    if (minfont) minfontsize = atoi(minfont);
    else minfontsize = 1;
@@ -400,122 +460,107 @@ _ellipsis_label_to_width(Evas_Object *obj, int linemode)
    deffont = edje_object_data_get(wd->lbl, "default_font_size");
    if (deffont) cur_fontsize = atoi(deffont);
    else cur_fontsize = 1;
-   if (minfontsize > maxfontsize || cur_fontsize == 1) return; // theme is not ready for ellipsis
+   if (minfontsize > maxfontsize || cur_fontsize == 1) return;  // theme is not ready for ellipsis
    if (eina_stringshare_strlen(wd->label) <= 0) return;
 
-   if (_get_value_in_key_string(wd->label, "font_size", &kvalue) == 0)
+   if (_get_value_in_key_string(wd->format, "font_size", &kvalue) == 0)
      {
-       if (*kvalue != NULL) cur_fontsize = atoi((char*)kvalue);
+        if (kvalue != NULL) cur_fontsize = atoi(kvalue);
      }
 
-   txtbuf = eina_strbuf_new();
-   eina_strbuf_append(txtbuf, wd->label);
-
-   while (_is_width_over(obj, linemode))
+   while (_is_width_over(obj))
      {
-       if (cur_fontsize > minfontsize)
-         {
-           cur_fontsize--;
-           if (fontbuf != NULL)
-             {
-               eina_strbuf_free(fontbuf);
-               fontbuf = NULL;
-             }
-           fontbuf = eina_strbuf_new();
-           eina_strbuf_append_printf(fontbuf, "%d", cur_fontsize);
-           _strbuf_key_value_replace(txtbuf, "font_size", eina_strbuf_string_get(fontbuf), 0);
-           edje_object_part_text_set(wd->lbl, "elm.text", eina_strbuf_string_get(txtbuf));
-           eina_strbuf_free(fontbuf);
-           fontbuf = NULL;
-         }
-       else
-         {
-           if (txtbuf != NULL)
-             {
-               eina_strbuf_free(txtbuf);
-               txtbuf = NULL;
-             }
-           txtbuf = eina_strbuf_new();
-           eina_strbuf_append_printf(txtbuf, "%s", edje_object_part_text_get(wd->lbl, "elm.text"));
-           len = eina_strbuf_length_get(txtbuf);
-           showcount = len - 1;
-           while (showcount > minshowcount)
-             {
-               unsigned char *ltxt = eina_strbuf_string_get(txtbuf);
-               len = eina_strbuf_length_get(txtbuf);
-               // FIXME : more reliable truncate routine is needed
-               //         it works on only EUC-KR
-               int delta = 0;
-                          if (ltxt[len-minshowcount-delta] >= 0x80)
-                 {
-                   delta = 2;
-                   showcount--;
-                 }
-               eina_strbuf_remove(txtbuf, len-minshowcount-delta, len);
-               eina_strbuf_append(txtbuf, ellipsis_string);
-               edje_object_part_text_set(wd->lbl, "elm.text", eina_strbuf_string_get(txtbuf));
-
-               if (_is_width_over(obj, linemode))
-                 showcount--;
-               else 
-                 break;
-             }
-         }
+        if (cur_fontsize > minfontsize)
+          {
+             cur_fontsize -= 3;
+             if (cur_fontsize < minfontsize) cur_fontsize = minfontsize;
+             _ellipsis_fontsize_set(obj, cur_fontsize);
+          }
+        else
+          {
+             break;
+          }
      }
-
-   if (txtbuf) eina_strbuf_free(txtbuf);
-   wd->changed = 1;
-   _sizing_eval(obj);
 }
 
-/*
- * setting internal state of mulitline entry
- * singleline doesn't need it
- */
-
-void _label_state_change(Evas_Object *obj)
+static void
+_label_sliding_change(Evas_Object *obj)
 {
    Widget_Data *wd = elm_widget_data_get(obj);
    if (!wd) return;
+   char *plaintxt;
+   int plainlen = 0;
 
+   // dosen't support multiline sliding effect
    if (wd->linewrap)
-   {
-          if (wd->wrapmode)
-                  edje_object_signal_emit(wd->lbl, "elm,state,wordwrap", "elm");
-          else
-                  edje_object_signal_emit(wd->lbl, "elm,state,default", "elm");
-   }
+     {
+        wd->slidingmode = EINA_FALSE;
+        return;
+     }
+
+   plaintxt = _elm_util_mkup_to_text(edje_object_part_text_get(wd->lbl, "elm.text"));
+   if (plaintxt != NULL)
+     {
+        plainlen = strlen(plaintxt);
+        free(plaintxt);
+     }
+   // too short to slide label
+   if (plainlen < 1)
+     {
+        wd->slidingmode = EINA_TRUE;
+        return;
+     }
+
+   if (wd->slidingmode)
+     {
+        Edje_Message_Float_Set *msg = alloca(sizeof(Edje_Message_Float_Set) + (sizeof(double)));
+
+        if (wd->ellipsis)
+          {
+             wd->slidingellipsis = EINA_TRUE;
+             elm_label_ellipsis_set(obj, EINA_FALSE);
+          }
+
+        msg->count = 1;
+        msg->val[0] = wd->slide_duration;
+
+        edje_object_message_send(wd->lbl, EDJE_MESSAGE_FLOAT_SET, 0, msg);
+        edje_object_signal_emit(wd->lbl, "elm,state,slide,start", "elm");
+     }
+   else
+     {
+        edje_object_signal_emit(wd->lbl, "elm,state,slide,stop", "elm");
+        if (wd->slidingellipsis)
+          {
+             wd->slidingellipsis = EINA_FALSE;
+             elm_label_ellipsis_set(obj, EINA_TRUE);
+          }
+     }
 }
 
-void _label_sliding_change(Evas_Object *obj)
+static void
+_elm_label_label_set(Evas_Object *obj, const char *item, const char *label)
 {
+   ELM_CHECK_WIDTYPE(obj, widtype);
    Widget_Data *wd = elm_widget_data_get(obj);
    if (!wd) return;
+   if (item && strcmp(item, "default")) return;
+   if (!label) label = "";
+   eina_stringshare_replace(&wd->label, label);
+   edje_object_part_text_set(wd->lbl, "elm.text", wd->format);
+   edje_object_part_text_append(wd->lbl, "elm.text", wd->label);
+   wd->changed = 1;
+   _sizing_eval(obj);
+}
 
-   if (wd->linewrap)
-   {
-          wd->slidingmode = EINA_FALSE;
-          fprintf(stderr, "ERR: label dosen't support multiline sliding effect!!!\n");
-   }
-
-   if (wd->slidingmode)
-   {
-          if (wd->ellipsis)
-          {
-                  wd->slidingellipsis = EINA_TRUE;
-                  elm_label_ellipsis_set(obj, EINA_FALSE);
-          }
-          edje_object_signal_emit(wd->lbl, "elm,state,slide,start", "elm");
-   }
-   else
-   {
-          if (wd->slidingellipsis)
-          {
-                  wd->slidingellipsis = EINA_FALSE;
-                  elm_label_ellipsis_set(obj, EINA_TRUE);
-          }
-          edje_object_signal_emit(wd->lbl, "elm,state,slide,stop", "elm");
-   }
+static const char *
+_elm_label_label_get(const Evas_Object *obj, const char *item)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) NULL;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (item && strcmp(item, "default")) return NULL;
+   if (!wd) return NULL;
+   return wd->label;
 }
 
 /**
@@ -533,36 +578,42 @@ elm_label_add(Evas_Object *parent)
    Evas *e;
    Widget_Data *wd;
 
-   wd = ELM_NEW(Widget_Data);
-   e = evas_object_evas_get(parent);
-   wd->bg = evas_object_rectangle_add(e);
-   evas_object_color_set(wd->bg, 0, 0, 0, 0);
-   obj = elm_widget_add(e);
+   ELM_WIDGET_STANDARD_SETUP(wd, Widget_Data, parent, e, obj, NULL);
+
    ELM_SET_WIDTYPE(widtype, "label");
    elm_widget_type_set(obj, "label");
    elm_widget_sub_object_add(parent, obj);
    elm_widget_data_set(obj, wd);
    elm_widget_del_hook_set(obj, _del_hook);
    elm_widget_theme_hook_set(obj, _theme_hook);
-   elm_widget_can_focus_set(obj, 0);
+   elm_widget_can_focus_set(obj, EINA_FALSE);
+   elm_widget_text_set_hook_set(obj, _elm_label_label_set);
+   elm_widget_text_get_hook_set(obj, _elm_label_label_get);
 
-   wd->linewrap = EINA_FALSE;
    wd->bgcolor = EINA_FALSE;
+   wd->bg = evas_object_rectangle_add(e);
+   evas_object_color_set(wd->bg, 0, 0, 0, 0);
+
+   wd->linewrap = EINA_FALSE;
    wd->ellipsis = EINA_FALSE;
-   wd->wrapmode = EINA_FALSE;
    wd->slidingmode = EINA_FALSE;
    wd->slidingellipsis = EINA_FALSE;
-   wd->wrap_w = 0;
-   wd->wrap_h = 0;
+   wd->wrap_w = -1;
+   wd->wrap_h = -1;
+   wd->slide_duration = 10;
 
    wd->lbl = edje_object_add(e);
    _elm_theme_object_set(obj, wd->lbl, "label", "base", "default");
+   wd->format = eina_stringshare_add("");
    wd->label = eina_stringshare_add("<br>");
-   edje_object_part_text_set(wd->lbl, "elm.text", "<br>");
+   edje_object_part_text_set(wd->lbl, "elm.text", wd->format);
+   edje_object_part_text_append(wd->lbl, "elm.text", wd->label);
+
    elm_widget_resize_object_set(obj, wd->lbl);
-   
-   evas_object_event_callback_add(wd->lbl, EVAS_CALLBACK_RESIZE, _resize, obj);
-   
+
+   evas_object_event_callback_add(wd->lbl, EVAS_CALLBACK_RESIZE, _lbl_resize, obj);
+
+   _mirrored_set(obj, elm_widget_mirrored_get(obj));
    wd->changed = 1;
    _sizing_eval(obj);
    return obj;
@@ -579,14 +630,7 @@ elm_label_add(Evas_Object *parent)
 EAPI void
 elm_label_label_set(Evas_Object *obj, const char *label)
 {
-   ELM_CHECK_WIDTYPE(obj, widtype);
-   Widget_Data *wd = elm_widget_data_get(obj);
-   if (!wd) return;
-   if (!label) label = "";
-   eina_stringshare_replace(&wd->label, label);
-   edje_object_part_text_set(wd->lbl, "elm.text", label);
-   wd->changed = 1;
-   _sizing_eval(obj);
+  _elm_label_label_set(obj, NULL, label);
 }
 
 /**
@@ -595,14 +639,12 @@ elm_label_label_set(Evas_Object *obj, const char *label)
  * @param obj The label object
  * @return The string inside the label
  * @ingroup Label
+ * @deprecated
  */
 EAPI const char *
 elm_label_label_get(const Evas_Object *obj)
 {
-   ELM_CHECK_WIDTYPE(obj, widtype) NULL;
-   Widget_Data *wd = elm_widget_data_get(obj);
-   if (!wd) return NULL;
-   return wd->label;
+  return _elm_label_label_get(obj, NULL);
 }
 
 /**
@@ -611,32 +653,56 @@ elm_label_label_get(const Evas_Object *obj)
  * @param obj The label object
  * @param wrap To wrap text or not
  * @ingroup Label
+ * @deprecated
  */
 EAPI void
-elm_label_line_wrap_set(Evas_Object *obj, Eina_Bool wrap)
+elm_label_line_wrap_set(Evas_Object *obj, Elm_Wrap_Type wrap)
 {
    ELM_CHECK_WIDTYPE(obj, widtype);
    Widget_Data *wd = elm_widget_data_get(obj);
+   const char *wrap_str;
+   int len;
+
    if (!wd) return;
-   const char *t;
    if (wd->linewrap == wrap) return;
    wd->linewrap = wrap;
-   t = eina_stringshare_add(elm_label_label_get(obj));
-   _theme_change(obj);
-   elm_label_label_set(obj, t);
-   eina_stringshare_del(t);
-   wd->changed = 1;
-   _sizing_eval(obj);
+   len = strlen(wd->label);
+   if (len <= 0) return;
+
+   switch (wrap)
+     {
+      case ELM_WRAP_CHAR:
+         wrap_str = "char";
+         break;
+      case ELM_WRAP_WORD:
+         wrap_str = "word";
+         break;
+      case ELM_WRAP_MIXED:
+         wrap_str = "mixed";
+         break;
+      default:
+         wrap_str = "none";
+         break;
+     }
+
+   if (_stringshare_key_value_replace(&wd->format,
+            "wrap", wrap_str, 0) == 0)
+     {
+        edje_object_part_text_set(wd->lbl, "elm.text", wd->format);
+        edje_object_part_text_append(wd->lbl, "elm.text", wd->label);
+        wd->changed = 1;
+        _sizing_eval(obj);
+     }
 }
 
 /**
  * Get the wrapping behavior of the label
  *
  * @param obj The label object
- * @return To wrap text or not
+ * @return Wrap type
  * @ingroup Label
  */
-EAPI Eina_Bool
+EAPI Elm_Wrap_Type
 elm_label_line_wrap_get(const Evas_Object *obj)
 {
    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
@@ -660,7 +726,11 @@ elm_label_wrap_width_set(Evas_Object *obj, Evas_Coord w)
    if (!wd) return;
    if (w < 0) w = 0;
    if (wd->wrap_w == w) return;
-   if (wd->ellipsis) edje_object_part_text_set(wd->lbl, "elm.text", wd->label);
+   if (wd->ellipsis)
+     {
+        edje_object_part_text_set(wd->lbl, "elm.text", wd->format);
+        edje_object_part_text_append(wd->lbl, "elm.text", wd->label);
+     }
    wd->wrap_w = w;
    _sizing_eval(obj);
 }
@@ -689,14 +759,19 @@ elm_label_wrap_width_get(const Evas_Object *obj)
  * @ingroup Label
  */
 EAPI void
-elm_label_wrap_height_set(Evas_Object *obj, Evas_Coord h)
+elm_label_wrap_height_set(Evas_Object *obj,
+                          Evas_Coord   h)
 {
    ELM_CHECK_WIDTYPE(obj, widtype);
    Widget_Data *wd = elm_widget_data_get(obj);
    if (!wd) return;
    if (h < 0) h = 0;
    if (wd->wrap_h == h) return;
-   if (wd->ellipsis) edje_object_part_text_set(wd->lbl, "elm.text", wd->label);
+   if (wd->ellipsis)
+     {
+        edje_object_part_text_set(wd->lbl, "elm.text", wd->format);
+        edje_object_part_text_append(wd->lbl, "elm.text", wd->label);
+     }
    wd->wrap_h = h;
    _sizing_eval(obj);
 }
@@ -718,7 +793,11 @@ elm_label_wrap_height_get(const Evas_Object *obj)
 }
 
 /**
- * Set the font size on the label object
+ * Set the font size on the label object.
+ *
+ * NEVER use this. It is for hyper-special cases only. use styles instead. e.g.
+ * "big", "medium", "small" - or better name them by use:
+ * "title", "footnote", "quote" etc.
  *
  * @param obj The label object
  * @param size font size
@@ -734,18 +813,20 @@ elm_label_fontsize_set(Evas_Object *obj, int fontsize)
    int len, removeflag = 0;
 
    if (!wd) return;
+   _elm_dangerous_call_check(__FUNCTION__);
    len = strlen(wd->label);
    if (len <= 0) return;
    fontbuf = eina_strbuf_new();
    eina_strbuf_append_printf(fontbuf, "%d", fontsize);
 
-   if (fontsize == 0) removeflag = 1; // remove fontsize tag
+   if (fontsize == 0) removeflag = 1;  // remove fontsize tag
 
-   if (_stringshare_key_value_replace(&wd->label, "font_size", eina_strbuf_string_get(fontbuf), removeflag) == 0)
+   if (_stringshare_key_value_replace(&wd->format, "font_size", eina_strbuf_string_get(fontbuf), removeflag) == 0)
      {
-       edje_object_part_text_set(wd->lbl, "elm.text", wd->label);
-       wd->changed = 1;
-       _sizing_eval(obj);
+        edje_object_part_text_set(wd->lbl, "elm.text", wd->format);
+        edje_object_part_text_append(wd->lbl, "elm.text", wd->label);
+        wd->changed = 1;
+        _sizing_eval(obj);
      }
    eina_strbuf_free(fontbuf);
 }
@@ -753,6 +834,10 @@ elm_label_fontsize_set(Evas_Object *obj, int fontsize)
 /**
  * Set the text align on the label object
  *
+ * NEVER use this. It is for hyper-special cases only. use styles instead. e.g.
+ * "big", "medium", "small" - or better name them by use:
+ * "title", "footnote", "quote" etc.
+ *
  * @param obj The label object
  * @param align align mode ("left", "center", "right")
  *
@@ -766,11 +851,15 @@ elm_label_text_align_set(Evas_Object *obj, const char *alignmode)
    int len;
 
    if (!wd) return;
+   _elm_dangerous_call_check(__FUNCTION__);
    len = strlen(wd->label);
    if (len <= 0) return;
 
-   if (_stringshare_key_value_replace(&wd->label, "align", alignmode, 0) == 0)
-     edje_object_part_text_set(wd->lbl, "elm.text", wd->label);
+   if (_stringshare_key_value_replace(&wd->format, "align", alignmode, 0) == 0)
+     {
+        edje_object_part_text_set(wd->lbl, "elm.text", wd->format);
+        edje_object_part_text_append(wd->lbl, "elm.text", wd->label);
+     }
 
    wd->changed = 1;
    _sizing_eval(obj);
@@ -780,15 +869,19 @@ elm_label_text_align_set(Evas_Object *obj, const char *alignmode)
  * Set the text color on the label object
  *
  * @param obj The label object
- * @param r Red property background color of The label object 
- * @param g Green property background color of The label object 
- * @param b Blue property background color of The label object 
- * @param a Alpha property background alpha of The label object 
+ * @param r Red property background color of The label object
+ * @param g Green property background color of The label object
+ * @param b Blue property background color of The label object
+ * @param a Alpha property background color of The label object
  *
  * @ingroup Label
  */
 EAPI void
-elm_label_text_color_set(Evas_Object *obj, unsigned int r, unsigned int g, unsigned int b, unsigned int a)
+elm_label_text_color_set(Evas_Object *obj,
+                         unsigned int r,
+                         unsigned int g,
+                         unsigned int b,
+                         unsigned int a)
 {
    ELM_CHECK_WIDTYPE(obj, widtype);
    Widget_Data *wd = elm_widget_data_get(obj);
@@ -796,38 +889,51 @@ elm_label_text_color_set(Evas_Object *obj, unsigned int r, unsigned int g, unsig
    int len;
 
    if (!wd) return;
+   _elm_dangerous_call_check(__FUNCTION__);
    len = strlen(wd->label);
    if (len <= 0) return;
    colorbuf = eina_strbuf_new();
    eina_strbuf_append_printf(colorbuf, "#%02X%02X%02X%02X", r, g, b, a);
 
-   if (_stringshare_key_value_replace(&wd->label, "color", eina_strbuf_string_get(colorbuf), 0) == 0)
+   if (_stringshare_key_value_replace(&wd->format, "color", eina_strbuf_string_get(colorbuf), 0) == 0)
      {
-       edje_object_part_text_set(wd->lbl, "elm.text", wd->label);
-       wd->changed = 1;
-       _sizing_eval(obj);
+        edje_object_part_text_set(wd->lbl, "elm.text", wd->format);
+        edje_object_part_text_append(wd->lbl, "elm.text", wd->label);
+        wd->changed = 1;
+        _sizing_eval(obj);
      }
    eina_strbuf_free(colorbuf);
 }
 
-
 /**
  * Set background color of the label
  *
+ * NEVER use this. It is for hyper-special cases only. use styles instead. e.g.
+ * "big", "medium", "small" - or better name them by use:
+ * "title", "footnote", "quote" etc.
+ *
  * @param obj The label object
- * @param r Red property background color of The label object 
- * @param g Green property background color of The label object 
- * @param b Blue property background color of The label object 
- * @param a Alpha property background alpha of The label object 
+ * @param r Red property background color of The label object
+ * @param g Green property background color of The label object
+ * @param b Blue property background color of The label object
+ * @param a Alpha property background alpha of The label object
+ *
  * @ingroup Label
  */
 EAPI void
-elm_label_background_color_set(Evas_Object *obj, unsigned int r, unsigned int g, unsigned int b, unsigned int a)
+elm_label_background_color_set(Evas_Object *obj,
+                               unsigned int r,
+                               unsigned int g,
+                               unsigned int b,
+                               unsigned int a)
 {
    ELM_CHECK_WIDTYPE(obj, widtype);
    Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
    evas_object_color_set(wd->bg, r, g, b, a);
 
+   if (!wd) return;
+   _elm_dangerous_call_check(__FUNCTION__);
    if (wd->bgcolor == EINA_FALSE)
      {
         wd->bgcolor = 1;
@@ -836,42 +942,56 @@ elm_label_background_color_set(Evas_Object *obj, unsigned int r, unsigned int g,
 }
 
 /**
- * Set the ellipsis behavior of the label
+ * Set the wrapmode of the label
  *
  * @param obj The label object
- * @param ellipsis To ellipsis text or not
+ * @param wrapmode 0 is charwrap, 1 is wordwrap
  * @ingroup Label
- */
+ * @deprecated 
+*/
 EAPI void
-elm_label_ellipsis_set(Evas_Object *obj, Eina_Bool ellipsis)
+elm_label_wrap_mode_set(Evas_Object *obj,
+                        Eina_Bool    wrapmode)
 {
-   ELM_CHECK_WIDTYPE(obj, widtype);
-   Widget_Data *wd = elm_widget_data_get(obj);
-   if (wd->ellipsis == ellipsis) return;
-   wd->ellipsis = ellipsis;
-   if (wd->linewrap) _theme_change(obj);
-   edje_object_part_text_set(wd->lbl, "elm.text", wd->label);
-   wd->changed = 1;
-   _sizing_eval(obj);
+   return;
 }
 
 /**
- * Set the wrapmode of the label
+ * Set the ellipsis behavior of the label
  *
  * @param obj The label object
- * @param wrapmode 0 is charwrap, 1 is wordwrap
+ * @param ellipsis To ellipsis text or not
  * @ingroup Label
  */
 EAPI void
-elm_label_wrap_mode_set(Evas_Object *obj, Eina_Bool wrapmode)
+elm_label_ellipsis_set(Evas_Object *obj, Eina_Bool ellipsis)
 {
    ELM_CHECK_WIDTYPE(obj, widtype);
    Widget_Data *wd = elm_widget_data_get(obj);
-   if (wd->wrapmode == wrapmode) return;
-   wd->wrapmode = wrapmode;
-   _label_state_change(obj);
-   wd->changed = 1;
-   _sizing_eval(obj);
+   Eina_Strbuf *fontbuf = NULL;
+   int len, removeflag = 0;
+
+   if (!wd) return;
+   if (wd->ellipsis == ellipsis) return;
+   wd->ellipsis = ellipsis;
+   len = strlen(wd->label);
+   if (len <= 0) return;
+
+   if (ellipsis == EINA_FALSE) removeflag = 1;  // remove fontsize tag
+
+   fontbuf = eina_strbuf_new();
+   eina_strbuf_append_printf(fontbuf, "%f", 1.0);
+
+   if (_stringshare_key_value_replace(&wd->format,
+            "ellipsis", eina_strbuf_string_get(fontbuf), removeflag) == 0)
+     {
+        edje_object_part_text_set(wd->lbl, "elm.text", wd->format);
+        edje_object_part_text_append(wd->lbl, "elm.text", wd->label);
+        wd->changed = 1;
+        _sizing_eval(obj);
+     }
+   eina_strbuf_free(fontbuf);
+
 }
 
 /**
@@ -882,7 +1002,8 @@ elm_label_wrap_mode_set(Evas_Object *obj, Eina_Bool wrapmode)
  * @ingroup Label
  */
 EAPI void
-elm_label_slide_set(Evas_Object *obj, Eina_Bool slide)
+elm_label_slide_set(Evas_Object *obj,
+                    Eina_Bool    slide)
 {
    ELM_CHECK_WIDTYPE(obj, widtype);
    Widget_Data *wd = elm_widget_data_get(obj);
@@ -899,15 +1020,52 @@ elm_label_slide_set(Evas_Object *obj, Eina_Bool slide)
  * get the text slide mode of the label
  *
  * @param obj The label object
- * @return slide set flag value
+ * @return slide slide mode value
  * @ingroup Label
  */
 EAPI Eina_Bool
 elm_label_slide_get(Evas_Object *obj)
 {
-   ELM_CHECK_WIDTYPE(obj, widtype);
+   ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
    Widget_Data *wd = elm_widget_data_get(obj);
    if (!wd) return EINA_FALSE;
-
    return wd->slidingmode;
 }
+
+/**
+ * set the slide duration(speed) of the label
+ *
+ * @param obj The label object
+ * @return The duration time in moving text from slide begin position to slide end position
+ * @ingroup Label
+ */
+EAPI void
+elm_label_slide_duration_set(Evas_Object *obj, double duration)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   Edje_Message_Float_Set *msg = alloca(sizeof(Edje_Message_Float_Set) + (sizeof(double)));
+
+   if (!wd) return;
+   wd->slide_duration = duration;
+   msg->count = 1;
+   msg->val[0] = wd->slide_duration;
+   edje_object_message_send(wd->lbl, EDJE_MESSAGE_FLOAT_SET, 0, msg);
+}
+
+/**
+ * get the slide duration(speed) of the label
+ *
+ * @param obj The label object
+ * @return The duration time in moving text from slide begin position to slide end position
+ * @ingroup Label
+ */
+EAPI double
+elm_label_slide_duration_get(Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) 0.0;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return 0;
+   return wd->slide_duration;
+}
+