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