Add filled_add option for default image option.
[apps/native/widget/widget-edje.git] / src / script_port.c
1 /*
2  * Copyright 2013  Samsung Electronics Co., Ltd
3  *
4  * Licensed under the Flora License, Version 1.1 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://floralicense.org/license/
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include <stdio.h>
18 #include <libgen.h>
19 #include <errno.h>
20 #include <unistd.h>
21 #include <ctype.h>
22
23 #include <Elementary.h>
24 #include <Evas.h>
25 #include <Edje.h>
26 #include <Eina.h>
27 #include <Ecore.h>
28 #include <Ecore_Evas.h>
29 #include <Eet.h>
30 #include <Ecore_X.h>
31
32 #include <system_settings.h>
33
34 #include <dlog.h>
35 #include <debug.h>
36 #include <vconf.h>
37 #include <livebox-errno.h>
38 #include <livebox-service.h>
39
40 #include "script_port.h"
41
42 #define TEXT_CLASS      "tizen"
43 #define DEFAULT_FONT_SIZE       -100
44 #define BASE_WIDTH      720.0f
45
46 #define PUBLIC __attribute__((visibility("default")))
47
48 struct image_option {
49         int orient;
50         int aspect;
51         enum {
52                 FILL_DISABLE,
53                 FILL_IN_SIZE,
54                 FILL_OVER_SIZE,
55         } fill;
56
57         int width;
58         int height;
59 };
60
61 struct info {
62         char *file;
63         char *group;
64         char *category;
65         int w;
66         int h;
67
68         Evas *e;
69
70         Eina_List *obj_list;
71 };
72
73 struct child {
74         Evas_Object *obj;
75         char *part;
76 };
77
78 struct obj_info {
79         char *id;
80         Eina_List *children;
81         Evas_Object *parent;
82         Eina_List *access_chain;
83 };
84
85 static struct {
86         char *font_name;
87         int font_size;
88 } s_info = {
89         .font_name = NULL,
90         .font_size = -100,
91 };
92
93 static inline double scale_get(void)
94 {
95         int width;
96         int height;
97         ecore_x_window_size_get(0, &width, &height);
98         return (double)width / BASE_WIDTH;
99 }
100
101 static inline Evas_Object *find_edje(struct info *handle, const char *id)
102 {
103         Eina_List *l;
104         Evas_Object *edje;
105         struct obj_info *obj_info;
106
107         EINA_LIST_FOREACH(handle->obj_list, l, edje) {
108                 obj_info = evas_object_data_get(edje, "obj_info");
109                 if (!obj_info) {
110                         ErrPrint("Object info is not valid\n");
111                         continue;
112                 }
113
114                 if (!id) {
115                         if (!obj_info->id)
116                                 return edje;
117
118                         continue;
119                 } else if (!obj_info->id) {
120                         continue;
121                 }
122
123                 if (!strcmp(obj_info->id, id))
124                         return edje;
125         }
126
127         DbgPrint("EDJE[%s] is not found\n", id);
128         return NULL;
129 }
130
131 static inline void rebuild_focus_chain(Evas_Object *obj)
132 {
133         struct obj_info *obj_info;
134         Evas_Object *ao;
135         Eina_List *l;
136
137         obj_info = evas_object_data_get(obj, "obj_info");
138         if (!obj_info) {
139                 ErrPrint("Object info is not available\n");
140                 return;
141         }
142
143         elm_object_focus_custom_chain_unset(obj);
144
145         DbgPrint("Rebuild focus chain begin\n");
146         EINA_LIST_FOREACH(obj_info->access_chain, l, ao) {
147                 DbgPrint("Append %p\n", ao);
148                 elm_object_focus_custom_chain_append(obj, ao, NULL);
149         }
150         DbgPrint("Rebuild focus chain done\n");
151 }
152
153 PUBLIC const char *script_magic_id(void)
154 {
155         return "edje";
156 }
157
158 PUBLIC int script_update_color(void *h, Evas *e, const char *id, const char *part, const char *rgba)
159 {
160         struct info *handle = h;
161         Evas_Object *edje;
162         int r[3], g[3], b[3], a[3];
163         int ret;
164
165         edje = find_edje(handle, id);
166         if (!edje)
167                 return LB_STATUS_ERROR_NOT_EXIST;
168
169         ret = sscanf(rgba, "%d %d %d %d %d %d %d %d %d %d %d %d",
170                                         r, g, b, a,                     /* OBJECT */
171                                         r + 1, g + 1, b + 1, a + 1,     /* OUTLINE */
172                                         r + 2, g + 2, b + 2, a + 2);    /* SHADOW */
173         if (ret != 12) {
174                 DbgPrint("id[%s] part[%s] rgba[%s]\n", id, part, rgba);
175                 return LB_STATUS_ERROR_INVALID;
176         }
177
178         ret = edje_object_color_class_set(elm_layout_edje_get(edje), part,
179                                 r[0], g[0], b[0], a[0], /* OBJECT */
180                                 r[1], g[1], b[1], a[1], /* OUTLINE */
181                                 r[2], g[2], b[2], a[2]); /* SHADOW */
182
183         DbgPrint("EDJE[%s] color class is %s changed", id, ret == EINA_TRUE ? "successfully" : "not");
184         return LB_STATUS_SUCCESS;
185 }
186
187 static void activate_cb(void *data, Evas_Object *part_obj, Elm_Object_Item *item)
188 {
189         Evas_Object *ao;
190         Evas_Object *edje;
191         Evas *e;
192         int x;
193         int y;
194         int w;
195         int h;
196         struct timeval tv;
197         double timestamp;
198
199         ao = evas_object_data_get(part_obj, "ao");
200         if (!ao)
201                 return;
202
203         edje = evas_object_data_get(ao, "edje");
204         if (!edje)
205                 return;
206
207         e = evas_object_evas_get(part_obj);
208         evas_object_geometry_get(part_obj, &x, &y, &w, &h);
209         x += w / 2;
210         y += h / 2;
211
212         if (gettimeofday(&tv, NULL) < 0) {
213                 ErrPrint("Failed to get time\n");
214                 timestamp = 0.0f;
215         } else {
216                 timestamp = (double)tv.tv_sec + ((double)tv.tv_usec / 1000000.0f);
217         }
218
219         DbgPrint("Cursor is on %dx%d\n", x, y);
220         evas_event_feed_mouse_move(e, x, y, timestamp, NULL);
221         evas_event_feed_mouse_down(e, 1, EVAS_BUTTON_NONE, timestamp + 0.01f, NULL);
222         evas_event_feed_mouse_move(e, x, y, timestamp + 0.02f, NULL);
223         evas_event_feed_mouse_up(e, 1, EVAS_BUTTON_NONE, timestamp + 0.03f, NULL);
224 }
225
226 PUBLIC int script_update_text(void *h, Evas *e, const char *id, const char *part, const char *text)
227 {
228         struct obj_info *obj_info;
229         struct info *handle = h;
230         Evas_Object *edje;
231         Evas_Object *to;
232
233         edje = find_edje(handle, id);
234         if (!edje) {
235                 ErrPrint("Failed to find EDJE\n");
236                 return LB_STATUS_ERROR_NOT_EXIST;
237         }
238
239         obj_info = evas_object_data_get(edje, "obj_info");
240         if (!obj_info) {
241                 ErrPrint("Object info is not available\n");
242                 return LB_STATUS_ERROR_FAULT;
243         }
244
245         elm_object_part_text_set(edje, part, text ? text : "");
246
247         to = (Evas_Object *)edje_object_part_object_get(elm_layout_edje_get(edje), part);
248         if (to) {
249                 Evas_Object *ao;
250                 char *utf8;
251
252                 ao = evas_object_data_get(to, "ao");
253                 if (!ao) {
254                         ao = elm_access_object_register(to, edje);
255                         if (!ao) {
256                                 ErrPrint("Unable to add ao: %s\n", part);
257                                 goto out;
258                         }
259                         obj_info->access_chain = eina_list_append(obj_info->access_chain, ao);
260                         evas_object_data_set(to, "ao", ao);
261                         evas_object_data_set(ao, "edje", edje);
262                         elm_access_activate_cb_set(ao, activate_cb, NULL);
263                         elm_object_focus_custom_chain_append(edje, ao, NULL);
264                 }
265
266                 if (!text || !strlen(text)) {
267                         obj_info->access_chain = eina_list_remove(obj_info->access_chain, ao);
268                         evas_object_data_del(to, "ao");
269                         evas_object_data_del(ao, "edje");
270                         elm_access_object_unregister(ao);
271                         DbgPrint("[%s] Remove access object\n", part);
272
273                         rebuild_focus_chain(edje);
274                         goto out;
275                 }
276
277                 utf8 = elm_entry_markup_to_utf8(text);
278                 if ((!utf8 || !strlen(utf8))) {
279                         free(utf8);
280
281                         obj_info->access_chain = eina_list_remove(obj_info->access_chain, ao);
282                         evas_object_data_del(to, "ao");
283                         evas_object_data_del(ao, "edje");
284                         elm_access_object_unregister(ao);
285                         DbgPrint("[%s] Remove access object\n", part);
286
287                         rebuild_focus_chain(edje);
288                         goto out;
289                 }
290
291                 elm_access_info_set(ao, ELM_ACCESS_INFO, utf8);
292                 DbgPrint("[%s] Update access object (%s)\n", part, utf8);
293                 free(utf8);
294         } else {
295                 ErrPrint("Unable to get text part[%s]\n", part);
296         }
297
298 out:
299         return LB_STATUS_SUCCESS;
300 }
301
302 static void parse_aspect(struct image_option *img_opt, const char *value, int len)
303 {
304         while (len > 0 && *value == ' ') {
305                 value++;
306                 len--;
307         }
308
309         if (len < 4)
310                 return;
311
312         img_opt->aspect = !strncasecmp(value, "true", 4);
313         DbgPrint("Parsed ASPECT: %d (%s)\n", img_opt->aspect, value);
314 }
315
316 static void parse_orient(struct image_option *img_opt, const char *value, int len)
317 {
318         while (len > 0 && *value == ' ') {
319                 value++;
320                 len--;
321         }
322
323         if (len < 4)
324                 return;
325
326         img_opt->orient = !strncasecmp(value, "true", 4);
327         DbgPrint("Parsed ORIENT: %d (%s)\n", img_opt->orient, value);
328 }
329
330 static void parse_size(struct image_option *img_opt, const char *value, int len)
331 {
332         int width;
333         int height;
334         char *buf;
335
336         while (len > 0 && *value == ' ') {
337                 value++;
338                 len--;
339         }
340
341         buf = strndup(value, len);
342         if (!buf) {
343                 ErrPrint("Heap: %s\n", strerror(errno));
344                 return;
345         }
346
347         if (sscanf(buf, "%dx%d", &width, &height) == 2) {
348                 img_opt->width = width;
349                 img_opt->height = height;
350                 DbgPrint("Parsed size : %dx%d (%s)\n", width, height, buf);
351         } else {
352                 DbgPrint("Invalid size tag[%s]\n", buf);
353         }
354
355         free(buf);
356 }
357
358 static void parse_fill(struct image_option *img_opt, const char *value, int len)
359 {
360         while (len > 0 && *value == ' ') {
361                 value++;
362                 len--;
363         }
364
365         if (!strncasecmp(value, "in-size", len))
366                 img_opt->fill = FILL_IN_SIZE;
367         else if (!strncasecmp(value, "over-size", len))
368                 img_opt->fill = FILL_OVER_SIZE;
369         else
370                 img_opt->fill = FILL_DISABLE;
371
372         DbgPrint("Parsed FILL: %d (%s)\n", img_opt->fill, value);
373 }
374
375 static inline void parse_image_option(const char *option, struct image_option *img_opt)
376 {
377         const char *ptr;
378         const char *cmd;
379         const char *value;
380         struct {
381                 const char *cmd;
382                 void (*handler)(struct image_option *img_opt, const char *value, int len);
383         } cmd_list[] = {
384                 {
385                         .cmd = "aspect", /* Keep the aspect ratio */
386                         .handler = parse_aspect,
387                 },
388                 {
389                         .cmd = "orient", /* Keep the orientation value: for the rotated images */
390                         .handler = parse_orient,
391                 },
392                 {
393                         .cmd = "fill", /* Fill the image to its container */
394                         .handler = parse_fill, /* Value: in-size, over-size, disable(default) */
395                 },
396                 {
397                         .cmd = "size",
398                         .handler = parse_size,
399                 },
400         };
401         enum {
402                 STATE_START,
403                 STATE_TOKEN,
404                 STATE_DATA,
405                 STATE_IGNORE,
406                 STATE_ERROR,
407                 STATE_END,
408         } state;
409         int idx;
410         int tag;
411
412         if (!option || !*option)
413                 return;
414
415         state = STATE_START;
416         /*!
417          * \note
418          * GCC 4.7 warnings uninitialized idx and tag value.
419          * But it will be initialized by the state machine. :(
420          * Anyway, I just reset idx and tag for reducing the GCC4.7 complains.
421          */
422         idx = 0;
423         tag = 0;
424         cmd = NULL;
425         value = NULL;
426
427         for (ptr = option; state != STATE_END; ptr++) {
428                 switch (state) {
429                 case STATE_START:
430                         if (*ptr == '\0') {
431                                 state = STATE_END;
432                                 continue;
433                         }
434
435                         if (isalpha(*ptr)) {
436                                 state = STATE_TOKEN;
437                                 ptr--;
438                         }
439                         tag = 0;
440                         idx = 0;
441
442                         cmd = cmd_list[tag].cmd;
443                         break;
444                 case STATE_IGNORE:
445                         if (*ptr == '=') {
446                                 state = STATE_DATA;
447                                 value = ptr;
448                         } else if (*ptr == '\0') {
449                                 state = STATE_END;
450                         }
451                         break;
452                 case STATE_TOKEN:
453                         if (cmd[idx] == '\0' && (*ptr == ' ' || *ptr == '\t' || *ptr == '=')) {
454                                 if (*ptr == '=') {
455                                         value = ptr;
456                                         state = STATE_DATA;
457                                 } else {
458                                         state = STATE_IGNORE;
459                                 }
460                                 idx = 0;
461                         } else if (*ptr == '\0') {
462                                 state = STATE_END;
463                         } else if (cmd[idx] == *ptr) {
464                                 idx++;
465                         } else {
466                                 ptr -= (idx + 1);
467
468                                 tag++;
469                                 if (tag == sizeof(cmd_list) / sizeof(cmd_list[0])) {
470                                         tag = 0;
471                                         state = STATE_ERROR;
472                                 } else {
473                                         cmd = cmd_list[tag].cmd;
474                                 }
475                                 idx = 0;
476                         }
477                         break;
478                 case STATE_DATA:
479                         if (*ptr == ';' || *ptr == '\0') {
480                                 cmd_list[tag].handler(img_opt, value + 1, idx);
481                                 state = *ptr ? STATE_START : STATE_END;
482                         } else {
483                                 idx++;
484                         }
485                         break;
486                 case STATE_ERROR:
487                         if (*ptr == ';')
488                                 state = STATE_START;
489                         else if (*ptr == '\0')
490                                 state = STATE_END;
491                         break;
492                 default:
493                         break;
494                 }
495         }
496 }
497
498 PUBLIC int script_update_access(void *_h, Evas *e, const char *id, const char *part, const char *text, const char *option)
499 {
500         struct info *handle = _h;
501         Evas_Object *edje;
502         struct obj_info *obj_info;
503         Evas_Object *to;
504
505         edje = find_edje(handle, id);
506         if (!edje) {
507                 ErrPrint("No such object: %s\n", id);
508                 return LB_STATUS_ERROR_NOT_EXIST;
509         }
510
511         obj_info = evas_object_data_get(edje, "obj_info");
512         if (!obj_info) {
513                 ErrPrint("Object info is not available\n");
514                 return LB_STATUS_ERROR_FAULT;
515         }
516
517         to = (Evas_Object *)edje_object_part_object_get(elm_layout_edje_get(edje), part);
518         if (to) {
519                 Evas_Object *ao;
520
521                 ao = evas_object_data_get(to, "ao");
522                 if (ao) {
523                         DbgPrint("[%s] Update access object (%s)\n", part, text);
524                         if (text && strlen(text)) {
525                                 elm_access_info_set(ao, ELM_ACCESS_INFO, text);
526                         } else {
527                                 obj_info->access_chain = eina_list_remove(obj_info->access_chain, ao);
528                                 evas_object_data_del(to, "ao");
529                                 evas_object_data_del(ao, "edje");
530                                 elm_access_object_unregister(ao);
531                                 DbgPrint("Successfully unregistered\n");
532
533                                 rebuild_focus_chain(edje);
534                         }
535                 } else if (text && strlen(text)) {
536                         ao = elm_access_object_register(to, edje);
537                         if (!ao) {
538                                 ErrPrint("Unable to register access object\n");
539                         } else {
540                                 elm_access_info_set(ao, ELM_ACCESS_INFO, text);
541                                 obj_info->access_chain = eina_list_append(obj_info->access_chain, ao);
542                                 evas_object_data_set(to, "ao", ao);
543                                 elm_object_focus_custom_chain_append(edje, ao, NULL);
544                                 DbgPrint("[%s] Register access info: (%s)\n", part, text);
545                                 evas_object_data_set(ao, "edje", edje);
546                                 elm_access_activate_cb_set(ao, activate_cb, NULL);
547                         }
548                 }
549         } else {
550                 ErrPrint("[%s] is not exists\n", part);
551         }
552
553         return LB_STATUS_SUCCESS;
554 }
555
556 PUBLIC int script_update_image(void *_h, Evas *e, const char *id, const char *part, const char *path, const char *option)
557 {
558         struct info *handle = _h;
559         Evas_Load_Error err;
560         Evas_Object *edje;
561         Evas_Object *img;
562         Evas_Coord w, h;
563         struct obj_info *obj_info;
564         struct child *child;
565         struct image_option img_opt = {
566                 .aspect = 0,
567                 .orient = 0,
568                 .fill = FILL_DISABLE,
569                 .width = -1,
570                 .height = -1,
571         };
572
573         edje = find_edje(handle, id);
574         if (!edje) {
575                 ErrPrint("No such object: %s\n", id);
576                 return LB_STATUS_ERROR_NOT_EXIST;
577         }
578
579         obj_info = evas_object_data_get(edje, "obj_info");
580         if (!obj_info) {
581                 ErrPrint("Object info is not available\n");
582                 return LB_STATUS_ERROR_FAULT;
583         }
584
585         img = elm_object_part_content_unset(edje, part);
586         if (img) {
587                 Eina_List *l;
588                 Eina_List *n;
589                 Evas_Object *ao;
590
591                 EINA_LIST_FOREACH_SAFE(obj_info->children, l, n, child) {
592                         if (child->obj != img)
593                                 continue;
594
595                         obj_info->children = eina_list_remove(obj_info->children, child);
596                         free(child->part);
597                         free(child);
598                         break;
599                 }
600
601                 DbgPrint("delete object %s %p\n", part, img);
602                 ao = evas_object_data_del(img, "ao");
603                 if (ao) {
604                         obj_info->access_chain = eina_list_remove(obj_info->access_chain, ao);
605                         evas_object_data_del(ao, "edje");
606                         elm_access_object_unregister(ao);
607                         DbgPrint("Successfully unregistered\n");
608                 }
609                 evas_object_del(img);
610
611                 rebuild_focus_chain(edje);
612         }
613
614         if (!path || !strlen(path) || access(path, R_OK) != 0) {
615                 DbgPrint("SKIP - Path: [%s]\n", path);
616                 return LB_STATUS_SUCCESS;
617         }
618
619         child = malloc(sizeof(*child));
620         if (!child) {
621                 ErrPrint("Heap: %s\n", strerror(errno));
622                 return LB_STATUS_ERROR_MEMORY;
623         }
624
625         child->part = strdup(part);
626         if (!child->part) {
627                 ErrPrint("Heap: %s\n", strerror(errno));
628                 free(child);
629                 return LB_STATUS_ERROR_MEMORY;
630         }
631
632         img = evas_object_image_add(e);
633         if (!img) {
634                 ErrPrint("Failed to add an image object\n");
635                 free(child->part);
636                 free(child);
637                 return LB_STATUS_ERROR_FAULT;
638         }
639
640         evas_object_image_preload(img, EINA_FALSE);
641         parse_image_option(option, &img_opt);
642         evas_object_image_load_orientation_set(img, img_opt.orient);
643
644         evas_object_image_file_set(img, path, NULL);
645         err = evas_object_image_load_error_get(img);
646         if (err != EVAS_LOAD_ERROR_NONE) {
647                 ErrPrint("Load error: %s\n", evas_load_error_str(err));
648                 evas_object_del(img);
649                 free(child->part);
650                 free(child);
651                 return LB_STATUS_ERROR_IO;
652         }
653
654         evas_object_image_size_get(img, &w, &h);
655         if (img_opt.aspect) {
656                 if (img_opt.fill == FILL_OVER_SIZE) {
657                         Evas_Coord part_w;
658                         Evas_Coord part_h;
659
660                         if (img_opt.width >= 0 && img_opt.height >= 0) {
661                                 part_w = img_opt.width * scale_get();
662                                 part_h = img_opt.height * scale_get();
663                         } else {
664                                 part_w = 0;
665                                 part_h = 0;
666                                 edje_object_part_geometry_get(elm_layout_edje_get(edje), part, NULL, NULL, &part_w, &part_h);
667                         }
668                         DbgPrint("Original %dx%d (part: %dx%d)\n", w, h, part_w, part_h);
669
670                         if (part_w > w || part_h > h) {
671                                 double fw;
672                                 double fh;
673
674                                 fw = (double)part_w / (double)w;
675                                 fh = (double)part_h / (double)h;
676
677                                 if (fw > fh) {
678                                         w = part_w;
679                                         h = (double)h * fw;
680                                 } else {
681                                         h = part_h;
682                                         w = (double)w * fh;
683                                 }
684                         }
685
686                         if (!part_w || !part_h || !w || !h) {
687                                 evas_object_del(img);
688                                 free(child->part);
689                                 free(child);
690                                 return LB_STATUS_ERROR_INVALID;
691                         }
692
693                         if (evas_object_image_region_support_get(img)) {
694                                 evas_object_image_load_region_set(img, (w - part_w) / 2, (h - part_h) / 2, part_w, part_h);
695                                 evas_object_image_load_size_set(img, part_w, part_h);
696                                 evas_object_image_fill_set(img, 0, 0, part_w, part_h);
697                                 DbgPrint("Size: %dx%d (region: %dx%d - %dx%d)\n", w, h, (w - part_w) / 2, (h - part_h) / 2, part_w, part_h);
698                         } else {
699                                 Ecore_Evas *ee;
700                                 Evas *e;
701                                 Evas_Object *src_img;
702                                 Evas_Coord rw, rh;
703                                 const void *data;
704
705                                 DbgPrint("Part loading is not supported\n");
706                                 ee = ecore_evas_buffer_new(part_w, part_h);
707                                 if (!ee) {
708                                         ErrPrint("Failed to create a EE\n");
709                                         evas_object_del(img);
710                                         free(child->part);
711                                         free(child);
712                                         return LB_STATUS_ERROR_FAULT;
713                                 }
714
715                                 e = ecore_evas_get(ee);
716                                 if (!e) {
717                                         ErrPrint("Unable to get Evas\n");
718                                         ecore_evas_free(ee);
719
720                                         evas_object_del(img);
721                                         free(child->part);
722                                         free(child);
723                                         return LB_STATUS_ERROR_FAULT;
724                                 }
725
726                                 src_img = evas_object_image_filled_add(e);
727                                 if (!src_img) {
728                                         ErrPrint("Unable to add an image\n");
729                                         ecore_evas_free(ee);
730
731                                         evas_object_del(img);
732                                         free(child->part);
733                                         free(child);
734                                         return LB_STATUS_ERROR_FAULT;
735                                 }
736
737                                 evas_object_image_load_orientation_set(src_img, img_opt.orient);
738                                 evas_object_image_file_set(src_img, path, NULL);
739                                 err = evas_object_image_load_error_get(src_img);
740                                 if (err != EVAS_LOAD_ERROR_NONE) {
741                                         ErrPrint("Load error: %s\n", evas_load_error_str(err));
742                                         evas_object_del(src_img);
743                                         ecore_evas_free(ee);
744
745                                         evas_object_del(img);
746                                         free(child->part);
747                                         free(child);
748                                         return LB_STATUS_ERROR_IO;
749                                 }
750                                 evas_object_image_size_get(src_img, &rw, &rh);
751                                 evas_object_image_fill_set(src_img, 0, 0, rw, rh);
752                                 evas_object_resize(src_img, w, h);
753                                 evas_object_move(src_img, -(w - part_w) / 2, -(h - part_h) / 2);
754                                 evas_object_show(src_img);
755
756                                 data = ecore_evas_buffer_pixels_get(ee);
757                                 if (!data) {
758                                         ErrPrint("Unable to get pixels\n");
759                                         evas_object_del(src_img);
760                                         ecore_evas_free(ee);
761
762                                         evas_object_del(img);
763                                         free(child->part);
764                                         free(child);
765                                         return LB_STATUS_ERROR_IO;
766                                 }
767
768                                 e = evas_object_evas_get(img);
769                                 evas_object_del(img);
770                                 img = evas_object_image_filled_add(e);
771                                 if (!img) {
772                                         evas_object_del(src_img);
773                                         ecore_evas_free(ee);
774
775                                         free(child->part);
776                                         free(child);
777                                         return LB_STATUS_ERROR_MEMORY;
778                                 }
779
780                                 evas_object_image_colorspace_set(img, EVAS_COLORSPACE_ARGB8888);
781                                 evas_object_image_smooth_scale_set(img, EINA_TRUE);
782                                 evas_object_image_alpha_set(img, EINA_TRUE);
783                                 evas_object_image_data_set(img, NULL);
784                                 evas_object_image_size_set(img, part_w, part_h);
785                                 evas_object_resize(img, part_w, part_h);
786                                 evas_object_image_data_copy_set(img, (void *)data);
787                                 evas_object_image_fill_set(img, 0, 0, part_w, part_h);
788                                 evas_object_image_data_update_add(img, 0, 0, part_w, part_h);
789
790                                 evas_object_del(src_img);
791                                 ecore_evas_free(ee);
792                         }
793                 } else if (img_opt.fill == FILL_IN_SIZE) {
794                         Evas_Coord part_w;
795                         Evas_Coord part_h;
796
797                         if (img_opt.width >= 0 && img_opt.height >= 0) {
798                                 part_w = img_opt.width * scale_get();
799                                 part_h = img_opt.height * scale_get();
800                         } else {
801                                 part_w = 0;
802                                 part_h = 0;
803                                 edje_object_part_geometry_get(elm_layout_edje_get(edje), part, NULL, NULL, &part_w, &part_h);
804                         }
805                         DbgPrint("Original %dx%d (part: %dx%d)\n", w, h, part_w, part_h);
806
807                         if (part_w > w || part_h > h) {
808                                 double fw;
809                                 double fh;
810
811                                 fw = (double)part_w / (double)w;
812                                 fh = (double)part_h / (double)h;
813
814                                 if (fw > fh) {
815                                         w = part_w;
816                                         h = (double)h * fw;
817                                 } else {
818                                         h = part_h;
819                                         w = (double)w * fh;
820                                 }
821                         }
822                         DbgPrint("Size: %dx%d\n", w, h);
823                         evas_object_image_fill_set(img, 0, 0, part_w, part_h);
824                         evas_object_size_hint_fill_set(img, EVAS_HINT_FILL, EVAS_HINT_FILL);
825                         evas_object_size_hint_weight_set(img, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
826                 } else {
827                         evas_object_image_fill_set(img, 0, 0, w, h);
828                         evas_object_size_hint_fill_set(img, EVAS_HINT_FILL, EVAS_HINT_FILL);
829                         evas_object_size_hint_aspect_set(img, EVAS_ASPECT_CONTROL_BOTH, w, h);
830                 }
831         } else {
832                 if (img_opt.width >= 0 && img_opt.height >= 0) {
833                         w = img_opt.width;
834                         h = img_opt.height;
835                         DbgPrint("Using given image size: %dx%d\n", w, h);
836                 }
837
838                 evas_object_image_fill_set(img, 0, 0, w, h);
839                 evas_object_size_hint_fill_set(img, EVAS_HINT_FILL, EVAS_HINT_FILL);
840                 evas_object_size_hint_weight_set(img, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
841                 evas_object_image_filled_set(img, EINA_TRUE);
842         }
843
844         /*!
845          * \note
846          * object will be shown by below statement automatically
847          */
848         DbgPrint("%s part swallow image %p (%dx%d)\n", part, img, w, h);
849         child->obj = img;
850         elm_object_part_content_set(edje, part, img);
851         obj_info->children = eina_list_append(obj_info->children, child);
852
853         /*!
854          * \note
855          * This object is not registered as an access object.
856          * So the developer should add it to access list manually, using DESC_ACCESS block.
857          */
858         return LB_STATUS_SUCCESS;
859 }
860
861 static void script_signal_cb(void *data, Evas_Object *obj, const char *emission, const char *source)
862 {
863         struct info *handle = data;
864         Evas_Coord w;
865         Evas_Coord h;
866         Evas_Coord px = 0;
867         Evas_Coord py = 0;
868         Evas_Coord pw = 0;
869         Evas_Coord ph = 0;
870         double sx;
871         double sy;
872         double ex;
873         double ey;
874
875         evas_object_geometry_get(obj, NULL, NULL, &w, &h);
876         edje_object_part_geometry_get(elm_layout_edje_get(obj), source, &px, &py, &pw, &ph);
877
878         sx = ex = 0.0f;
879         if (w) {
880                 sx = (double)px / (double)w;
881                 ex = (double)(px + pw) / (double)w;
882         }
883
884         sy = ey = 0.0f;
885         if (h) {
886                 sy = (double)py / (double)h;
887                 ey = (double)(py + ph) / (double)h;
888         }
889
890         DbgPrint("Signal emit: source[%s], emission[%s]\n", source, emission);
891         script_signal_emit(handle->e, source, emission, sx, sy, ex, ey);
892 }
893
894 static void edje_del_cb(void *_info, Evas *e, Evas_Object *obj, void *event_info)
895 {
896         struct info *handle = _info;
897         struct obj_info *obj_info;
898         struct obj_info *parent_obj_info;
899         struct child *child;
900         Evas_Object *ao;
901
902         handle->obj_list = eina_list_remove(handle->obj_list, obj);
903
904         obj_info = evas_object_data_del(obj, "obj_info");
905         if (!obj_info) {
906                 ErrPrint("Object info is not valid\n");
907                 return;
908         }
909
910         DbgPrint("delete object %s %p\n", obj_info->id, obj);
911         parent_obj_info = evas_object_data_get(obj_info->parent, "obj_info");
912         if (parent_obj_info) {
913                 Eina_List *l;
914                 Eina_List *n;
915
916                 EINA_LIST_FOREACH_SAFE(parent_obj_info->children, l, n, child) {
917                         if (child->obj != obj)
918                                 continue;
919
920                         /*!
921                          * \note
922                          * If this code is executed,
923                          * The parent is not deleted by desc, this object is deleted by itself.
924                          * It is not possible, but we care it.
925                          */
926                         DbgPrint("Parent's children is updated: %s\n", child->part);
927                         parent_obj_info->children = eina_list_remove(parent_obj_info->children, child);
928                         free(child->part);
929                         free(child);
930                         break;
931                 }
932         } else {
933                 DbgPrint("Parent EDJE\n");
934         }
935
936         elm_object_signal_callback_del(obj, "*", "*", script_signal_cb);
937
938         elm_object_focus_custom_chain_unset(obj);
939
940         EINA_LIST_FREE(obj_info->children, child) {
941                 DbgPrint("delete object %s %p\n", child->part, child->obj);
942                 if (child->obj) {
943                         Evas_Object *ao;
944                         ao = evas_object_data_del(child->obj, "ao");
945                         if (ao) {
946                                 obj_info->access_chain = eina_list_remove(obj_info->access_chain, ao);
947                                 evas_object_data_del(ao, "edje");
948                                 elm_access_object_unregister(ao);
949                         }
950                         evas_object_del(child->obj);
951                 }
952                 free(child->part);
953                 free(child);
954         }
955
956         EINA_LIST_FREE(obj_info->access_chain, ao) {
957                 evas_object_data_del(ao, "edje");
958                 elm_access_object_unregister(ao);
959         }
960
961         free(obj_info->id);
962         free(obj_info);
963 }
964
965 /*!
966         LB_ACCESS_HIGHLIGHT             0
967         LB_ACCESS_HIGHLIGHT_NEXT        1
968         LB_ACCESS_HIGHLIGHT_PREV        2
969         LB_ACCESS_ACTIVATE              3
970         LB_ACCESS_ACTION                4
971         LB_ACCESS_SCROLL                5
972 */
973 PUBLIC int script_feed_event(void *h, Evas *e, int event_type, int x, int y, int down, double timestamp)
974 {
975         struct info *handle = h;
976         Evas_Object *edje;
977         struct obj_info *obj_info;
978         int ret = LB_STATUS_SUCCESS;
979
980         DbgPrint("event: %d, x: %d, y: %d\n", event_type, x, y);
981
982         edje = find_edje(handle, NULL); /*!< Get the base layout */
983         if (!edje) {
984                 ErrPrint("Base layout is not exist\n");
985                 return LB_STATUS_ERROR_NOT_EXIST;
986         }
987
988         obj_info = evas_object_data_get(edje, "obj_info");
989         if (!obj_info) {
990                 ErrPrint("Object info is not valid\n");
991                 return LB_STATUS_ERROR_INVALID;
992         }
993
994         if (event_type & LB_SCRIPT_ACCESS_EVENT) {
995                 Elm_Access_Action_Info *info;
996                 Elm_Access_Action_Type action;
997                 const Eina_List *chain;
998
999                 info = calloc(1, sizeof(*info));
1000                 if (!info) {
1001                         ErrPrint("Error: %s\n", strerror(errno));
1002                         return LB_STATUS_ERROR_MEMORY;
1003                 }
1004
1005                 chain = elm_object_focus_custom_chain_get(edje);
1006                 DbgPrint("Focus chain : %d\n", eina_list_count(chain));
1007
1008                 if ((event_type & LB_SCRIPT_ACCESS_HIGHLIGHT) == LB_SCRIPT_ACCESS_HIGHLIGHT) {
1009                         action = ELM_ACCESS_ACTION_HIGHLIGHT;
1010                         info->x = x;
1011                         info->y = y;
1012                         ret = elm_access_action(edje, action, info);
1013                         DbgPrint("ACCESS_HIGHLIGHT: %dx%d returns %d\n", x, y, ret);
1014                         ret = (ret == EINA_FALSE) ? LB_ACCESS_STATUS_ERROR : LB_ACCESS_STATUS_DONE;
1015                 } else if ((event_type & LB_SCRIPT_ACCESS_HIGHLIGHT_NEXT) == LB_SCRIPT_ACCESS_HIGHLIGHT_NEXT) {
1016                         action = ELM_ACCESS_ACTION_HIGHLIGHT_NEXT;
1017                         info->highlight_cycle = EINA_FALSE;
1018                         ret = elm_access_action(edje, action, info);
1019                         DbgPrint("ACCESS_HIGHLIGHT_NEXT, returns %d\n", ret);
1020                         ret = (ret == EINA_FALSE) ? LB_ACCESS_STATUS_LAST : LB_ACCESS_STATUS_DONE;
1021                 } else if ((event_type & LB_SCRIPT_ACCESS_HIGHLIGHT_PREV) == LB_SCRIPT_ACCESS_HIGHLIGHT_PREV) {
1022                         action = ELM_ACCESS_ACTION_HIGHLIGHT_PREV;
1023                         info->highlight_cycle = EINA_FALSE;
1024                         ret = elm_access_action(edje, action, info);
1025                         DbgPrint("ACCESS_HIGHLIGHT_PREV, returns %d\n", ret);
1026                         ret = (ret == EINA_FALSE) ? LB_ACCESS_STATUS_FIRST : LB_ACCESS_STATUS_DONE;
1027                 } else if ((event_type & LB_SCRIPT_ACCESS_ACTIVATE) == LB_SCRIPT_ACCESS_ACTIVATE) {
1028                         action = ELM_ACCESS_ACTION_ACTIVATE;
1029                         ret = elm_access_action(edje, action, info);
1030                         DbgPrint("ACCESS_ACTIVATE, returns %d\n", ret);
1031                         ret = (ret == EINA_FALSE) ? LB_ACCESS_STATUS_ERROR : LB_ACCESS_STATUS_DONE;
1032                 } else if ((event_type & LB_SCRIPT_ACCESS_ACTION) == LB_SCRIPT_ACCESS_ACTION) {
1033                         if (down == 0) {
1034                                 action = ELM_ACCESS_ACTION_UP;
1035                                 ret = elm_access_action(edje, action, info);
1036                                 DbgPrint("ACCESS_ACTION(%d), returns %d\n", down, ret);
1037                                 ret = (ret == EINA_FALSE) ? LB_ACCESS_STATUS_ERROR : LB_ACCESS_STATUS_DONE;
1038                         } else if (down == 1) {
1039                                 action = ELM_ACCESS_ACTION_DOWN;
1040                                 ret = elm_access_action(edje, action, info);
1041                                 DbgPrint("ACCESS_ACTION(%d), returns %d\n", down, ret);
1042                                 ret = (ret == EINA_FALSE) ? LB_ACCESS_STATUS_ERROR : LB_ACCESS_STATUS_DONE;
1043                         } else {
1044                                 ErrPrint("Invalid access event\n");
1045                                 ret = LB_ACCESS_STATUS_ERROR;
1046                         }
1047                 } else if ((event_type & LB_SCRIPT_ACCESS_SCROLL) == LB_SCRIPT_ACCESS_SCROLL) {
1048                         action = ELM_ACCESS_ACTION_SCROLL;
1049                         info->x = x;
1050                         info->y = y;
1051                         switch (down) {
1052                         case 0:
1053                                 info->mouse_type = 0;
1054                                 ret = elm_access_action(edje, action, info);
1055                                 DbgPrint("ACCESS_HIGHLIGHT_SCROLL, returns %d\n", ret);
1056                                 ret = (ret == EINA_FALSE) ? LB_ACCESS_STATUS_ERROR : LB_ACCESS_STATUS_DONE;
1057                                 break;
1058                         case -1:
1059                                 info->mouse_type = 1;
1060                                 ret = elm_access_action(edje, action, info);
1061                                 DbgPrint("ACCESS_HIGHLIGHT_SCROLL, returns %d\n", ret);
1062                                 ret = (ret == EINA_FALSE) ? LB_ACCESS_STATUS_ERROR : LB_ACCESS_STATUS_DONE;
1063                                 break;
1064                         case 1:
1065                                 info->mouse_type = 2;
1066                                 ret = elm_access_action(edje, action, info);
1067                                 DbgPrint("ACCESS_HIGHLIGHT_SCROLL, returns %d\n", ret);
1068                                 ret = (ret == EINA_FALSE) ? LB_ACCESS_STATUS_ERROR : LB_ACCESS_STATUS_DONE;
1069                                 break;
1070                         default:
1071                                 ret = LB_ACCESS_STATUS_ERROR;
1072                                 break;
1073                         }
1074                 } else if ((event_type & LB_SCRIPT_ACCESS_UNHIGHLIGHT) == LB_SCRIPT_ACCESS_UNHIGHLIGHT) {
1075                         action = ELM_ACCESS_ACTION_UNHIGHLIGHT;
1076                         ret = elm_access_action(edje, action, info);
1077                         DbgPrint("ACCESS_UNHIGHLIGHT, returns %d\n", ret);
1078                         ret = (ret == EINA_FALSE) ? LB_ACCESS_STATUS_ERROR : LB_ACCESS_STATUS_DONE;
1079                 } else {
1080                         DbgPrint("Invalid event\n");
1081                         ret = LB_ACCESS_STATUS_ERROR;
1082                 }
1083
1084                 free(info);
1085         } else if (event_type & LB_SCRIPT_MOUSE_EVENT) {
1086                 switch (event_type) {
1087                 case LB_SCRIPT_MOUSE_DOWN:
1088                         evas_event_feed_mouse_move(e, x, y, timestamp, NULL);
1089                         evas_event_feed_mouse_down(e, 1, EVAS_BUTTON_NONE, timestamp + 0.01f, NULL);
1090                         break;
1091                 case LB_SCRIPT_MOUSE_MOVE:
1092                         evas_event_feed_mouse_move(e, x, y, timestamp, NULL);
1093                         break;
1094                 case LB_SCRIPT_MOUSE_UP:
1095                         evas_event_feed_mouse_move(e, x, y, timestamp, NULL);
1096                         evas_event_feed_mouse_up(e, 1, EVAS_BUTTON_NONE, timestamp + 0.1f, NULL);
1097                         break;
1098                 case LB_SCRIPT_MOUSE_IN:
1099                         evas_event_feed_mouse_in(e, timestamp, NULL);
1100                         break;
1101                 case LB_SCRIPT_MOUSE_OUT:
1102                         evas_event_feed_mouse_out(e, timestamp, NULL);
1103                         break;
1104                 default:
1105                         return LB_STATUS_ERROR_INVALID;
1106                 }
1107         } else if (event_type & LB_SCRIPT_KEY_EVENT) {
1108                 DbgPrint("Key event is not implemented\n");
1109                 return LB_STATUS_ERROR_NOT_IMPLEMENTED;
1110         }
1111
1112         return ret;
1113 }
1114
1115 PUBLIC int script_update_script(void *h, Evas *e, const char *src_id, const char *target_id, const char *part, const char *path, const char *group)
1116 {
1117         struct info *handle = h;
1118         Evas_Object *edje;
1119         Evas_Object *obj;
1120         struct obj_info *obj_info;
1121         struct child *child;
1122         char _target_id[32];
1123
1124         DbgPrint("src_id[%s] target_id[%s] part[%s] path[%s] group[%s]\n", src_id, target_id, part, path, group);
1125
1126         edje = find_edje(handle, src_id);
1127         if (!edje) {
1128                 ErrPrint("Edje is not exists\n");
1129                 return LB_STATUS_ERROR_NOT_EXIST;
1130         }
1131
1132         obj_info = evas_object_data_get(edje, "obj_info");
1133         if (!obj_info) {
1134                 ErrPrint("Object info is not valid\n");
1135                 return LB_STATUS_ERROR_INVALID;
1136         }
1137
1138         obj = elm_object_part_content_unset(edje, part);
1139         if (obj) {
1140                 Eina_List *l;
1141                 Eina_List *n;
1142
1143                 EINA_LIST_FOREACH_SAFE(obj_info->children, l, n, child) {
1144                         if (child->obj != obj)
1145                                 continue;
1146
1147                         obj_info->children = eina_list_remove(obj_info->children, child);
1148
1149                         free(child->part);
1150                         free(child);
1151                         break;
1152                 }
1153
1154                 DbgPrint("delete object %s %p\n", part, obj);
1155                 /*!
1156                  * \note
1157                  * This will call the edje_del_cb.
1158                  * It will delete all access objects
1159                  */
1160                 evas_object_del(obj);
1161         }
1162
1163         if (!path || !strlen(path) || access(path, R_OK) != 0) {
1164                 DbgPrint("SKIP - Path: [%s]\n", path);
1165                 return LB_STATUS_SUCCESS;
1166         }
1167
1168         if (!target_id) {
1169                 if (find_edje(handle, part)) {
1170                         double timestamp;
1171                         struct timeval tv;
1172
1173                         do {
1174                                 if (gettimeofday(&tv, NULL) < 0) {
1175                                         static int local_idx = 0;
1176                                         timestamp = (double)(local_idx++);
1177                                 } else {
1178                                         timestamp = (double)tv.tv_sec + ((double)tv.tv_usec / 1000000.0f);
1179                                 }
1180
1181                                 snprintf(_target_id, sizeof(_target_id), "%lf", timestamp);
1182                         } while (find_edje(handle, _target_id));
1183
1184                         target_id = _target_id;
1185                 } else {
1186                         target_id = part;
1187                 }
1188
1189                 DbgPrint("Anonymouse target id: %s\n", target_id);
1190         }
1191
1192         obj = elm_layout_add(edje);
1193         if (!obj) {
1194                 ErrPrint("Failed to add a new edje object\n");
1195                 return LB_STATUS_ERROR_FAULT;
1196         }
1197
1198         if (!elm_layout_file_set(obj, path, group)) {
1199                 int err;
1200                 const char *errmsg;
1201
1202                 err = edje_object_load_error_get(elm_layout_edje_get(obj));
1203                 errmsg = edje_load_error_str(err);
1204                 ErrPrint("Could not load %s from %s: %s\n", group, path, errmsg);
1205                 evas_object_del(obj);
1206                 return LB_STATUS_ERROR_IO;
1207         }
1208
1209         evas_object_show(obj);
1210
1211         obj_info = calloc(1, sizeof(*obj_info));
1212         if (!obj_info) {
1213                 ErrPrint("Failed to add a obj_info\n");
1214                 evas_object_del(obj);
1215                 return LB_STATUS_ERROR_MEMORY;
1216         }
1217
1218         obj_info->id = strdup(target_id);
1219         if (!obj_info->id) {
1220                 ErrPrint("Failed to add a obj_info\n");
1221                 free(obj_info);
1222                 evas_object_del(obj);
1223                 return LB_STATUS_ERROR_MEMORY;
1224         }
1225
1226         obj_info->parent = edje;
1227
1228         child = malloc(sizeof(*child));
1229         if (!child) {
1230                 ErrPrint("Error: %s\n", strerror(errno));
1231                 free(obj_info->id);
1232                 free(obj_info);
1233                 evas_object_del(obj);
1234                 return LB_STATUS_ERROR_MEMORY;
1235         }
1236
1237         child->part = strdup(part);
1238         if (!child->part) {
1239                 ErrPrint("Error: %s\n", strerror(errno));
1240                 free(child);
1241                 free(obj_info->id);
1242                 free(obj_info);
1243                 evas_object_del(obj);
1244                 return LB_STATUS_ERROR_MEMORY;
1245         }
1246
1247         child->obj = obj;
1248
1249         evas_object_data_set(obj, "obj_info", obj_info);
1250         evas_object_event_callback_add(obj, EVAS_CALLBACK_DEL, edje_del_cb, handle);
1251         elm_object_signal_callback_add(obj, "*", "*", script_signal_cb, handle);
1252         handle->obj_list = eina_list_append(handle->obj_list, obj);
1253
1254         DbgPrint("%s part swallow edje %p\n", part, obj);
1255         elm_object_part_content_set(edje, part, obj);
1256
1257         obj_info = evas_object_data_get(edje, "obj_info");
1258         obj_info->children = eina_list_append(obj_info->children, child);
1259         return LB_STATUS_SUCCESS;
1260 }
1261
1262 PUBLIC int script_update_signal(void *h, Evas *e, const char *id, const char *part, const char *signal)
1263 {
1264         struct info *handle = h;
1265         Evas_Object *edje;
1266
1267         DbgPrint("id[%s], part[%s], signal[%s]\n", id, part, signal);
1268
1269         edje = find_edje(handle, id);
1270         if (!edje)
1271                 return LB_STATUS_ERROR_NOT_EXIST;
1272
1273         elm_object_signal_emit(edje, signal, part);
1274         return LB_STATUS_SUCCESS;
1275 }
1276
1277 PUBLIC int script_update_drag(void *h, Evas *e, const char *id, const char *part, double x, double y)
1278 {
1279         struct info *handle = h;
1280         Evas_Object *edje;
1281
1282         DbgPrint("id[%s], part[%s], %lfx%lf\n", id, part, x, y);
1283
1284         edje = find_edje(handle, id);
1285         if (!edje)
1286                 return LB_STATUS_ERROR_NOT_EXIST;
1287
1288         edje_object_part_drag_value_set(elm_layout_edje_get(edje), part, x, y);
1289         return LB_STATUS_SUCCESS;
1290 }
1291
1292 PUBLIC int script_update_size(void *han, Evas *e, const char *id, int w, int h)
1293 {
1294         struct info *handle = han;
1295         Evas_Object *edje;
1296
1297         edje = find_edje(handle, id);
1298         if (!edje)
1299                 return LB_STATUS_ERROR_NOT_EXIST;
1300
1301         if (!id) {
1302                 handle->w = w;
1303                 handle->h = h;
1304         }
1305
1306         DbgPrint("Resize object to %dx%d\n", w, h);
1307         evas_object_resize(edje, w, h);
1308         return LB_STATUS_SUCCESS;
1309 }
1310
1311 PUBLIC int script_update_category(void *h, Evas *e, const char *id, const char *category)
1312 {
1313         struct info *handle = h;
1314
1315         DbgPrint("id[%s], category[%s]\n", id, category);
1316
1317         if (handle->category) {
1318                 free(handle->category);
1319                 handle->category = NULL;
1320         }
1321
1322         if (!category)
1323                 return LB_STATUS_SUCCESS;
1324
1325         handle->category = strdup(category);
1326         if (!handle->category) {
1327                 ErrPrint("Error: %s\n", strerror(errno));
1328                 return LB_STATUS_ERROR_MEMORY;
1329         }
1330
1331         return LB_STATUS_SUCCESS;
1332 }
1333
1334 PUBLIC void *script_create(const char *file, const char *group)
1335 {
1336         struct info *handle;
1337
1338         DbgPrint("file[%s], group[%s]\n", file, group);
1339
1340         handle = calloc(1, sizeof(*handle));
1341         if (!handle) {
1342                 ErrPrint("Error: %s\n", strerror(errno));
1343                 return NULL;
1344         }
1345
1346         handle->file = strdup(file);
1347         if (!handle->file) {
1348                 ErrPrint("Error: %s\n", strerror(errno));
1349                 free(handle);
1350                 return NULL;
1351         }
1352
1353         handle->group = strdup(group);
1354         if (!handle->group) {
1355                 ErrPrint("Error: %s\n", strerror(errno));
1356                 free(handle->file);
1357                 free(handle);
1358                 return NULL;
1359         }
1360
1361         return handle;
1362 }
1363
1364 PUBLIC int script_destroy(void *_handle)
1365 {
1366         struct info *handle;
1367         Evas_Object *edje;
1368
1369         handle = _handle;
1370
1371         edje = eina_list_nth(handle->obj_list, 0);
1372         if (edje)
1373                 evas_object_del(edje);
1374
1375         free(handle->category);
1376         free(handle->file);
1377         free(handle->group);
1378         free(handle);
1379         return LB_STATUS_SUCCESS;
1380 }
1381
1382 PUBLIC int script_load(void *_handle, Evas *e, int w, int h)
1383 {
1384         struct info *handle;
1385         Evas_Object *edje;
1386         struct obj_info *obj_info;
1387
1388         handle = _handle;
1389
1390         obj_info = calloc(1, sizeof(*obj_info));
1391         if (!obj_info) {
1392                 ErrPrint("Heap: %s\n", strerror(errno));
1393                 return LB_STATUS_ERROR_MEMORY;
1394         }
1395
1396         obj_info->parent = evas_object_rectangle_add(e);
1397         if (!obj_info->parent) {
1398                 ErrPrint("Unable to create a parent box\n");
1399                 free(obj_info);
1400                 return LB_STATUS_ERROR_FAULT;
1401         }
1402
1403         edje = elm_layout_add(obj_info->parent);
1404         if (!edje) {
1405                 ErrPrint("Failed to create an edje object\n");
1406                 evas_object_del(obj_info->parent);
1407                 free(obj_info);
1408                 return LB_STATUS_ERROR_FAULT;
1409         }
1410
1411         DbgPrint("Load edje: %s - %s\n", handle->file, handle->group);
1412         if (!elm_layout_file_set(edje, handle->file, handle->group)) {
1413                 int err;
1414                 const char *errmsg;
1415
1416                 err = edje_object_load_error_get(elm_layout_edje_get(edje));
1417                 errmsg = edje_load_error_str(err);
1418                 ErrPrint("Could not load %s from %s: %s\n", handle->group, handle->file, errmsg);
1419                 evas_object_del(edje);
1420                 evas_object_del(obj_info->parent);
1421                 free(obj_info);
1422                 return LB_STATUS_ERROR_IO;
1423         }
1424
1425         handle->e = e;
1426         handle->w = w;
1427         handle->h = h;
1428
1429         elm_object_signal_callback_add(edje, "*", "*", script_signal_cb, handle);
1430         evas_object_event_callback_add(edje, EVAS_CALLBACK_DEL, edje_del_cb, handle);
1431         evas_object_size_hint_weight_set(edje, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
1432         evas_object_size_hint_fill_set(edje, EVAS_HINT_FILL, EVAS_HINT_FILL);
1433         evas_object_resize(edje, handle->w, handle->h);
1434         evas_object_show(edje);
1435         evas_object_data_set(edje, "obj_info", obj_info);
1436
1437         handle->obj_list = eina_list_append(handle->obj_list, edje);
1438         return LB_STATUS_SUCCESS;
1439 }
1440
1441 PUBLIC int script_unload(void *_handle, Evas *e)
1442 {
1443         struct info *handle;
1444         Evas_Object *edje;
1445         Evas_Object *parent = NULL;
1446
1447         handle = _handle;
1448
1449         DbgPrint("Unload edje: %s - %s\n", handle->file, handle->group);
1450         edje = eina_list_nth(handle->obj_list, 0);
1451         if (edje) {
1452                 struct obj_info *obj_info;
1453
1454                 obj_info = evas_object_data_get(edje, "obj_info");
1455                 if (obj_info)
1456                         parent = obj_info->parent;
1457                 evas_object_del(edje);
1458         }
1459
1460         if (parent) {
1461                 DbgPrint("Delete parent box\n");
1462                 evas_object_del(parent);
1463         }
1464
1465         handle->e = NULL;
1466         return LB_STATUS_SUCCESS;
1467 }
1468
1469 static void access_cb(keynode_t *node, void *user_data)
1470 {
1471         int state;
1472
1473         if (!node) {
1474                 if (vconf_get_bool(VCONFKEY_SETAPPL_ACCESSIBILITY_TTS, &state) != 0) {
1475                         ErrPrint("Idle lock state is not valid\n");
1476                         state = 0; /* DISABLED */
1477                 }
1478         } else {
1479                 state = vconf_keynode_get_bool(node);
1480         }
1481
1482         DbgPrint("ELM CONFIG ACCESS: %d\n", state);
1483         elm_config_access_set(state);
1484 }
1485
1486 static void update_font_cb(void *data)
1487 {
1488         elm_config_font_overlay_set(TEXT_CLASS, s_info.font_name, DEFAULT_FONT_SIZE);
1489         DbgPrint("Update text class %s (%s, %d)\n", TEXT_CLASS, s_info.font_name, DEFAULT_FONT_SIZE);
1490 }
1491
1492 static void font_changed_cb(keynode_t *node, void *user_data)
1493 {
1494         char *font_name;
1495
1496         font_name = vconf_get_str("db/setting/accessibility/font_name");
1497         if (!font_name) {
1498                 ErrPrint("Invalid font name (NULL)\n");
1499                 return;
1500         }
1501
1502         if (s_info.font_name && !strcmp(s_info.font_name, font_name)) {
1503                 DbgPrint("Font is not changed (Old: %s(%p) <> New: %s(%p))\n", s_info.font_name, s_info.font_name, font_name, font_name);
1504                 free(font_name);
1505                 return;
1506         }
1507
1508         if (s_info.font_name) {
1509                 DbgPrint("Release old font name: %s(%p)\n", s_info.font_name, s_info.font_name);
1510                 free(s_info.font_name);
1511                 s_info.font_name = NULL;
1512         }
1513
1514         s_info.font_name = font_name;
1515         DbgPrint("Font name is changed to %s(%p)\n", s_info.font_name, s_info.font_name);
1516
1517         /*!
1518          * \NOTE
1519          * Try to update all liveboxes
1520          */
1521         update_font_cb(NULL);
1522 }
1523
1524 static inline int convert_font_size(int size)
1525 {
1526         switch (size) {
1527         case SYSTEM_SETTINGS_FONT_SIZE_SMALL:
1528                 size = -80;
1529                 break;
1530         case SYSTEM_SETTINGS_FONT_SIZE_NORMAL:
1531                 size = -100;
1532                 break;
1533         case SYSTEM_SETTINGS_FONT_SIZE_LARGE:
1534                 size = -150;
1535                 break;
1536         case SYSTEM_SETTINGS_FONT_SIZE_HUGE:
1537                 size = -190;
1538                 break;
1539         case SYSTEM_SETTINGS_FONT_SIZE_GIANT:
1540                 size = -250;
1541                 break;
1542         default:
1543                 size = -100;
1544                 break;
1545         }
1546
1547         DbgPrint("Return size: %d\n", size);
1548         return size;
1549 }
1550
1551 static void font_size_cb(system_settings_key_e key, void *user_data)
1552 {
1553         int size;
1554
1555         if (system_settings_get_value_int(SYSTEM_SETTINGS_KEY_FONT_SIZE, &size) != SYSTEM_SETTINGS_ERROR_NONE)
1556                 return;
1557
1558         size = convert_font_size(size);
1559
1560         if (size == s_info.font_size) {
1561                 DbgPrint("Font size is not changed\n");
1562                 return;
1563         }
1564
1565         s_info.font_size = size;
1566         DbgPrint("Font size is changed to %d, but don't update the font info\n", size);
1567 }
1568
1569 PUBLIC int script_init(void)
1570 {
1571         int ret;
1572         int size = DEFAULT_FONT_SIZE;
1573         char *argv[] = {
1574                 "livebox.edje",
1575                 NULL,
1576         };
1577         /* ecore is already initialized */
1578         elm_init(1, argv);
1579         elm_config_scale_set(scale_get());
1580
1581         ret = vconf_notify_key_changed(VCONFKEY_SETAPPL_ACCESSIBILITY_TTS, access_cb, NULL);
1582         if (ret < 0)
1583                 ErrPrint("Failed to access cb\n");
1584
1585         access_cb(NULL, NULL);
1586
1587         ret = vconf_notify_key_changed("db/setting/accessibility/font_name", font_changed_cb, NULL);
1588         DbgPrint("System font is changed: %d\n", ret);
1589         
1590         ret = system_settings_set_changed_cb(SYSTEM_SETTINGS_KEY_FONT_SIZE, font_size_cb, NULL);
1591         DbgPrint("System font size is changed: %d\n", ret);
1592
1593         s_info.font_name = vconf_get_str("db/setting/accessibility/font_name");
1594         DbgPrint("Current font: %s\n", s_info.font_name);
1595
1596         ret = system_settings_get_value_int(SYSTEM_SETTINGS_KEY_FONT_SIZE, &size);
1597         s_info.font_size = convert_font_size(size);
1598         DbgPrint("Current size: %d\n", s_info.font_size);
1599
1600         return LB_STATUS_SUCCESS;
1601 }
1602
1603 PUBLIC int script_fini(void)
1604 {
1605         int ret;
1606         ret = system_settings_unset_changed_cb(SYSTEM_SETTINGS_KEY_FONT_SIZE);
1607         ret = system_settings_unset_changed_cb(SYSTEM_SETTINGS_KEY_FONT_TYPE);
1608         ret = vconf_ignore_key_changed(VCONFKEY_SETAPPL_ACCESSIBILITY_TTS, access_cb);
1609         elm_shutdown();
1610         return LB_STATUS_SUCCESS;
1611 }
1612
1613 /* End of a file */