[elm_datefield] support i18n
[framework/uifw/elementary.git] / src / lib / elm_datefield.c
1 #include <Elementary.h>
2 #include "elm_priv.h"
3 #include <langinfo.h>
4
5 /**
6  * @defgroup Datefield Datefield
7  * @ingroup Elementary
8  *
9  * This is a date editfield. it is used to input date and time using keypad
10  */
11
12 typedef struct _Widget_Data Widget_Data;
13
14 enum 
15 {
16   DATE_YEAR,
17   DATE_MON,
18   DATE_DAY,
19   DATE_MAX
20 };
21
22 enum
23 {
24   TIME_HOUR,
25   TIME_MIN,
26   TIME_MAX
27 };
28
29 enum
30 {
31   DATE_FORMAT_YYMMDD,
32   DATE_FORMAT_YYDDMM,
33   DATE_FORMAT_MMYYDD,
34   DATE_FORMAT_MMDDYY,
35   DATE_FORMAT_DDYYMM,
36   DATE_FORMAT_DDMMYY,
37   DATE_FORMAT_MAX
38 };
39
40 #define YEAR_MAX_LENGTH 4
41 #define DAY_MAX_LENGTH 2
42 #define TIME_MAX_LENGTH 2
43
44 #define MONTH_MAXIMUM 12
45 #define HOUR_24H_MAXIMUM 23
46 #define HOUR_12H_MAXIMUM 12
47 #define MIN_MAXIMUM 59
48
49 struct _Widget_Data
50 {
51    Evas_Object *base;
52    Evas_Object *date[DATE_MAX];
53    Evas_Object *time[TIME_MAX];
54    Ecore_Event_Handler *handler;
55    Ecore_Idler *idler;
56    int layout;
57
58    int year, month, day, hour, min;
59    int y_max, m_max, d_max;
60    int y_min, m_min, d_min;
61    int date_format;
62    Eina_Bool pm:1;
63    Eina_Bool time_mode:1;
64    Eina_Bool format_exists:1;
65    Eina_Bool editing:1;
66
67    void (*func)(void *data, Evas_Object *obj, int value);
68    void *func_data;
69 };
70
71 static const char *widtype = NULL;
72
73 static void _del_hook(Evas_Object *obj);
74 static void _theme_hook(Evas_Object *obj);
75 static void _sizing_eval(Evas_Object *obj);
76 static void _on_focus_hook(void *data, Evas_Object *obj);
77
78 static void _signal_rect_mouse_down(void *data, Evas_Object *obj, const char *emission, const char *source);
79 static void _signal_ampm_mouse_down(void *data, Evas_Object *obj, const char *emission, const char *source);
80 static void _signal_ampm_clicked(void *data, Evas_Object *obj, const char *emission, const char *source);
81 static void _entry_focused_cb(void *data, Evas_Object *obj, void *event_info);
82 static void _entry_unfocused_cb(void *data, Evas_Object *obj, void *event_info);
83 static void _entry_key_up_cb(void *data, Evas *e , Evas_Object *obj , void *event_info);
84 static Eina_Bool _imf_event_commit_cb(void *data, int type, void *event);
85 static void _input_panel_event_callback(void *data, Ecore_IMF_Context *ctx, int value);
86
87 static void _date_entry_add(Evas_Object *obj);
88 static void _time_entry_add(Evas_Object *obj);
89 static void _date_update(Evas_Object *obj);
90 static Eina_Bool _focus_idler_cb(void *obj);
91 static void _entry_focus_move(Evas_Object *obj, Evas_Object *focus_obj);
92 static Eina_Bool _check_input_done(Evas_Object *obj, Evas_Object *focus_obj, int strlen);
93 static char* _get_i18n_string(Evas_Object *obj, nl_item item);
94 static int _maximum_day_get(int year, int month);
95 static int _check_date_boundary(Evas_Object *obj, int num, int flag);
96
97 static void
98 _del_hook(Evas_Object *obj)
99 {
100    Widget_Data *wd = elm_widget_data_get(obj);
101    if (!wd) return ;
102
103    ecore_event_handler_del(wd->handler);
104
105    free(wd);
106 }
107
108 static void
109 _on_focus_hook(void *data, Evas_Object *obj)
110 {
111    Widget_Data *wd = elm_widget_data_get(obj);
112    if (!wd || !wd->base) return ;
113
114    if (elm_widget_focus_get(obj)) wd->idler = ecore_idler_add(_focus_idler_cb, obj);
115 }
116
117 static void
118 _theme_hook(Evas_Object *obj)
119 {
120    Widget_Data *wd = elm_widget_data_get(obj);
121    char sig[32] = {0,};
122    int i;
123
124    if (!wd || !wd->base) return;
125
126    if (wd->layout == ELM_DATEFIELD_LAYOUT_DATEANDTIME)
127      {
128         _elm_theme_object_set(obj, wd->base, "datefield", "dateandtime", elm_widget_style_get(obj));
129
130         for (i = 0; i < DATE_MAX; i++)
131           elm_object_style_set(wd->date[i], "datefield/hybrid");
132         for (i = 0; i < TIME_MAX; i++)
133           elm_object_style_set(wd->time[i], "datefield/hybrid");
134      }
135    else if (wd->layout == ELM_DATEFIELD_LAYOUT_DATE)
136      {
137         _elm_theme_object_set(obj, wd->base, "datefield", "date", elm_widget_style_get(obj));
138
139         for (i = 0; i < DATE_MAX; i++)
140           elm_object_style_set(wd->date[i], "datefield");
141
142         for (i = 0; i < TIME_MAX; i++)
143           evas_object_hide(wd->time[i]);
144      }
145    else if (wd->layout == ELM_DATEFIELD_LAYOUT_TIME)
146      {
147         _elm_theme_object_set(obj, wd->base, "datefield", "time", elm_widget_style_get(obj));
148
149         for (i = 0; i < TIME_MAX; i++)
150           elm_object_style_set(wd->time[i], "datefield");
151
152         for (i = 0; i < DATE_MAX; i++)
153           evas_object_hide(wd->date[i]);
154      }
155
156    if (wd->layout == ELM_DATEFIELD_LAYOUT_DATEANDTIME || wd->layout == ELM_DATEFIELD_LAYOUT_DATE)
157      {
158         edje_object_part_swallow(wd->base, "elm.swallow.date.year", wd->date[DATE_YEAR]);
159         edje_object_part_swallow(wd->base, "elm.swallow.date.month", wd->date[DATE_MON]);
160         edje_object_part_swallow(wd->base, "elm.swallow.date.day", wd->date[DATE_DAY]);
161         edje_object_part_text_set(wd->base, "elm.text.date.comma", ",");
162      }
163
164    if (wd->layout == ELM_DATEFIELD_LAYOUT_DATEANDTIME || wd->layout == ELM_DATEFIELD_LAYOUT_TIME)
165      {
166         edje_object_part_swallow(wd->base, "elm.swallow.time.hour", wd->time[TIME_HOUR]);
167         edje_object_part_swallow(wd->base, "elm.swallow.time.min", wd->time[TIME_MIN]);
168         edje_object_part_text_set(wd->base, "elm.text.colon", ":");
169      }
170
171    edje_object_scale_set(wd->base, elm_widget_scale_get(obj) * _elm_config->scale);
172
173    //set date format
174    if (wd->format_exists)
175      sprintf(sig, "elm,state,format,%s", elm_datefield_date_format_get(obj));
176    else
177      {
178         char *str = _get_i18n_string(obj, D_FMT);
179         if (str) 
180           {
181              if (!strcmp(str, "yymmdd")) wd->date_format = DATE_FORMAT_YYMMDD;
182              else if (!strcmp(str, "yyddmm")) wd->date_format = DATE_FORMAT_YYDDMM;
183              else if (!strcmp(str, "mmyydd")) wd->date_format = DATE_FORMAT_MMYYDD;
184              else if (!strcmp(str, "mmddyy")) wd->date_format = DATE_FORMAT_MMDDYY;
185              else if (!strcmp(str, "ddyymm")) wd->date_format = DATE_FORMAT_DDYYMM;
186              else if (!strcmp(str, "ddmmyy")) wd->date_format = DATE_FORMAT_DDMMYY;
187              sprintf(sig, "elm,state,format,%s",str);
188              free(str);
189           }
190      }
191    edje_object_signal_emit(wd->base, sig, "elm");
192
193    _date_update(obj);
194    _sizing_eval(obj);
195 }
196
197    static void
198 _sizing_eval(Evas_Object *obj)
199 {
200    Widget_Data *wd = elm_widget_data_get(obj);
201    Evas_Coord minw = -1, minh = -1;
202
203    edje_object_size_min_calc(wd->base, &minw, &minh);
204    evas_object_size_hint_min_set(obj, minw, minh);
205    evas_object_size_hint_max_set(obj, -1, -1);
206 }
207
208    static void
209 _signal_ampm_mouse_down(void *data, Evas_Object *obj, const char *emission, const char *source)
210 {
211    Widget_Data *wd = elm_widget_data_get(data);
212    Evas_Object *focus_obj;
213
214    if (!wd || !wd->base) return ;
215
216    focus_obj = elm_widget_focused_object_get(data);
217    if (focus_obj) elm_object_unfocus(focus_obj);
218 }
219
220 static void
221 _signal_ampm_clicked(void *data, Evas_Object *obj, const char *emission, const char *source)
222 {
223    Widget_Data *wd = elm_widget_data_get(data);
224    char *str;
225
226    if (!wd || !wd->base) return ;
227
228    wd->pm = !wd->pm; 
229    if (wd->pm)
230      {
231         str = _get_i18n_string(data, PM_STR);
232         if (str) 
233           {
234              edje_object_part_text_set(wd->base, "elm.text.ampm", str);
235              free(str);
236           }
237         wd->hour += HOUR_12H_MAXIMUM;
238      }
239    else
240      {
241         str = _get_i18n_string(data, AM_STR);
242         if (str)
243           {
244              edje_object_part_text_set(wd->base, "elm.text.ampm", str);
245              free(str);
246           }
247         wd->hour -= HOUR_12H_MAXIMUM;
248      }
249    evas_object_smart_callback_call(data, "changed", NULL);
250 }
251
252 static void
253 _signal_rect_mouse_down(void *data, Evas_Object *obj, const char *emission, const char *source)
254 {
255    Widget_Data *wd = elm_widget_data_get(data);
256    if (!wd) return;
257
258    if (!strcmp(source, "elm.rect.date.year.over"))
259      elm_object_focus(wd->date[DATE_YEAR]);
260    else if (!strcmp(source, "elm.rect.date.month.over"))
261      elm_object_focus(wd->date[DATE_MON]);
262    else if (!strcmp(source, "elm.rect.date.day.over"))
263      elm_object_focus(wd->date[DATE_DAY]);
264    else if (!strcmp(source, "elm.rect.time.hour.over"))
265      elm_object_focus(wd->time[TIME_HOUR]);
266    else if (!strcmp(source, "elm.rect.time.min.over"))
267      elm_object_focus(wd->time[TIME_MIN]);
268    else if (!strcmp(source, "elm.rect.date.left.pad"))
269      {
270         switch (wd->date_format)
271           {
272            case DATE_FORMAT_YYDDMM:
273            case DATE_FORMAT_YYMMDD:
274              elm_object_focus(wd->date[DATE_YEAR]);
275              break;
276            case DATE_FORMAT_MMDDYY:
277            case DATE_FORMAT_MMYYDD:
278              elm_object_focus(wd->date[DATE_MON]);
279              break;
280            case DATE_FORMAT_DDMMYY:
281            case DATE_FORMAT_DDYYMM:
282              elm_object_focus(wd->date[DATE_DAY]);
283           }
284      }
285    else if (!strcmp(source, "elm.rect.date.right.pad"))
286      {
287         switch (wd->date_format)
288           {
289            case DATE_FORMAT_MMDDYY:
290            case DATE_FORMAT_DDMMYY:
291              elm_object_focus(wd->date[DATE_YEAR]);
292              break;
293            case DATE_FORMAT_DDYYMM:
294            case DATE_FORMAT_YYDDMM:
295              elm_object_focus(wd->date[DATE_MON]);
296              break;
297            case DATE_FORMAT_YYMMDD:
298            case DATE_FORMAT_MMYYDD:
299              elm_object_focus(wd->date[DATE_DAY]);
300           }
301      }
302 }
303
304 static Eina_Bool 
305 _focus_idler_cb(void *obj)
306 {
307    Widget_Data *wd = elm_widget_data_get(obj);
308    Evas_Object *focus_obj;
309
310    focus_obj = elm_widget_focused_object_get(obj);
311    if (focus_obj == obj)
312      {
313         if (wd->layout == ELM_DATEFIELD_LAYOUT_TIME)
314           elm_object_focus(wd->time[TIME_HOUR]);
315
316         else if (wd->layout == ELM_DATEFIELD_LAYOUT_DATEANDTIME || wd->layout == ELM_DATEFIELD_LAYOUT_DATE)
317           {
318              switch (wd->date_format)
319                {
320                 case DATE_FORMAT_YYDDMM:
321                 case DATE_FORMAT_YYMMDD:
322                   elm_object_focus(wd->date[DATE_YEAR]);
323                   break;
324                 case DATE_FORMAT_MMDDYY:
325                 case DATE_FORMAT_MMYYDD:
326                   elm_object_focus(wd->date[DATE_MON]);
327                   break;
328                 case DATE_FORMAT_DDMMYY:
329                 case DATE_FORMAT_DDYYMM:
330                   elm_object_focus(wd->date[DATE_DAY]);
331                }
332           }
333      }
334    wd->idler = NULL;
335    return EINA_FALSE;
336 }
337
338 static void
339 _entry_focused_cb(void *data, Evas_Object *obj, void *event_info)
340 {
341    Widget_Data *wd = elm_widget_data_get(data);
342    if (!wd || !wd->base) return;
343
344    if (wd->idler) 
345      {
346         ecore_idler_del(wd->idler);
347         wd->idler = NULL;
348      }
349
350    if (obj == wd->date[DATE_YEAR])
351      edje_object_signal_emit(wd->base, "elm,state,year,focus,in", "elm");
352    else if (obj == wd->date[DATE_MON])
353      edje_object_signal_emit(wd->base, "elm,state,month,focus,in", "elm");
354    else if (obj == wd->date[DATE_DAY])
355      edje_object_signal_emit(wd->base, "elm,state,day,focus,in", "elm");
356    else if (obj == wd->time[TIME_HOUR])
357      edje_object_signal_emit(wd->base, "elm,state,hour,focus,in", "elm");
358    else if (obj == wd->time[TIME_MIN])
359      edje_object_signal_emit(wd->base, "elm,state,min,focus,in", "elm");
360 }
361
362 static void
363 _entry_unfocused_cb(void *data, Evas_Object *obj, void *event_info)
364 {
365    Widget_Data *wd = elm_widget_data_get(data);
366    char str[YEAR_MAX_LENGTH+1] = {0,};
367    char *i18n_str;
368    int num = 0;
369
370    if (!wd || !wd->base) return;
371    wd->editing = FALSE;
372
373    if (obj == wd->date[DATE_YEAR])
374      {
375         if (strlen(elm_entry_entry_get(wd->date[DATE_YEAR])))
376           wd->year = atoi(elm_entry_entry_get(wd->date[DATE_YEAR]));
377         wd->year = _check_date_boundary(data, wd->year, DATE_YEAR);
378         sprintf(str, "%d", wd->year);
379         elm_entry_entry_set(wd->date[DATE_YEAR], str);
380         //check month boundary
381         if (wd->month != (num = _check_date_boundary(data, wd->month, DATE_MON)))
382           {
383              wd->month = num;
384              i18n_str = _get_i18n_string(obj, ABMON_1+wd->month-1);
385              if (i18n_str)
386                {
387                   elm_entry_entry_set(wd->date[DATE_MON], i18n_str);
388                   free(i18n_str);
389                }
390           }
391         //check day boundary
392         if (wd->day != (num = _check_date_boundary(data, wd->day, DATE_DAY)))
393           {
394              wd->day = num;
395              sprintf(str, "%d", wd->day);
396              elm_entry_entry_set(wd->date[DATE_DAY], str);
397           }
398         edje_object_signal_emit(wd->base, "elm,state,year,focus,out", "elm");
399      }
400    else if (obj == wd->date[DATE_MON])
401      {
402         if (wd->month != (num = _check_date_boundary(data, wd->month, DATE_MON)))
403           {
404              wd->month = num;
405              i18n_str = _get_i18n_string(obj, ABMON_1+wd->month-1);
406              if (i18n_str)
407                {
408                   elm_entry_entry_set(wd->date[DATE_MON], i18n_str);
409                   free(i18n_str);
410                }  
411           }
412         //check day boundary
413         if (wd->day != (num = _check_date_boundary(data, wd->day, DATE_DAY)))
414           {
415              wd->day = num;
416              sprintf(str, "%d", wd->day);               
417              elm_entry_entry_set(wd->date[DATE_DAY], str);
418           }
419         edje_object_signal_emit(wd->base, "elm,state,month,focus,out", "elm");
420      }
421    else if (obj == wd->date[DATE_DAY])
422      {
423         if (strlen(elm_entry_entry_get(wd->date[DATE_DAY])))
424           wd->day = atoi(elm_entry_entry_get(wd->date[DATE_DAY]));
425         wd->day = _check_date_boundary(data, wd->day, DATE_DAY);
426         sprintf(str, "%d", wd->day);
427         elm_entry_entry_set(wd->date[DATE_DAY], str);
428         edje_object_signal_emit(wd->base, "elm,state,day,focus,out", "elm");
429      }
430    else if (obj == wd->time[TIME_HOUR])
431      {
432         if (strlen(elm_entry_entry_get(wd->time[TIME_HOUR])))
433           num = atoi(elm_entry_entry_get(wd->time[TIME_HOUR]));
434         else num = wd->hour;
435
436         if (!wd->time_mode) // 24 mode
437           {
438              if (num > HOUR_24H_MAXIMUM) num = HOUR_24H_MAXIMUM;
439              wd->hour = num;
440           }
441         else // 12 mode
442           {
443              if (num > HOUR_24H_MAXIMUM || num == 0)
444                {
445                   num = HOUR_12H_MAXIMUM;
446                   wd->pm = EINA_FALSE;
447                }
448              else if (num > HOUR_12H_MAXIMUM)
449                {
450                   num -= HOUR_12H_MAXIMUM;
451                   wd->pm = EINA_TRUE;
452                }
453              wd->hour = (wd->pm == EINA_TRUE)? num + HOUR_12H_MAXIMUM : num;
454              if ((wd->hour % 12) == 0) wd->hour -= HOUR_12H_MAXIMUM;
455              if (wd->pm) 
456                {
457                   i18n_str = _get_i18n_string(data, PM_STR);
458                   if (i18n_str)
459                     {
460                        edje_object_part_text_set(wd->base, "elm.text.ampm", i18n_str);
461                        free(i18n_str);
462                     }
463                }
464              else 
465                {
466                   i18n_str = _get_i18n_string(data, AM_STR);
467                   if (i18n_str)
468                     {
469                        edje_object_part_text_set(wd->base, "elm.text.ampm", i18n_str);
470                        free(i18n_str);
471                     }
472                }
473           }
474         sprintf(str, "%02d", num);
475         elm_entry_entry_set(wd->time[TIME_HOUR], str);
476         edje_object_signal_emit(wd->base, "elm,state,hour,focus,out", "elm");
477      }
478    else if (obj == wd->time[TIME_MIN])
479      {
480         if (strlen(elm_entry_entry_get(wd->time[TIME_MIN]))) 
481           wd->min = atoi(elm_entry_entry_get(wd->time[TIME_MIN]));
482         if (wd->min > MIN_MAXIMUM) wd->min = MIN_MAXIMUM;
483
484         sprintf(str, "%02d", wd->min);
485         elm_entry_entry_set(wd->time[TIME_MIN], str);
486         edje_object_signal_emit(wd->base, "elm,state,min,focus,out", "elm");
487      }
488    evas_object_smart_callback_call(data, "changed", NULL);
489 }
490
491 static void 
492 _entry_focus_move(Evas_Object *obj, Evas_Object *focus_obj)
493 {
494    Widget_Data *wd = elm_widget_data_get(obj);
495    if (!wd) return;
496
497    if (focus_obj == wd->date[DATE_YEAR])
498      {
499         switch (wd->date_format)
500           {
501            case DATE_FORMAT_DDMMYY:
502            case DATE_FORMAT_MMDDYY:
503              {
504                  if (wd->layout == ELM_DATEFIELD_LAYOUT_DATEANDTIME)
505                    elm_object_focus(wd->time[TIME_HOUR]);
506                  else if (wd->layout == ELM_DATEFIELD_LAYOUT_DATE)
507                    elm_object_unfocus(wd->date[DATE_YEAR]);
508              }
509              break;
510            case DATE_FORMAT_DDYYMM:
511            case DATE_FORMAT_YYMMDD:
512              elm_object_focus(wd->date[DATE_MON]);
513              break;
514            case DATE_FORMAT_MMYYDD:
515            case DATE_FORMAT_YYDDMM:
516              elm_object_focus(wd->date[DATE_DAY]);
517           }
518      }
519    else if (focus_obj == wd->date[DATE_MON])
520      {
521         switch (wd->date_format)
522           {
523            case DATE_FORMAT_DDYYMM:
524            case DATE_FORMAT_YYDDMM:
525              {
526                 if (wd->layout == ELM_DATEFIELD_LAYOUT_DATEANDTIME)
527                   elm_object_focus(wd->time[TIME_HOUR]);
528                 else if (wd->layout == ELM_DATEFIELD_LAYOUT_DATE)
529                   elm_object_unfocus(wd->date[DATE_MON]);
530              }
531              break;
532            case DATE_FORMAT_DDMMYY:
533            case DATE_FORMAT_MMYYDD:
534              elm_object_focus(wd->date[DATE_YEAR]);
535              break;
536            case DATE_FORMAT_MMDDYY:
537            case DATE_FORMAT_YYMMDD:
538              elm_object_focus(wd->date[DATE_DAY]);
539           }
540      }
541    else if (focus_obj == wd->date[DATE_DAY])
542      {
543         switch (wd->date_format)
544           {
545            case DATE_FORMAT_YYMMDD:
546            case DATE_FORMAT_MMYYDD:
547              {
548                 if (wd->layout == ELM_DATEFIELD_LAYOUT_DATEANDTIME)
549                   elm_object_focus(wd->time[TIME_HOUR]);
550                 else if (wd->layout == ELM_DATEFIELD_LAYOUT_DATE)
551                   elm_object_unfocus(wd->date[DATE_DAY]);
552              }
553              break;
554            case DATE_FORMAT_DDYYMM:
555            case DATE_FORMAT_MMDDYY:
556              elm_object_focus(wd->date[DATE_YEAR]);
557              break;
558            case DATE_FORMAT_DDMMYY:
559            case DATE_FORMAT_YYDDMM:
560              elm_object_focus(wd->date[DATE_MON]);
561           }
562      }
563    else if (focus_obj == wd->time[TIME_HOUR])
564      elm_object_focus(wd->time[TIME_MIN]);
565    else if (focus_obj == wd->time[TIME_MIN])
566      elm_object_unfocus(wd->time[TIME_MIN]);
567 }
568
569 static int
570 _check_date_boundary(Evas_Object *obj, int num, int flag)
571 {
572    Widget_Data *wd = elm_widget_data_get(obj);
573    if (flag == DATE_YEAR)
574      {
575         if (num > wd->y_max) num = wd->y_max;
576         else if (num < wd->y_min) num = wd->y_min;
577         return num;
578      }
579
580    else if (flag == DATE_MON)
581      {
582         if (wd->year == wd->y_max && num > wd->m_max) num = wd->m_max;
583         else if (wd->year == wd->y_min && num < wd->m_min) num = wd->m_min;
584         else if (num > MONTH_MAXIMUM) num = MONTH_MAXIMUM;
585         else if (num <= 0) num = 1;
586         return num;
587      }
588
589    else if (flag == DATE_DAY)
590      {
591         int day_of_month = _maximum_day_get(wd->year, wd->month);
592         if (wd->year == wd->y_max && wd->month == wd->m_max && num > wd->d_max) num = wd->d_max;
593         else if (wd->year == wd->y_min && wd->month == wd->m_min && num < wd->d_min) num = wd->d_min;
594         else if (num > day_of_month) num = day_of_month;
595         else if (num <= 0) num = 1;
596         return num;
597      }
598    return num;
599 }
600
601 static char*
602 _get_i18n_string(Evas_Object *obj, nl_item item)
603 {
604    Widget_Data *wd = elm_widget_data_get(obj);
605    const char *fmt;
606    char *str = NULL;
607    int i = 0, j = 0;
608
609    if (!wd) return NULL;
610
611    fmt = nl_langinfo(item);
612    if (!fmt) return NULL;
613
614    switch (item)
615      {
616       case D_FMT:
617          str = calloc(7, sizeof(char));
618          while (fmt[i]) 
619            {
620               if (fmt[i] == '%' && fmt[i+1]) 
621                 {
622                    i++;
623                    switch (fmt[i]) 
624                      {
625                       case 'Y': case 'M': case 'D': case 'y': case 'm': case 'd':
626                          str[j++] = tolower(fmt[i]);
627                          str[j++] = tolower(fmt[i]);
628                          break;
629                      }
630                 }
631               i++;
632            }
633          return str;
634       case AM_STR: 
635       case PM_STR:
636          if (strlen(fmt) > 0)
637            {
638               str = calloc(strlen(fmt)+1, sizeof(char));
639               strcpy(str, fmt);
640            }
641          else
642            {
643               str = calloc(3, sizeof(char));
644               if (item == AM_STR) strcpy(str, "AM");
645               else if (item == PM_STR) strcpy(str, "PM");
646            }
647          return str;
648       case ABMON_1: case ABMON_2: case ABMON_3: case ABMON_4: case ABMON_5: case ABMON_6:
649       case ABMON_7: case ABMON_8: case ABMON_9: case ABMON_10: case ABMON_11: case ABMON_12:
650          str = calloc(strlen(fmt)+1, sizeof(char));
651          while (fmt[i])
652            {
653               str[j++] = fmt[i];
654               if (fmt[i] >= '1' && fmt[i] <= '9')
655                 {
656                    if (fmt[i+1] >= '1' && fmt[i+1] <= '9')
657                      str[j] = fmt[i+1];
658                    break;
659                 }
660               i++;
661            }
662          return str;     
663      }
664    return NULL;
665 }
666
667 static int
668 _maximum_day_get(int year, int month)
669 {
670    int day_of_month = 0;
671    if (year == 0 || month == 0) return 0;
672
673    switch (month)
674      {
675       case 4:
676       case 6:
677       case 9:
678       case 11:
679         day_of_month = 30;
680         break;
681       case 2:
682         {
683            if ((!(year % 4) && (year % 100)) || !(year % 400))
684              day_of_month = 29;
685            else
686              day_of_month = 28;
687         }
688         break;
689       default:
690         day_of_month = 31;
691         break;
692      }
693
694    return day_of_month;
695 }
696
697 static Eina_Bool 
698 _check_input_done(Evas_Object *obj, Evas_Object *focus_obj, int strlen)
699 {
700    Widget_Data *wd = elm_widget_data_get(obj);
701
702    if (!wd) return EINA_FALSE;
703
704    if (focus_obj == wd->date[DATE_YEAR] && strlen == YEAR_MAX_LENGTH)
705      wd->editing = EINA_FALSE;
706    else if (focus_obj == wd->date[DATE_MON])
707      wd->editing = EINA_FALSE;
708    else if (focus_obj == wd->date[DATE_DAY])
709      {
710         if (strlen == DAY_MAX_LENGTH || atoi(elm_entry_entry_get(focus_obj)) > 3)
711           wd->editing = EINA_FALSE;
712      }
713    else if (focus_obj == wd->time[TIME_HOUR])
714      {
715         if (strlen == TIME_MAX_LENGTH || atoi(elm_entry_entry_get(focus_obj)) > 2)
716           wd->editing = EINA_FALSE;
717      }
718    else if (focus_obj == wd->time[TIME_MIN])
719      {
720         if (strlen == TIME_MAX_LENGTH || atoi(elm_entry_entry_get(focus_obj)) > 5) 
721           wd->editing = EINA_FALSE;
722      }
723    return !wd->editing;
724 }
725
726 static void
727 _entry_key_up_cb(void *data, Evas *e , Evas_Object *obj , void *event_info)
728 {
729    Evas_Event_Key_Up *ev = (Evas_Event_Key_Up *) event_info;
730
731    if (!strcmp(ev->keyname, "BackSpace"))
732      elm_entry_entry_set(obj, "");
733 }
734
735 static Eina_Bool 
736 _imf_event_commit_cb(void *data, int type, void *event)
737 {
738    Widget_Data *wd = elm_widget_data_get(data);
739    Ecore_IMF_Event_Commit *ev = (Ecore_IMF_Event_Commit *) event;
740    Evas_Object *focus_obj;
741    char str[YEAR_MAX_LENGTH+1] = {0,};
742
743    if (!wd) return ECORE_CALLBACK_PASS_ON;
744    if (!elm_widget_focus_get(data)) return ECORE_CALLBACK_PASS_ON;
745
746    focus_obj = elm_widget_focused_object_get(data);
747    if (!wd->editing) 
748      {
749         elm_entry_entry_set(focus_obj, "");
750         wd->editing = EINA_TRUE;
751      }
752    if (focus_obj == wd->date[DATE_MON])
753      {
754         char *i18n_str;
755         wd->month = atoi(ev->str);
756         i18n_str = _get_i18n_string(data, ABMON_1+wd->month-1);
757         if (i18n_str)
758           {
759              elm_entry_entry_set(focus_obj, i18n_str);
760              //strncpy(str, i18n_str, 15);
761              free(i18n_str);
762           }
763      }
764    else
765      {
766         strcpy(str, elm_entry_entry_get(focus_obj));
767         str[strlen(str)] = ev->str[0];
768         elm_entry_entry_set(focus_obj, str);
769      }
770    //elm_entry_entry_set(focus_obj, str);
771
772    if (_check_input_done(data, focus_obj, strlen(str)))
773      _entry_focus_move(data, focus_obj);
774
775    return ECORE_CALLBACK_DONE;
776 }
777
778 static void 
779 _input_panel_event_callback(void *data, Ecore_IMF_Context *ctx, int value)
780 {
781    Widget_Data *wd = elm_widget_data_get(data);
782
783    if (!wd) return;
784
785    if (wd->func)  
786      wd->func(wd->func_data, data, value);
787 }
788
789 static void
790 _date_update(Evas_Object *obj)
791 {
792    Widget_Data *wd = elm_widget_data_get(obj);
793    char str[YEAR_MAX_LENGTH+1] = {0,};
794    char *i18n_str;
795
796    if (!wd || !wd->base) return;
797
798    sprintf(str, "%d", wd->year);
799    elm_entry_entry_set(wd->date[DATE_YEAR], str);
800
801    i18n_str = _get_i18n_string(obj, ABMON_1+wd->month-1);
802    if (i18n_str)
803      {
804         elm_entry_entry_set(wd->date[DATE_MON], i18n_str);
805         free(i18n_str);
806      }
807
808    sprintf(str, "%d", wd->day);
809    elm_entry_entry_set(wd->date[DATE_DAY], str);
810
811    if (!wd->time_mode) //24 mode
812      sprintf(str, "%d", wd->hour);
813    else
814      {
815         if (wd->hour >= HOUR_12H_MAXIMUM)
816           {
817              wd->pm = EINA_TRUE;
818              i18n_str = _get_i18n_string(obj, PM_STR);
819              if (i18n_str) 
820                {
821                   edje_object_part_text_set(wd->base, "elm.text.ampm", i18n_str);
822                   free(i18n_str);
823                }
824           }
825         else
826           {
827              wd->pm = EINA_FALSE;
828              i18n_str = _get_i18n_string(obj, AM_STR);
829              if (i18n_str)
830                {
831                   edje_object_part_text_set(wd->base, "elm.text.ampm", i18n_str);               
832                   free(i18n_str);
833                }
834           }
835
836         if (wd->hour > HOUR_12H_MAXIMUM)
837           sprintf(str, "%02d", wd->hour - HOUR_12H_MAXIMUM);
838         else if (wd->hour == 0)
839           sprintf(str, "%02d", HOUR_12H_MAXIMUM);
840         else
841           sprintf(str, "%02d", wd->hour);
842      }
843    elm_entry_entry_set(wd->time[TIME_HOUR], str);
844    sprintf(str, "%02d", wd->min);
845    elm_entry_entry_set(wd->time[TIME_MIN], str);
846 }
847
848 static void 
849 _date_entry_add(Evas_Object *obj)
850 {
851    Widget_Data *wd = elm_widget_data_get(obj);
852    int i;
853
854    if (!wd) return;     
855
856    for (i = 0; i < DATE_MAX; i++)
857      {
858         wd->date[i] = elm_entry_add(obj);
859         elm_entry_single_line_set(wd->date[i], EINA_TRUE);
860         elm_entry_context_menu_disabled_set(wd->date[i], EINA_TRUE);
861         if (i == DATE_MON) elm_entry_input_panel_layout_set(wd->date[i], ELM_INPUT_PANEL_LAYOUT_MONTH);
862         else elm_entry_input_panel_layout_set(wd->date[i], ELM_INPUT_PANEL_LAYOUT_NUMBERONLY);
863         evas_object_size_hint_weight_set(wd->date[i], EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
864         evas_object_size_hint_align_set(wd->date[i], EVAS_HINT_FILL, EVAS_HINT_FILL);
865         evas_object_smart_callback_add(wd->date[i], "focused", _entry_focused_cb, obj);
866         evas_object_smart_callback_add(wd->date[i], "unfocused", _entry_unfocused_cb, obj);
867         evas_object_event_callback_add(wd->date[i], EVAS_CALLBACK_KEY_UP, _entry_key_up_cb, obj);
868         elm_widget_sub_object_add(obj, wd->date[i]);
869      }
870    elm_entry_maximum_bytes_set(wd->date[DATE_YEAR], YEAR_MAX_LENGTH);
871    elm_entry_maximum_bytes_set(wd->date[DATE_DAY], DAY_MAX_LENGTH);
872 }
873
874 static void 
875 _time_entry_add(Evas_Object *obj)
876 {
877    Widget_Data *wd = elm_widget_data_get(obj);
878    int i;
879
880    if (!wd) return;
881
882    for (i = 0; i < TIME_MAX; i++)
883      {
884         wd->time[i] = elm_entry_add(obj);
885         elm_entry_single_line_set(wd->time[i], EINA_TRUE);
886         elm_entry_context_menu_disabled_set(wd->time[i], EINA_TRUE);
887         elm_entry_input_panel_layout_set(wd->time[i], ELM_INPUT_PANEL_LAYOUT_NUMBERONLY);
888         elm_entry_maximum_bytes_set(wd->time[i], TIME_MAX_LENGTH);
889         evas_object_size_hint_weight_set(wd->time[i], EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
890         evas_object_size_hint_align_set(wd->time[i], EVAS_HINT_FILL, EVAS_HINT_FILL);
891         evas_object_smart_callback_add(wd->time[i], "focused", _entry_focused_cb, obj);
892         evas_object_smart_callback_add(wd->time[i], "unfocused", _entry_unfocused_cb, obj);
893         evas_object_event_callback_add(wd->time[i], EVAS_CALLBACK_KEY_UP, _entry_key_up_cb, obj);
894         elm_widget_sub_object_add(obj, wd->time[i]);
895      }
896 }
897
898 /**
899  * Add a new datefield object
900  * The date format and strings are based on current locale
901  *
902  * @param parent The parent object
903  * @return The new object or NULL if it cannot be created
904  *
905  * @ingroup Datefield
906  */
907 EAPI Evas_Object *
908 elm_datefield_add(Evas_Object *parent)
909 {
910    Evas_Object *obj;
911    Evas *e;
912    Widget_Data *wd;
913
914    e = evas_object_evas_get(parent);
915    if (!e) return NULL; 
916    wd = ELM_NEW(Widget_Data);
917    obj = elm_widget_add(e); 
918    ELM_SET_WIDTYPE(widtype, "datefield");
919    elm_widget_type_set(obj, "datefield");
920    elm_widget_sub_object_add(parent, obj);
921    elm_widget_data_set(obj, wd);
922    elm_widget_del_hook_set(obj, _del_hook);
923    elm_widget_theme_hook_set(obj, _theme_hook);
924    elm_widget_on_focus_hook_set( obj, _on_focus_hook, NULL );
925    elm_widget_can_focus_set(obj, EINA_TRUE);
926
927    wd->base = edje_object_add(e);
928    elm_widget_resize_object_set(obj, wd->base);
929    edje_object_signal_callback_add(wd->base, "mouse,down,1", "elm.rect.date.left.pad", _signal_rect_mouse_down, obj);
930    edje_object_signal_callback_add(wd->base, "mouse,down,1", "elm.rect.date.year.over", _signal_rect_mouse_down, obj);
931    edje_object_signal_callback_add(wd->base, "mouse,down,1", "elm.rect.date.month.over", _signal_rect_mouse_down, obj);
932    edje_object_signal_callback_add(wd->base, "mouse,down,1", "elm.rect.date.day.over", _signal_rect_mouse_down, obj);
933    edje_object_signal_callback_add(wd->base, "mouse,down,1", "elm.rect.date.right.pad", _signal_rect_mouse_down, obj);
934
935    edje_object_signal_callback_add(wd->base, "mouse,down,1", "elm.rect.time.hour.over", _signal_rect_mouse_down, obj);
936    edje_object_signal_callback_add(wd->base, "mouse,down,1", "elm.rect.time.min.over", _signal_rect_mouse_down, obj);
937    edje_object_signal_callback_add(wd->base, "mouse,down,1", "elm.rect.time.ampm.over", _signal_ampm_mouse_down, obj);
938    edje_object_signal_callback_add(wd->base, "mouse,clicked,1", "elm.rect.time.ampm.over", _signal_ampm_clicked, obj);
939
940    wd->handler =  ecore_event_handler_add(ECORE_IMF_EVENT_COMMIT, _imf_event_commit_cb, obj);
941    _date_entry_add(obj);
942    _time_entry_add(obj);
943
944    wd->y_min = 1900;
945    wd->m_min = 1;
946    wd->d_min = 1;
947    wd->y_max = 2099;
948    wd->m_max = 12;
949    wd->d_max = 31;
950    wd->year = wd->y_min;
951    wd->month = 1;
952    wd->day = 1;
953
954    wd->layout = ELM_DATEFIELD_LAYOUT_DATEANDTIME;
955    wd->time_mode = EINA_TRUE;
956
957    _theme_hook(obj);
958
959    return obj;
960 }
961
962 /**
963  * set layout for the datefield
964  *
965  * @param obj The datefield object
966  * @param layout set layout for date/time/dateandtime (default: ELM_DATEFIELD_LAYOUT_DATEANDTIME)
967  *
968  * @ingroup Datefield
969  */
970 EAPI void
971 elm_datefield_layout_set(Evas_Object *obj, Elm_Datefield_Layout layout)
972 {
973    ELM_CHECK_WIDTYPE(obj, widtype);
974    Widget_Data *wd = elm_widget_data_get(obj);
975
976    if (!wd) return;
977    if (layout < ELM_DATEFIELD_LAYOUT_TIME ||layout > ELM_DATEFIELD_LAYOUT_DATEANDTIME) return;
978
979    if (wd->layout != layout)
980      {
981         wd->layout = layout;
982         _theme_hook(obj);
983      }
984    return;
985 }
986
987 /**
988  * get layout of the datefield
989  *
990  * @param obj The datefield object
991  * @return layout of the datefield
992  *
993  * @ingroup Datefield
994  */
995 EAPI Elm_Datefield_Layout
996 elm_datefield_layout_get(const Evas_Object *obj)
997 {
998    ELM_CHECK_WIDTYPE(obj, widtype) 0;
999    Widget_Data *wd = elm_widget_data_get(obj);
1000
1001    if (!wd) return 0;
1002
1003    return wd->layout;
1004 }
1005
1006 /**
1007  * Set selected date of the datefield
1008  *
1009  * @param obj The datefield object
1010  * @param year The year to set
1011  * @param month The month to set
1012  * @param day The day to set
1013  * @param hour The hours to set (24hour mode - 0~23)
1014  * @param min The minutes to set (0~59)
1015  * 
1016  * @ingroup Datefield
1017  */
1018 EAPI void
1019 elm_datefield_date_set(Evas_Object *obj, int year, int month, int day, int hour, int min)
1020 {
1021    ELM_CHECK_WIDTYPE(obj, widtype);
1022    Widget_Data *wd = elm_widget_data_get(obj);
1023
1024    if (!wd) return;
1025
1026    wd->year = _check_date_boundary(obj, year, DATE_YEAR);
1027    wd->month = _check_date_boundary(obj, month, DATE_MON);
1028    wd->day = _check_date_boundary(obj, day, DATE_DAY);
1029
1030    if (hour > HOUR_24H_MAXIMUM) wd->hour = HOUR_24H_MAXIMUM;
1031    else if (hour < 0) wd->hour = 0;
1032    else wd->hour = hour;
1033
1034    if (min > MIN_MAXIMUM) wd->min = MIN_MAXIMUM;
1035    else if (min < 0) wd->min = 0;
1036    else wd->min = min;
1037
1038    _date_update(obj);
1039 }
1040
1041 /**
1042  * Get selected date of the datefield
1043  *
1044  * @param obj The datefield object
1045  * @param year The pointer to the variable get the selected year
1046  * @param month The pointer to the variable get the selected month
1047  * @param day The pointer to the variable get the selected day
1048  * @param hour The pointer to the variable get the selected hour (24hour mode)
1049  * @param hour The pointer to the variable get the selected min
1050  *
1051  * @ingroup Datefield
1052  */
1053 EAPI void
1054 elm_datefield_date_get(const Evas_Object *obj, int *year, int *month, int *day, int *hour, int *min)
1055 {
1056    ELM_CHECK_WIDTYPE(obj, widtype);
1057    Widget_Data *wd = elm_widget_data_get(obj);
1058
1059    if (!wd) return;
1060
1061    if (year)
1062      *year = wd->year;
1063    if (month)
1064      *month = wd->month;
1065    if (day)
1066      *day = wd->day;
1067    if (hour)
1068      *hour = wd->hour;
1069    if (min)
1070      *min = wd->min;
1071 }
1072
1073 /**
1074  * Set upper boundary of the datefield
1075  *
1076  * @param obj The datefield object
1077  * @param year The year to set
1078  * @param month The month to set
1079  * @param day The day to set
1080  * @return TRUE/FALSE
1081  *
1082  * @ingroup Datefield
1083  */
1084 EAPI Eina_Bool
1085 elm_datefield_date_max_set(Evas_Object *obj, int year, int month, int day)
1086 {
1087    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
1088    Widget_Data *wd = elm_widget_data_get(obj);
1089    int day_of_month;
1090    Eina_Bool update = EINA_FALSE;
1091
1092    if (!wd) return EINA_FALSE;
1093    if (month < 1 || month > MONTH_MAXIMUM) return EINA_FALSE;
1094    day_of_month = _maximum_day_get(year, month);
1095    if (day < 1 || day > day_of_month) return EINA_FALSE;
1096
1097    wd->y_max = year;
1098    wd->m_max = month;
1099    wd->d_max = day;
1100
1101    if (wd->year > wd->y_max)
1102      {
1103         wd->year = wd->y_max;
1104         update = EINA_TRUE;
1105      }
1106    if (wd->year == wd->y_max && wd->month > wd->m_max)
1107      {
1108         wd->month = wd->m_max;
1109         update = EINA_TRUE;
1110      }
1111    if (wd->year == wd->y_max && wd->month == wd->m_max && wd->day > wd->d_max)
1112      {
1113         wd->day = wd->d_max;
1114         update = EINA_TRUE;
1115      }
1116
1117    if (update) _date_update(obj);
1118    return EINA_TRUE;
1119 }
1120
1121 /**
1122  * Get upper boundary of the datefield
1123  *
1124  * @param obj The datefield object
1125  * @param year The pointer to the variable get the maximum year
1126  * @param month The pointer to the variable get the maximum month
1127  * @param day The pointer to the variable get the maximum day
1128  *
1129  * @ingroup Datefield
1130  */
1131 EAPI void
1132 elm_datefield_date_max_get(const Evas_Object *obj, int *year, int *month, int *day)
1133 {
1134    ELM_CHECK_WIDTYPE(obj, widtype);
1135    Widget_Data *wd = elm_widget_data_get(obj);
1136
1137    if (!wd) return;
1138
1139    if (year)
1140      *year = wd->y_max;
1141    if (month)
1142      *month = wd->m_max;
1143    if (day)
1144      *day = wd->d_max;
1145 }
1146
1147 /**
1148  * Set lower boundary of the datefield
1149  *
1150  * @param obj The datefield object
1151  * @param year The year to set
1152  * @param month The month to set
1153  * @param day The day to set
1154  * @return TRUE/FALSE
1155  *
1156  * @ingroup Datepicker
1157  */
1158 EAPI Eina_Bool
1159 elm_datefield_date_min_set(Evas_Object *obj, int year, int month, int day)
1160 {
1161    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
1162    Widget_Data *wd = elm_widget_data_get(obj);
1163    int day_of_month;
1164    Eina_Bool update = EINA_FALSE;
1165
1166    if (!wd) return EINA_FALSE;
1167    if (month < 1 || month > MONTH_MAXIMUM) return EINA_FALSE;
1168    day_of_month = _maximum_day_get(year, month);
1169    if (day < 1 || day > day_of_month) return EINA_FALSE;
1170
1171    wd->y_min = year;
1172    wd->m_min = month;
1173    wd->d_min = day;
1174
1175    if (wd->year < wd->y_min)
1176      {
1177         wd->year = wd->y_min;
1178         update = EINA_TRUE;
1179      }
1180    if (wd->year == wd->y_min && wd->month < wd->m_min)
1181      {
1182         wd->month = wd->m_min;
1183         update = EINA_TRUE;
1184      }
1185    if (wd->year == wd->y_min && wd->month == wd->m_min && wd->day < wd->d_min)
1186      {
1187         wd->day = wd->d_min;
1188         update = EINA_TRUE;
1189      }
1190
1191    if (update) _date_update(obj);
1192    return EINA_TRUE;
1193 }
1194
1195 /**
1196  * Get lower boundary of the datefield
1197  *
1198  * @param obj The datefield object
1199  * @param year The pointer to the variable get the maximum year
1200  * @param month The pointer to the variable get the maximum month
1201  * @param day The pointer to the variable get the maximum day
1202  *
1203  * @ingroup Datefield
1204  */
1205 EAPI void
1206 elm_datefield_date_min_get(const Evas_Object *obj, int *year, int *month, int *day)
1207 {
1208    ELM_CHECK_WIDTYPE(obj, widtype);
1209    Widget_Data *wd = elm_widget_data_get(obj);
1210
1211    if (!wd) return;
1212
1213    if (year)
1214      *year = wd->y_min;
1215    if (month)
1216      *month = wd->m_min;
1217    if (day)
1218      *day = wd->d_min;
1219 }
1220
1221 /**
1222  * Set if the datefield show hours in military or am/pm mode
1223  *
1224  * @param obj The datefield object
1225  * @param mode option for the hours mode. If true, it is shown as 12h mode, if false, it is shown as 24h mode. Default value is true 
1226  *
1227  * @ingroup Datefield
1228  */
1229 EAPI void
1230 elm_datefield_time_mode_set(Evas_Object *obj, Eina_Bool mode)
1231 {
1232    ELM_CHECK_WIDTYPE(obj, widtype);
1233    Widget_Data *wd = elm_widget_data_get(obj);
1234
1235    if (!wd) return;
1236
1237    if (wd->time_mode != mode) 
1238      {
1239         char str[YEAR_MAX_LENGTH+1];
1240
1241         wd->time_mode = mode;
1242         if (!wd->time_mode) edje_object_signal_emit(wd->base, "elm,state,mode,24h", "elm");
1243         else edje_object_signal_emit(wd->base, "elm,state,mode,12h", "elm");
1244
1245         _date_update(obj);
1246      }
1247 }
1248
1249 /**
1250  * get time mode of the datefield
1251  *
1252  * @param obj The datefield object
1253  * @return time mode (EINA_TRUE: 12hour mode / EINA_FALSE: 24hour mode) 
1254  *
1255  * @ingroup Datefield
1256  */
1257 EAPI Eina_Bool
1258 elm_datefield_time_mode_get(const Evas_Object *obj)
1259 {
1260    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
1261    Widget_Data *wd = elm_widget_data_get(obj);
1262
1263    if (!wd) return EINA_FALSE;
1264
1265    return wd->time_mode;
1266 }
1267
1268 /**
1269  * Set date format of datefield
1270  *
1271  * @param obj The datefield object
1272  * @param fmt The date format, ex) yymmdd. Default value is mmddyy.
1273  *
1274  * @ingroup Datefield
1275  */
1276 EAPI void
1277 elm_datefield_date_format_set(Evas_Object *obj, const char *fmt)
1278 {
1279    ELM_CHECK_WIDTYPE(obj, widtype);
1280    Widget_Data *wd = elm_widget_data_get(obj);
1281    char sig[32] = "elm,state,format,";
1282    int i = 0, j;
1283
1284    if (!wd || !fmt) return;
1285
1286    j = strlen(sig);
1287    while (j < 32)
1288      {
1289         sig[j++] = tolower(fmt[i++]);
1290      }
1291    sig[j] = '\0';
1292    edje_object_signal_emit(wd->base, sig, "elm");
1293
1294    if (strstr(sig, "yymmdd")) wd->date_format = DATE_FORMAT_YYMMDD;
1295    else if (strstr(sig, "yyddmm")) wd->date_format = DATE_FORMAT_YYDDMM;
1296    else if (strstr(sig, "mmyydd")) wd->date_format = DATE_FORMAT_MMYYDD;
1297    else if (strstr(sig, "mmddyy")) wd->date_format = DATE_FORMAT_MMDDYY;
1298    else if (strstr(sig, "ddyymm")) wd->date_format = DATE_FORMAT_DDYYMM;
1299    else if (strstr(sig, "ddmmyy")) wd->date_format = DATE_FORMAT_DDMMYY;
1300    wd->format_exists = EINA_TRUE;
1301 }
1302
1303 /**
1304  * get date format of the datefield
1305  *
1306  * @param obj The datefield object
1307  * @return date format string. ex) yymmdd
1308  *
1309  * @ingroup Datefield
1310  */
1311 EAPI const char *
1312 elm_datefield_date_format_get(const Evas_Object *obj)
1313 {
1314    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1315    Widget_Data *wd = elm_widget_data_get(obj);
1316
1317    switch (wd->date_format)
1318      {
1319       case DATE_FORMAT_YYMMDD: return "yymmdd";
1320       case DATE_FORMAT_YYDDMM: return "yyddmm";
1321       case DATE_FORMAT_MMYYDD: return "mmyydd";
1322       case DATE_FORMAT_MMDDYY: return "mmddyy";
1323       case DATE_FORMAT_DDYYMM: return "ddyymm";
1324       case DATE_FORMAT_DDMMYY: return "ddmmyy";
1325      }
1326 }
1327
1328 /**
1329  * Add a callback function for input panel state
1330  *
1331  * @param obj The datefield object
1332  * @param func The function to be called when the event is triggered (value will be the Ecore_IMF_Input_Panel_State)
1333  * @param data The data pointer to be passed to @p func 
1334  *
1335  * @ingroup Datefield
1336  */
1337 EAPI void 
1338 elm_datefield_input_panel_state_callback_add(Evas_Object *obj, void (*pEventCallbackFunc) (void *data, Evas_Object *obj, int value), void *data)
1339 {
1340    ELM_CHECK_WIDTYPE(obj, widtype);
1341    Widget_Data *wd = elm_widget_data_get(obj);
1342    int i;
1343
1344    if (!wd) return;
1345
1346    if (wd->func && (wd->func != pEventCallbackFunc))
1347      elm_datefield_input_panel_state_callback_del(obj, wd->func);
1348
1349    if (wd->func != pEventCallbackFunc)
1350      {
1351         wd->func = pEventCallbackFunc;
1352         wd->func_data = data;
1353
1354         for (i = 0; i < DATE_MAX; i++)
1355           ecore_imf_context_input_panel_event_callback_add(
1356         elm_entry_imf_context_get(wd->date[i]), ECORE_IMF_INPUT_PANEL_STATE_EVENT, _input_panel_event_callback, obj);
1357
1358         for (i = 0; i < TIME_MAX; i++)
1359           ecore_imf_context_input_panel_event_callback_add(
1360         elm_entry_imf_context_get(wd->time[i]), ECORE_IMF_INPUT_PANEL_STATE_EVENT, _input_panel_event_callback, obj);
1361      }
1362 }
1363
1364 /**
1365  * Delete a callback function for input panel state
1366  *
1367  * @param obj The datefield object
1368  * @param func The function to be called when the event is triggered
1369  *
1370  * @ingroup Datefield
1371  */
1372 EAPI void 
1373 elm_datefield_input_panel_state_callback_del(Evas_Object *obj, void (*pEventCallbackFunc) (void *data, Evas_Object *obj, int value))
1374 {
1375    ELM_CHECK_WIDTYPE(obj, widtype);
1376    Widget_Data *wd = elm_widget_data_get(obj);
1377    int i;
1378
1379    if (!wd) return;
1380
1381    if (wd->func && wd->func == pEventCallbackFunc) 
1382      {
1383         for (i = 0; i < DATE_MAX; i++)
1384           ecore_imf_context_input_panel_event_callback_del(
1385         elm_entry_imf_context_get(wd->date[i]), ECORE_IMF_INPUT_PANEL_STATE_EVENT, _input_panel_event_callback);
1386
1387         for (i = 0; i < TIME_MAX; i++)
1388           ecore_imf_context_input_panel_event_callback_del(
1389         elm_entry_imf_context_get(wd->time[i]), ECORE_IMF_INPUT_PANEL_STATE_EVENT, _input_panel_event_callback);
1390
1391         wd->func = NULL;
1392         wd->func_data = NULL;
1393      }
1394 }